For å "blit" er å kopiere biter fra en del av datamaskinens grafiske minne til en annen del. Denne teknikken handler direkte med piksler av et bilde, og trekker dem direkte til skjermen, noe som gjør det til en veldig rask gjengivelsesteknikk som ofte er perfekt for raske 2D-actionspill.
De fleste gamedev-plattformene støtter en form for blitting; her bruker jeg vanlig Flash og AS3 for en web-vennlig demo.
Først må vi vite hvordan du lager en overflate i grafisk minne. I Flash kan vi gjøre slik:
var bmd: BitmapData = ny BitmapData (550, 500);
Dette skaper et rektangel som består av 550 ganger 500 piksler - dvs. farger. Vi kan da vise disse pikslene ved å overføre denne pikseldata til en bitmapobjekt og legge den til skjermen:
var bitmap: Bitmap = ny Bitmap (bmd); addChild (bitmap); // legg til på skjermen ved hjelp av Flashs visningsliste
Dette vil bare vise et hvitt rektangel på 550x500px, siden hvit er standardfarge for piksler i en ny BitmapData
gjenstand.
La oss nå antar at vi vil tegne en bakgrunn på dette rektangel. Vi kan gjøre dette ved å kopiere piksler av bakgrunnsbildet vårt direkte inn i eksisterende BitmapData
gjenstand, heller enn å legge til et nytt bilde på skjermen.
// ikke vist: importerer et bilde til bakgrunnen bildeobjekt. var backgroundRectangle: Rectangle = new Rectangle (); backgroundRectangle.x = 0; backgroundRectangle.y = 0; backgroundRectangle.width = backgroundImage.width; backgroundRectangle.height = backgroundImage.height; bmd.copyPixels (backgroundImage, backgroundRectangle, new Point (0,0));
I ovennevnte kode importerte vi et bilde i bakgrunnsbilde
objekt (dette kan være et JPEG-bilde, et bilde fra brukerens webkamera, en prosedyrisk generert bakgrunn - det spiller ingen rolle), og deretter definert et rektangel som skisserte et område på dette bildet (i dette tilfellet har vi nettopp skissert hele bildet).
Da kopierte vi piksler fra dette rektangulære området av bildet til eksisterende 550x500px BitmapData
objekt fra før - den nytt punkt (0,0)
sier bare at vi skal starte på koordinatene (0,0)
(dvs. øverste venstre hjørne) på 550x500px BitmapData
.
Forutsatt at det importerte bildet også er 550x500px, betyr dette at det helt vil dekke våre glatte hvite BitmapData
. Nå siden vår bmp
Bitmap er knyttet til dette BitmapData
, Vi ser at bildet vises på skjermen!
Vi kan da legge til et annet bilde på toppen av dette. La oss si det faceImage
er et 75x75px bilde av et ansikt, med en gjennomsiktig bakgrunn. Vi kan ganske enkelt gjøre dette:
// ikke vist: importerer et bilde til faceImage-objektet. var faceRectangle: Rectangle = new Rectangle (); faceRectangle.x = 0; faceRectangle.y = 0; faceRectangle.width = faceImage.width; faceRectangle.height = faceImage.height; bmd.copyPixels (faceImage, faceRectangle, nytt punkt (Math.random () * 550, Math.random () * 500));
Det er nesten samme kode som før: pikslene fra ansiktsbildet blir kopiert på BitmapData
, på toppen av de eksisterende pikslene som ble kopiert fra bakgrunnsbildet. Den store forskjellen er at vi kopierer ansiktet til en tilfeldig posisjon, i stedet for (0,0)
.
Slik ser dette ut i handlingen:
Det er viktig å nevne at dette ansiktsbildet ikke bare er "lagdelt" på toppen av bakgrunnsbildet; piksler av (opprinnelig vanlig hvit) BitmapData
ble hver for seg endret for å matche piksler av bakgrunnsbildet, og deretter ble et område på piksler på 75x75px endret en gang til for å matche pikslene i ansiktsbildet. Når du tilbakestiller demoen ovenfor, alle piksler i 550x500px BitmapData
endres for å matche piksler av bakgrunnsbildet igjen.
Fordi datamaskinen endrer direkte de enkelte pikslene i bitmappen, i stedet for å forsøke å holde styr på flere forskjellige lag, er denne metoden utrolig rask. I demonstrasjonen nedenfor har jeg lagt til litt enkel fysikk, og blitser hundrevis av bilder per sekund.
Selv om blitting allerede er veldig rask, er det ting vi kan gjøre for å gjøre det enda raskere.
Først kan vi låse bitmapet før du gjør noen endringer i BitmapData
at det er knyttet til.
Mens bitmapet er låst opp, vil det forsøke å gjøre alle endringene gjort på BitmapData
som disse endringene er gjort - så hvis vi blir 100 bilder i en enkelt sløyfe, må datamaskinen håndtere alle disse endringene, den ene etter den andre, på svært kort tid.
I stedet kan vi låse bitmapet, blit 100 objektene til BitmapData
, og deretter låse opp bitmapet; Bitmapet endres ikke mens det er låst, selv om BitmapData
endres 100 ganger. Det betyr at datamaskinen bare må gjengi bitmappen en gang per loop, i stedet for 100 ganger - mye raskere!
En annen optimaliseringsteknikk er å redusere antall piksler vi bliter på en gang. For eksempel, la oss anta at vi bliter et bakgrunnsbilde, og deretter blit et ansiktsbilde på toppen av det, og da vil vi fjerne Ansiktet og gå tilbake til en tom bakgrunn. (Husk at bildene ikke er lagdelt, piksler i ansiktet er kopiert over piksler i bakgrunnen.)
Den enkleste måten å gjøre dette på er å bare kaste hele 550x500px bakgrunnsbildet inn på BitmapData
igjen, dekket opp alt som var der før.
Men her er et alternativ: Vi kan finne ut hvilket område av skjermen ansiktsbildet dekker opp, og så blit en rektangulær del av bakgrunnen over det området! Denne teknikken er kjent som skitne rektangler.
Blitting er ofte et godt valg av gjengivelsesmetode for 2D actionspill, da det gir en rask måte å gjøre mange individuelle endringer på skjermen veldig raskt, på grunn av å manipulere pikslene direkte.
Det er ofte mindre minneintensivt enn andre metoder for gjengivelse, siden mindre grafisk informasjon må lagres - alt er i en enkelt bitmappe.
Husk at denne hastigheten og kraften vanligvis kommer til en pris av bekvemmelighet - for eksempel hvis du vil gjøre et forgrunnsobjekt krympe til ingenting, så kan du ikke bare endre dens bredde
og høyde
verdier; du må trekke opp bakgrunnen på toppen av den og deretter gjenopprette objektet litt mindre, om og om igjen.