Snabbtips Kollisionsdetektion mellan cirklar

Kollisionsdetektering är en gren av algoritmer som kontrollerar om två former överlappar varandra. Om du bygger fysik eller actionspel med ActionScript kommer du säkert inte att undvika bekanta med detta ämne. Detta är den första i serien om kollisionsdetektering. I denna snabba tips ska vi titta på ActionScripts inbyggda kollisionsdetekteringsmetod, hitTestObject (), och skriv vår egen för att upptäcka överlapp mellan två cirklar.


Slutresultatförhandsvisning

Detta är den slutliga SWF vi ska skapa i denna Snabba Tips. Klicka på den blå cirkeln och dra den mot den gröna. När de överlappar varandra ändrar den gröna cirkeln sin färg; Om du tar bort den blå cirkeln igen, kommer den andra att återgå till att vara grön.


Steg 1: Bindande rutjekontroller

De som är bekanta med ActionScript 2.0 kommer definitivt att känna igen metoden, hitTest (). Detta kommando kontrollerar överlappning mellan två former, eller mellan en form och en enda punkt. I ActionScript 3.0 delas den i två separata metoder: hitTestObject () och hitTestPoint ().

Vi ska titta på hitTestObject () först. Denna kommando passar i allmänhet kollisionsdetektering för boxliknande former (kvadrater, rektanglar). En avgränsningslåda är ritad runt former och när dessa avgränsande lådor överlappar varandra, hitTestObject () returnerar sant.

Kolla in exemplet nedan. Dra den blå rutan mot den gröna. När de överlappar varandra mörkar den gröna lådans skugga.

Jag bifogar här motsvarande ActionScript som genererar ovanstående presentation. Låda är en anpassad skriftlig klass för att enkelt generera kvadratiska former. Jag har inkluderat klasserna i källkatalogen hänvisa till dem. Det viktiga skriptet för kollisionsdetektering framhävs nedan.

 paket import flash.display.Graphics; importera flash.display.Sprite; importera flash.events.MouseEvent; / ** * Enkelt hitTest med lådor * @author Shiu * / [SWF (bredd = 400, höjd = 300)] allmän klass Enkel utökar Sprite privat var box1: Box, box2: Box; allmän funktion Enkel () box1 = ny Box (0x0000FF); addChild (box1); box1.x = 250; box1.y = 250; box1.addEventListener (MouseEvent.MOUSE_DOWN, start); box1.addEventListener (MouseEvent.MOUSE_UP, slutet); box2 = ny rutan (0x00FF00); addChild (box2); box2.x = 100; box2.y = 50;  privatfunktionsstart (e: MouseEvent): void e.target.startDrag (); e.target.addEventListener (MouseEvent.MOUSE_MOVE, check);  privatfunktionens slut (e: MouseEvent): void e.target.stopDrag (); e.target.removeEventListener (MouseEvent.MOUSE_MOVE, check);  privata funktionskontroll (e: MouseEvent): void if (e.target.hitTestObject (box2)) box2.color = 0x00AA00; annars box2.color = 0x00FF00; 

Steg 2: Brister i bindande lådor

Kollision mellan cirklar kan emellertid inte kontrolleras effektivt med hjälp av det här kommandot. Kolla in presentationen nedan. Dra den blå cirkeln mot den gröna. Innan formerna kolliderar, överlappar deras gränsvärdar redan och hitTestObject () är sant. Vi behöver en mer exakt lösning.

Detta problem är utbrett inte bara för kollisionsdetektering mellan cirklar men icke-kvadratiska former i allmänhet. Observera diagrammet nedan. För organiska former som är svåra att lösa av polygoner, ska vi använda pixel-precision kollisionsdetektering.


Olika felaktiga kollisioner upptäcks genom hitTestObject.

Steg 3: Avstånd mellan centra

Lösningen på det här problemet är ganska enkelt: vi ska mäta avståndet mellan centren i dessa cirklar. Om centren blir tillräckligt nära varandra ska vi flagga kollisionen som sant. Men hur nära är nära nog?


Avstånd mellan cirklar.

Observera diagrammet ovan. r1 hänvisar till radien av cirkel 1 och r2 refererar till cirkelns radie2. Avståndet mellan cirklar beräknas på varje ram. Om (och endast om) det är lika med eller mindre än summan av båda radierna (r1+ r2), då måste de två cirklarna röra eller överlappa varandra.


Steg 4: Cirkel-Cirkel Kollisionsdetektion

Här är den viktiga ActionScript för genomförandet av konceptet ovan:

 minDist = circle1.radius + circle2.radius;
 privata funktionskontroll (e: MouseEvent): void varavstånd: Number = Math2.Pythagoras (circle1.x, circle1.y, circle2.x, circle2.y); om (avstånd <= minDist) circle2.color = 0x00FFAA; else circle2.color = 0x00FF00; 

Steg 5: Provlösning

Här är ett urval av lösningen. Dra den blå cirkeln mot den gröna. När de överlappar varandra ser du gröns färgförändringar. Den återgår till normala när båda cirklarna inte kolliderar.

Jag har inkluderat ActionScript-implementeringen nedan.

 paket import flash.display.Sprite; importera flash.events.MouseEvent; / ** * Enkel kollision mellan 2 cirklar * @author Shiu * / [SWF (bredd = 400, höjd = 300)] allmän klass Simple3 utökar Sprite privat var cirkel1: Cirkel, cirkel2: Cirkel; privat var minDist: Nummer; allmän funktion Enkel3 () circle1 = ny cirkel (0x0055AA, 30); addChild (circle1); cirkel1.x = 250; circle1.y = 250; circle1.addEventListener (MouseEvent.MOUSE_DOWN, start); circle1.addEventListener (MouseEvent.MOUSE_UP, slutet); circle2 = ny cirkel (0x00FF00, 30); addChild (circle2); circle2.x = 100; circle2.y = 50; minDist = circle1.radius + circle2.radius;  privatfunktionsstart (e: MouseEvent): void e.target.startDrag (); e.target.addEventListener (MouseEvent.MOUSE_MOVE, check);  privatfunktionens slut (e: MouseEvent): void e.target.stopDrag (); e.target.removeEventListener (MouseEvent.MOUSE_MOVE, check);  privata funktionskontroll (e: MouseEvent): void varavstånd: Number = Math2.Pythagoras (circle1.x, circle1.y, circle2.x, circle2.y); om (avstånd <= minDist) circle2.color = 0x00FFAA; else circle2.color = 0x00FF00;   

Slutsats

Som du kan se är den allmänna principen om kollisionsdetektering att använda matematiska formler för att kontrollera överlappningar mellan olika former. Vector matematik spelar också en viktig roll. Framöver är kollision mellan en cirkel och en linje. Tack för att du läser och ser dig snart.