Actionscript 3.0 for beginners: lesson #3
Domenica 28 Settembre, 2008Continuiamo 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:
-
/**
-
* Disegno graficamente la griglia (3x3) a video
-
*
-
* @param void
-
* @return void
-
* @private
-
*/
-
private function createGrid():void {
-
// puntatore temporaneo ad uno oggetto MovieClip
-
// nota: qui si sarebbe potuto usare anche un oggetto Sprite
-
// ma in questo caso mi serve di poter estendere l'oggetto
-
// aggiungendo alcune proproetà personali. L'oggetto Sprite
-
// è una classe chiusa e quindi non estendibile runtime, mentre
-
// la classe MovieClip è una classe dinamica e quindi rende
-
// possibile l'aggiunta di proprietà runtime
-
var tm:MovieClip, i:uint = 0;
-
// aggiungo in uno schema 3x3 i MovieClip
-
for(; i <9; i++) {
-
tm = new MovieClip();
-
addChild( tm );
-
tm.x = OFFSETX+( (i%3)*(PLAYER_WIDTH+PLAYER_OFFSET) )
-
tm.y = OFFSETY+Math.floor(i/3)*(PLAYER_HEIGHT+PLAYER_OFFSET)
-
tm._index = i;
-
drawPlayer( tm, 0 );
-
}
-
// disegno le 2 linee veriticali e le 2 orizzontali
-
with( this.graphics ) {
-
lineStyle(6,0x666666);
-
moveTo(OFFSETX,OFFSETY+(PLAYER_HEIGHT+15));
-
lineTo(OFFSETX+( (PLAYER_WIDTH+20)*3 ),OFFSETY+(PLAYER_HEIGHT+15));
-
moveTo(OFFSETX,OFFSETY+(PLAYER_HEIGHT+20)*2);
-
lineTo(OFFSETX+( (PLAYER_WIDTH+20)*3 ),OFFSETY+(PLAYER_HEIGHT+20)*2);
-
moveTo(OFFSETX+(PLAYER_WIDTH+15),OFFSETY);
-
lineTo(OFFSETX+(PLAYER_WIDTH+15),OFFSETY+( (PLAYER_HEIGHT+20)*3 ));
-
moveTo(OFFSETX+(PLAYER_WIDTH+20)*2,OFFSETY);
-
lineTo(OFFSETX+(PLAYER_WIDTH+20)*2,OFFSETY+( (PLAYER_HEIGHT+20)*3 ));
-
}
-
}
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.
-
/**
-
* Disegna un cerchio o una croce in base al giocatore
-
*
-
* @param (movieclip) p=MovieClip dove disegnare
-
* @param (uint) pl=numero del giocatore: 1 o 2 - se 0 disegna un rettangolo per intercettare l'evento click
-
*/
-
private function drawPlayer(p:MovieClip, pl:uint):void {
-
switch(pl) {
-
// questo è un caso particolare: viene disegnato un rettangolo
-
// usato per rilevare il click del mouse
-
case 0:
-
with(p.graphics) {
-
clear();
-
beginFill(CELL_EVENT_COLOR, CELL_EVENT_ALPHA);
-
drawRect(0,0,60,60);
-
endFill();
-
}
-
p.useHandCursor = p.buttonMode = true;
-
// aggiungo l'evento click da questa casella
-
p.addEventListener( MouseEvent.CLICK, onCellClick );
-
break;
-
// player 1 (o)
-
case 1:
-
with(p.graphics) {
-
clear();
-
lineStyle(PLAYER_LINE_WIDTH, PLAYER_1_COLOR);
-
drawCircle(30,30,30);
-
}
-
p.useHandCursor = p.buttonMode = false;
-
// rimuovo l'evento click da questa casella
-
p.removeEventListener(MouseEvent.CLICK, onCellClick);
-
break;
-
// player 2 (x)
-
case 2:
-
with(p.graphics) {
-
clear();
-
lineStyle(PLAYER_LINE_WIDTH, PLAYER_2_COLOR);
-
moveTo(0,0);
-
lineTo(60,60);
-
moveTo(60,0);
-
lineTo(0,60);
-
}
-
p.useHandCursor = p.buttonMode = false;
-
// rimuovo l'evento click da questa casella
-
p.removeEventListener(MouseEvent.CLICK, onCellClick);
-
break;
-
}
-
}
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():
-
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:
-
/**
-
* Questo evento viene rilasciato quando si fa click su una cella di gioco
-
*/
-
private function onCellClick(e:MouseEvent = null):void {
-
// controllo che il gioco non sia in pausa o bloccato
-
if( !__stop ) {
-
// incremento il contatore dei click
-
__clickNumber++;
-
// prelevo il puntatore al player "cliccato"
-
var p:MovieClip = e.currentTarget as MovieClip;
-
// disegno (o) o (x)
-
drawPlayer( p, __player );
-
// riflette la giocata nell'array lineare
-
__cell[p._index] = (__player==1)?PLAYER_1_WIN:PLAYER_2_WIN;
-
// controllo se qualcuno ha vinto
-
checkCell();
-
// cambio turno: se ha giocato il player 1 imposto il player 2 e viceversa
-
__player = (__player==1)?2:1;
-
// segnalo a video il nuovo turno del giocatore
-
turno_txt.text = "PLAYER "+__player;
-
}
-
}
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:
-
__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:
-
/**
-
* Questa funzione controlla l'array per verificare se qualche
-
* giocatore ha vinto. Viene chiamata ogni volta che un giocatore
-
* segna una casella con una (x) o un (o).
-
* Inoltre se la variabile __clickNumber è uguale a 9, significa
-
* che tutte le caselle sono stati riempite e, non essendoci nessun
-
* vincitore, nessuno ha vinto!
-
*
-
* @private
-
*/
-
private function checkCell():void {
-
// in base al valore di __player viene impostato il
-
// valore di controllo per verificare una vincita
-
var winValue:uint = (__player==1)?3*PLAYER_1_WIN:3*PLAYER_2_WIN;
-
// controlla tutte le righe, colonne e le due diagonali
-
var c:Array = __cell;
-
// controllo le prime 3 righe
-
if( c[0] + c[1] + c[2] == winValue ||
-
c[3] + c[4] + c[5] == winValue ||
-
c[6] + c[7] + c[8] == winValue ||
-
// le 3 colonne
-
c[0] + c[3] + c[6] == winValue ||
-
c[1] + c[4] + c[7] == winValue ||
-
c[2] + c[5] + c[8] == winValue ||
-
// le 2 diagonali
-
c[0] + c[4] + c[8] == winValue ||
-
c[2] + c[4] + c[6] == winValue ) {
-
// se una di queste condizioni è verificata
-
// qualcuno ha vinto e mostro quindi il pannello
-
// di "vittoria" (1)
-
showPanel(1);
-
} else {
-
// se nessuno ha vinto, controllo se tutte le caselle
-
// sono piene. In caso affermativo mostro il pannello
-
// di fine partita e "nessun vincitore" (0)
-
if( __clickNumber == 9 ) {
-
showPanel(0);
-
}
-
}
-
}
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.



















Lascia un commento