Giocare con collisioni elastiche

In questo tutorial creeremo un gioco in cui l'obiettivo è impedire che altri oggetti entrino in collisione con il cursore. Non useremo il built-in di Flash hitTestObject () metodi; invece scriveremo le nostre routine di rilevamento delle collisioni.

Tutorial ripubblicato

Ogni poche settimane, rivisitiamo alcuni dei post preferiti del nostro lettore da tutta la cronologia del sito. Questo tutorial è stato pubblicato per la prima volta nel febbraio del 2011.


Anteprima del risultato finale

Diamo un'occhiata al risultato finale su cui lavoreremo:


Step 1: Start Off

Crea un nuovo file Flash (ActionScript 3.0)

Imposta le dimensioni dello stage su 500x500px e FPS su 32.


Step 2: The Ball Class

Questa classe conterrà tutti i dati relativi a una palla. Una palla ha un _massa, un _raggio, un _xSpeed e a _ySpeed. Quindi faremo una proprietà per ciascuno. Nel costruttore passiamo la massa, l'angolo e la velocità della palla. Poiché la classe sarà collegata a un oggetto di visualizzazione, possiamo recuperare il raggio della nostra palla dividendo la larghezza dell'oggetto di visualizzazione di 2. Il _xSpeed e _ySpeed può essere calcolato usando semplici funzioni seno e coseno.

 pacchetto import flash.display.Stage import flash.display.Sprite import flash.events.Event public class Ball estende Sprite 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 (angolo) this.ySpeed ​​= velocità * Math.cos (angolo)

Per ulteriori informazioni su queste funzioni trigonometriche Math.sin () e Math.cos (), vedere questo suggerimento rapido.


Passaggio 3: fornitura di getter e setter

Nella nostra classe Ball forniamo getter e setter per le nostre proprietà.

 funzione pubblica get radius (): Number return this._radius funzione pubblica set massa (massa: Number): void this._mass = massa public function get mass (): Number return this._mass public function set xSpeed (xSpeed: Number): void this._xSpeed ​​= xSpeed public function get xSpeed ​​(): Number return this._xSpeed set di funzioni pubbliche ySpeed ​​(ySpeed: Number): void this._ySpeed ​​= ySpeed funzione pubblica get ySpeed (): Numero return this._ySpeed

Passaggio 4: funzione di aggiornamento

Questa funzione aggiorna le proprietà x e y della nostra palla secondo il _xSpeed e _ySpeed. Implementeremo questa funzione nel nostro Palla classe.

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

Passaggio 5: La classe completata

Finiremo il nostro Palla classe in questo passaggio.

 pacchetto import flash.display.Stage import flash.display.Sprite import flash.events.Event public class Ball estende Sprite 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 (angolo) this.ySpeed ​​= velocità * Math.cos (angolo) funzione pubblica get radius (): Number return this._radius funzione pubblica set massa (massa: Number): void this._mass = massa public function get massa (): Number return this._mass set di funzioni pubblico xSpeed ​​(xSpeed: Number): void this._xSpeed ​​= xSpeed public function get xSpeed ​​(): Number return this._xSpeed public function set ySpeed ​​(ySpeed: Number): void this._ySpeed ​​= ySpeed public function get ySpeed ​​(): Number return this._ySpeed public function update (): void this.x + = _xSpeed ​​this.y + = _ySpeed 

Passaggio 6: Visualizza oggetti per la nostra classe di palle

Nei file di origine ho incluso un FLA di inizio che contiene tutti gli elementi della libreria necessari. Puoi disegnarli tu stesso, se vuoi, ovviamente. Assicurati che il tuo FLA abbia i seguenti oggetti di visualizzazione:

(Nota: questo è un refuso: "ennemyball" dovrebbe dire "enemyball".)


Passaggio 7: collegamento dei nostri oggetti della libreria

Il Palla la classe che abbiamo appena creato deve essere collegata al enemyball Sprite nella biblioteca.

Il playerball Sprite deve avere Palla come classe base e PlayerBall come classe.

Il Punto il filmato deve avere un Punto classe.


Passaggio 8: la classe dell'applicazione (classe documento)

Il Applicazione la classe conterrà tutta la logica di gioco. Importiamo tutte le classi di cui abbiamo bisogno. Come puoi vedere useremo TweenMax.

Successivamente definiamo le nostre variabili di campo. La prima variabile di campo è il giocatore di baseball.

Perché la classe base del nostro playerball Sprite è Palla possiamo memorizzare questa classe nel giocatore di baseball variabile. Ciò rende più facile in seguito verificare le collisioni tra il giocatore di baseball e le palle nemiche.

La seconda variabile di campo è una matrice che conterrà tutte le nostre palle nemiche. La terza variabile è il timer che verrà utilizzato per eseguire il ciclo di gioco principale. Il quarto e ultimo campo è un'istanza del nostro Punto oggetto della biblioteca che verrà utilizzato per visualizzare il tempo di gioco trascorso. Nel costruttore chiamiamo il dentro() funzione che spiegherò nel prossimo passaggio.

 package 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 Application estende Sprite private var ballPlayer: Ball private var eballs: Array private var tmr: Timer private var score: Punteggio public function Application (): void init ( )

Non dimenticare di collegare la classe del documento!.


Passaggio 9: la funzione init ()

Dai un'occhiata a questo codice:

 funzione privata init (): void ballPlayer = new PlayerBall () eballs = new Array () tmr = new Timer (10) score = new 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)

Nelle prime quattro righe inizializziamo le nostre variabili di campo.

Successivamente ci assicuriamo che il nostro stadio sia allineato all'angolo in alto a sinistra e non si riduca.

Nascondiamo il cursore del mouse. Il nostro cursore sarà sostituito con il playerball Sprite. Quindi chiamiamo il setBackground funzione (spiegato nel passaggio successivo).

Noi centriamo il nostro Punto sullo schermo e aggiungerlo all'elenco di visualizzazione. Per aggiornare la posizione di giocatore di baseball alleghiamo un evento MouseEvent.MOUSE_MOVE sul palco.

Il updatePlayerBall la funzione (spiegata nel passaggio 11) gestirà questo MouseEvent. Successivamente aggiungiamo il giocatore di baseball alla lista di visualizzazione.

Il timer verrà utilizzato per visualizzare il tempo di gioco. Alleghiamo un ascoltatore TimerEvent.TIMER al nostro timer, che attiverà il tempo di aggiornamento() funzione (spiegata al punto 12) ogni 10 millisecondi.

Infine, aggiungiamo MouseEvent.CLICK al nostro palco. Il inizia il gioco funzione (spiegato nel passaggio 13) inizierà quindi il nostro gioco.


Passaggio 10: funzione setBackground ()

Questa funzione aggiunge uno sfondo sfumato radiale all'elenco di visualizzazione. Per disegnare una sfumatura su uno Sprite devi definire il tipo di sfumatura, i colori che vuoi usare, i valori alfa dei colori, i rapporti (che definiscono la distribuzione dei colori) e il metodo di diffusione.

Per ulteriori informazioni, vedere questo suggerimento rapido sulle sfumature.

 funzione privata setBackground (): void var type: String = "radial" var colori: Array = [0xffffff, 0xcccccc] var alphas: Array = [1, 1] var ratio: Array = [0, 255] var matr: Matrix = new Matrix () matr.createGradientBox (stage.stageWidth, stage.stageHeight, Math.PI / 2, 0, 0) // SpreadMethod definirà la modalità di diffusione del gradiente. Nota!!! Flash utilizza CONSTANTS per rappresentare i letterali String var sprMethod: String = "pad" // Avvia Gradietn e passa le nostre variabili ad esso var sprite: Sprite = new Sprite () // Salva digitando + aumenta le prestazioni attraverso il riferimento locale ad un oggetto Graphics var g: Graphics = sprite.graphics g.beginGradientFill (type, colors, alphas, ratios, matr, sprMethod) g.drawRect (0,0, stage.stageWidth, stage.stageHeight) stage.addChild (sprite)

Passaggio 11: funzione updatePlayerBall ()

Questa funzione aggiorna la posizione di giocatore di baseball in base alla posizione del tuo mouse.

 funzione privata updatePlayerBall (e: MouseEvent): void ballPlayer.x = mouseX ballPlayer.y = mouseY

Passaggio 12: funzione updateTime ()

Calcoliamo il tempo in secondi e lo inseriamo nella casella di testo del nostro Punto Sprite. Ogni 5000ms (cinque secondi) aggiungiamo una nuova palla al gioco.

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

Passaggio 13: funzione startGame ()

Il gioco è iniziato facendo clic sul palco. Per prima cosa rimuoviamo l'ascoltatore per il clic dello stage, in modo che non possiamo avviare le volte serveral del gioco. Aggiungiamo tre palline al gioco chiamando il addBall () funzione (spiegata nel passaggio successivo) tre volte. Iniziamo il nostro timer che aggiornerà il nostro tempo di gioco.

Infine aggiungiamo un evento ENTER_FRAME al nostro palco. Il gameLoop () la funzione (spiegata al punto 15) aggiornerà la posizione delle nostre palle nemiche.

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

Passaggio 14: funzione addBall ()

Per prima cosa creiamo una nuova istanza del nostro Palla classe. Posizioniamo il palla in modo casuale sul palco con un alfa di 0 e aggiungerlo all'elenco di visualizzazione.

Quindi passiamo l'alpha a 1. (utilizzo TweenMax, è incluso nei file di origine. Puoi anche utilizzare il motore di interpolazione Flash incorporato). La seconda interpolazione non è in realtà un'interpolazione. Aspetta solo un secondo e il onComplete la funzione spinge il palla nel nostro eballs array. In questo modo il gameLoop () funzione (spiegato nel passaggio successivo) in grado di gestire il resto.

 funzione privata 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))

Passaggio 15: funzione gameLoop ()

Ogni frame passerà attraverso questa funzione.

 funzione privata 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])  

Iniziamo iterando attraverso tutte le nostre palle nemiche.

Il secondo controllo del ciclo per le collisioni tra le palle nemiche. Il ciclo inizia da "i + 1". In questo modo non controlliamo le collisioni.

Quindi controlliamo se il giocatore di baseball colpisce la palla nemica. Se è così, il gioco è finito. Quindi aggiorniamo la posizione della nostra palla nemica.

Ci assicuriamo che le palline rimangano nella schermata di gioco chiamando la funzione checkBounds () (spiegato più avanti).


Passo 16: funzione collisione ()

Questa funzione controlla se una determinata coppia di palline si scontrano.

Per prima cosa calcoliamo la distanza x e la distanza y tra le due sfere. Usando il Teorema di Pitagora (vedi lo schema seguente) calcoliamo la distanza assoluta tra di loro. Se la distanza è inferiore o uguale alla somma dei raggi delle palle abbiamo una collisione.

 collisione di funzione privata (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 

Passaggio 17: funzione doCollision ()

Questa funzione calcolerà le nuove velocità x ed y delle sfere in base alla velocità e all'angolo della collisione. Attenzione: matematica;)

Per prima cosa calcoliamo la distanza orizzontale tra le due sfere e quindi la distanza verticale tra le sfere. Con queste distanze (e un po 'più di trigonometria) possiamo calcolare l'angolo tra le sfere (vedi diagramma).

Quindi calcoliamo quello che chiamo il grandezza di ogni palla. (Abbiamo un vettore xspeed e un vettore yspeed, la magnitudine è la somma vettoriale di questi.) Quindi calcoliamo l'angolo di ciascuna sfera (simile al calcolo dell'angolo precedente).

Successivamente ruotiamo le nuove velocità x e y di ogni palla. Quello che stiamo effettivamente facendo è ruotare il sistema di coordinate. Ruotando i nostri assi abbiamo una collisione 1D. (Vedi lo schema seguente).

Newton dice che la quantità totale di energia cinetica in un sistema chiuso è costante. Ora usiamo queste formule:

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

dove:
v1 = final xSpeedBall 1
v2 = final xSpeedBall 2
m1 = palla di massa 1
m2 = palla di massa 2
u1 = iniziale speed ball 1
u2 = velocità iniziale palla 2

Le velocità y non cambiano in quanto si tratta di una collisione 1D.

Con queste formule possiamo calcolare il xSpeed e yspeed di ogni palla.

Ora abbiamo le nuove velocità x e y nel nostro sistema di coordinate ruotato. L'ultimo passaggio consiste nel convertire tutto in un normale sistema di coordinate. Noi usiamo Math.PI / 2 perché l'angolo tra xSpeed e yspeed deve sempre essere di 90 gradi (pi / 2 radianti).

 funzione privata 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

Per ulteriori informazioni sulle collisioni elastiche, consulta hoomanr.com.


Passaggio 18: Funzione endOfGame ()

Questo viene eseguito quando il gioco finisce.

 funzione privata 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, facilità: Bounce.easeOut) eballs.splice (0,1) TweenMax.to (ballPlayer, 0.5, scaleX: 0, scaleY: 0, facilità: Bounce.easeOut)

Prima di tutto fermiamo il timer. Mostriamo di nuovo il mouse. Successivamente rimuoviamo sia i listener di eventi MOUSE_MOVE che ENTER_FRAME. Finalmente rendiamo invisibili tutte le palle sul palco.


Passaggio 19: funzione checkBounds ()

Questa funzione assicura che le palline rimangano all'interno della schermata di gioco. Quindi se la palla colpisce il lato superiore o inferiore, invertiamo la yspeed. se la palla colpisce il lato sinistro o destro dello schermo, invertiamo la xSpeed. Utilizza la logica simile alla funzione di rilevamento della collisione della palla per verificare se i bordi della palla colpiscono un bordo dello schermo.

 private function checkBounds (ball: 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  

Passaggio 20: la classe di applicazione completa

Abbiamo completato la nostra classe di applicazione. Ora abbiamo un gioco funzionante!!!

 pacchetto 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 Application estende Sprite private var ballPlayer: Ball; private var eballs: Array; private var tmr: Timer; private var score: Score; funzione pubblica Application (): void init ();  funzione privata init (): void ballPlayer = new PlayerBall (); eballs = new Array (); tmr = new Timer (10); punteggio = nuovo punteggio (); 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);  funzione privata setBackground (): void var type: String = "radial"; var colors: Array = [0xffffff, 0xcccccc]; var alphas: Array = [1,1]; var ratio: Array = [0,255]; var matr: Matrix = new Matrix (); matr.createGradientBox (stage.stageWidth, stage.stageHeight, Math.PI / 2, 0, 0); // SpreadMethod definirà la modalità di diffusione del gradiente. Nota!!! Flash utilizza CONSTANTS per rappresentare i letterali String var sprMethod: String = "pad"; // Avvia Gradietn e passa le nostre variabili ad esso var sprite: Sprite = new Sprite (); // Salva digitando + aumenta le prestazioni attraverso il riferimento locale a un oggetto Graphics var g: Graphics = sprite.graphics; g.beginGradientFill (type, colors, alphas, ratios, 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 ();  funzione privata 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 (sfera); TweenMax.to (palla, 0,5, alpha: 1); TweenMax.to (ball, 0, delay: 1, onComplete: function (): void eballs.push (ball));  funzione privata 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, facilità: Bounce.easeOut); eballs.splice (0,1);  TweenMax.to (ballPlayer, 0.5, scaleX: 0, scaleY: 0, facilità: Bounce.easeOut);  private function checkBounds (ball: 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;    

Conclusione

Questo è tutto per questo tutorial. Ovviamente potresti aggiungere la possibilità di riavviare il gioco, ma non dovrebbe essere troppo difficile. Questo esempio di base di collisioni elastiche può essere utilizzato per giochi più grandi come un gioco di biliardo o simili.

Spero che questo tutorial ti sia piaciuto, grazie per la lettura!