Tot nu toe zijn onze collisiedetectiemethoden wiskundig gebaseerd. Hoewel dit nuttig is, zijn er gevallen waarin de wiskundige benadering gewoon niet de moeite waard is, zoals met een onregelmatige, organische vorm - de vereiste berekeningen zijn te ingewikkeld en te duur om te rechtvaardigen. In plaats daarvan kunnen we elke afzonderlijke pixel van de vormen controleren. Dit is ook een dure benadering, maar het kan op zijn minst worden geoptimaliseerd.
Dit is het laatste stuk dat we zullen proberen te creëren. Sleep de haak over de kokospalm en noteer wat de tekst onderaan zegt.
Stel dat we twee bitmaps hebben en we willen controleren of ze botsen, pixel voor pixel: wat betekent dit? Laten we aannemen dat beide bitmaps 3x3px zijn en dat alle pixels zijn gevuld.
We zullen dit letterlijk doen:
Er zijn een paar opmerkingen waar ik op wil wijzen.
observatie | Omschrijving |
Pixels linksboven | De pixels links bovenaan voor beide bitmaps worden gebruikt als startpunt voor controles. Bijvoorbeeld, al is de startpixel gecontroleerd tegen alle pixels in b, die begint met b1. Beide pixels linksboven. |
Scan-line progressie | Zoals vermeld in het vorige punt, wordt de controle uitgevoerd in de volgorde a1, a2, a3 ... a9. Let op de manier waarop deze pixels zijn gerangschikt. |
Gemeenschappelijke coördinaatruimte | Stel dat beide afbeeldingen worden toegevoegd aan de weergavelijst van de stage. De locatie van elke pixel in beide bitmaps, in de coördinatenruimte van de stage, worden vergeleken om te zien of overlappingen optreden. |
Dure berekening | Voor twee 3x3 bitmaps is een maximum van 9x9 herhalingen vereist. Als mijn bitmapgrootte naar 100x100 gaat, kunt u zien hoe snel de totale berekening groeit. Als echter één controle een positief resultaat oplevert, kan de rest van de controles worden afgebroken, omdat wanneer een pixel overlapt in beide bitmaps, we kunnen zeggen dat er een botsing plaatsvindt tussen de bitmaps |
Nu kan stap 1 letterlijk worden genomen als alle pixels zijn gevuld. Met bitmapafbeeldingen definiëren we een gebied met een rechthoekige dimensie. Maar niet alle pixels zijn gevuld om de afbeelding te vormen.
Het onderstaande voorbeeld toont de juiste bitmap die alleen b2, b4, b5, b6 en b8 inneemt. In dit geval moeten we elke pixel in de linkerbitmap (a1, a2, a3 ... a9) alleen controleren op de pixels b2, b4, b5, b6, b8 in de rechterbitmap.
Nu biedt ActionScript ons een andere parameter, alpha
, die de transparantie van de pixel definieert, waarbij 0 volledig transparant is en 1 volledig ondoorzichtig is. Voor b2, b4, b5, b6, b8 kunnen we een drempelwaarde definiëren voor alpha
, zeg 0.5.
Stel dus dat b2 en b8 beide pixels zijn alpha
0,1; omdat ze kleiner zijn dan de drempelwaarde van 0,5, beschouwen we ze niet als gevulde pixels en controleren ze daarom niet. Dus uiteindelijk wordt elke pixel in de linkerbitmap (a1, a2, a3 ... a9) alleen in de juiste bitmap vergeleken met b4, b5, b6.
In ActionScript kunnen we vectorafbeeldingen toevoegen aan BitmapData
instances. Je kunt je voorstellen dat ActionScript een röntgenfoto van een vectorafbeelding maakt en deze naar een kopie van de afbeelding verplaatst BitmapData
, die werkt als de fotografische film.
(Tip: als u in Flash IDE tekent en vervolgens exporteert naar FlashDevelop terwijl ik bezig ben, zorg er dan voor dat de afmetingen van de BitmapData
zijn groot genoeg om de tekening te bevatten.)
Hier, Ctree
en Haak
zijn twee MovieClip-symbolen, getekend in Flash; we "röntgen" ze om een BitmapData-instantie voor elk te verkrijgen:
private var coconut: CTree, hk: Hook; private var bdat1: BitmapData, bdat2: BitmapData; private var t1: TextField; openbare functie Matrix_Bitmap () coconut = nieuwe CTree (); addChild (kokos); coconut.x = stage.stageWidth * 0.3; coconut.y = stage.stageHeight * 0.2; bdat1 = nieuwe BitmapData (150, 150, waar, 0x00000000); bdat1.draw (kokos); hk = nieuwe Hook (); addChild (HK); bdat2 = nieuwe BitmapData (100, 50, true, 0x00000000); bdat2.draw (HK); hk.addEventListener (MouseEvent.MOUSE_DOWN, start); hk.addEventListener (MouseEvent.MOUSE_UP, einde); t1 = nieuw TextField (); addChild (t1); t1.x = stage.stageWidth * 0.2; t1.y = stage.stageHeight * 0.8; t1.width = 300; t1. hoogte = 100; stage.addEventListener (Event.ENTER_FRAME, check);
Dus daarna starten we de controles met behulp van de hitTest ()
methode van de BitmapData
klasse.
Op elk frame dat binnenkomt, zullen we de locatie van de pixel links bovenaan voor elke bitmap bijwerken voordat exemplaren worden geplaatst BitmapData
door deze rigoureuze hitTest ()
cheques. Merk ook op dat het bereik voor alpha
invoer is hier 0 ~ 255 - d.w.z. er is geen drempel. Meer over transparantie in de volgende stap.
persoonlijke functiecontrole (e: Event): void var point1: Point = new Point (coconut.x, coconut.y); // pixel linksboven van tree var point2: Point = new Point (hk.x, hk.y); // pixel linksboven als (bdat1.hitTest (punt1, 255, bdat2, punt2, 255)) // controleer of overlappende pixels overlappen t1.text = "Ten minste één pixel is gebotst" else t1 .text = "Geen botsing"
Hier is een voorbeeld van de uitvoer van ActionScript hierboven. Klik op de haak en breng hem in de buurt van de kokospalm en controleer het antwoord op het tekstvak. Speel hiermee rond door het uiteinde van de haak dicht bij de rand van de bladeren van de kokosnootboom te brengen, om te zien of deze botsing van pixelniveau is.
Als u een afbeelding hebt die langzaam verdwijnt (transparant wordt), kunt u ActionScript vertellen op welk transparantieniveau u een pixel geschikt vindt om botsingen uit te voeren.
Neem het onderstaande voorbeeld: er zijn verschillende transparantieniveaus op de sprite en, zoals u ziet, wordt deze geleidelijk naar rechts verlaagd. Als we het transparantieniveau instellen op 0,5, wordt elke pixel met een alpha van 0,5 ~ 1 als ondoorzichtig beschouwd en geschikt voor botsingdetectie. Die lager dan 0,5 worden als transparant beschouwd. Zelfs wanneer deze pixels botsen met die van een ander object, registreren ze geen echte botsing.
Een ander detail dat ik zojuist noemde, is dat ActionScript BitmapData
's hitTest-functie alpha
parameterwaarde ligt eigenlijk tussen 0 ~ 255. Dus wat ik doe is simpelweg mijn drempelwaarde vermenigvuldigen met 255 om het bereik te converteren.
persoonlijke functiecontrole (e: Event): void var point1: Point = new Point (bar1.x, bar1.y); var point2: Point = new Point (bar2.x, bar2.y); var threshold: Number = 255 * 0.5 if (bdat1.hitTest (point1, threshold, bdat2, point2, threshold)) t1.text = "Ten minste één pixel is gebotst" else t1.text = "Geen botsing"
Ik heb gezegd dat collisiedetectie op pixelniveau rekenkundig duur is. Dit betekent dat we er alleen voor kiezen als het strikt noodzakelijk is. Als twee objecten erg ver uit elkaar staan, is er geen reden om deze benadering te gebruiken en een botsingdetectie met normale begrenzingsbox (hitTestObject ()
) zal ik doen.
Dit is het idee:
hitTestObject ()
om te zien of de begrenzende vakken van twee objecten zijn gebotst.functiecontrole (e: Event): void var closeEnough: Boolean = coconut.hitTestObject (hk) if (closeEnough) var point1: Point = new Point (coconut.x, coconut.y); var point2: Point = new Point (hk.x, hk.y); if (bdat1.hitTest (point1, 255, bdat2, point2, 255)) t1.text = "Ten minste één pixel is gebotst" else t1.text = "Geen botsing"
Raadpleeg voor een volledige ActionScript-verwijzing Matrix_Bitmap3.as
van de brondownload.
Bedankt voor het lezen. In de volgende Snelle tip zullen we matrices gebruiken om te transformeren BitmapData
.