Rond spelen met elastische botsingen

In deze tutorial zullen we een spel maken waarbij het doel is om te voorkomen dat andere objecten in botsing komen met je cursor. We zullen de ingebouwde Flash niet gebruiken hitTestObject () methoden; in plaats daarvan zullen we onze eigen botsingsdetectieroutines schrijven.

Opnieuw gepubliceerde zelfstudie

Om de paar weken bekijken we enkele van onze favoriete lezers uit de geschiedenis van de site. Deze tutorial werd voor het eerst gepubliceerd in februari 2011.


Eindresultaat voorbeeld

Laten we eens kijken naar het eindresultaat waar we naartoe zullen werken:


Stap 1: Start Uit

Maak een nieuw Flash-bestand (ActionScript 3.0)

Stel de stage afmetingen in op 500x500px en FPS op 32.


Stap 2: De ballenklasse

Deze klasse bevat alle gegevens met betrekking tot één bal. Een bal heeft een _massa, een _radius, een _xSpeed en een _ySpeed. Dus we zullen een eigendom voor elk maken. In de constructor passeren we de massa, de hoek en de snelheid van de bal. Omdat de klasse aan een weergaveobject wordt gekoppeld, kunnen we de straal van onze bal ophalen door de breedte van het weergaveobject met 2 te delen. _xSpeed en _ySpeed kan worden berekend met behulp van eenvoudige sinus- en cosinusfuncties.

 package import flash.display.Stage import flash.display.Sprite import flash.events.Event public class Ball breidt Sprite uit private var _radius: Number = 0 private var _mass: Number = 0 private var _xSpeed: Number = 0 private var _ySpeed : Number = 0 public function Ball (massa: Number = 10.0, angle: Number = Math.PI, speed: Number = 10.0): void this.mass = massa this._radius = this.width / 2 this.xSpeed ​​= speed * Math.sin (hoek) this.ySpeed ​​= snelheid * Math.cos (hoek)

Zie deze snelle tip voor meer informatie over deze trigonometrische functies Math.sin () en Math.cos ().


Stap 3: Getters en Setters aanbieden

In onze Ball-klasse bieden we getters en setters voor onze eigendommen.

 public function get radius (): Number return this._radius public function set massa (massa: Number): void this._mass = massa public function get massa (): Number return this._mass openbare functieset xSpeed (xSpeed: Number): void this._xSpeed ​​= xSpeed public function get xSpeed ​​(): Number return this._xSpeed openbare functieset ySpeed ​​(ySpeed: Number): void this._ySpeed ​​= ySpeed public function get ySpeed (): Nummer return this._ySpeed

Stap 4: Update-functie

Deze functie werkt de x- en y-eigenschappen van onze bal bij volgens de _xSpeed en _ySpeed. We zullen deze functie implementeren in onze Bal klasse.

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

Stap 5: De voltooide klasse

We eindigen onze Bal klasse in deze stap.

 package import flash.display.Stage import flash.display.Sprite import flash.events.Event public class Ball breidt Sprite uit private var _radius: Number = 0 private var _mass: Number = 0 private var _xSpeed: Number = 0 private var _ySpeed : Number = 0 public function Ball (massa: Number = 10.0, angle: Number = Math.PI, speed: Number = 10.0): void this.mass = massa this._radius = this.width / 2 this.xSpeed ​​= speed * Math.sin (hoek) this.ySpeed ​​= snelheid * Math.cos (hoek) public function get radius (): Number return this._radius public function set massa (aantal: Number): void this._mass = massa public function get massa (): Number return this._mass openbare functieset xSpeed ​​(xSpeed: Number): void this._xSpeed ​​= xSpeed public function get xSpeed ​​(): Number return this._xSpeed openbare functie set ySpeed ​​(ySpeed: Number): void this._ySpeed ​​= ySpeed public function get ySpeed ​​(): Number return this._ySpeed update openbare functie (): void this.x + = _xSpeed ​​this.y + = _ySpeed 

Stap 6: weergaveobjecten voor onze ballklasse

In de bronbestanden heb ik een start-FLA opgenomen die alle bibliotheekitems bevat die je nodig hebt. Je kunt ze zelf tekenen als je dat wilt, natuurlijk. Zorg ervoor dat uw FLA de volgende weergaveobjecten heeft:

(Let op: dat is een typfout: "ennemyball" zou "vijandelijk" moeten zeggen.)


Stap 7: onze bibliotheekobjecten koppelen

De Bal klasse die we zojuist hebben gemaakt, moet worden gekoppeld aan de enemyball Sprite in de bibliotheek.

De playerball Sprite moet hebben Bal als basisklasse en PlayerBall als klas.

De partituur filmclip moet een partituur klasse.


Stap 8: De toepassingsklasse (documentklasse)

De Toepassing klasse bevat alle spellogica. We importeren alle klassen die we nodig hebben. Zoals je ziet, gebruiken we TweenMax.

Vervolgens definiëren we onze veldvariabelen. De eerste veldvariabele is de ballplayer.

Omdat de basisklasse van onze playerball Sprite is Bal we kunnen deze klasse opslaan in de ballplayer variabel. Dit maakt het later gemakkelijker om te controleren op botsingen tussen de ballplayer en de vijandelijke ballen.

De tweede veldvariabele is een array die al onze vijandelijke ballen bevat. De derde variabele is de timer die zal worden gebruikt om de hoofdgame-loop uit te voeren. Het vierde en laatste veld is een voorbeeld van onze partituur bibliotheekobject dat zal worden gebruikt om de verstreken speeltijd weer te geven. In de constructor noemen we de in het() functie die ik in de volgende stap zal uitleggen.

 pakket import flash.display.Sprite import flash.display.Graphics import flash.events.Event import flash.events.TimerEvent import flash.events.MouseEvent import flash.geom.Matrix import flash.utils.Timer import flash.ui.Mouse import com.greensock.TweenMax import com.greensock.easing. * public class Applicatie breidt uit private var ballPlayer: Ball private var eballs: Array private var tmr: Timer private var score: Score public function Application (): void init ( )

Vergeet niet om de documentklasse te linken!.


Stap 9: De init () functie

Bekijk deze code:

 private function init (): void ballPlayer = new PlayerBall () eballs = new Array () tmr = new Timer (10) score = nieuw Score () stage.align = "TL" stage.scaleMode = "noScale" Mouse.hide () setBackground () score.x = stage.stageWidth / 2 score.y = stage.stageHeight / 2 stage.addChild (score) stage.addEventListener (MouseEvent.MOUSE_MOVE, updatePlayerBall) stage.addChild (ballPlayer) tmr.addEventListener (TimerEvent .TIMER, updateTime) stage.addEventListener (MouseEvent.CLICK, startGame)

In de eerste vier regels initialiseren we onze veldvariabelen.

Vervolgens zorgen we ervoor dat onze fase is uitgelijnd met de linkerbovenhoek en niet schaalt.

We verbergen de muiscursor. Onze cursor zal worden vervangen door de playerball Sprite. Vervolgens noemen we de achtergrond instellen functie (uitgelegd in de volgende stap).

We centreren onze partituur op het scherm en voeg het toe aan de weergavelijst. Om de positie van te updaten ballplayer we voegen een MouseEvent.MOUSE_MOVE-gebeurtenis toe aan het podium.

De updatePlayerBall functie (uitgelegd in stap 11) zal deze MouseEvent afhandelen. Vervolgens voegen we de ballplayer naar de displaylijst.

De timer zal worden gebruikt om de speelduur weer te geven. We hechten een TimerEvent.TIMER-luisteraar aan onze timer, die het update tijd() functie (uitgelegd in stap 12) elke 10 milliseconden.

Ten slotte voegen we een MouseEvent.CLICK toe aan onze fase. De start het spel functie (uitgelegd in stap 13) start dan onze game.


Stap 10: setBackground () Functie

Met deze functie wordt een radiale gradient-achtergrond toegevoegd aan de weergavelijst. Als u een verloop wilt tekenen op een Sprite, moet u het type verloop, de kleuren die u wilt gebruiken, de alpha-waarden van de kleuren, de verhoudingen (deze bepaalt de verdeling van de kleuren) en de verspreidingsmethode definiëren.

Zie deze Snelle tip voor verlopen voor meer informatie.

 privé-functie setBackground (): void var type: String = "radial" var colors: Array = [0xffffff, 0xcccccc] var alphas: Array = [1, 1] var-ratio's: Array = [0, 255] var matr: Matrix = new Matrix () matr.createGradientBox (stage.stageWidth, stage.stageHeight, Math.PI / 2, 0, 0) // SpreadMethod bepaalt hoe de gradient wordt verspreid. Notitie!!! Flash gebruikt CONSTANTS om String-literals te vertegenwoordigen var sprMethod: String = "pad" // Start de Gradietn en geef onze variabelen door aan var sprite: Sprite = nieuwe Sprite () // Typ opslaan + verbeter prestaties door lokale verwijzing naar een Graphics-object var g: Graphics = sprite.graphics g.beginGradientFill (type, kleuren, alpha's, verhoudingen, matr, sprMethod) g.drawRect (0,0, stage.stageWidth, stage.stageHeight) stage.addChild (sprite)

Stap 11: updatePlayerBall () Functie

Met deze functie wordt de positie van bijgewerkt ballplayer volgens de positie van uw muis.

 persoonlijke functie updatePlayerBall (e: MouseEvent): void ballPlayer.x = mouseX ballPlayer.y = mouseY

Stap 12: UpdateTime () Functie

We berekenen de tijd in seconden en plaatsen deze in het tekstvak van onze partituur Sprite. Elke 5000ms (vijf seconden) voegen we een nieuwe bal toe aan het spel.

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

Stap 13: startGame () Functie

Het spel wordt gestart door op het podium te klikken. Eerst verwijderen we de luisteraar voor de fase klik, zodat we het spel niet meerdere keren kunnen starten. We voegen drie ballen toe aan het spel door het te gebruiken addBall () functie (uitgelegd in de volgende stap) drie keer. We beginnen onze timer die onze speeltijd zal updaten.

Eindelijk voegen we een ENTER_FRAME-gebeurtenis toe aan onze fase. De gameLoop () functie (uitgelegd in stap 15) zal de positie van onze vijandelijke ballen bijwerken.

 persoonlijke functie startGame (e: MouseEvent): void stage.removeEventListener (MouseEvent.CLICK, startGame) addBall () addBall () addBall () tmr.start () stage.addEventListener (Event.ENTER_FRAME, gameLoop)

Stap 14: addBall () Functie

Eerst maken we een nieuw exemplaar van onze Bal klasse. We positioneren de bal willekeurig op het podium met een alpha van 0 en voeg het toe aan de displaylijst.

Vervolgens tweenen we de alpha terug naar 1. (Ik gebruik TweenMax, het is opgenomen in de bronbestanden. Je kunt ook de ingebouwde Flash tween-engine gebruiken.) De tweede tween is niet echt een tween. Het wacht gewoon een seconde en de onComplete functie duwt de bal in onze eballs matrix. Op deze manier de gameLoop () functie (uitgelegd in de volgende stap) kan de rest verwerken.

 privéfunctie addBall (): void var ball: Ball = new Ball (10, Math.random () * Math.PI * 2, 5) ball.x = Math.random () * stage.stageWidth ball.y = Math .random () * stage.stageHeight ball.alpha = 0 stage.addChild (ball) TweenMax.to (ball, 0.5, alpha: 1) TweenMax.to (ball, 0, delay: 1, onComplete: function ( ): void eballs.push (ball))

Stap 15: gameLoop () Functie

Elk frame gaat door deze functie.

 privéfunctiegameLoop (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])  

We beginnen met het herhalen van al onze vijandelijke ballen.

De tweede for-loop controleert op botsingen tussen de vijandelijke ballen. De lus begint bij 'i + 1'. Op deze manier controleren we de botsingen niet dubbel.

Vervolgens controleren we of het ballplayer raakt de vijandelijke bal. Als dat zo is, is het spel afgelopen. Vervolgens werken we de positie van onze vijandelijke bal bij.

We zorgen ervoor dat de ballen in het spelscherm blijven door de functie aan te roepen checkBounds () (later uitgelegd).


Stap 16: botsing () Functie

Deze functie controleert of een bepaald paar ballen botsen.

Eerst berekenen we de x-afstand en de y-afstand tussen de twee ballen. Met behulp van de stelling van Pythagoras (zie het volgende diagram) berekenen we de absolute afstand tussen hen. Als de afstand kleiner of gelijk is aan de som van de stralen van de ballen, hebben we een botsing.

 botsing met een privéfunctie (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) return Dist <= ball1.radius + ball2.radius 

Stap 17: doCollision () Functie

Met deze functie worden de nieuwe x- en y-snelheden van de ballen berekend op basis van de snelheid en de hoek van de botsing. Waarschuwing: wiskunde;)

Eerst berekenen we de horizontale afstand tussen de twee ballen en vervolgens de verticale afstand tussen de ballen. Met deze afstanden (en een beetje meer trigonometrie) kunnen we de hoek tussen de ballen berekenen (zie diagram).

Vervolgens berekenen we wat ik de omvang van elke bal. (We hebben een xspeed-vector en een yspeed-vector, de magnitude is de vectorsom daarvan.) Vervolgens berekenen we de hoek van elke bal (vergelijkbaar met de vorige hoekberekening).

Vervolgens roteren we de nieuwe x- en y-snelheden van elke bal. Wat we eigenlijk doen, is het coördinatensysteem draaien. Door onze assen te draaien hebben we een 1D-botsing. (Zie het volgende diagram).

Newton zegt dat de totale hoeveelheid kinetische energie in een gesloten systeem constant is. Nu gebruiken we deze formules:

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

waar:
v1 = laatste xSpeedBall 1
v2 = laatste xSpeedBall 2
m1 = massakogel 1
m2 = massakogel 2
u1 = beginsnelheid bal 1
u2 = beginsnelheid bal 2

De y-snelheden veranderen niet omdat het een 1D-botsing is.

Met deze formules kunnen we het berekenen xSpeed en ySpeed van elke bal.

Nu hebben we de nieuwe x- en y-snelheden in ons geroteerde coördinatensysteem. De laatste stap is om alles terug te zetten naar een normaal coördinatensysteem. We gebruiken Math.PI / 2 omdat de hoek ertussen xSpeed en ySpeed moet altijd 90 graden zijn (pi / 2 radialen).

 privéfunctie 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) * 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

Voor meer informatie over elastische botsingen, kijk op hoomanr.com.


Stap 18: endOfGame () Functie

Dit wordt uitgevoerd wanneer het spel eindigt.

 privéfunctie 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, gemak: Bounce.easeOut)

Allereerst stoppen we de timer. We tonen de muis opnieuw. Vervolgens verwijderen we zowel de MOUSE_MOVE als de ENTER_FRAME-gebeurtenislisteners. Eindelijk maken we alle ballen op het podium onzichtbaar.


Stap 19: checkBounds () Functie

Deze functie zorgt ervoor dat de ballen in het spelscherm blijven. Dus als de bal de boven- of onderkant raakt, keren we de ySpeed. als de bal de linker- of rechterzijde van het scherm raakt, keren we de xSpeed. Het gebruikt dezelfde logica als de balbotsingsdetectiefunctie om te controleren of de randen van de bal een rand van het scherm raken.

 private function checkBounds (bal: Ball): void if ((ball.x + ball.radius)> stage.stageWidth) ball.x = stage.stageWidth - ball.radius ball.xSpeed ​​* = -1 if (( 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 if ((ball.y - ball.radius) < 0)  ball.y = 0 + ball.radius ball.ySpeed *= - 1  

Stap 20: De volledige aanvraagklasse

We hebben onze Application Class voltooid. We hebben nu een werkgame!!!

 pakket import flash.display.Sprite; import flash.display.Graphics; import flash.events.Event; import flash.events.TimerEvent; import flash.events.MouseEvent; import flash.geom.Matrix; import flash.utils.Timer; import flash.ui.Mouse; import com.greensock.TweenMax; import com.greensock.easing. *; openbare klasse Toepassing breidt uit privé var ballPlayer: Ball; private var eballs: Array; privé var tmr: Timer; privé var-score: Score; public function Application (): void init ();  private function init (): void ballPlayer = new PlayerBall (); eballs = new Array (); tmr = nieuwe timer (10); score = nieuwe Score (); stage.align = "TL"; stage.scaleMode = "noScale"; Mouse.hide (); achtergrond instellen(); score.x = stage.stageWidth / 2; score.y = stage.stageHeight / 2; stage.addChild (score); stage.addEventListener (MouseEvent.MOUSE_MOVE, updatePlayerBall); stage.addChild (ballplayer); tmr.addEventListener (TimerEvent.TIMER, updateTime); stage.addEventListener (MouseEvent.CLICK, startGame);  persoonlijke functie setBackground (): void var type: String = "radial"; var kleuren: Array = [0xffffff, 0xcccccc]; var alphas: Array = [1,1]; var-verhoudingen: Array = [0,255]; var matr: Matrix = nieuwe matrix (); matr.createGradientBox (stage.stageWidth, stage.stageHeight, Math.PI / 2, 0, 0); // SpreadMethod bepaalt hoe de gradiënt wordt verspreid. Notitie!!! Flash gebruikt CONSTANTS om String-literals te vertegenwoordigen var sprMethod: String = "pad"; // Start de Gradietn en geef onze variabelen door aan var sprite: Sprite = nieuwe Sprite (); // Typ opslaan + verbeter prestaties door middel van lokale verwijzing naar een grafisch object var g: Graphics = sprite.graphics; g.beginGradientFill (type, kleuren, alpha's, verhoudingen, matr, sprMethod); g.drawRect (0,0, stage.stageWidth, Stage.stageHeight); stage.addChild (sprite);  private function updatePlayerBall (e: MouseEvent): void ballPlayer.x = mouseX; ballPlayer.y = mouseY;  private function updateTime (e: TimerEvent): void score.txtScore.text = String (((tmr.currentCount * tmr.delay) / 1000) .toFixed (2)); if ((tmr.currentCount * tmr.delay)% 5000 == 0) addBall ();  persoonlijke functie startGame (e: MouseEvent): void stage.removeEventListener (MouseEvent.CLICK, startGame); addBall (); addBall (); addBall (); tmr.start (); stage.addEventListener (Event.ENTER_FRAME, gameLoop);  private function addBall (): void var ball: Ball = new Ball (10, Math.random () * Math.PI * 2,5); ball.x = Math.random () * stage.stageWidth; ball.y = Math.random () * stage.stageHeight; ball.alpha = 0; stage.addChild (bol); TweenMax.to (bal, 0,5, alpha: 1); TweenMax.to (ball, 0, delay: 1, onComplete: function (): void eballs.push (ball));  private function 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, ease: Bounce.easeOut);  private functie checkBounds (bal: Ball): void if ((ball.x + ball.radius)> stage.stageWidth) ball.x = stage.stageWidth - ball.radius; ball.xSpeed ​​* = -1;  if ((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;  if ((ball.y - ball.radius) < 0)  ball.y = 0 + ball.radius; ball.ySpeed *= -1;    

Conclusie

Dat is het voor deze tutorial. Je zou natuurlijk de mogelijkheid kunnen toevoegen om het spel opnieuw te starten, maar dat zou niet al te moeilijk moeten zijn. Dit eenvoudige voorbeeld van elastische botsingen kan worden gebruikt voor grotere spellen zoals een biljartspel of iets dergelijks.

Ik hoop dat je deze tutorial leuk vond, bedankt voor het lezen!