CocaDozzer
Moderator
Din: Garda de Fier
Inregistrat: acum 16 ani
Postari: 197
|
|
Calcolare le collisioni
Per eseguire i calcoli delle collisioni useremo l'oggetto Rectangle, che ci permette di ottenere informazioni su di un oggetto quali posizione (x e y), dimensione (larghezza e altezza) e controllare singolarmente i bordi superiore, inferiore, sinistro e destro. Per calcolare le collisioni della pallina utilizzeremo due sue posizioni, ovvero quella attuale e quella appena precedente, questo ad esempio per evitare delle eccessive sovrapposizioni tra gli oggetti.
Un oggetto Rectangle richiede 4 parametri: x, y, larghezza e altezza. Ecco come creare i tre oggetti Rectangle relativi rispettivamente alla vecchia posizione della pallina, alla nuova posizione della pallina e alla posizione del pad.
Listato 9. Variabili sulla posizione della pallina
Code:
var pallinaRectOld = new Rectangle(pallina.x-raggio,pallina.y-raggio, raggio*2, raggio*2);
var pallinaRectNew = new Rectangle(newX-raggio, newY-raggio, raggio*2, raggio*2);
var padRect = new Rectangle(pad.x-padW/2, pad.y-paddleHt/2, padW, paddleHt); |
A questo punto, per stabilire se la pallina ha colpito il pad, possiamo confrontare il bordo inferiore del rettangolo della pallina con il bordo superiore del rettangolo del pad, in questo modo:
Code:
if (pallinaRectNew.bottom >= padRect.top) { |
Vogliamo anche essere sicuri che la pallina non stesse toccando il pad già nella posizione precedente e soprattutto vogliamo controllare che la pallina sia interna al pad, in caso contrario vorrebbe dire che è caduta e quindi dobbiamo sottrarre una vita all'utente.
Listato 10. Controlla la posizione della pallina
Code:
if (pallinaRectNew.bottom >= padRect.top) {
if (pallinaRectOld.bottom < padRect.top) {
// se la pallina colpisce il pad, rimbalza
if (pallinaRectNew.right > padRect.left && pallinaRectNew.left < padRect.right) {
// rimbalzo verticale
newY -= pallinaRectNew.bottom - padRect.top; // nuova posizione
pallinaDY *= -1; // nuova direzione verticale
// impostazione del nuovo angolo
pallinaDX = (newX-pad.x)*padCurve;
}
}else if (pallinaRectNew.top > 400) {
// altrimenti viene persa una vita
removeChild(pallina);
pallina = null;
if(vite==0){
gameOver();
}
return;
}
} |
Se il bordo inferiore della pallina (pallinaRectNew.bottom) risulta più in basso del bordo superiore del pad (padRect.top) controlliamo che la pallina non stesse già toccando il pad in precedenza e che si trovi all'interno dei margini del pad stesso (padRect.left e padRect.right), nel qual caso impostiamo la nuova Y uguale al bordo del pad (per evitare che la pallina si sovrapponga troppo a esso), quindi impostiamo la nuova direzione verticale (-1) e la nuova direzione orizzontale, calcolata in base alla distanza tra le coordinate orizzontali di pallina e pad, moltiplicato per la curvatura del pad.
Quando la pallina non è compresa nell'area del pad, non la rimuoviamo immediatamente ma aspettiamo che il suo bordo superiore sia uscito dallo stage (> 400). Nel caso in cui quella persa fosse l'ultima vita, richiameremo la funzione gameOver, altrimenti l'utente potrà giocare una nuova pallina cliccando sullo stage.
Il richiamo alla funzione gameOver è commentato dato che non la abbiamo ancora dichiarata.
Modifichiamo la funzione muoviOggetti aggiungendo il richiamo alla funzione muoviPalla.
Rimbalzo della pallina sul pad - esempio
Passiamo ora alle collisioni coi muri; il concetto è identico a quanto visto per il pad, con due eccezioni: nel caso di collisione con i muri laterali, il rimbalzo sarà in orizzontale, inoltre, poiché abbiamo già dichiarato le variabili con le posizioni dei muri superiore, destro e sinistro l'unico oggetto Rectangle che useremo sarà quello della pallina. Ultima differenza sarà che il rimbalzo avverà allo stesso modo su tutto il muro, differentemente dal pad dove colpire più o meno lontano dal centro causa un diverso effetto sulla pallina.
Listato 11. Gestisce i rimbalzi
Code:
// muro superiore
if (pallinaRectNew.top < muroTop) {
newY += muroTop - pallinaRectNew.top;
pallinaDY *= -1;
}
// muro sinistro
if (pallinaRectNew.left < muroSx) {
newX += muroSx - pallinaRectNew.left;
pallinaDX *= -1;
}
// muro destro
if (pallinaRectNew.right > muroDx) {
newX += muroDx - pallinaRectNew.right;
pallinaDX *= -1;
} |
Nel caso in cui il la posizione della palla sia inferiore (nel caso di muri superiore e sinistro) o superiore (nel caso del muro destro) al valore indicato, viene cambiata direzione alla palla.
Rimbalzo della pallina sul pad e sui muri - esempio
Se per pad e muri la pallina può colpire solamente da un lato, ogni mattoncino può essere colpito da qualsiasi direzione. Dobbiamo poi controllare ogni volta tutti i mattoncini presenti nel gioco ed eliminare quelli colpiti.
Per prima cosa creiamo un ciclo che analizzi tutti i mattoncini, sfruttando l'array mattoncini che contiene il riferimento a ogni mattoncino presente nel gioco.
Code:
for(var i:int=mattoncini.length-1;i>=0;i--) {
Per ogni mattoncino creiamo il relativo rettangolo.
var mattoncinoRect:Rectangle = mattoncini[i].getRect(this); |
Prima di calcolare da quale lato avviene la collisione ci interessa sapere se la pallina e il mattoncino sono entrati in contatto: è meno dispendioso in termini di memoria controllare prima la collisione "generica" e poi eventualmente valutare da quale lato sia avvenuta, piuttosto che analizzare sempre i quattro lati di ogni mattoncino. Per questo scopo è molto utile il comando intersects, un metodo della classe Rectangle che si occupa di valutare l'intersezione tra due oggetti di tipo Rectangle. Nel nostro caso possiamo sfruttarlo per confrontare i rettangoli di pallina e mattoncino:
Code:
if (mattoncinoRect.intersects(pallinaRectNew)) { |
Possiamo ora passare al controllo del lato da cui è avvenuta effettivamente la collisione: per questo confronteremo ogni bordo del mattoncino con il rispettivo bordo della pallina.
Listato 12. Controlla il lato del mattoncino colpito
Code:
if (pallinaRectOld.right < mattoncinoRect.left){
newX += 2*(mattoncinoRect.left - pallinaRectOld.right);
pallinaDX *= -1;
}else if (pallinaRectOld.left > mattoncinoRect.right){
newX += 2*(mattoncinoRect.right - pallinaRectOld.left);
pallinaDX *= -1;
}else if (pallinaRectOld.top > mattoncinoRect.bottom){
pallinaDY *= -1;
newY += 2*(mattoncinoRect.bottom-pallinaRectNew.top);
}else if (pallinaRectOld.bottom < mattoncinoRect.top){
pallinaDY *= -1;
newY += 2*(mattoncinoRect.top - pallinaRectNew.bottom);
} |
Vediamo che il rimbalzo è calcolato impostando la nuova coordinata e la nuova direzione orizzontale o verticale a seconda del bordo che è stato colpito.
Le ultime operazioni da eseguire sono la rimozione del mattoncino colpito sia dallo schermo che dall'array, il controllo dei mattoncini rimasti e la fine del gioco quando non ci sono più mattoncini.
Listato 13. Rimuove i mattincini e calcola la fine del gioco
Code:
removeChild(mattoncini[i]); mattoncini.splice(i,1); if (mattoncini.length < 1) { //gameOver(); return; } |
_______________________________________ PM-URI
JUST SAY THANKS-it only takes a second!!!!
|
|