Actionscript 3.0 for beginners: lesson #3

Domenica 28 Settembre, 2008

Continuiamo l'analisi dell'esempio del gioco Tic Tac Toe, presentato in Actionscript 3.0 for beginners: lesson #2. Eravamo arrivati alla funzione che crea la griglia di gioco:

Actionscript:
  1. /**
  2. * Disegno graficamente la griglia (3x3) a video
  3. *
  4. * @param        void
  5. * @return       void
  6. * @private
  7. */
  8. private function createGrid():void {
  9.     // puntatore temporaneo ad uno oggetto MovieClip
  10.     // nota: qui si sarebbe potuto usare anche un oggetto Sprite
  11.     // ma in questo caso mi serve di poter estendere l'oggetto
  12.     // aggiungendo alcune proproetà personali. L'oggetto Sprite
  13.     // è una classe chiusa e quindi non estendibile runtime, mentre
  14.     // la classe MovieClip è una classe dinamica e quindi rende
  15.     // possibile l'aggiunta di proprietà runtime
  16.     var tm:MovieClip, i:uint = 0;
  17.     // aggiungo in uno schema 3x3 i MovieClip
  18.     for(; i <9; i++) {
  19.         tm                    = new MovieClip();
  20.         addChild( tm );
  21.         tm.x                  = OFFSETX+( (i%3)*(PLAYER_WIDTH+PLAYER_OFFSET) )
  22.         tm.y                  = OFFSETY+Math.floor(i/3)*(PLAYER_HEIGHT+PLAYER_OFFSET)
  23.         tm._index             = i;
  24.         drawPlayer( tm, 0 );
  25.     }
  26.     // disegno le 2 linee veriticali e le 2 orizzontali
  27.     with( this.graphics ) {
  28.         lineStyle(6,0x666666);
  29.         moveTo(OFFSETX,OFFSETY+(PLAYER_HEIGHT+15));
  30.         lineTo(OFFSETX+( (PLAYER_WIDTH+20)*3 ),OFFSETY+(PLAYER_HEIGHT+15));
  31.         moveTo(OFFSETX,OFFSETY+(PLAYER_HEIGHT+20)*2);
  32.         lineTo(OFFSETX+( (PLAYER_WIDTH+20)*3 ),OFFSETY+(PLAYER_HEIGHT+20)*2);
  33.         moveTo(OFFSETX+(PLAYER_WIDTH+15),OFFSETY);
  34.         lineTo(OFFSETX+(PLAYER_WIDTH+15),OFFSETY+( (PLAYER_HEIGHT+20)*3 ));
  35.         moveTo(OFFSETX+(PLAYER_WIDTH+20)*2,OFFSETY);
  36.         lineTo(OFFSETX+(PLAYER_WIDTH+20)*2,OFFSETY+( (PLAYER_HEIGHT+20)*3 ));
  37.     }
  38. }

Questo meotdo svolge due compiti: aggiunge un MovieClip usato per intercettare il click del mouse (la casella "cerchio" o "croce") e disegna le due righe verticali e le due orizzontali rappresentati della graglia (se classiche stanghezza che si fanno con la matita). Come indicato nel commento del metodo, è stato scelto l'oggetto MovieClip, invece del più semplice Sprite, perchè quest'ultimo non permette l'aggiunta di proprietà o metodi in fase di runtime.
Dopo la creazione del MovieClip viene chiamata una speciale funzione drawPlayer() che ha il compito di disegnare sul MovieClip vuoto appena creato uno dei giocatori (la casella "cerchio" o "croce"), in base al secondo parametro passato nel Inputs.

Actionscript:
  1. /**
  2. * Disegna un cerchio o una croce in base al giocatore
  3. *
  4. * @param    (movieclip)        p=MovieClip dove disegnare
  5. * @param    (uint)            pl=numero del giocatore: 1 o 2 - se 0 disegna un rettangolo per intercettare l'evento click
  6. */
  7. private function drawPlayer(p:MovieClip, pl:uint):void {
  8.     switch(pl) {
  9.         // questo è un caso particolare: viene disegnato un rettangolo
  10.         // usato per rilevare il click del mouse
  11.         case 0:
  12.             with(p.graphics) {
  13.                 clear();
  14.                 beginFill(CELL_EVENT_COLOR, CELL_EVENT_ALPHA);
  15.                 drawRect(0,0,60,60);
  16.                 endFill();
  17.             }
  18.             p.useHandCursor = p.buttonMode = true;
  19.             // aggiungo l'evento click da questa casella
  20.             p.addEventListener( MouseEvent.CLICK, onCellClick );
  21.             break;
  22.         // player 1 (o)
  23.         case 1:
  24.             with(p.graphics) {
  25.                 clear();
  26.                 lineStyle(PLAYER_LINE_WIDTH, PLAYER_1_COLOR);
  27.                 drawCircle(30,30,30);
  28.             }
  29.             p.useHandCursor = p.buttonMode = false;
  30.             // rimuovo l'evento click da questa casella
  31.             p.removeEventListener(MouseEvent.CLICK, onCellClick);
  32.             break;
  33.         // player 2 (x)   
  34.         case 2:
  35.             with(p.graphics) {
  36.                 clear();
  37.                 lineStyle(PLAYER_LINE_WIDTH, PLAYER_2_COLOR);
  38.                 moveTo(0,0);
  39.                 lineTo(60,60);
  40.                 moveTo(60,0);
  41.                 lineTo(0,60);
  42.             }
  43.             p.useHandCursor = p.buttonMode = false;
  44.             // rimuovo l'evento click da questa casella
  45.             p.removeEventListener(MouseEvent.CLICK, onCellClick);
  46.             break;
  47.     }
  48. }

Il case 0 corrisponde alla casella vuota. Questa circostanza si verifica all'inizializzazione del gioco: si veda infatti la chiamata a drawPlayer() nel metodo createGrid():

Actionscript:
  1. drawPlayer( tm, 0 );

In questa circostanza la casella è pronta a rispondere agli input utente. Viene infatti aggiunto un listener per intercettare l'evento click del mouse. Notare che quando viene disegnato uno dei due giocatori (caso 1 e 2, giocatore "cerchio" e "croce"), il listener viene semplicemente rimosso, così da evitare una "doppia giocata"!

Eventi

Come abbiamo visto sopra, la casella "vuota" risponde all'evento click del mouse:

Actionscript:
  1. /**
  2. * Questo evento viene rilasciato quando si fa click su una cella di gioco
  3. */
  4. private function onCellClick(e:MouseEvent = null):void {
  5.     // controllo che il gioco non sia in pausa o bloccato
  6.     if( !__stop ) {
  7.         // incremento il contatore dei click
  8.         __clickNumber++;
  9.         // prelevo il puntatore al player "cliccato"
  10.         var p:MovieClip = e.currentTarget as MovieClip;
  11.         // disegno (o) o (x)
  12.         drawPlayer( p, __player );
  13.         // riflette la giocata nell'array lineare
  14.         __cell[p._index] = (__player==1)?PLAYER_1_WIN:PLAYER_2_WIN;
  15.         // controllo se qualcuno ha vinto
  16.         checkCell();
  17.         // cambio turno: se ha giocato il player 1 imposto il player 2 e viceversa
  18.         __player = (__player==1)?2:1;
  19.         // segnalo a video il nuovo turno del giocatore
  20.         turno_txt.text = "PLAYER "+__player;
  21.     }
  22. }

Il flag __stop, che corrisponde ad una variabile globale all'interno della nostra classe, è una tecnica standard che consente di controllare lo stato del gioco. Nel nostro caso l'ho usata per distinguere la modalità "gioco" __stop = false, e la modalità "in pausa" __stop = true. Quando scatta l'evento onCellClick(), al click del mouse sulla casella, controllo appunto che il gioco non sia "in pausa". Se stiamo giocando incremento la variabile __clickNumber che tiene conto del numero di click (o di giocate) effettuate. Questo "contatore" ci tornerà utile più avanti per capire se tutte le caselle sono state selezionate.
Tramite la proprietà e.currentTarget recupero il puntatore alla casella su cui si è effettuato il click e su questa disegno uno dei due possibili segni ("cerchio" o "croce") in base al giocatore attivo indicato in __player; utilizzando sempre il meotdo drawPlayer(). La riga:

Actionscript:
  1. __cell[p._index] = (__player==1)?PLAYER_1_WIN:PLAYER_2_WIN;

è importante in quanto riflette la giocata nell'array logico lineare usato - come vedremo più avanti - per determinare la vincita di uno dei due giocatori. Le costanti PLAYER_1_WIN (valore 1) e PLAYER_2_WIN (valore 10) indicano nell'array lineare chi ha effettuato la giocata.

Vedi per ulteriori informazioni: Undolibrary MatrixArray: un’estensione della classe Array

checkCell(): the core

Deichiamo un paragrafo a questo metodo essendo, nel contesto di questo esempio, il vero cuore del gioco. Il metodo checkCell(), infatti, controlla se c'è stata una vincita da parte di uno dei due giocatori:

Actionscript:
  1. /**
  2. * Questa funzione controlla l'array per verificare se qualche
  3. * giocatore ha vinto. Viene chiamata ogni volta che un giocatore
  4. * segna una casella con una (x) o un (o).
  5. * Inoltre se la variabile __clickNumber è uguale a 9, significa
  6. * che tutte le caselle sono stati riempite e, non essendoci nessun
  7. * vincitore, nessuno ha vinto!
  8. *
  9. * @private
  10. */
  11. private function checkCell():void {
  12.     // in base al valore di __player viene impostato il
  13.     // valore di controllo per verificare una vincita
  14.     var winValue:uint     = (__player==1)?3*PLAYER_1_WIN:3*PLAYER_2_WIN;
  15.     // controlla tutte le righe, colonne e le due diagonali
  16.     var c:Array = __cell;
  17.     // controllo le prime 3 righe
  18.     if( c[0] + c[1] + c[2] == winValue ||
  19.         c[3] + c[4] + c[5] == winValue ||
  20.         c[6] + c[7] + c[8] == winValue ||
  21.         // le 3 colonne
  22.         c[0] + c[3] + c[6] == winValue ||
  23.         c[1] + c[4] + c[7] == winValue ||
  24.         c[2] + c[5] + c[8] == winValue ||
  25.         // le 2 diagonali
  26.         c[0] + c[4] + c[8] == winValue ||
  27.         c[2] + c[4] + c[6] == winValue ) {
  28.         // se una di queste condizioni è verificata
  29.         // qualcuno ha vinto e mostro quindi il pannello
  30.         // di "vittoria" (1)
  31.         showPanel(1);
  32.     } else {
  33.         // se nessuno ha vinto, controllo se tutte le caselle
  34.         // sono piene. In caso affermativo mostro il pannello
  35.         // di fine partita e "nessun vincitore" (0)
  36.         if( __clickNumber == 9 ) {
  37.             showPanel(0);
  38.         }
  39.     }
  40. }

Il metodo, nella sua semplicità, si commenta da solo. Esso viene richiamato ad ogni click sulla scacchiera decidendo le sorti del gioco! L'array logico viene utilizzato per "sommare" righe, colonne e diagonali alla ricerca di un possibile "tris" da parte del giocatore attuale, indicato dalla variabile __player. Inoltre, come può accadere, __clickNumber tiene conto dei click effettuati. Questa variabile non dovrebbe mai raggiungere il valore 9, a meno che nessuno dei due giocatori ha vinto.

La prossima volta esamineremo alcune caratteristiche specifiche del linguaggio Actionscript 3.0 usate in questa demo.

Post correlati

Lascia un commento

TAG XHTML permessi: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Usa <pre> per racchiudere codice