Matteo Pignatelli
a- a+

La gravità

Questo tutorial spiegherà come simulare diverse forze di gravità applicate ad un oggetto in un movie Flash.
Lo scriverò diviso per livelli, ogni livello porterà ad avere un movie completo e funzionante e ad ogni livello successivo verrano aggiunte alcune istruzioni rispetto al livello precedente.

Dunque, la linea guida generale sarà questa:

A. Creare un oggetto e muoverlo in una direzione (per esempio orizzontalmente).
B. Fare rimbalzare l'oggetto su un lato dello schermo e poi su due lati.
C. Muoverlo anche verticalmente e farlo rimbalzare sui due lati dello schermo
D. Aggiungere la gravità
E. Aggiungere l'attrito
F. Aggiungere un livello variabile di rimbalzo
G. Avere la possibilità di prendere l'oggetto e scagliarlo per lo schermo.

A. CREARE L'OGGETTO E MUOVERLO

In questo livello creeremo un oggetto e lo faremo muovere ad un tasso costante usando solo ActionScript.

Creiamo un nuovo movie.
Modifichiamo il colore di sfondo in nero ed il frame rate in 20, questo farà sembrare le cose un po' più fluide.
Manteniamo anche le misure di default che sono 550X400.


Disegniamo un cerchio, selezioniamolo e trasformiamolo in un movie clip.


Doppio click sul movie clip per editarlo.


Cambiamo il nome del primo layer in "ball".


Creiamo un altro layer e chiamiamolo "actions".


Inseriamo 3 keyframes nel layer "action" e assicuriamoci che il layer "ball" si estenda anch'esso di tre frames.


Torniamo nel layer "actions".
Nel primo frame inizializzeremo l'oggetto.
Selezioniamo il frame, andiamo nel pannello delle actions e digitiamo il codice seguente (raccomando l'uso dell'Expert Mode in modo da poter digitare liberamente):

_x=10;
_y=200;
xspeed=5;

Il significato di queste action è facile: posizionare l'oggetto alle coordinate 10,200 ed assegnare ad una variabile xspeed il valore di 5.
Questo passo può essere anche fatto all'interno dell'evento "onClipEvent(load)" applicato all'oggetto stesso, ma per chiarezza ho lasciato il codice nella timeline.


Ora spostiamoci sul secondo frame, sempre nel layer "actions" e digitiamo:

_x=_x+xspeed ;

Anche questo è abbastanza semplice.
Non si tratta niene altro che dell'incremento della coordinata x dell'oggetto di 5 (il valore della variabile "xspeed").


Ora andiamo sul frame 3 e digitiamo:

gotoAndPlay(2);

Questo innescherà un loop continuo tra i frame 2 e 3 che cambierà in maniera costante la posizione dell'oggetto in base alla sua variabile di velocità (xspeed).


Testiamo il movie.
La sfera si muoverà da sinistra verso destra e sparirà nell'oblio dopo la fine del monitor...
Proviamo pure a cambiare il valore della variabile "xspeed" per vedere le diverse velocità che può assumere la sfera (ricordate che 5 in questo caso sono 5 pixel).
Niente di assolutamente eccitante per il momento, ma questo rappresenta l'intelaiatura per il resto del movie.
Sicuramente la sfera si comporterà come ci aspettiamo quindi ora possiamo costruire un altro pezzo di movie senza problemi.
Ora aggiungeremo l'effetto del rimbalzo.


B. FACCIAMO RIMBALZARE LA PALLA

Ora faremo in modo di farla rimbalzare indietro quando raggiunge il bordo.

Le prime cose da sapere sono dove si trova il bordo e quando la sfera lo raggiunge.
Quindi andiamo nel nostro movie clip, nel primo frame del layer "actions" (il frame dove inizializziamo tutto) e aggiungiamo questa linea:

rightedge=550;

Questo valore è la larghezza di default di un movie Flash.


Ok, ora che sappiamo dov'è il bordo, bisogna sapere quando ci arriviamo con la sfera.
Andiamo sul secondo frame (quello dove inseriamo le istruzioni per il movimento).
Dopo aver aggiunto la velocità alla posizione, abbiamo bisogno di controllare se la sfera ha oltrepassato il bordo destro.
Se lo ha fatto, dobbiamo piazzarla SUL bordo destro e cambiare di conseguenza la direzione del movimento.
In pratica:

if(_x+_width/2>rightedge) {
_x=rightedge-_width/2;
xspeed=-xspeed;
}

Che cos'è questo "_width/2" ?
Ricordiamoci che la posizione _x di un oggetto è il suo centro.
Se noi mettiamo questo sul bordo dello schermo, la sfera sarà mezza dentro e mezza fuori del monitor, quindi dobbiamo prendere metà della sua larghezza (la proprietà _width) e aggiungerla o sottrarla dalla posizione corrente.

Nella prima linea, testiamo se il bordo destro della sfera (_x+_width/2) è più in là del bordo destro dello schermo.
Se lo è, metteremo il bordo destro della sfera SUL bordo destro dello schermo.
In questo modo sembrerà che la sfera colpisca il bordo.
Questa non sarà la maniera perfetta di posizionare un oggetto sul punto del rimbalzo, particolarmente quando siamo in due dimensioni, ma è un metodo semplice e visivamente rende bene nel prodotto finale.

L'ultima linea cambia la velocità da un fattore positivo ad uno negativo e quindi inverte la direzione della sfera (come vedremo più avanti, la stessa linea cambierà la velocità da negativa a positiva quando colpirà il bordo opposto).


Testiamo il movie.
La sfera dovrebbe colpire il lato destro dello schermo e rimbalzare alla stessa velocità nella direzione opposta.
Ancora niente di eccezionale, ma qui siamo arrivati...
Ora facciamo rimbalzare la sfera sul bordo sinitro.


Aggiungiamo questa linea nel frame 1:

leftedge=0;

Non penso che questa riga abbia bisogno di spiegazioni...


Ora aggiungiamo queste righe nel frame 2.

if(_x-_width/2<leftedge) {
_x=leftedge+_width/2;
xspeed=-xspeed;
}

Questo è essenzialmente lo stesso codice trattato un po' più su, tranne che serve per il controllo del bordo sinistro.


Proviamo di nuovo il movie.
Ora la sfera dovrebbe rimbalzare sui due bordi, avanti e indietro.
Ancora non è quel che si dice super realistico, ma sta migliorando ed ora abbiamo una buona base per continuare il nostro lavoro.

C. MOVIMENTO VERTICALE

Ora abbiamo bisogno che la sfera si possa muovere su due dimensioni e questo sarà molto pià facile di quello che pensiamo.
Fondamentalmente abbiamo solo bisogno di duplicare tutto quello che abbiamo fatto finora ed applicarlo alla dimensione "y" , quindi:

La prima cosa da fare è aggiungere una velocità verticale.
Andiamo sul primo frame del layer "actions" e inseriamo:

yspeed=20;

Aggiorniamo anche la velocità xspeed a questo valore, giusto per velocizzare un po' la cosa.


Ora dobbiamo conoscere quali sono i valori di basso e alto, quindi aggiungiamo:

topedge=0;
bottomedge=400;


Ora passiamo al frame 2.
Copiamo tutto quello che c'è e incolliamo immediatamente sotto al testo già esistente.
Fatto questo, nel testo appena incollato dobbiamo:

- cambiare _x in _y
- cambiare xspeed in yspeed
- cambiare leftedge in topedge
- cambiare rightedge in bottomedge
- cambiare _width in _height

Testiamo il movie.
La sfera ora dovrebbe rimbalzare per lo schermo, rimbalzando di nuovo una volta raggiunto un bordo.
Sebbene questo possa essere abbastanza realistico per un gioco tipo "pong" , lo modificheremo ancora nel prossimo livello.


D. AGGIUNGIAMO LA GRAVITA'

Questo livello sarà un po' più lungo ma renderà la sfera molto più realistica.
Per capire quello che stiamo per fare, dobbiamo prima dare un'occhiata a che cos'è la gravità e come agisce.
Nel nostro movie Flash, questo significa una porzione di codice che aggiunge costantemente un valore "y" positivo (ricordiamoci che il valore y aumenta quando si va verso il basso dello schermo).
Se lanciamo un oggetto da una posizione elevata questo partirà con una certa velocità (un valore y positivo), ma la gravità agirà in modo di aggiungere velocità fino a quando questo oggetto non toccherà il suolo.
In altre parole, la sua variabile yspeed aumenterà continuamente.
Se lanciamo una palla in aria le diamo una variabile yspeed negativa, ma la gravità le darà una direzione y positiva aggiungendo un valore y positivo fino a quando la sua variabile yspeed non raggiungerà lo zero, dopodichè la palla inizierà di nuovo a cadere perchè la variabile yspeed tornerà positiva.
Traducendo questo in codice, la gravità è semplicemente un numero che viene aggiunto alla variabile yspeed ad ogni loop.
Praticamente:

Andiamo sul frame 1 ad aggiungiamo la variabile per la gravità

gravity=2;


Ora, sul frame 2 al fondo

yspeed=yspeed+gravity;


Testiamo il movie.
La sfera dovrebbe rimbalzare per lo schermo in una maniera molto più realistica.
Possiamo sperimentare con le variabili di gravità e velocità per vedere cosa succede.
A questo punto il movie non sembrerà più un "Pong" ma piuttosto una partita di tennis con dei giocatori invisibili...
Questo perchè la sfera non perde mai la sua velocità acquisita, potrebbe eventualmente essere trascinata in basso dalla gravità ma comunque continuerebbe a rimbalzare per lo schermo in maniera perpetua, come se fosse costantemente colpita per mantenere la sua velocità.
Nel mondo reale, ci sono due fattori che possono farla rallentare:
- la frizione: le molecole di aria con le quali si viene a contatto imprimono una piccola quantità di attrito
- la forza: un oggetto che rimbalza perde un po' di forza quando colpisce il suolo, perciò quando si rialza dal rimbalzo lo fa con un po' meno velocità di prima.
Ora vedremo come applicare questi due fattori.

E. L'ATTRITO

Se proviamo a sparare un proiettile nello spazio esterno esso procederà, teoricamente, alla stessa velocità all'infinito e niente lo rallenterà.
Sulla Terra invece, ogni oggetto in movimento è soggetto ad attrito da parte dell'aria, dell'acqua o da qualunque altra cosa oltrepassi.
Se appallottoliamo un foglio di carta e proviamo a lanciarlo, noteremo che non andrà molto distante.
Questo perchè l'aria lo frenerà.
Ora daremo una consistenza a questa forza nel nostro universo Flash, creeremo una sorta di trascinamento, di freno.
Chiameremo questa variabile "drag" e sarà il fattore che riduce qualunque velocità di una piccola percentuale, sia questa xspeed o yspeed ed in qualunque direzione.
Quindi tutto quello che dobbiamo fare è moltiplicare le nostre variabili di velocità per esempio di uno 0.98 % ad ogni loop.

Torniamo sul frame 1 e creiamo la variabile "drag"

drag=.98;

Poi, per mantenere le cose interessanti, cambiamo le variabili xspeed e yspeed in questo modo

xspeed=Math.random()*30;
yspeed=Math.random()*30;

Math.random() crea un numero casuale tra 0 e 1.
Moltiplicandolo per 30 diamo alle variabili xspeed e yspeed un valore da 0 a 30 che sarà differente tutte le volte che faremo partire il movie.


Nel frame 2 modifichiamo la linea

yspeed=yspeed+gravity;

in

yspeed=yspeed*drag+gravity;

e poi aggiungiamo questa linea

xspeed=xspeed*drag;


Testiamo il movie.
Adesso il realismo comincia a farsi vedere, è meraviglioso cosa possano fare poche righe di codice.
Anche qui possiamo sperimentare e vedere cosa succede se modifichiamo i valori di attrito, gravità ecc. ecc.


F. AGGIUNGIAMO UN LIVELLO DIVERSO DI RIMBALZO

Ora la nostra sfera è veramente realistica, assomiglia ad una bella palla di gomma.
Ma mettiamo il caso che vogliamo simulare una sfera di legno, o di acciaio o di qualunque altro materiale.
Ognuno di questi avrà un rimbalzo diverso, colpirà il suolo (o il muro oppure il soffitto) con una certa velocità e magari potrà avere un rimbalzo molto più piccolo o con meno velocità e quindi con meno forza.
Questo fattore di rimbalzo ridurrà la velocità di una certa percentuale in maniera molto simile all'attrito, ma questa volta ridurrà solo la velocità nel momento in cui colpisce una superficie.
Chiameremo questo fattore "bounce" , rimbalzo.
Una teorica e perfetta "superpalla" può avere un fattore di rimbalzo di 1 e cioè rimbalzerà con la stessa velocità con la quale ha toccato la superficie (benchè ci sia la nostra variabile "drag" che le riduce la velocità).
Invece una sfera di piombo avrà un fattore di rimbalzo molto vicino allo zero, cioè ci si aspetta che appena toccato il suolo rimanga praticamente dov'è o quasi.
Una sfera di legno sta nel mezzo delle due, cioè rimbalza meno di una di gomma ma più di una di piombo e così via.


Nel frame 1 e aggiungiamo la variabile "bounce"

bounce=.9;


Ora spostiamoci sul frame 2 ed aggiungiamo questo fattore nella stessa maniera con la quale abbiamo inserito la variabile "drag" , ma solo per quando la sfera rimbalza.
Abbiamo quattro cicli If, ognuno dei quali ha questa asserzione

xspeed=-xspeed;

oppure

yspeed=-yspeed;

Questa asserzione è il momento del rimbalzo, cioè quando la direzione viene invertita e qui dobbiamo aggiungere il nostro fattore di rimbalzo.
Quindi cambieremo queste asserzioni in questa maniera

xspeed=-xspeed*bounce;

e

yspeed=-yspeed*bounce;


Testiamo il file.
Non c'è molta differenza, vero ?
Questo perchè abbiamo un alto fattore di rimbalzo, 0.9
Proviamo a cambiarlo con qualcosa di più piccolo tipo 0.3 e guardiamo la differenza.
Con questa variabile possiamo quindi cambiare il materiale del quale è composta la nostra sfera.
E con questo abbiamo coperto in maniera sufficiente la simulazione delle forze che agiscono nel mondo reale.
Nella prossima sezione impareremo come interagire con la nostra sfera prendendola e lanciandola.
Sarà un po' più complicato rispetto ai passi svolti fino ad ora, ma meno di quanto ci aspettiamo...
Prima di proseguire, ecco il codice completo di quello che abbiamo trattato fino qui.

Da inserire nel frame 1:

_x=10;
_y=200;
xspeed=Math.random()*60-30;
yspeed=Math.random()*60-30;
rightedge=550;
leftedge=0;
topedge=0;
bottomedge=400;
gravity=2;
drag=.98;
bounce=.9;

Da inserire nel frame 2:

_x=_x+xspeed;
if(_x+_width/2>rightedge) {
_x=rightedge-_width/2;
xspeed=-xspeed*bounce;
}
if(_x-_width/2<leftedge) {
_x=leftedge+_width/2;
xspeed=-xspeed*bounce;
}
_y=_y+yspeed;
if(_y+_height/2>bottomedge) {
_y=bottomedge-_height/2;
yspeed=-yspeed*bounce;
}
if(_y-_height/2<topedge) {
_y=topedge+_height/2;
yspeed=-yspeed*bounce;
}
yspeed=yspeed*drag+gravity;
xspeed=xspeed*drag;

G. TRASCINAMENTO E LANCIO DELLA SFERA

Fino ad ora, abbiamo una sfera che appare, si muove in una direzione a caso e rimbalza fino a fermarsi.
Ora aggiungeremo l'interattività e impareremo come prenderla e lanciarla.
Lo scopo è avere la possibilità di lanciarla in qualunque direzione e imprimere la sua velocità mediante la velocità del nostro lancio.
Nessun problema, per fare ciò abbiamo bisogno di rendere il movie clip trascinabile.
Spero che conosciate il meccanismo di come si trascinano i movie clips.
Nel caso contrario, imparerete come si fa.

Per prima cosa abbiamo bisogno di un pulsante invisibile.
Creiamo un nuovo simbolo, nominiamolo "invisibleButton" e assicuriamoci che sia selezionato come pulsante.


Un pulsante invisibile è un pulsante che ha solo uno stato attivo, quello chiamato "hit".
Non possiamo vederlo, ma possiamo interagire con esso.
Creiamo un keyframe nello stato "hit" e lasciamo vuoti i rimanenti tre, cioè gli stati "up" , "over" e "down".
Ora disegniamo un cerchio nello stato "hit".
Questo cerchio deve essere pieno, non solo con il contorno e deve essere perfettamente centrato con il mirino al centro dello stage.
Per fare questo basta usare la griglia e l'aggancio alla griglia, oppure disegnarlo e usare il tool per l'allineamento con lo stage.


Torniamo sul movie clip della sfera e creiamo un nuovo layer, chiamandolo "button".


Apriamo la nostra libreria e trasciniamo una copia di "invisibleButton" sullo stage all'interno del layer "button".
Vedremo un leggero contorno blu del pulsante.
Questo contorno serve solo per farci sapere che il pulsante è presente sulla scena e che è attivo lo stato "hit" , quando lanceremo il movie questo pulsante non si vedrà.


Posizioniamolo sopra la sfera e, se necessario, scaliamolo in grandezza in modo da coprirla perfettamente.


Assicuriamoci di aver selezionato il pulsante, apriamo il pannello delle actions e digitiamo lo script seguente:

on(press){
startDrag(this);
dragging=true;
}
on(release, releaseOutside){
stopDrag();
dragging=false;
}

Praticamente, quando premiamo il pulsante del mouse diciamo al movie clip di seguire il mouse e settiamo la variabile "dragging" a true.
Quando rilasciamo il pulsante del mouse fermiamo il trascinamento del movie clip e settiamo la variabile "dragging" a false.
Vedremo in seguito come usare questa variabile.


Se testiamo il movie noteremo che ora abbiamo la possibilità di prendere la sfera e trascinarla ma, dato che le altre forze in gioco sono ancora attive, la sfera scivolerà via.
Dobbiamo disabilitare la gravità, l'attrito, il rimbalzo e la velocità mentre trasciniamo la sfera.
E qui entra in gioco la variabile "dragging".
Servirà per sapere quando stiamo trascinando e quando smettiamo di trascinare.
Andiamo quindi sul frame 2 del movie clip della sfera e aggiungiamo questa linea in testa al codice già presente:

 

if(!dragging){

//mentre alla fine di tutto il codice chiudiamo la parentesi graffa

}

 

Il punto esclamativo "!" significa "not" e serve per capire quando la variabile "dragging" mostra il valore "false".
Funziona in questa maniera:

se "dragging" is not true (e quindi è false, condizione che si presenta quando rilasciamo il pulsante del mouse) esegui tutto il codice compreso nel ciclo If e quindi applica gravità ecc. ecc.

se no (e quindi "dragging" è true, condizione che si presenta quando premiamo il pulsante del mouse) ignora tutto il codice compreso nel ciclo If e quindi non applicare niente.

Testiamo il movie.
Ora possiamo prendere la sfera e lasciarla andare.


Il prossimo passo è lanciare la sfera e imprimergli velocità e direzione.
Tutto quello che dobbiamo fare è tenere traccia della posizione del movie clip mentre lo stiamo trascinando.
Memorizzeremo questa traccia in due variabili che chiameremo "oldx" e "oldy".
Ad ogni loop, sottrarremo "oldx" dal valore corrente di "_x" ottenendo un "xspeed" paragonabile alla velocità di trascinamento.
Facciamo un esempio:

Ipotizziamo che quando iniziamo a trascinare, "_x" valga 100.
Memorizziamo questo valore in "oldx".
Al prossimo loop, mettiamo di aver mosso la sfera verso destra con una certa velocità e quindi ci troviamo con "_x" che ora vale diciamo 110.
110-100 = 10 oppure _x - oldx = xspeed
Proviamo a muovere la sfera in modo da coprire più distanza nello stesso tempo (e quindi aumentando la velocità) e mettiamo di trovarci al prossimo loop con "_x" che vale 130.
Seguendo l'operazione di prima
130-100 = 30 (come vedete la variabile "xspeed" è maggiore e questo vuol dire più velocità).
Ora mettiamo di muoverci a sinistra.
"_x" ora vale 90
90-100 = -10 (valore di "xspeed" negativo, quindi movimento verso sinistra).
La stessa cosa dobbiamo applicarla per il movimento verticale e quindi per le variabili "_y" , "oldy" e "yspeed".

Tutto questo deve essere effettuato solo quando stiamo trascinando la sfera.
Abbiamo già un ciclo If che si accorge del trascinamento e del codice che agisce quando NON stiamo trascinando, quindi dobbiamo aggiungere un "else" al ciclo If per far capire a Flash cosa eseguire quando stiamo trascinando.
Aggiungiamo allora questo "else" alla fine della parentesi graffa chiusa:

} else {
xspeed=_x-oldx;
yspeed=_y-oldy;
oldx=_x;
oldy=_y;
}

Ecco fatto, questo è tutto.
Ve l'avevo detto che era facile... :-)
Nel mio movie finale, ho settato degli sliders per poter modificare gravità, attrito e rimbalzo.
Lascio alla vostra fantasia come realizzarli.
Volendo fare i puristi, si possono spostare alcune delle proprietà al di fuori del movie clip e quindi in "_root".
Questo è un passo verso una più precisa programmazione orientata agli oggetti.
Cose come posizione, velocità e rimbalzo sono proprietà della sfera e rimangono della sfera.
Cose come attrito, gravità e posizione di muri, pavimento e soffitto non sono proprietà della sfera, ma dell'ambiente che la circonda e quindi è corretto gestirle al di fuori di questa.
In questo modo possiamo avere diverse sfere che rimbalzano per il movie, ognuna con il suo fattore di rimbalzo (e quindi simulando materiali diversi), la sua posizione e velocità, ma tutte avranno in comune la stessa gravità, lo stesso attrito e le stesse barriere (con il non indifferente vantaggio di dover settare questi valori in un posto solo...).

Per finire, ecco il codice finale di ogni sezione:

Frame 1:

_x=10;
_y=200;
xspeed=Math.random()*60-30;
yspeed=Math.random()*60-30;
rightedge=550;
leftedge=0;
topedge=0;
bottomedge=400;
gravity=2;
drag=.98;
bounce=.9;

Frame 2:

if (!dragging) {
_x = _x+xspeed;
if (_x+_width/2>rightedge) {
_x = rightedge-_width/2;
xspeed = -xspeed*bounce;
}
if (_x-_width/2<leftedge) {
_x = leftedge+_width/2;
xspeed = -xspeed*bounce;
}
_y = _y+yspeed;
if (_y+_height/2>bottomedge) {
_y = bottomedge-_height/2;
yspeed = -yspeed*bounce;
}
if (_y-_height/2<topedge) {
_y = topedge+_height/2;
yspeed = -yspeed*bounce;
}
yspeed = yspeed*drag+gravity;
xspeed = xspeed*drag;
} else {
xspeed=_x-oldx;
yspeed=_y-oldy;
oldx=_x;
oldy=_y;
}

Frame 3:

gotoAndPlay(2);

Pulsante:

on(press){
startDrag(this);
dragging=true;
}
on(release, releaseOutside){
stopDrag();
dragging=false;
}



Ti potrebbe interessare anche

commenta la notizia

C'è 1 commento
Sara
Hai dubbi su questo articolo?