Pixel-Level Collision Detection Basert på Pixel Farger
to
Del
Del
Del
Dette Cyber mandag Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av.
Dette innlegget er en del av en serie som heter dueller og Reaction.Predicting Kollisjons Points Med Math i AS3This innlegget er en del av en serie som heter skytespillet Up.Build en Stage3D skytespillet -Up: Score, helse, liv, HUD og TransitionsBuild en Stage3D skytespillet Up: Full-Screen Boss Battles og polsk
I denne opplæringen, vil jeg følge den tilnærmingen foreslått av Richard Davey (Takk, Richard! ), og brukes av ham og andre, i å oppdage kollisjoner mellom punktgrafikk med en subtil endring. Jeg vil også sammenligne resultatene mellom ulike tilnærminger av bitmap dueller bruker Grant Skinners Performance sele
Merk:. I tillegg til å være en del av skytespillet Up Session , denne artikkelen er også en del av Collision Detection og Reaction jeg beskrive dette alternativ tilnærming i kort her Først sjekker vi om de to punktgrafikk 'grenseboksene er overlappende hjelp rektangel. Skriptene er som følger. Først variablene Her sjekker vi for noen overlappende område mellom boksene. Sjekk ut DetectVisible.as i kilde nedlasting for hele manuset Her er en demo. Dra mindre romskip rundt. (ikke bry deg om den røde boksen som blir "etterlatt" når skipet er dratt ut av den andre avgrensende rute.) Så hvis det er en kryssende boksen området, fortsetter vi å sjekke om det er overlappende piksler i området. Men la oss først prøve å trekke bitmap inn i dette krysset området. Den fulle skriptet i DetectVisible2.as Merk at siden vi trekker området ved bruk av en matrise, noe skalering, forvrenger og andre transformasjoner på begge bitmaps blir tatt hensyn til. Her er en demo; sjekk ut boksen i nedre venstre hjørne Så hvordan sjekker vi trenger for riktig pixel? Vel først av alt, vi gir fargen på dette krysset boksen en nyanse av svart (Rød = 0, Grønn = 0, Blå = 0). Deretter vil skyggen av de mindre romskipet malt inn i denne mørke boksen som grønn, med blanding modus for ADD. Tilsvarende vil skyggen av større stasjonære fremmed romskip males rød. Så nå, vil det være områder av rødt og grønt for romskip, og svart hvis det er ingen overlappende område. Men hvis det er piksler fra disse to bitmaps som overlapper hverandre, disse vil bli trukket i gult (Rød = 255, Grønn = 255, Blå = 0). Vi bruker metoden Bitmapdata.getColorBoundsRect å sjekke for eksistensen av dette området Her er biten i Main.as Merk at vi undertrykke den røde og blå komponenter i tråd 113 til maks ut Grønn for den lille romskipet. På linje 112 gjør vi det samme med fremmed romskip med blå og grønne komponenter. Så etter å ha fått kommentarer på ytelsesproblemer om dueller, besluttet jeg å gjøre noen raske og skitne tester på disse tilnærmingene. Jeg opprettet 20 fiendtlige romskip og en spiller romskip og sjekket dueller mellom at en spiller skip mot den andre 20. Disse sprites er pakket inn i samme nærhet å tvinge dueller for alle tilnærminger til å ha en fullstendig kjørt. Den første tilnærmingen er den enkleste. BitmapData er fanget på initiering og for hver ramme, er dueller kontrolleres ved hjelp BitmapData.hitTest (). For den andre tilnærmingen, er BitmapData oppdateres hver ramme og dueller er gjort basert på disse BitmapData fanget. Den tredje viser til tilnærmingen foreslått av denne opplæringen. Så resultatet for en av testene jeg har gjort er som følger. The Performancetest gir ulike resultater når jeg kjører test. Så jeg kjørte det et par ganger og hentet en gjennomsnittlig tid. Konklusjon: den raskeste måten er det først, fulgt av den tredje og den andre tilnærming. Så lagring bort BitmapData for punktgrafikk når de først introdusert i scenen og sjekke for hitTest hver ramme etter er faktisk effektiv, forutsatt at disse sprites ikke utfør noen andre enn oversettelse transformasjoner (som rotasjon, forvrenger og skalering ) over tid. Ellers vil du bli tvunget til å adoptere enten andre eller tredje tilnærming, og den tredje er mer effektiv som indikert av bildet ovenfor. Du kan sjekke ut Collisions.as og Results.as for hele manuset . Jeg la ut etterpå for å søke etter bestemte linjer med kode som tok opp mer beregning tid. Den andre og tredje metode tok lengre tid, så jeg avledet flere funksjoner fra dem, hver bryter ved forskjellige punkter. Sjekk ut et av resultatene below. The første, andre, og tredje ganger refererer til den andre fremgangsmåten på forskjellige brytningspunkt, og den fjerde og femte ganger refererer til tredje tilnærming. Ser vi på den tredje og femte gang resultatene, synes BitmapData.draw å ta mye beregning tid. Og den tiden det tar for å tegne med den andre tilnærmingen synes å være dyrere i beregningen tid, noe som fører meg til å tenke at størrelsene for BitmapData.draw å operere på spiller ingen rolle. Du kan sjekke ut Collisions2.as og Results2.as for full skript. En ting jeg finner litt urovekkende er inkonsekvensen av disse testene - Jeg har alltid ikke får de samme tids resultater, selv om de nesten følge den samme rangeringen til enhver tid. Så, det er bra nok til å gjøre noen enkel sammenligning mellom funksjoner. Vel, takk for tiden din ute leser dette lite tips. Håper det har vært nyttig. Må legge inn kommentarer hvis du ikke er enig med noe i denne opplæringen. Jeg vil gjerne svare på tilbakemelding! Anmeldelser
Trinn 1:.. Oversikt
< li> Sjekk om det er noen overlapping mellom de to punktgrafikk.
Hvis det er, videre til # 3. Ellers droppe ut.
Trinn 2:. Markeringsbokser
private Var enemy1: Bitmap, MinForsendelse: Bitmap, private Var myShipSp. Sprite, private Var rec_e: rektangel, rec_m: rektangel, private Var intersec: rektangel; enemy1 = new E1 som Bitmap; addChild (enemy1); MinForsendelse = new My som Bitmap; myShipSp = new Sprite; addChild (myShipSp); myShipSp.addChild (MinForsendelse); enemy1.x = stage.stageWidth > > 1; myShipSp.x = stage.stageWidth > > 1; enemy1.y = stage.stageHeight * 0,2; myShipSp.y = stage.stageHeight * 0,8; //tegning bokser rundt spritedraw (enemy1.getBounds (scene), dette, 0); uavgjort (myShipSp.getBounds (scene), dette, 0);
privat funksjon refresh (e: Hendelses): void {//bestemme markeringsrammen skjæringsområdet rec_e = enemy1.getBounds (scene); rec_m = myShipSp.getBounds (scene); intersec = rec_e.intersection (rec_m); //tegne markeringsrammen for begge sprites this.graphics.clear (); Draw (enemy1.getBounds (scene), dette, 0); Draw (myShipSp.getBounds (scene), dette, 0); //bare trekke markeringsrammen skjærings området hvis det er en hvis {lines.graphics.clear () (intersec.isEmpty ()!); tegne (intersec, linjer); t.text = "Veikryss området ved rød firkant." } Else {t.text = "Ingen krysset området." }}
Trinn 3: Tegning i skjæringspunktet området
privat funksjon refresh (e: Hendelses): void {//bestemme markeringsrammen skjæringsområdet rec_e = enemy1.getBounds (scene); rec_m = myShipSp.getBounds (scene); intersec = rec_e.intersection (rec_m); //tegne markeringsrammen for begge sprites this.graphics.clear (); Draw (enemy1.getBounds (scene), dette, 0); Draw (myShipSp.getBounds (scene), dette, 0); //bare trekke markeringsrammen skjærings området hvis det er en hvis {lines.graphics.clear () (intersec.isEmpty ()!); tegne (intersec, linjer); //trekke krysset området og sjekker for overlapping av farget område Var eM: Matrix = enemy1.transform.matrix; Var MYM: Matrix = myShipSp.transform.matrix; bdt_intersec = new BitmapData (intersec.width, intersec.height, falsk, 0) eM.tx - = intersec.x; eM.ty - = intersec.y myM.tx - = intersec.x; myM.ty - = intersec.y bdt_intersec.draw (enemy1, eM); bdt_intersec.draw (MinForsendelse, MYM); bm_intersec.bitmapData = bdt_intersec; bm_intersec.x = 10 bm_intersec.y = stage.stageHeight * 0,8 - bm_intersec.height; t.text = "Veikryss området ved rød firkant. \\ n"} else {t.text = "Ingen krysset området." }}
Trinn 4:. Sjekk for Color i krysset området
//trekke krysset området og sjekker for overlapping av farget areavar eM. Matrix = enemy1.transform.matrix; Var MYM: Matrix = myShipSp.transform.matrix; bdt_intersec = new BitmapData (intersec.width, intersec.height, falsk, 0) eM.tx - = intersec.x; eM.ty - = intersec.ymyM.tx - = intersec.x; myM.ty - = intersec.y //tweak colorbdt_intersec.draw (enemy1, eM, ny ColorTransform (1,1,1,1,255, -255, -255), BlendMode.ADD); bdt_intersec.draw (MinForsendelse, MYM, ny ColorTransform (1,1,1,1, -255 255, -255), BlendMode.ADD); bm_intersec.bitmapData = bdt_intersec; bm_intersec.x = 10bm_intersec.y = stage.stageHeight * 0,8 - bm_intersec.height; t.text = "Veikryss området ved rød firkant \\ n." //sjekk for eksistensen av retten colorintersec_color = bdt_intersec.getColorBoundsRect (0xFFFFFF, 0xffff00), hvis t.appendText ("Og det er interesecting piksler (intersec_color.isEmpty ()!) i området. ");
Sammenligning Approaches
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––bitmapdata fast (1000 iterasjoner) Player versjon: WIN 11,1,102,55 (debug)––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––method...................................................ttl ms ... avg msbitmapdata fast 168 0.17––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––bitmapdata oppdateringer (1000 iterasjoner) Player versjon: WIN 11,1,102,55 (debug)––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––method...................................................ttl ms ... avg msbitmapdata oppdateringer 5003 5.00––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––custom metode (1000 iterasjoner) Player versjon: WIN 11,1,102,55 (debug)––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––method...................................................ttl ms ... avg mscustom metode 4408 4.41––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
Searching for kostbare metoder
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––default hitTest (1000 iterasjoner) Player versjon: WIN 11,1,102,55 (debug) inkluderer grenser ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––method...................................................ttl ms ... avg msdefault hitTest 189 0.19––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––default hitTest (1000 iterasjoner) Player versjon: VINN 11,1,102,55 (debug) inkluderer trans ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––method...................................................ttl ms ... avg msdefault hitTest 357 0.36––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––default hitTest (1000 iterasjoner) Player versjon: VINN 11,1,102,55 (debug) inkluderer hitTest ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––method...................................................ttl ms ... avg msdefault hitTest 4427 4.43––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––custom metode (1000 iterasjoner) Player versjon: WIN 11,1,102,55 (debug) Inneholder grensene og transformere ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––method...................................................ttl ms ... avg mscustom metode 411 0.41––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––custom metode (1000 iterasjoner) Player versjon: WIN 11,1,102,55 (debug) inkluderer tegne og grenser ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––method...................................................ttl ms ... avg mscustom metode 3320 3.32––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
Konklusjon