Sei sulla pagina 1di 1

Sistema di movimento del personaggio

* Gestione dell'input utente


* Collisioni
* Fisica
* Movimento
* Codice integrale

==============================================================
Sistema di movimento del personaggio
==============================================================

Un sistema di movimento per il personaggio in un ambiente 2D


deve occuparsi essenzialmente di:
- gestire l'input dell'utente
- verificare le collisioni con pavimento, mura, ecc...
- emulare le leggi della fisica per i salti e le cadute
- muovere il personaggio in base a tali dati

Prima di procedere oltre bisogna prima spiegare come, dove e


quando il codice sarà implementato.
Il codice sarà ovviamente eseguito dal personaggio, che
chiameremo d'ora in poi 'player'. Occorre specificare anche
che sarà eseguito ad ogni frame, quindi 30 volte al secondo;
pertanto va inserito all'interno del movieClip 'player'
nell'evento:
> onClipEvent(enterFrame) {
> /* codice */
> }

Prima di muovere realmente il personaggio, lo script


stabilisce di quanti pixel muoverlo sull'asse delle ascisse e
su quelle delle ordinate, salvando tali valori nelle variabili
'xvect' e 'yvect' inizializzate a zero la prima volta che
viene eseguito lo script, cioè quando viene caricato 'player'
sullo schermo, quindi:
> onClipEvent (load) {
> /* [...] */
> yvect=0;
> xvect=0;
> }

--------------------------------------------------------------
Gestione dell'input utente
--------------------------------------------------------------
In base a quanto detto, alla pressione dei tasti 'RIGHT' e
'LEFT', 'xvect' deve essere incrementato o decrementato di una
quantità uguale alla velocità del personaggio espressa in
pixel/frame il cui valore è memorizzato nella costante
'speed':
> if (Key.isDown(Key.RIGHT)) xvect+=speed;
> if (Key.isDown(Key.LEFT)) xvect-=speed;

Infine accade la stessa cosa anche con i salti:


> if (_root.ground.hitTest(this.d._x+_x, this.d._y+_y, true)
&& Key.isDown(Key.UP) )
> yvect=-jump;
Dove 'jump' è una costante in cui è memorizzato il valore
dell'altezza del salto. Tra le condizioni dell''if' c'è anche
una funzione 'hitTest()', che verifica le collisioni, ma di
questo ne parleremo dopo. In ogni caso all'interno dell''if'
si occupa di rendere possibile il salto solo a patto che il
personaggio poggi su qualcosa.

--------------------------------------------------------------
Collisioni
--------------------------------------------------------------
Come accennavo poc'anzi la funzione che gestisce le collisioni
è 'hitTest()'. Le collisioni da prendere in considerazione
sono quelle con il movieClip 'ground', che contiene i
pavimenti, le mura e via discorrendo, cioè tutto ciò che al
personaggio non è consentito di attraversare.
All'interno di 'player', vi sono ben 5 movieClip figli che si
occupando delle collisioni:
- 'D': collisioni sull'asse y
- 'R' e 'L': collisioni sull'asse x
- 'br' e 'bl': collisioni sull'asse x (con superfici
oblique)

In particolare se viene rilevata una collisione con 'br' o


'bl', ma non con il corrispettivo 'R' o 'L', che si trova più
in alto e più distanziato dal personaggio, allora vuol dire
che l'inclinazione è abbastanza ridotta da poterla scalare,
quindi lo script fa risalire il movieclip lungo l'asse y fino
a quando tale collisione non si verifica più:

> if (_root.ground.hitTest(this.br._x+_x, this.br._y+_y,


true) && !_root.ground.hitTest(this.r._x+_x, this.r._y+_y,
true))
> while (_root.ground.hitTest(this.br._x+_x, this.br._y+_y,
true))
> _y--;
> if (_root.ground.hitTest(this.bl._x+_x, this.bl._y+_y,
true) && !_root.ground.hitTest(this.l._x+_x, this.l._y+_y,
true))
> while (_root.ground.hitTest(this.bl._x+_x, this.bl._y+_y,
true))
> _y--;

Le collisioni con 'L', 'R' e 'D', inoltre impostano a 0


'xvect' e 'yvect':

> if (_root.ground.hitTest(this.d._x+_x, this.d._y+_y, true)


&& yvect>0) yvect=0;
[...]
> if (xvect>0 && _root.ground.hitTest(this.r._x+_x,
this.r._y+_y, true)) xvect=0;
> if (xvect<0 && _root.ground.hitTest(this.l._x+_x,
this.l._y+_y, true)) xvect=0;

--------------------------------------------------------------
Fisica
--------------------------------------------------------------
Per quanto riguarda la forza di gravità:
> if (!_root.ground.hitTest(this.d._x+_x, this.d._y+_y,
true)) yvect+=gforce;
cioè 'yvect' viene incrementato di una costante 'gforce'
contenente il valore dell'accelerazione di gravità.

Per dare un certo attrito e per evitare moti perpetui, alla


fine di ogni frame, dopo aver quindi effettuato il movimento,
si riduce il valore di 'xvect' preso in valore assoluto,
moltiplicandolo per un numero non intero, memorizzato nella
costante 'friction':
> xvect*=friction;

--------------------------------------------------------------
Movimento
--------------------------------------------------------------
Dato che il movimento si arresta quando viene verificata la
collisione, per evitare che questo si arresti solo quando
ormai il 'player' ha già "sfondato" il 'ground', all'interno
di ogni frame, il movimento previsto da 'xvect' viene
scomposto in tanti piccoli movimenti unitari, alla fine di
ognuno dei quali viene effettuato 'hitTest()'.

> for (c=0; c<Math.abs(xvect); c++) {


[hitTest() di 'R' ed 'L']
> _x+=xvect/Math.abs(xvect);
[hitTest() di 'br' ed 'bl']
> }
Dove 'xvect/Math.abs(xvect)' restituisce un valore unitario
col segno di 'xvect'.

Non è necessario invece fare la stessa cosa sull'asse y,


poiché al verificarsi delle collisioni con 'br' e 'bl' il
personaggio viene comunque "tirato fuori" da 'ground'.

--------------------------------------------------------------
Codice integrale
--------------------------------------------------------------

/*
Source code developed by Giuseppe Antonio Nanna
*/

onClipEvent (load) {
gforce = 2;
jump = 20;
friction = .6;
speed = 3;

yvect=0;
xvect=0;
}

onClipEvent (enterFrame) {

if ((_root.ground.hitTest(this.d._x+_x, this.d._y+_y,
true)||_root.ground.hitTest(this.bl._x+_x, this.bl._y+_y,
true)||_root.ground.hitTest(this.br._x+_x, this.br._y+_y,
true) )&& Key.isDown(Key.UP) ) yvect=-jump;

if (!_root.ground.hitTest(this.d._x+_x, this.d._y+_y,
true)) {
dvar=1;
yvect+=gforce;
} else if (yvect>0) yvect=0;

c=0;
while (!_root.ground.hitTest(this.d._x+_x, this.d._y+_y,
true) && c<yvect) {
_y++;
c++;
}

if (yvect<0) _y+=yvect;

if (Key.isDown(Key.RIGHT)) xvect+=speed;
if (Key.isDown(Key.LEFT)) xvect-=speed;

if (Math.abs(xvect)>friction) for (c=0;


c<Math.abs(xvect); c++) {
if (xvect>0 && _root.ground.hitTest(this.r._x+_x,
this.r._y+_y, true)) xvect=0;
if (xvect<0 && _root.ground.hitTest(this.l._x+_x,
this.l._y+_y, true)) xvect=0;
_x+=xvect/Math.abs(xvect);
if (_root.ground.hitTest(this.br._x+_x,
this.br._y+_y, true) && !_root.ground.hitTest(this.r._x+_x,
this.r._y+_y, true)) while
(_root.ground.hitTest(this.br._x+_x, this.br._y+_y,
true))_y--;
if (_root.ground.hitTest(this.bl._x+_x,
this.bl._y+_y, true) && !_root.ground.hitTest(this.l._x+_x,
this.l._y+_y, true)) while
(_root.ground.hitTest(this.bl._x+_x, this.bl._y+_y,
true))_y--;
}

xvect*=friction;
}

Potrebbero piacerti anche