Spille rundt med elastiske kollisjoner

I denne opplæringen vil vi lage et spill der målet er å forhindre at andre objekter kolliderer med markøren. Vi vil ikke bruke Flash-innebygd hitTestObject () fremgangsmåter; I stedet vil vi skrive våre egne kollisionsdetekteringsrutiner.

Publisert opplæring

Noen få uker besøker vi noen av leserens favorittinnlegg fra hele historien til nettstedet. Denne opplæringen ble først publisert i februar 2011.


Endelig resultatforhåndsvisning

La oss se på det endelige resultatet vi vil jobbe for:


Trinn 1: Start av

Opprett en ny Flash-fil (ActionScript 3.0)

Still scenens dimensjoner til 500x500px og FPS til 32.


Trinn 2: Ballklassen

Denne klassen inneholder alle data knyttet til en ball. En ball har a _masse, en _radius, en _xSpeed og a _ySpeed. Så vi vil lage en eiendom for hver. I konstruktøren passerer vi massen, vinkelen og fartens hastighet. Fordi klassen vil være knyttet til et visningsobjekt, kan vi hente radiusen til vår ball ved å dividere bredden på skjermobjektet med 2. _xSpeed og _ySpeed kan beregnes ved hjelp av enkle sinus- og cosinusfunksjoner.

 pakke import flash.display.Stage import flash.display.Sprite import flash.events.Event offentlig klasse Ball utvider Sprite private var _radius: Nummer = 0 privat var _mass: Nummer = 0 privat var _xSpeed: Nummer = 0 privat var _ySpeed : Nummer = 0 offentlig funksjon Ball (masse: Nummer = 10,0, vinkel: Nummer = Math.PI, hastighet: Nummer = 10,0): tomrom this.mass = masse this._radius = this.width / 2 this.xSpeed ​​= speed * Math.sin (vinkel) this.ySpeed ​​= speed * Math.cos (vinkel)

For mer informasjon om disse trigonometriske Math.sin () og Math.cos () -funksjonene, se denne Quick Tip.


Trinn 3: Gir Getters og Setters

I vår Ball-klasse tilbyr vi getters og setters for våre eiendommer.

 offentlig funksjon få radius (): tall return this._radius offentlig funksjon sett masse (masse: tall): void this._mass = mass offentlig funksjon få masse (): tall return this._mass offentlig funksjon sett xSpeed (xSpeed: Nummer): void this._xSpeed ​​= xSpeed offentlig funksjon få xSpeed ​​(): Nummer return this._xSpeed offentlig funksjon sett ySpeed ​​(ySpeed: Nummer): void this._ySpeed ​​= ySpeed offentlig funksjon få ySpeed (): Nummer return this._ySpeed

Trinn 4: Oppdateringsfunksjon

Denne funksjonen oppdaterer x- og y-egenskapene til vår ball i henhold til _xSpeed og _ySpeed. Vi implementerer denne funksjonen i vår Ball klasse.

 offentlig funksjon oppdatering (): void this.x + = _xSpeed ​​this.y + = _ySpeed

Trinn 5: Den fullførte klassen

Vi avslutter vår Ball klasse i dette trinnet.

 pakke import flash.display.Stage import flash.display.Sprite import flash.events.Event offentlig klasse Ball utvider Sprite private var _radius: Nummer = 0 privat var _mass: Nummer = 0 privat var _xSpeed: Nummer = 0 privat var _ySpeed : Nummer = 0 offentlig funksjon Ball (masse: Nummer = 10,0, vinkel: Nummer = Math.PI, hastighet: Nummer = 10,0): tomrom this.mass = masse this._radius = this.width / 2 this.xSpeed ​​= speed * Math.sin (vinkel) this.ySpeed ​​= hastighet * Math.cos (vinkel) offentlig funksjon få radius (): Nummer return this._radius offentlig funksjon sett masse (masse: tall): void this._mass = masse offentlig funksjon få masse (): Nummer return this._mass Offentlig funksjon sett xSpeed ​​(xSpeed: Nummer): void this._xSpeed ​​= xSpeed offentlig funksjon få xSpeed ​​(): Nummer return this._xSpeed offentlig funksjon sett ySpeed ​​(ySpeed: Nummer): void this._ySpeed ​​= ySpeed offentlig funksjon få ySpeed ​​(): Nummer return this._ySpeed offentlig funksjon oppdatering (): void this.x + = _xSpeed ​​this.y + = _ySpeed 

Trinn 6: Vis objekter for våre ballklasser

I kildefilene inkluderte jeg en start FLA som inneholder alle bibliotekene du trenger. Du kan selv tegne dem selv hvis du vil. Pass på at FLA har følgende skjermobjekter:

(Ed. Notat: det er en skrivefeil: "ennemyball" burde si "fiendball".)


Trinn 7: Kobling av bibliotekobjekter

De Ball klasse vi nettopp har opprettet, må være knyttet til enemyball Sprite i biblioteket.

De playerball Sprite må ha Ball som base klasse og PlayerBall som klasse.

De poengsum filmklipp må ha en Score klasse.


Trinn 8: Programklassen (Dokumentklasse)

De applikasjon klassen vil inneholde alle spilllogikken. Vi importerer alle klassene vi trenger. Som du kan se bruker vi TweenMax.

Deretter definerer vi våre feltvariabler. Den første feltvariabelen er ballspiller.

Fordi basen av vår playerball Sprite er Ball Vi kan lagre denne klassen i ballspiller variabel. Dette gjør det lettere senere å sjekke for kollisjoner mellom ballspiller og fiendens baller.

Den andre feltvariabelen er en gruppe som vil inneholde alle våre fiendens baller. Den tredje variabelen er timeren som vil bli brukt til å utføre hovedspillet. Det fjerde og siste feltet er en forekomst av vår Score bibliotek objekt som vil bli brukt til å vise den forløpte spilletiden. I konstruktøren kaller vi i det() funksjon som jeg skal forklare i neste trinn.

 pakke import flash.display.Sprite import flash.display.Graphics importer flash.events.Event import flash.events.TimerEvent import flash.events.MouseEvent import flash.geom.Matrix import flash.utils.Timer importere flash.ui.Mouse import com.greensock.TweenMax import com.greensock.easing. * offentlig klasse Søknad utvider Sprite private var ballPlayer: Ball private var eballs: Array privat var tmr: Timer privat var score: Score offentlig funksjon Program (): void init ( )

Ikke glem å knytte dokumentklassen!.


Trinn 9: init () -funksjonen

Ta en titt på denne koden:

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

I de første fire linjene initialiserer vi våre feltvariabler.

Deretter sørger vi for at scenen vår er justert til øverste venstre hjørne og ikke skaleres.

Vi skjuler musemarkøren. Markøren vår vil bli erstattet med playerball Sprite. Neste kaller vi setBackground funksjon (forklart i neste trinn).

Vi senterer vår poengsum på skjermen og legg den til i visningslisten. For å oppdatere posisjonen til ballspiller Vi legger til en MouseEvent.MOUSE_MOVE-hendelse til scenen.

De updatePlayerBall funksjonen (forklart i trinn 11) vil håndtere denne MouseEvent. Neste legger vi til ballspiller til visningslisten.

Timeren vil bli brukt til å vise spilletiden. Vi knytter en TimerEvent.TIMER lytter til timeren vår, som vil utløse updateTime () funksjon (forklart i trinn 12) hver 10 millisekunder.

Til slutt legger vi til en MouseEvent.CLICK til vårt stadium. De start spill funksjonen (forklart i trinn 13) vil da starte spillet vårt.


Trinn 10: setBackground () Funksjon

Denne funksjonen legger til en radial gradientbakgrunn i displaylisten. For å tegne en gradient på en Sprite må du definere typen gradient, farger du vil bruke, alfaverdier av fargene, forholdene (disse definerer fordelingen av fargene) og spredningsmetoden.

For mer informasjon, se denne raske tipsen på gradienter.

 privat funksjon setBackground (): void var type: String = "radial" var farger: Array = [0xffffff, 0xcccccc] var alfa: Array = [1, 1] var forhold: Array = [0, 255] var matr: Matrix = New Matrix () matr.createGradientBox (stage.stageWidth, stage.stageHeight, Math.PI / 2, 0, 0) // SpreadMethod vil definere hvordan gradienten spres. Merk!!! Flash bruker CONSTANTS til å representere String literals var sprMethod: String = "pad" // Start Gradietn og send våre variabler til det var sprite: Sprite = new Sprite () // Lagre skrive + øke ytelsen gjennom lokal referanse til et grafikkobjekt var g: Graphics = sprite.graphics g.beginGradientFill (type, farger, alfas, forhold, matr, sprMethod) g.drawRect (0,0, scene.stageWidth, stage.stageHeight) stage.addChild (sprite)

Trinn 11: UpdatePlayerBall () Funksjon

Denne funksjonen oppdaterer posisjonen til ballspiller i henhold til musens posisjon.

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

Trinn 12: UpdateTime () Funksjon

Vi beregner tiden i sekunder og legger den inne i tekstboksen til vår poengsum Sprite. Hver 5000ms (fem sekunder) legger vi til en ny ball i spillet.

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

Trinn 13: startGame () Funksjon

Spillet startes ved å klikke på scenen. Først fjerner vi lytteren til sceneklikk, slik at vi ikke kan starte spillet servertider. Vi legger til tre baller til spillet ved å ringe addBall () funksjon (forklart i neste trinn) tre ganger. Vi starter vår tidtaker som vil oppdatere vår spilletid.

Til slutt legger vi til en ENTER_FRAME-hendelse på scenen vår. De gameLoop () funksjonen (forklart i trinn 15) vil oppdatere posisjonen til fiendens baller.

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

Trinn 14: addBall () Funksjon

Først lager vi en ny forekomst av vår Ball klasse. Vi posisjonerer ball tilfeldig på scenen med en alfa på 0 og legg den til i visningslisten.

Deretter går vi mellom alfa tilbake til 1. (Jeg bruker TweenMax, den er inkludert i kildefilene. Du kan også bruke den innebygde Flash-tween-motoren.) Den andre tweenen er egentlig ikke en tween. Det venter bare et sekund og onComplete funksjonen skyver ball inn i vår eballs array. På denne måten gameLoop () funksjon (forklart i neste trinn) kan håndtere resten.

 privat funksjon addBall (): void var ball: Ball = ny Ball (10, Math.random () * Math.PI * 2, 5) ball.x = Math.random () * stadium.stageWidth ball.y = Math .random () * stadium.stageHeight ball.alpha = 0 stage.addChild (ball) TweenMax.to (ball, 0.5, ala: 1) TweenMax.to (ball, 0, forsinkelse: 1, onComplete: function ): void eballs.push (ball))

Trinn 15: gameLoop () Funksjon

Hver ramme vil gå gjennom denne funksjonen.

 privat funksjon gameLoop (e: Event): void for (var jeg: 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 starter med å iterere gjennom alle våre fiendens baller.

Den andre for-loop kontrollerer for kollisjoner mellom fiendens baller. Sløyfen begynner på 'jeg + 1'. Slik kontrollerer vi ikke kollisjonene.

Deretter sjekker vi om ballspiller treffer fiendens ball. I så fall er spillet ferdig. Da oppdaterer vi posisjonen til fiendens ball.

Vi sørger for at ballene forblir i spillskjermbildet ved å ringe funksjonen checkBounds () (forklart senere).


Trinn 16: Kollisjon () Funksjon

Denne funksjonen kontrollerer om et gitt par baller kolliderer.

Først beregner vi x-avstanden og y-avstanden mellom de to ballene. Ved hjelp av Pythagoras teoremåte (se følgende diagram) beregner vi den absolutte avstanden mellom dem. Hvis avstanden er mindre eller lik summen av ballens radius, har vi en kollisjon.

 Kollisjon for privat funksjon (ball1: Ball, ball2: Ball): Boolsk var xDist: Nummer = ball1.x - ball2.x var yDist: Nummer = ball1.y - ball2.y var Dist: Nummer = Math.sqrt (xDist * xDist + yDist * yDist) retur Dist <= ball1.radius + ball2.radius 

Trinn 17: doCollision () Funksjon

Denne funksjonen beregner den nye x- og y-hastigheten til ballene i henhold til kollisjonens fart og vinkel. Advarsel: matematikk;)

Først beregner vi den horisontale avstanden mellom de to ballene og deretter den vertikale avstanden mellom ballene. Med disse avstandene (og litt mer trigonometri) kan vi beregne vinkelen mellom kulene (se diagram).

Deretter beregner vi det jeg kaller omfanget av hver ball. (Vi har en xspeed-vektor og en yspeed-vektor, størrelsen er vektorsummen av disse.) Da beregner vi vinkelen til hver ball (lik den forrige vinkelberegningen).

Deretter roterer vi de nye x- og y-hastighetene til hver ball. Det vi faktisk gjør er å rotere koordinatsystemet. Ved å rotere våre akser har vi en 1D kollisjon. (Se følgende diagram).

Newton sier at den totale mengden av kinetisk energi i et lukket system er konstant. Nå bruker vi disse formlene:

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

hvor:
v1 = endelig xSpeedBall 1
v2 = endelig xSpeedBall 2
m1 = masse ball 1
m2 = masse ball 2
u1 = starthastighetskule 1
u2 = starthastighetskule 2

Y-hastighetene endres ikke da det er en 1D-kollisjon.

Med disse formlene kan vi beregne xSpeed og ySpeed av hver ball.

Nå har vi de nye x- og y-hastighetene i vårt roterte koordinatsystem. Det siste trinnet er å konvertere alt tilbake til et normalt koordinatsystem. Vi bruker Math.PI / 2 fordi vinkelen mellom xSpeed og ySpeed må alltid være 90 grader (pi / 2 radianer).

 privat funksjon doCollision (ball1: Ball, ball2: Ball): void var xDist: Nummer = ball1.x - ball2.x var yDist: Nummer = ball1.y - ball2.y var kollisjonAngle: Nummer = Math.atan2 (yDist, xDist) var magBall1: Nummer = Math.sqrt (ball1.xSpeed ​​* ball1.xSpeed ​​+ ball1.ySpeed ​​* ball1.ySpeed) var magBall2: Nummer = Math.sqrt (ball2.xSpeed ​​* ball2.xSpeed ​​+ ball2.ySpeed ​​* ball2. ySpeed) var vinkelBall1: Nummer = Math.atan2 (ball1.ySpeed, ball1.xSpeed) var vinkelBall2: Nummer = Math.atan2 (ball2.ySpeed, ball2.xSpeed) var xSpeedBall1: Nummer = magBall1 * Math.cos (angleBall1-collisionAngle ) var ySpeedBall1: Nummer = magBall1 * Math.sin (angleBall1-collisionAngle) var xSpeedBall2: Nummer = magBall2 * Math.cos (angleBall2-collisionAngle) var ySpeedBall2: Nummer = magBall2 * Math.sin (angleBall2-collisionAngle) var finalxSpeedBall1: Nummer = (ball1.mass-ball2.mass) * xSpeedBall1 + (ball2.mass + ball2.mass) * xSpeedBall2) / (ball1.mass + ball2.mass) var finalxSpeedBall2: Nummer = ((ball1.mass + ball1.mass) * xSpeedBall1 + (ball2.mass-ball1.mass) * xSpeedBall 2) / (ball1.mass + ball2.mass) var finalySpeedBall1: Nummer = ySpeedBall1 var finalySpeedBall2: Nummer = 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

For å finne mer informasjon om elastiske kollisjoner, ta en titt på hoomanr.com.


Trinn 18: endOfGame () Funksjon

Dette kjøres når spillet avsluttes.

 privat funksjon endOfGame (): void tmr.stop () Mouse.show () stage.removeEventListener (MouseEvent.MOUSE_MOVE, updatePlayerBall) stage.removeEventListener (Event.ENTER_FRAME, gameLoop) mens (eballs.length> 0) TweenMax.to (eballs [0], 0.5, scaleX: 0, scaleY: 0, lette: Bounce.easeOut) eballs.splice (0,1) TweenMax.to (ballPlayer, 0.5, scaleX: 0, scaleY: 0, enkelhet: Bounce.easeOut)

Først av alt stopper vi timeren. Vi viser musen igjen. Deretter fjerner vi både MOUSE_MOVE og ENTER_FRAME hendelseslytterne. Til slutt gjør vi alle ballene på scenen usynlig.


Trinn 19: checkBounds () Funksjon

Denne funksjonen sikrer at ballene forblir inne i spillskjermbildet. Så hvis ballen treffer øvre eller nedre side vender vi om ySpeed. hvis ballen treffer venstre eller høyre side av skjermen vender vi om xSpeed. Den bruker lignende logikk til kollisjonssensorfunksjonen for å kontrollere om kantene på ballen treffer en kant av skjermen.

 privat funksjon checkBounds (ball: Ball): void if ((ball.x + ball.radius)> stadium.stageWidth) ball.x = stage.stageWidth - ball.radius ball.xSpeed ​​* = -1 hvis ball.x - ball.radius) < 0)  ball.x = 0 + ball.radius ball.xSpeed *= -1  if((ball.y + ball.radius) > stadium.stageHeight) ball.y = scene.stageHeight - ball.radius ball.ySpeed ​​* = - 1 hvis ((ball.y - ball.radius) < 0)  ball.y = 0 + ball.radius ball.ySpeed *= - 1  

Trinn 20: Den komplette applikasjonsklassen

Vi har fullført vår søknadsklasse. Vi har nå et arbeidsspill!!!

 pakke import flash.display.Sprite; importer flash.display.Graphics; importere flash.events.Event; importer flash.events.TimerEvent; importer flash.events.MouseEvent; importer flash.geom.Matrix; importere flash.utils.Timer; importere flash.ui.Mouse; importer com.greensock.TweenMax; importer com.greensock.easing. *; offentlig klasse Søknad utvider Sprite private var ballPlayer: Ball; private var eballs: Array; Privat var tmr: Timer; privat var score: Score; offentlig funksjon Program (): void init ();  privat funksjon init (): void ballPlayer = ny PlayerBall (); eballs = nytt Array (); tmr = ny timer (10); score = nytt score (); stage.align = "TL"; stage.scaleMode = "noScale"; Mouse.hide (); setBackground (); score.x = scene.stageWidth / 2; score.y = scene.stageHeight / 2; stage.addChild (score); stage.addEventListener (MouseEvent.MOUSE_MOVE, updatePlayerBall); stage.addChild (ballspiller); tmr.addEventListener (TimerEvent.TIMER, updateTime); stage.addEventListener (MouseEvent.CLICK, startGame);  privatfunksjonssettBackground (): void var type: String = "radial"; var farger: Array = [0xffffff, 0xcccccc]; var alfa: Array = [1,1]; var forhold: Array = [0,255]; var matr: Matrise = ny Matrix (); matr.createGradientBox (scene.stageWidth, stage.stageHeight, Math.PI / 2, 0, 0); // SpreadMethod vil definere hvordan gradienten spres. Merk!!! Flash bruker CONSTANTS til å representere String literals var sprMethod: String = "pad"; // Start Gradietn og send våre variabler til det var sprite: Sprite = new Sprite (); // Lagre skrive + øke ytelsen gjennom lokal referanse til et grafikkobjekt var g: Graphics = sprite.graphics; g.beginGradientFill (type, farger, alfaer, forhold, matr, sprMethod); g.drawRect (0,0, stage.stageWidth, stage.stageHeight); stage.addChild (sprite);  privat funksjon updatePlayerBall (e: MouseEvent): void ballPlayer.x = mouseX; ballplayer.y = mouseY;  privat funksjon updateTime (e: TimerEvent): void score.txtScore.text = String (((tmr.currentCount * tmr.delay) / 1000) .toFixed (2)); hvis ((tmr.currentCount * tmr.delay)% 5000 == 0) addBall ();  privat funksjon startGame (e: MouseEvent): void stage.removeEventListener (MouseEvent.CLICK, startGame); addBall (); addBall (); addBall (); tmr.start (); stage.addEventListener (Event.ENTER_FRAME, gameLoop);  privat funksjon addBall (): void var ball: Ball = ny Ball (10, Math.random () * Math.PI * 2,5); ball.x = Math.random () * scene.stageWidth; ball.y = Math.random () * scene.stageHeight; ball.alpha = 0; stage.addChild (ball); TweenMax.to (ball, 0.5, ala: 1); TweenMax.to (ball, 0, delay: 1, onComplete: function (): void eballs.push (ball));  privat funksjon gameLoop (e: Event): void for (var jeg: 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 funksjon checkBounds (ball: Ball): void if ((ball.x + ball.radius)> stage.stageWidth) ball.x = stage.stageWidth - ball.radius; ball.xSpeed ​​* = -1;  hvis ((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;  hvis ((ball.y - ball.radius) < 0)  ball.y = 0 + ball.radius; ball.ySpeed *= -1;    

Konklusjon

Det er det for denne opplæringen. Selvfølgelig kan du legge til muligheten for å starte spillet på nytt, men det burde ikke være for vanskelig. Dette grunnleggende eksempelet på elastiske kollisjoner kan brukes til større spill som biljardspill eller lignende.

Jeg håper du likte denne opplæringen, takk for å lese!