Spelar runt med elastiska kollisioner

I denna handledning skapar vi ett spel där målet är att förhindra att andra objekt kolliderar med markören. Vi använder inte Flash-inbyggd hitTestObject () metoder; i stället skriver vi våra egna kollisionsdetekteringsrutiner.

Publicerad handledning

Varje par veckor besöker vi några av våra läsares favoritinlägg från hela webbplatsens historia. Denna handledning publicerades först i februari 2011.


Slutresultatförhandsvisning

Låt oss ta en titt på det slutliga resultatet vi ska arbeta för:


Steg 1: Starta av

Skapa en ny Flash-fil (ActionScript 3.0)

Ställ in scendimensionerna till 500x500px och FPS till 32.


Steg 2: Bollklassen

Denna klass innehåller alla data relaterade till en boll. En boll har a _massa, en _radie, en _xSpeed och a _ySpeed. Så vi ska göra en fastighet för varje. I konstruktören passerar vi massan, vinkeln och hastigheten på bollen. Eftersom klassen kommer att kopplas till ett visningsobjekt kan vi hämta radien hos vår boll genom att dividera displayens bredd med 2. _xSpeed och _ySpeed kan beräknas med hjälp av enkla sinus- och cosinusfunktioner.

 paket import flash.display.Stage import flash.display.Sprite import flash.events.Event offentlig klass Ball sträcker Sprite privat var _radius: Number = 0 privat var _mass: Number = 0 privat var _xSpeed: Number = 0 privat var _ySpeed : Nummer = 0 allmän funktion Boll (massa: Nummer = 10,0, vinkel: Nummer = Math.PI, hastighet: Nummer = 10,0): void this.mass = mass this._radius = this.width / 2 this.xSpeed ​​= speed * Math.sin (vinkel) this.ySpeed ​​= hastighet * Math.cos (vinkel)

För mer information om dessa trigonometriska Math.sin () och Math.cos () -funktioner, se denna Snabba Tips.


Steg 3: Getters och Setters

I vår bollklass ger vi getters och setters till våra fastigheter.

 allmän funktion få radien (): Nummer return this._radius allmän funktionsuppsättning massa (massa: Nummer): void this._mass = mass allmän funktion få massa (): Nummer return this._mass public function set xSpeed (xSpeed: Number): void this._xSpeed ​​= xSpeed allmän funktion få xSpeed ​​(): Nummer return this._xSpeed allmän funktion set ySpeed ​​(ySpeed: Number): void this._ySpeed ​​= ySpeed allmän funktion få ySpeed (): Number return this._ySpeed

Steg 4: Uppdateringsfunktion

Denna funktion uppdaterar x- och y-egenskaperna hos vår boll enligt _xSpeed och _ySpeed. Vi genomför denna funktion i vår Boll klass.

 public function update (): void this.x + = _xSpeed ​​this.y + = _ySpeed

Steg 5: Den färdiga klassen

Vi avslutar vår Boll klass i detta steg.

 paket import flash.display.Stage import flash.display.Sprite import flash.events.Event offentlig klass Ball sträcker Sprite privat var _radius: Number = 0 privat var _mass: Number = 0 privat var _xSpeed: Number = 0 privat var _ySpeed : Nummer = 0 allmän funktion Boll (massa: Nummer = 10,0, vinkel: Nummer = Math.PI, hastighet: Nummer = 10,0): void this.mass = mass this._radius = this.width / 2 this.xSpeed ​​= speed * Math.sin (vinkel) this.ySpeed ​​= hastighet * Math.cos (vinkel) allmän funktion få radie (): Antal return this._radius public function set massa (massa: Number): void this._mass = mass allmän funktion få massa (): Nummer return this._mass allmän funktionssättning xSpeed ​​(xSpeed: Number): void this._xSpeed ​​= xSpeed allmän funktion få xSpeed ​​(): Nummer returnera this._xSpeed Ange ySpeed ​​(ySpeed: Nummer): void this._ySpeed ​​= ySpeed allmän funktion få ySpeed ​​(): Nummer return this._ySpeed public function update (): void this.x + = _xSpeed ​​this.y + = _ySpeed 

Steg 6: Visa objekt för vår bollklass

I källfilerna inkluderade jag en start FLA som innehåller alla de biblioteksposter du behöver. Du kan själv rita dem själv om du vill ha det. Se till att din FLA har följande visningsobjekt:

(Ed. Notering: det är ett typsnitt: "ennemyball" ska säga "fiendeboll".)


Steg 7: Länkar våra biblioteksobjekt

De Boll den klass vi just skapat måste kopplas till enemyball Sprite i biblioteket.

De playerball Sprite måste ha Boll som basklass och PlayerBall som klass.

De Göra filmklipp måste ha en Göra klass.


Steg 8: Tillämpningsklassen (Dokumentklass)

De Ansökan klassen innehåller alla spellogik. Vi importerar alla de klasser vi behöver. Som du kan se använder vi TweenMax.

Därefter definierar vi våra fältvariabler. Den första fältvariabeln är basebollspelare.

Eftersom basklassen hos vår playerball Sprite är Boll vi kan lagra den här klassen i basebollspelare variabel. Detta gör det lättare senare att kontrollera efter kollisioner mellan basebollspelare och fiendens bollar.

Den andra fältvariabeln är en grupp som innehåller alla våra fiendens bollar. Den tredje variabeln är den tid som används för att utföra huvudspelslingan. Det fjärde och sista fältet är en förekomst av vår Göra bibliotek objekt som kommer att användas för att visa den förflutna speltiden. I konstruktören kallar vi i det() funktion som jag förklarar i nästa steg.

 paketet import flash.display.Sprite import flash.display.Graphics importera flash.events.Event import flash.events.TimerEvent importera flash.events.MouseEvent importera flash.geom.Matrix importera flash.utils.Timer importera flash.ui.Mouse importera com.greensock.TweenMax import com.greensock.easing. * offentlig klass Programmet sträcker sig Sprite private var ballPlayer: Ball privat var eballs: Array privat var tmr: Timer privat var poäng: Betyg public function Application (): void init ( )

Glöm inte att länka dokumentklassen!.


Steg 9: init () -funktionen

Ta en titt på den här koden:

 privat funktion init (): void ballPlayer = ny PlayerBall () eballs = ny Array () tmr = ny Timer (10) score = nytt poäng () stage.align = "TL" stage.scaleMode = "noScale" Mouse.hide () set.Background () score.x = stage.stageWidth / 2 score.y = stage.stageHeight / 2 stage.addChild (poäng) stage.addEventListener (MouseEvent.MOUSE_MOVE, updatePlayerBall) stage.addChild (ballPlayer) tmr.addEventListener (TimerEvent .TIMER, updateTime) stage.addEventListener (MouseEvent.CLICK, startspel)

I de första fyra raderna initierar vi våra fältvariabler.

Därefter ser vi till att vårt stadium ligger i det övre vänstra hörnet och inte skala.

Vi gömmer muspekaren. Vår markör kommer att ersättas med playerball Sprite. Nästa kallar vi setBackground funktion (förklaras i nästa steg).

Vi centrerar vår Göra på skärmen och lägg till den i visningslistan. För att uppdatera positionen för basebollspelare vi bifogar en MouseEvent.MOUSE_MOVE-händelse till scenen.

De updatePlayerBall funktionen (förklaras i steg 11) hanterar denna MouseEvent. Nästa lägger vi till basebollspelare till visningslistan.

Timern används för att visa speltiden. Vi bifogar en TimerEvent.TIMER-lyssnare till vår timer, vilket kommer att utlösa uppdaterings tid() funktion (förklaras i steg 12) var 10: e millisekunder.

Slutligen lägger vi till en MouseEvent.CLICK till vårt stadium. De starta spelet funktionen (förklarad i steg 13) startar sedan vårt spel.


Steg 10: setBackground () Funktion

Denna funktion lägger till en radial gradientbakgrund till displaylistan. För att rita en gradient på en Sprite måste du definiera typen av gradient, färgerna du vill använda, alfavärdena för färgerna, förhållandena (dessa definierar färgens fördelning) och spridningsmetoden.

För mer information, se denna snabba tips om gradienter.

 privat funktion setBackground (): void var typ: String = "radial" var färger: Array = [0xffffff, 0xcccccc] var alfa: Array = [1, 1] var förhållanden: Array = [0, 255] var matr: Matrix = New Matrix () matr.createGradientBox (stage.stageWidth, stage.stageHeight, Math.PI / 2, 0, 0) // SpreadMethod definierar hur gradienten sprids. Notera!!! Flash använder CONSTANTS för att representera String literals var sprMethod: String = "pad" // Starta Gradietn och skicka våra variabler till det var sprite: Sprite = new Sprite () // Spara typing + öka prestanda genom lokal referens till ett grafiskt objekt var g: Graphics = sprite.graphics g.beginGradientFill (typ, färger, alfas, förhållanden, matr, sprMethod) g.drawRect (0,0, stage.stageWidth, stage.stageHeight) stage.addChild (sprite)

Steg 11: UpdatePlayerBall () Funktion

Den här funktionen uppdaterar positionen för basebollspelare enligt musens position.

 privat funktion updatePlayerBall (e: MouseEvent): void ballPlayer.x = mouseX ballPlayer.y = mouseY

Steg 12: UpdateTime () Funktion

Vi beräknar tiden i sekunder och lägger den in i textrutan på vår Göra Sprite. Varje 5000ms (fem sekunder) lägger vi till en ny boll i spelet.

 privat funktion updateTime (e: TimerEvent): void score.txtScore.text = String (((tmr.currentCount * tmr.delay) / 1000) .toFixed (2)); om ((tmr.currentCount * tmr.delay)% 5000 == 0) addBall (); 

Steg 13: startGame () Funktion

Spelet startas genom att klicka på scenen. Först tar vi bort lyssnaren för scenklicket, så att vi inte kan starta spelets servertider. Vi lägger till tre bollar till spelet genom att ringa addBall () funktionen (förklaras i nästa steg) tre gånger. Vi startar vår timer som uppdaterar vår speltid.

Slutligen lägger vi till en ENTER_FRAME-händelse i vårt skede. De gameLoop () funktionen (förklaras i steg 15) kommer att uppdatera placeringen av våra fiendens bollar.

 privat funktion startspel (e: MouseEvent): void stage.removeEventListener (MouseEvent.CLICK, startGame) addBall () addBall () addBall () tmr.start () stage.addEventListener (Event.ENTER_FRAME, gameLoop)

Steg 14: addBall () Funktion

Först gör vi en ny instans av vår Boll klass. Vi placerar boll slumpmässigt på scenen med en alfa av 0 och lägg till den i visningslistan.

Därefter vi mellan alfa tillbaka till 1. (Jag använder TweenMax, det ingår i källfilerna. Du kan också använda den inbyggda Flash-tween-motorn.) Den andra tweenen är inte riktigt en tween. Det väntar bara en sekund och onComplete funktionen trycker på boll in i vårt eballs array. På så sätt gameLoop () funktionen (förklaras i nästa steg) kan hantera resten.

 privat funktion addBall (): void var boll: Boll = ny boll (10, Math.random () * Math.PI * 2, 5) ball.x = Math.random () * stage.stageWidth ball.y = Math .random () * stadium.stageHeight ball.alpha = 0 stage.addChild (boll) TweenMax.to (boll, 0,5, alfa: 1) TweenMax.to (boll, 0, fördröjning: 1, onComplete: function ): void eballs.push (boll))

Steg 15: gameLoop () Funktion

Varje ram går igenom den här funktionen.

 privat funktion gameLoop (e: Event): void for (var i: uint = 0; i < eballs.length; i++)  for (var j:uint = i + 1; j < eballs.length; j++)  if (collision(eballs[i], eballs[j]))  doCollision(eballs[i], eballs[j])   if(collision(eballs[i], ballPlayer))  endOfGame() break  eballs[i].update() checkBounds(eballs[i])  

Vi börjar genom att iterera genom alla våra fiendens bollar.

Den andra för-loop kontrollerar kollisioner mellan fiendens bollar. Slingan börjar på 'i + 1'. På så sätt kontrollerar vi inte kollisionerna dubbel.

Nästa kontrollerar vi om basebollspelare träffar fiendens boll. Om så är fallet, är spelet klart. Då uppdaterar vi positionen för vår fiendens boll.

Vi ser till att bollarna stannar i spelskärmen genom att ringa funktionen checkBounds () (förklaras senare).


Steg 16: Kollision () Funktion

Denna funktion kontrollerar om ett givet par bollar kolliderar.

Först beräknar vi x-avståndet och y-avståndet mellan de två bollarna. Med hjälp av Pythagoras teorem (se följande diagram) beräknar vi det absoluta avståndet mellan dem. Om avståndet är mindre eller lika med summan av bollens radier har vi en kollision.

 privatkollision (ball1: Ball, ball2: Ball): Boolean var xDist: Number = ball1.x - ball2.x var yDist: Number = ball1.y - ball2.y var Dist: Nummer = Math.sqrt (xDist * xDist + yDist * yDist) returnera Dist <= ball1.radius + ball2.radius 

Steg 17: doCollision () Funktion

Denna funktion kommer att beräkna bollens nya x- och y-hastighet enligt kollisionens hastighet och vinkel. Varning: matematik;)

Först beräknar vi det horisontella avståndet mellan de två bollarna och sedan det vertikala avståndet mellan bollarna. Med dessa avstånd (och lite mer trigonometri) kan vi beräkna vinkeln mellan bollarna (se diagram).

Nästa beräknar vi vad jag kallar magnitud av varje boll. (Vi har en xspeed-vektor och en yspeed-vektor, storleken är vektorsumman av dessa.) Sedan beräknar vi vinkeln för varje boll (liknar den tidigare vinkelberäkningen).

Därefter roterar vi de nya x- och y-hastigheterna för varje boll. Vad vi faktiskt gör är att rotera koordinatsystemet. Genom att rotera våra axlar har vi en 1D kollision. (Se följande diagram).

Newton säger att den totala mängden kinetisk energi i ett slutet system är konstant. Nu använder vi dessa formler:

  • v1 = (u1 * (m1-m2) + 2 * m2 * u2) / (m1 + m2)
  • v2 = (u2 * (m2-m1) + 2 * m1 * u1) / (m1 + m2)

var:
v1 = slutlig xSpeedBall 1
v2 = slutlig xSpeedBall 2
m1 = massboll 1
m2 = massboll 2
u1 = starthastighetskula 1
u2 = initialhastighetskula 2

Y-hastigheterna förändras inte eftersom det är en 1D-kollision.

Med dessa formler kan vi beräkna xSpeed och ySpeed av varje boll.

Nu har vi de nya x- och y-hastigheterna i vårt roterade koordinatsystem. Det sista steget är att konvertera allt tillbaka till ett normalt koordinatsystem. Vi använder Math.PI / 2 eftersom vinkeln mellan xSpeed och ySpeed måste alltid vara 90 grader (pi / 2 radianer).

 privata funktion doCollision (ball1: Ball, ball2: Ball): void var xDist: Nummer = ball1.x - ball2.x var yDist: Number = ball1.y - ball2.y var collisionAngle: Number = Math.atan2 (yDist, xDist) var magBall1: Nummer = Math.sqrt (ball1.xSpeed ​​* ball1.xSpeed ​​+ ball1.ySpeed ​​* ball1.ySpeed) var magBall2: Number = Math.sqrt (ball2.xSpeed ​​* ball2.xSpeed ​​+ ball2.ySpeed ​​* ball2. ySpeed) var vinkelBall1: Nummer = Math.atan2 (ball1.ySpeed, ball1.xSpeed) varvinkelBall2: Nummer = Math.atan2 (ball2.ySpeed, ball2.xSpeed) var xSpeedBall1: Number = magBall1 * Math.cos (angleBall1-collisionAngle ) var ySpeedBall1: Number = magBall1 * Math.sin (angleBall1-collisionAngle) var xSpeedBall2: Number = magBall2 * Math.cos (angleBall2-collisionAngle) var ySpeedBall2: Number = magBall2 * Math.sin (angleBall2-collisionAngle) var finalxSpeedBall1: Number = ((ball1.mass-ball2.mass) * xSpeedBall1 + (ball2.mass + ball2.mass) * xSpeedBall2) / (ball1.mass + ball2.mass) var finalxSpeedBall2: Number = ((ball1.mass + ball1.mass) * xSpeedBall1 + (ball2.mass-ball1.mass) * xSpeedBall 2) / (ball1.mass + ball2.mass) var finalySpeedBall1: Number = ySpeedBall1 var finalySpeedBall2: Number = ySpeedBall2 ball1.xSpeed ​​= Math.cos (collisionAngle) * finalxSpeedBall1 + Math.cos (collisionAngle + Math.PI / 2) * finalySpeedBall1 ball1.ySpeed ​​= Math.sin (collisionAngle) * finalxSpeedBall1 + Math.sin (collisionAngle + Math.PI / 2) * finalySpeedBall1 ball2.xSpeed ​​= Math.cos (collisionAngle) * finalxSpeedBall2 + Math.cos (collisionAngle + Math.PI / 2) * finalySpeedBall2 ball2.ySpeed ​​= Math.sin (collisionAngle) * finalxSpeedBall2 + Math.sin (collisionAngle + Math.PI / 2) * finalySpeedBall2

För att hitta mer information om elastiska kollisioner, ta en titt på hoomanr.com.


Steg 18: endOfGame () Funktion

Detta körs när spelet avslutas.

 privat funktion endOfGame (): void tmr.stop () Mouse.show () stage.removeEventListener (MouseEvent.MOUSE_MOVE, updatePlayerBall) stage.removeEventListener (Event.ENTER_FRAME, gameLoop) medan (eballs.length> 0) TweenMax.to (eballs [0], 0.5, scaleX: 0, scaleY: 0, lätthet: Bounce.easeOut) eballs.splice (0,1) TweenMax.to (ballPlayer, 0,5, scaleX: 0, scaleY: 0, lätthet: Bounce.easeOut)

Först av allt stoppar vi timern. Vi visar musen igen. Därefter tar vi bort både MOUSE_MOVE och ENTER_FRAME händelse lyssnare. Slutligen gör vi alla bollar på scenen osynliga.


Steg 19: checkBounds () Funktion

Denna funktion säkerställer att bollarna ligger inne i spelskärmen. Så om bollen träffar övre eller nedre sidan, vänder vi om ySpeed. Om bollen träffar vänster eller höger sida av skärmen vänder vi om xSpeed. Den använder liknande logik på kollisionsdetekteringsfunktionen för att kontrollera om kanten på bollen träffar en kant av skärmen.

 privat funktion checkBounds (boll: Boll): void if ((ball.x + ball.radius)> stadium.stageWidth) ball.x = stage.stageWidth - ball.radius ball.xSpeed ​​* = -1 om ball.x - ball.radius) < 0)  ball.x = 0 + ball.radius ball.xSpeed *= -1  if((ball.y + ball.radius) > stadium.stageHeight) ball.y = stadium.stageHeight - ball.radius ball.ySpeed ​​* = - 1 om ((ball.y - ball.radius) < 0)  ball.y = 0 + ball.radius ball.ySpeed *= - 1  

Steg 20: Den fullständiga applikationsklassen

Vi har slutfört vår applikationsklass. Vi har nu ett arbetsspel!!!

 paket import flash.display.Sprite; importera flash.display.Graphics; importera flash.events.Event; importera flash.events.TimerEvent; importera flash.events.MouseEvent; importera flash.geom.Matrix; importera flash.utils.Timer; importera flash.ui.Mouse; importera com.greensock.TweenMax; importera com.greensock.easing. *; offentlig klass Ansökan utökar Sprite private var ballPlayer: Ball; privata varbollar: Array; privat var tmr: Timer; privat var poäng: poäng; allmän funktion Program (): void init ();  privatfunktion init (): void ballPlayer = new PlayerBall (); eballs = ny Array (); tmr = ny timer (10); score = nytt poäng (); stage.align = "TL"; stage.scaleMode = "noScale"; Mouse.hide (); setBackground (); score.x = stage.stageWidth / 2; score.y = stage.stageHeight / 2; stage.addChild (poäng); stage.addEventListener (MouseEvent.MOUSE_MOVE, updatePlayerBall); stage.addChild (basebollspelare); tmr.addEventListener (TimerEvent.TIMER, updateTime); stage.addEventListener (MouseEvent.CLICK, startGame);  privatfunktionsuppsättningBackground (): void var type: String = "radial"; var färger: Array = [0xffffff, 0xcccccc]; var alfa: Array = [1,1]; varförhållanden: Array = [0,255]; var matr: Matrix = ny matris (); matr.createGradientBox (stage.stageWidth, stage.stageHeight, Math.PI / 2, 0, 0); // SpreadMethod definierar hur gradienten sprids. Notera!!! Flash använder CONSTANTS för att representera String literals var sprMethod: String = "pad"; // Starta Gradietn och skicka våra variabler till det var sprite: Sprite = new Sprite (); // Spara typing + öka prestanda genom lokal referens till ett grafikobjekt var g: Graphics = sprite.graphics; g.beginGradientFill (typ, färger, alfas, förhållanden, matr, sprMethod); g.drawRect (0,0, stage.stageWidth, stage.stageHeight); stage.addChild (sprite);  privatfunktionsuppdateringPlayerBall (e: MouseEvent): void ballPlayer.x = mouseX; bollSpelare.y = mouseY;  privat funktion updateTime (e: TimerEvent): void score.txtScore.text = String (((tmr.currentCount * tmr.delay) / 1000) .toFixed (2)); om ((tmr.currentCount * tmr.delay)% 5000 == 0) addBall ();  privat funktion startspel (e: MouseEvent): void stage.removeEventListener (MouseEvent.CLICK, startGame); addBall (); addBall (); addBall (); tmr.start (); stage.addEventListener (Event.ENTER_FRAME, gameLoop);  privat funktion addBall (): void var boll: Boll = ny boll (10, Math.random () * Math.PI * 2,5); ball.x = Math.random () * stadium.stageWidth; ball.y = Math.random () * stadium.stageHeight; ball.alpha = 0; stage.addChild (boll); TweenMax.to (boll, 0,5, alfa: 1); TweenMax.to (boll, 0, fördröjning: 1, onComplete: function (): void eballs.push (boll));  privat funktion gameLoop (e: Event): void for (var i: uint = 0; i < eballs.length; i++)  for (var j:uint = i + 1; j < eballs.length; j++)  if (collision(eballs[i],eballs[j]))  doCollision(eballs[i], eballs[j]);   if (collision(eballs[i],ballPlayer))  endOfGame(); break;  eballs[i].update(); checkBounds(eballs[i]);   private function collision(ball1:Ball, ball2:Ball):Boolean  var xDist:Number = ball1.x - ball2.x; var yDist:Number = ball1.y - ball2.y; var Dist:Number = Math.sqrt(xDist * xDist + yDist * yDist); if (Dist <= ball1.radius + ball2.radius)  if (ball1.x < ball2.x)  ball1.x -= 2; ball2.x += 2;  else  ball1.x += 2; ball2.x -= 2;  if (ball1.y < ball2.y)  ball1.y -= 2; ball2.y += 2;  else  ball1.y += 2; ball2.y -= 2;   return Dist <= ball1.radius + ball2.radius;  private function doCollision(ball1:Ball, ball2:Ball):void  var xDist:Number = ball1.x - ball2.x; var yDist:Number = ball1.y - ball2.y; var collisionAngle:Number = Math.atan2(yDist,xDist); var magBall1:Number = Math.sqrt(ball1.xSpeed * ball1.xSpeed + ball1.ySpeed * ball1.ySpeed); var magBall2:Number = Math.sqrt(ball2.xSpeed * ball2.xSpeed + ball2.ySpeed * ball2.ySpeed); var angleBall1:Number = Math.atan2(ball1.ySpeed,ball1.xSpeed); var angleBall2:Number = Math.atan2(ball2.ySpeed,ball2.xSpeed); var xSpeedBall1:Number = magBall1 * Math.cos(angleBall1 - collisionAngle); var ySpeedBall1:Number = magBall1 * Math.sin(angleBall1 - collisionAngle); var xSpeedBall2:Number = magBall2 * Math.cos(angleBall2 - collisionAngle); var ySpeedBall2:Number = magBall2 * Math.sin(angleBall2 - collisionAngle); var finalxSpeedBall1:Number = ((ball1.mass-ball2.mass)*xSpeedBall1+(ball2.mass+ball2.mass)*xSpeedBall2)/(ball1.mass+ball2.mass); var finalxSpeedBall2:Number = ((ball1.mass+ball1.mass)*xSpeedBall1+(ball2.mass-ball1.mass)*xSpeedBall2)/(ball1.mass+ball2.mass); var finalySpeedBall1:Number = ySpeedBall1; var finalySpeedBall2:Number = ySpeedBall2; ball1.xSpeed = Math.cos(collisionAngle) * finalxSpeedBall1 + Math.cos(collisionAngle + Math.PI / 2) * finalySpeedBall1; ball1.ySpeed = Math.sin(collisionAngle) * finalxSpeedBall1 + Math.sin(collisionAngle + Math.PI / 2) * finalySpeedBall1; ball2.xSpeed = Math.cos(collisionAngle) * finalxSpeedBall2 + Math.cos(collisionAngle + Math.PI / 2) * finalySpeedBall2; ball2.ySpeed = Math.sin(collisionAngle) * finalxSpeedBall2 + Math.sin(collisionAngle + Math.PI / 2) * finalySpeedBall2;  private function endOfGame():void  tmr.stop(); Mouse.show(); stage.removeEventListener(MouseEvent.MOUSE_MOVE, updatePlayerBall); stage.removeEventListener(Event.ENTER_FRAME, gameLoop); while (eballs.length > 0) TweenMax.to (eballs [0], 0.5, scaleX: 0, scaleY: 0, ease: Bounce.easeOut); eballs.splice (0,1);  TweenMax.to (ballPlayer, 0.5, scaleX: 0, scaleY: 0, lätthet: Bounce.easeOut);  privat funktion checkBounds (boll: Boll): void if ((ball.x + ball.radius)> stage.stageWidth) ball.x = stage.stageWidth - ball.radius; ball.xSpeed ​​* = -1;  om ((ball.x - ball.radius) < 0)  ball.x = 0 + ball.radius; ball.xSpeed *= -1;  if ((ball.y + ball.radius) > stage.stageHeight) ball.y = stage.stageHeight - ball.radius; ball.ySpeed ​​* = -1;  om ((ball.y - ball.radius) < 0)  ball.y = 0 + ball.radius; ball.ySpeed *= -1;    

Slutsats

Det är det för den här handledningen. Självklart kan du lägga till möjligheten att starta om spelet, men det borde inte vara för svårt. Detta grundläggande exempel på elastiska kollisioner kan användas för större spel som ett biljardspel eller liknande.

Jag hoppas att du gillade den här handledningen, tack för att du läste!