1. Introduzione
  2. Iniziamo
  3. Nemici Multipli
  4. Game Over
  5. Punteggi e Orologio
  6. Tanti Piccoli Miglioramenti
  7. Usiamo la Tastiera
  8. Aggiungere un Preloader (Parte 1 - Parte 2)
  9. Aggiungere Musica ed Effetti Sonori
  10. Livelli Multipli
  11. Salvare e Caricare Informazioni
  12. Garbage Collection

In questo quinto appuntamento della nostra guida dedicata all’apprendimento del Flash / Actionscript3, aggiungeremo qualcosa in più al nostro gioco. Stavolta è il turno di un piccolo sistema di conteggio dei punti e un semplice orologio. Vi avverto: l’articolo stavolta sarà abbastanza lungo.

Tuttavia, nel caso vogliate fare un break, potete interrompere nel mezzo in modo tale da tenere la mente ugualmente fresca e non strafare eccessivamente.

Nel caso vogliate iniziare da qua, prelevate i file necessari dalla fine della precedente lezione, altrimenti prendete le vostre copie di backup e via.


Tutto Conta.

Prima di buttarci a capofitto nella creazione di cose e la scrittura di codice, fermiamoci un secondo e riflettiamo su un particolare molto interessante: un orologio e un contatore di punti possono avere in comune un sacco di cose.

Per esempio, in comune potrebbero avere una variabile di tipo numerico, contenente il punteggio attuale del giocatore oppure il tempo trascorso.

Ed ancora ben tre funzioni in comune:

  • Una funzione addToValue( amountToAdd:Number ) che a seconda dei casi (ogni tick oppure ad ogni azione degna di essere considerata come punteggio) viene richiamata;
  • Una funzione reset() che serve a re-impostare il nostro punteggio/tempo trascorso al valore iniziale (per esempio zero)
  • Una funzione updateDisplay(), che si occupi di aggiornare la visione su schermo del valore del timer/punteggio attuale.

Ciò che invece, probabilmente, non sarà comune ad entrambi sarà la visualizzazione. Questo significa che la funzione updateDisplay() sarà diversa a seconda dello “scopo” dell’oggetto. Insomma, due classi molto simili da creare. Questo vuol dire che davvero dobbiamo scrivere da zero due classi separate?

Ovviamente, no.

Come di sicuro ricorderete, in passato abbiamo usato la parola chiave extends per indicare che una determinata classe (o un evento) estende appunto le capacità di una classe considerata “basilare” come MovieClip o Event.

A fronte di queste riflessioni, ecco il nostro piano d’azione:

  • Inizieremo con una classe base che conterrà tutti gli elementi in comune dell’orologio e del segnapunti. Questa classe non avrà una rappresentazione visuale come le altre precedentemente create, in quanto non l’andremo ad usare direttamente. Chiameremo questa classe “Counter”
  • Successivamente creeremo una classe “Score” estendendo “Counter”, adattando l’elemento visuale per lo scopo da noi prefissato.
  • Infine creeremo un’altra classe derivata da “Counter”, che chiameremo “Clock” che rappresenterà il nostro orologio.

Ad alcuni di voi questo ragionamento potrà sembrare inizialmente un po’ contorto, ma vi assicuro che non lo è! Stiamo usando la programmazione ad oggetti. Nello specifico il concetto di ereditarietà, perno del paradigma della programmazione ad oggetti. Rimando alla specifica voce su Wikipedia per maggiori informazioni.

Ora che ci siamo ed abbiamo riflettuto, mettiamoci all’opera ;)


Impariamo a Contare… di nuovo.

Basandoci sulle indicazioni date precedentemente, ecco come abbiamo scritto la nostra classe Counter:

package
{
  import flash.display.MovieClip;
  public class Counter extends MovieClip
  {
    public var currentValue:Number;

    public function Counter()
    {

    }

    public function addToValue( amountToAdd:Number ):void
    {

    }

    public function reset():void
    {

    }

    public function updateDisplay():void
    {

    }
  }
}

Salviamo il file come Counter.as nella cartella delle Classi. Ormai mi aspetto che siate capaci di comprendere il tutto, per cui eviterò una spiegazione riga per riga di cose già fatte precedentemente in maniera abbondante. L’unica cosa su cui vorrei focalizzare l’attenzione è il “extends MovieClip”. Dato che un oggetto di tipo MovieClip può contenere altri oggetti rappresentabili sullo schermo, questo porterà il nostro Counter a poter mostrare oggetti sullo schermo, a sua volta.

Nota: avremmo potuto usare altre classi come Sprite oppure DisplayObjectContainer, ma abbiamo optato per MovieClip in quanto ci permette di creare l’orologio ed il punteggio in flash, anzichè riprogrammare tutto per disegnare via codice.

Arrivati a questo punto, potreste chiedervi: perchè estendere la classe MovieClip (con la classe Counter) anzichè estendere entrambi separatamente nelle nuove classi? (Per esempio, la classe Clock estende sia Counter che MovieClip)

La risposta è presto data: è impossibile estendere due classi contemporaneamente in un unica classe. La cosidetta Ereditarietà Multipla, infatti, non è contemplata.

Se siete dei novizi della programmazione alcuni di questi concetti come “Ereditarietà Multipla” potrebbero sembrarvi ostrogoto. Non vi preoccupate, è del tutto normale e un approfondimento (se volete) sulla cara vecchia Wikipedia fa sempre un gran bene.

Ma torniamo a noi: abbiamo scritto lo “scheletro” di alcune funzioni, precedentemente. Facciamo in modo che queste funzioni inizino a svolgere qualche compito preciso.

Partiamo da “reset()”: ecco il codice che dovremo usare al suo interno.

public function reset():void
{
  currentValue = 0;
}

Mi pare abbastanza semplice ;) In questo modo azzeriamo il nostro contatore, qualsiasi cosa indichi.

Altrettanto ovvia è l’implementazione di “addToValue()”:

public function addToValue( amountToAdd:Number ):void
{
  currentValue = currentValue + amountToAdd;
}

Abbiamo il valore “amountToAdd” passato come parametro e lo aggiungiamo a quello che è il valore corrente. Per esempio, avendo

  • currentValue = 10
  • amountToAdd = 5

currentValue, dopo l’esecuzione della funzione, avrà valore 15. Lo so, non c’era neanche bisogno di spiegarlo ma ogni tanto è meglio spendere due parole in più per essere chiari!

Abbiamo detto, inoltre, che dobbiamo resettare il nostro oggetto appena viene creato. Senza riscrivere istruzioni inutili, basta richiamare nel costruttore il metodo “reset()”:

public function Counter()
{
  reset();
}

Infine dobbiamo considerare un ultima cosa: avevamo deciso che l’aspetto dell’oggetto doveva essere aggiornato ad ogni cambiamento del valore di currentValue. Per cui dovremo richiamare “updateDisplay()” nei due momenti opportuni:

  • all’esecuzione di reset()
  • all’esecuzione di addToValue()

Ed ecco il codice di conseguenza:

public function addToValue( amountToAdd:Number ):void
{
  currentValue = currentValue + amountToAdd;
  updateDisplay();
}

public function reset():void
{
  currentValue = 0;
  updateDisplay();
}

E’ vero, è decisamente strano usare così di frequente una funzione che, al momento, non fa assolutamente niente. Ma pensate sia davvero quello che abbiamo nei nostri piani? ;)


Disegnamo il Punteggio

L’idea di estendere una classe da noi personalizzata può essere davvero confusa, per tutti coloro che sono alle prime armi. In realtà è una di quelle cose semplici da capire, con un po’ di pratica. Nel caso non dovreste riuscirci ecco il consiglio che vi do:

Continuate a seguire questo tutorial finchè non avremo creato qualcosa di “visualizzabile” e di concreto. Un esempio a volte vale più di mille parole e alla fine riuscirete a capire quel che intendo :)

È proprio ora di fare qualcosa in flash adesso. Torniamo al nostro file .fla e creiamo un nuovo simbolo. Chiamiamolo “Score” e la tipologia sarà ovviamente “Clip filmato”. Nelle opzioni di concatenamento esportiamolo per Actionscript, con il nome “Score”. Cliccando su ok ci ritroveremo nella modalità di modifica del clip, come di consueto.

Per non complicare eccessivamente le cose, per indicare il nostro punteggio utilizzeremo del semplice testo. Qualcosa come questo che vedete di seguito:

AvoiderGame_Part5_03Non badate al numero, è solamente per far vedere come verrà visualizzato.

Il punteggio chiaramente varierà di volta in volta, dato che è una variabile e quindi varia nel tempo. Ora, quindi, faremo in modo di “collegare” questo testo e il punteggio attraverso il codice. Per prima cosa, nel pannello delle proprietà di questo oggetto, cambiamo la tipologia in “Testo Dinamico” nel caso non sia già selezionato.

Vi ricordate nella lezione tre quando per il GameOver avevamo cambiato il testo da Dinamico a Statico? Ora facciamo l’opposto ;)

AvoiderGame_Part5_04

Una volta deselezionato il nostro testo avremo il bordo puntato intorno ad esso:

AvoiderGame_Part5_06

Dato che agiremo sul testo passando dal codice (durante il gioco) dobbiamo dare un nome all’istanza, proprio come per tutti gli oggetti. Il nome d’istanza si può cambiare dal pannello delle proprietà: stavolta optiamo per “scoreDisplay”.

AvoiderGame_Part5_07

Piccola Nota: una cosa molto fastidiosa, a volte, è che flash rende il testo dinamico selezionabile di default. Questo vuol dire che quando il cursore del mouse si ritroverà sul nostro testo, cambierà nel cursore di sistema destinato al testo.

Se volete eliminare questo problema, selezionate l’oggetto e cliccate successivamente sulla casellina con su scritte le lettere “Ab”:

AvoiderGame_Part5_08

Fate quello che volete per personalizzarlo: ovviamente potete aggiungere bordi, colori e disegnarci di tutto. Sul nostro, giusto per fare qualcosa, abbiamo aggiunto un semplice testo a lato:

AvoiderGame_Part5_11

Direi che così basta per ora. Ricordate che la casella di testo dove ho scritto “Score”, al contrario dell’altro testo, è di tipo “Testo Statico”.

Ed ora, andiamo al codice.


Funzioni da Mammà, Variabili da Papà

Creiamo un nuovo file ActionScript, chiamiamolo Score.as e salviamolo nella cartella delle nostre classi. Di seguito vi riporto il codice da metterci dentro. Notate bene che sulla linea 3 riporto l’istruzione d’importazione della classe TextField, in quanto stiamo utilizzando del testo dinamico.

package
{
  import flash.text.TextField;
  public class Score extends Counter
  {
    public function Score()
    {

    }
  }
}

Alla prima occhiata le cose non potrebbero sembrare un granchè chiare. Dove sono tutte quelle funzioni e variabili che ci eravamo prefissati di creare per l’orologio ed il punteggio? Lo so, siete dei ragazzi svegli ed avete capito che stiamo estendendo la classe Counter che questi oggetti già li ha!

Grazie a questa piccola mossa, quindi, non dovremo riscrivere più i metodi reset(), addToValue() e la definizione della classe ;) la bellezza della programmazione ad oggetti e di quel concetto meraviglioso che è l’ereditarietà.

In poche parole adesso ecco cosa abbiamo: la nostra classe Score che contiene tutte le funzionalità già previste per la classe Counter. C’è una sola eccezione però: il metodo costruttore.

Il costruttore di questa nuova classe, Score(), non erediterà i contenuti del metodo Counter() della classe omonima. Questo è decisamente noioso in quanto copiare pari pari i contenuti di un metodo nell’altro non è un granchè bello.

Ma ancora una volta, la funzione “super()” arriva in nostro soccorso. L’avevamo già usata precedentemente e credo ve la ricordate, anche se non avevo spiegato per bene cosa facesse. Eccovi serviti:

La funzione super() permette ad una classe di accedere alle funzioni della sua classe base. Eccovi un esempio per capire meglio:

public function Score()
{
  super();
}

Nel costruttore della classe Score verrà richiamato il super come metodo. Ciò si traduce nell’esecuzione delle istruzioni contenute nel metodo costruttore della sua classe base, ovvero Counter! In questo caso quindi verrà eseguita come da programma la funzione “reset()”. Esattamente ciò che volevamo. Con una sola riga di codice.

Adesso, sicuri della nostra conoscenza, sappiamo che abbiamo già scritto i metodi base per tutto quanto. Ci manca solo una funzione da “trattare”. Parliamo di “updateDisplay()”, la funzione che precedentemente avevamo lasciato vuota e senza istruzioni.

C’è, tuttavia, un piccolo imprevisto. Nel caso scrivessimo, nel codice, semplicemente queste istruzioni (ovviamente parlo della classe Score):

public function updateDisplay():void
{

}

riceveremmo un errore, perché ci sono due funzioni chiamate updateDisplay nella classe:

  • una è quella appena scritta
  • l’altra è quella ereditata dalla classe base

Non vi preoccupate, c’è una soluzione semplice per questo problema. Basta usare la parola chiave override. Tutto quello che dobbiamo fare infatti è posizionare questa parola chiave prima della parola public:

override public function updateDisplay():void
{

}

Dobbiamo considerare una cosa però: con la parola chiave override noi perdiamo la funzione updateDisplay() originale! Proprio come precedentemente era successo col costruttore (in quel caso non avevamo utilizzato la parola override, anche perché i nomi delle classi erano diversi). Comunque sia, la parola chiave “super” torna in nostro soccorso ancora una volta:
override public function updateDisplay():void
{
  super.updateDisplay();
}

In questo modo verranno eseguite tutte le istruzioni contenute nella funzione updateDisplay() originale, permettendoci inoltre di scriverne di nuove per la nostra nuova classe. Piano piano le cose saranno più semplici e chiare con la pratica.

Adesso possiamo scrivere altro codice aggiuntivo:

override public function updateDisplay():void
{
  super.updateDisplay();
  scoreDisplay.text = currentValue.toString();
}

Penso quest’ulteriore istruzione sia semplice da comprendere, ma la spiegherò ugualmente. “scoreDisplay” è il nostro testo dinamico. La variabile “text” dell’oggetto rappresenta la stringa di testo che deve scrivere sullo schermo. Quello che noi facciamo è quindi dargli il valore del punteggio attuale (currentValue) convertendolo in stringa tramite il metodo “toString”.

Perché convertire in stringa il punteggio? Perchè è di tipo numerico e quindi deve essere convertito in un formato contemplato dal tipo della variabile scoreDisplay.text. Dopo questa istruzione, dobbiamo provvedere ad implementare a tutti gli effetti il punteggio nel gioco!


Punteggio in Posizione

Per posizionare il nostro punteggio sullo schermo avremmo potuto usare il codice, modificando la classe PlayScreen. Ma a ben pensarci, invece di complicarci la vita in questo modo potremmo semplicemente usare l’ide del flash.

Dalla libreria, infatti, prendete lo Score e posizionatelo dove volete nella PlayScreen. Qui di seguito, ecco come lo abbiamo posizionato noi:

AvoiderGame_Part5_12

Inoltre, dobbiamo ricordarci di dargli un nome d’istanza. Dopo aver selezionato l’istanza cambiamone il nome dal pannello delle Proprietà, come di consueto per questa procedura. Noi gli abbiamo dato il nome “gameScore”. Salviamo tutto e lanciamo il gioco, ecco cosa ci apparirà:

AvoiderGame_Part5_13

Cavolo, il contatore dei punti rimane a zero!

Possiamo risolvere al volo questo piccolo inconveniente. Innanzitutto dobbiamo scegliere il criterio con il quale assegnare i punti oppure no. Ecco la nostra scelta: il punteggio, per ogni tick del gioco, aumenterà di 10. Questo vuol dire che richiameremo la funzione “addToValue( 10 )” dell’oggetto ad ogni tick, in modo tale da incrementare il punteggio della quantità desiderata.

Apriamo dunque il file AvoiderGame.as:

public function onTick( timerEvent:TimerEvent ):void
{
  if ( Math.random() < 0.1 )
  {
    var randomX:Number = Math.random() * 400;
    var newEnemy:Enemy = new Enemy( randomX, -15 );
    army.push( newEnemy );
    addChild( newEnemy );
    gameScore.addToValue( 10 );
  }

L’ultima istruzione che leggete è quella che abbiamo aggiunto. Il risultato?

AvoiderGame_Part5_14

Il punteggio ora aumenterà regolarmente.

Cavolo, inizia quasi a sembrare un gioco vero ora! ;) I motivi per cui aggiungete il punteggio al vostro gioco, ovviamente, possono essere i più disparati: un semplice elemento di sfida o magari una gara tra amici. Ora, potremmo mettere una nuova istanza di Score nel GameOverScreen, per indicare al giocatore il numero preciso di punti una volta terminato il gioco.

Non è di sicuro la scelta più appropriata! Insomma, sarebbe uno spreco allucinante. Per questo motivo ora inseriremo un testo dinamico nel nostro GameOverScreen, che comunichi al giocatore il punteggio finale. Penso che ormai sappiate come potete fare:

  • Doppio click sull’elemento GameOverScreen nella libreria;
  • Creiamo una nuova casella di testo impostando la sua tipologia come “Testo Dinamico”;
  • Usiamo come nome d’istanza “finalScore”, in modo tale da utilizzarla via codice.

Come fare per “trasferire” il punteggio finale dalla schermata di gioco a quella di Game Over? Il posto migliore è sicuramente la classe documento, nella funzione onAvatarDeath. Infatti guardate come abbiamo modificato il detto metodo:

public function onAvatarDeath( avatarEvent:AvatarEvent ):void
{
  var finalScore:Number = playScreen.getFinalScore();

  gameOverScreen = new GameOverScreen();
  gameOverScreen.addEventListener( NavigationEvent.RESTART, onRequestRestart );
  gameOverScreen.x = 0;
  gameOverScreen.y = 0;
  gameOverScreen.setFinalScore( finalScore );
  addChild( gameOverScreen );

  playScreen = null;
}

Usiamo la variabile finalScore per memorizzare il punteggio attuale. Successivamente richiamiamo la funzione gameOverScreen.setFinalScore, passando come parametro il punteggio finale.

Ma un attimo, questo metodo “setFinalScore” da dove esce? Non temete, lo stiamo andando a realizzare proprio adesso. Aprite GameOverScreen.as e come prima cosa importiamo le definizioni della classe per la textbox dinamica:

package
{
  import flash.display.MovieClip;
  import flash.display.SimpleButton;
  import flash.events.MouseEvent;
  import flash.text.TextField;

Ed ora creiamo il semplice metodo setFinalScore:
public function setFinalScore( scoreValue:Number ):void
{
  finalScore.text = scoreValue.toString();
}

Salvate tutto ed avrete il risultato bello servito. Ovviamente dovrete perdere per controllare che sia tutto a posto ;) Fate questo sacrificio per la vostra anima di pro gamer.

AvoiderGame_Part5_18

Mitico! Qualcosa del genere, otto o nove anni fa, avrebbe conquistato la Frontpage di Newgrounds.


Ma… il nostro Orologio?

Diamine, quasi quasi ci stavamo scordando dell’orologio. Lo ammetto, ci siamo dilungati un po’ tanto sullo score, ma c’era un motivo preciso per cui l’ho fatto: se avete ben compreso le dinamiche con la quali abbiamo raggiunto il nostro risultato, le cose ora saranno in discesa e a fare il nostro orologio ci metteremo cinque minuti esatti.

Questa volta, tuttavia, non useremo output numerici, bensì una semplice animazione. Giusto per estremizzare la lezione di oggi riguardante l’ereditarietà e l’overriding.

Torniamo al nostro file FLA e creiamo un nuovo Movie Clip (“Inserisci > Nuovo Simbolo”, lo sapete) e chiamiamolo Stopwatch. questa volta non esportiamolo per Actionscript: il nostro scopo è utilizzarlo come animazione essenzialmente.

Appena passiamo nella modalità modifica disegnamo un orologio (o quello che volete voi, anche se lo scopo è far capire che sta passando il tempo, quindi): di seguito trovate il nostro.

AvoiderGame_Part5_19

Ora: ricordate il lavoro che avevamo fatto con i pulsanti, la lezione scorsa, aggiungendo un keyframe per ogni “stato” del pulsante? Le cose qui saranno leggermente diverse ma andremo sempre a gestire un animazione. La differenza, infatti, starà nel fatto che stavolta ogni keyframe che aggiungeremo sarà un nuovo frame della nostra animazione. I frame vengono quindi riprodotti uno dopo l’altro.

Nel caso siate già abili nell’uso di flash come animation tool, allora divertitevi come volete. Altrimenti continuate a seguire l’articolo.

Cliccate con il pulsante destro del mouse sul secondo frame del nostro nuovo orologio, e selezionate “Inserisci Fotogramma Chiave”.

AvoiderGame_Part5_20

Ora eseguiamo qualche modifica che faccia intuire il passaggio del tempo nel gioco:

AvoiderGame_Part5_21

Wow.

Se volete potete continuare ad aggiungere nuovi frame man mano che si va avanti per creare un animazione più complessa e più gradevole alla vista. Nulla vi vieta di lasciare i due frame creati fino ad ora ;)

L’uso che faremo di questa animazione sarà, in un certo senso, lo stesso del testo dinamico nella scoreboard fatta prima. Creiamo quindi un nuovo simbolo ancora, chiamato “Clock”. Questo sarà il nostro vero orologio. Stavolta effettueremo anche l’esportazione per Actionscript: il nome scelto per la classe sarà ovviamente Clock.

Essendo sicuri di essere in modalità di modifica del nostro nuovo simbolo (nel caso non ci fossimo basta selezionare Clock dalla libreria, cliccarci con il pulsante destro del mouse e scegliere Modifica) prendiamo la nostra animazione creata prima, Stopwatch, e trasciniamola sullo schermo, nell’area del Clock. Diamo inoltre all’animazione Stopwatch appena creata un nome d’istanza: chiamiamola “clockDisplay”.

Sarà questo Clock quindi il MovieClip che utilizzeremo nella nostra schermata di gioco, la PlayScreen.

Ricapitolando:

  • abbiamo creato l’animazione
  • abbiamo creato un nuovo simbolo “contenitore” per l’animazione, chiamato Clock (l’orologio vero e proprio esportato in ActionScript)
  • inseriamo il nostro Clock nella PlayScreen, la schermata di gioco.

Spero di essere stato abbastanza chiaro.

Ora creiamo un nuovo file Actionscript e chiamiamolo Clock.as. Il contenuto di questo file è il seguente:

package
{
  import flash.display.MovieClip;
  public class Clock extends Counter
  {
    public function Clock()
    {
      super();
    }

    override public function updateDisplay():void
    {
      super.updateDisplay();

    }
  }
}

Se notate, è praticamente identico al file Score.as, ad eccezione del fatto che stiamo importando la classe MovieClip anziché TextField. D’altronde, stavolta stiamo usando un animazione e non un testo dinamico ;)

Per quanto riguarda la nostra cara funzione updateDisplay(), invece, stavolta dovrà occuparsi di mostrare il frame giusto della nostra animazione. La funzione che si occupa di questo compito, per le animazioni, è gotoAndStop(). La sintassi è la seguente:

gotoAndStop( frameDaMostrare )

Questo vuol dire che, per esempio, volendo mostrare il frame 3 di una animazione x, useremo la sintassi:
x.gotoAndStop(3);

Ma STOP!

Dobbiamo pianificare un po’ di cose prima di procedere. Infatti:

Come uso tutte queste informazioni?

Ogni quanto deve cambiare il frame dell’animazione?

Come faccio a mostrare i frame in modo corretto?

Non possiamo buttarci a capofitto sul codice, occorre invece riflettere sulle cose e sui problemi da risolvere.

Dobbiamo aggiornare il valore interno del nostro orologio ad ogni tick. Un modo per fare tutto questo sarebbe quello di aggiungere il valore in millisecondi del tempo tra un tick e l’altro. 25 millisecondi. Il tutto sarebbe poco produttivo però: dovremmo cercare il frame 25, poi il 50, il 75 e dopo qualche secondo più di 2000. Non so voi, ma nel fare l’animazione dell’orologio ho portato il lavoro avanti fino al dodicesimo frame, poi mi sono rotto.

Per cui, la soluzione più logica per risolvere il problema è la seguente:

  • dividere il valore attuale del nostro Clock (il currentValue) per intenderci, per il numero di frame della nostra animazione (quindi, per cinque frame di animazione divideremo per cinque, per otto frame divideremo per otto e così via). Questo eviterà il salto dei frame;
  • successivamente torneremo al primo frame una volta superato l’ultimo.

Con questi punti in mente ecco come abbiamo scritto la funzione updateDisplay per l’oggetto Clock:

override public function updateDisplay():void
{
  super.updateDisplay();

  var frameToSkipTo:Number = currentValue / 1000;
  frameToSkipTo = Math.floor( frameToSkipTo );
  frameToSkipTo = frameToSkipTo + 1;
  if ( frameToSkipTo > 12 )
  {
    frameToSkipTo = frameToSkipTo - 12;
  }
  clockDisplay.gotoAndStop( frameToSkipTo );
}

Spieghiamo un po di codice:

  • var frameToSkipTo… : crea una variabile che contiene il numero di secondi passati. Il numero di secondi viene ottenuto dividendo i millisecondi (contenuti nella currentValue) per mille;
  • frameToSkipTo = Math.Floor( frameToSkipTo ) : qui utilizziamo la funzione Math.Floor. Non ne abbiamo parlato prima, comunque sia consente di arrotondare per difetto il numero passato come parametro.
  • frameToSkipTo = frameToSkipTo + 1 : l’istruzione incrementa di uno la variabile frameToSkipTo. Questo perché non si parte dal frame 0 per l’animazione, bensì dal frame numero 1;
  • if ( frameToSkipTo > 12 ) : queste istruzioni servono a controllare se il nuovo frame calcolato è oltre il numero di frame totali dell’animazione. Sarebbe il colmo infatti cercare il frame 14 di un animazione con 12 frames;
  • clockDisplay.gotoAndStop( frameToSkipTo ) : muove l’animazione al frame specificato.

Se provassimo l’animazione, tuttavia, funzionerebbe per qualche secondo e poi si fermerebbe. Perchè? Perchè una volta raggiunto un valore maggiore di 25 il programma sottrarrebbe 12 e si ritroverebbe come valore per il frame da mostrare 13.

E non abbiamo più di 12 frame.

Come aggiustare le cose? Anzichè l’if, usiamo un bel while:

override public function updateDisplay():void
{
  super.updateDisplay();

  var frameToSkipTo:Number = currentValue / 1000;
  frameToSkipTo = Math.floor( frameToSkipTo );
  frameToSkipTo = frameToSkipTo + 1;
  while ( frameToSkipTo > 12 )
  {
    frameToSkipTo = frameToSkipTo - 12;
  }
  clockDisplay.gotoAndStop( frameToSkipTo );
}

Ovviamente, sentitevi liberi di modifcare tutto quello che volete per prendere dimestichezza con il sistema.

Potrei continuare a parlare di come aggiungere il Clock al nostro gioco, sul PlayScreen, oppure di come aggiungere il valore 25 all’orologio ad ogni tick. Ma non lo farò. Il motivo è che è una cosa che ho detto così tante volte che ormai ho quasi la nausea, ed in questa lezione, se studiata bene, c’è tutto il necessario per capirlo da soli.

Non è difficile, non vi preoccupate assolutamente. Se proprio doveste avere problemi allora commentate e sarò felice di spiegarvi tutto (nei limiti di tempo che ho XD)

Come al solito provate tutto dopo aver salvato e se volete scaricate i file di questa parte da Qui.

Nella prossima parte, invece, metteremo a punto tante piccole modifiche, sulla base di suggerimenti pervenuti all’autore originale della guida.

Alla prossima!

ERRATA CORRIGE:

Su segnalazione del buon Mattia evidenzio due metodi che dovete aggiungere alla classe AvoiderGame.as, altrimenti il gioco non funzionerà. Nei file scaricabili questi due metodi già ci sono, tuttavia nell’articolo mi sono sfuggiti. Aggiungete questi due metodi alla fine della classe AvoiderGame:

    public function getFinalScore():Number
    {
      return gameScore.currentValue;
    }

    public function getFinalClockTime():Number
    {
      return gameClock.currentValue;
    }

  • Share/Bookmark