Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Creare un quiz con Actionscript 3

Vediamo, passo dopo passo, come creare una struttura di un quiz, che si interfaccia con un file XML per cambiare le domande in modo semplice e veloce
Vediamo, passo dopo passo, come creare una struttura di un quiz, che si interfaccia con un file XML per cambiare le domande in modo semplice e veloce
Link copiato negli appunti

Il quiz viene utilizzato in vari ambiti e ovviamente, con Internet, i quiz si sono espansi a macchia d'olio, ciò grazie soprattutto alla possibilità di creare delle strutture popolabili con domande prese da fonti esterne.

Utilizzando Flash CS3 e Actionscript 3 è possibile creare un filmato in grado di caricare una serie di domande e risposte, da un file XML, basterà variare la fonte per trovarci di fronte un quiz totalmente nuovo, pur mantenendo la struttura "principale" e tutte le sue caratteristiche: in pratica con una sola struttura "base" potremo caricare qualsiasi tipo di quiz, a patto ovviamente che il file XML rispetti la struttura richiesta dal filmato.

Preparazione dello stage

Il nostro quiz avrà una semplice schermata iniziale (graficamente uguale alle schermate di gioco) e una schermata finale per informare il giocatore del termine del gioco, andremo quindi a creare due fotogrammi chiave sulla linea temporale di un nuovo FLA.

Nel primo fotogramma inseriamo il pulsante per avviare il gioco (pulsante con nome istanza gioca), oltre ad eventuali elementi decorativi (titolo del quiz, logo, linee o altri elementi grafici per delimitare la domanda e dividerla dalle risposte).

Figura 1. Esempio di struttura grafica del quiz
Screenshot dello stage

La stessa struttura sarà riproposta nel secondo fotogramma, che però avrà per il pulsante una diversa etichetta (ad esempio "Gioca ancora") e nome istanza rigioca.

Creazione delle icone per le risposte

Oltre alle schermate di inizio e fine gioco avremo anche bisogno di alcuni elementi aggiuntivi (che aggiungeremo dinamicamente al nostro filmato durante l'esecuzione) e precisamente delle "icone/cursori" per le alternative (che saranno anche il metodo con cui l'utente potrà dare la sua risposta) e un clip che funzionerà da timer.

Possiamo creare la clip per le icone inserendo un nuovo simbolo (Insert -> New Symbol oppure Ctrl+F8), scegliendo come tipologia Movieclip. Poichè creeremo dinamicamente tramite Actionscript un'icona per ogni risposta andiamo ad impostare l'esportazione per Actionscript di questa clip.

Figura 2. Creazione del simbolo "Icona" e relativo linkage
Screenshot del pannello Nuovo Simbolo

Ogni icona avrà al suo interno una campo di testo dinamico (con nome istanza lettera) che utilizzeremo per dare un'identificazione alla risposta (le classiche "A", "B", "C", "D" che si vedono nei quiz) e uno sfondo, che nell'esempio è un cerchio con gli stessi colori del logo usato nel filmato.

Il testo dovrà essere di tipo single line e non essere selezionabile.

Figura 3. Il campo di testo dinamico lettera nella clip "Icona"
Screenshot dello stage

Non posizioniamo istanze di questa clip sullo stage, ma ne manteniamo solo una copia nella libreria.

Creazione della clip timer

Per quanto riguarda la creazione della clip timer, realizzeremo semplicemente un movieclip con un'animazione della durata di circa 3 secondi (ovvero il tempo che daremo all'utente per rispondere); anche in questo caso creiamo una nuova clip e ne impostiamo il linkage per Actionscript con identificativo Tempo. L'animazione può essere a piacere, il suo avanzamento verrà regolato tramite Actionscript.

Come ultima operazione impostiamo la Document Class su quiz, quindi salviamo il FLA come quiz.fla.

Figura 4. Impostazione della Document Class
Screenshot del pannello Proprieta

Impostazione della classe

Una volta predisposto lo stage passiamo al lato Actionscript: praticamente tutti gli aspetti del gioco saranno regolati dalla classe quiz.as; per prima cosa creiamo un nuovo documento Actionscript e salviamolo come quiz.as.

Le prime righe di codice da inserire nella classe sono relative ai package da importare; per il nostro quiz useremo i seguenti package:

  • flash.display.*: per l'uso delle icone, del timer e per l'estensione dell'oggetto MovieClip;
  • flash.text.*: per la creazione dei campi di testo di domande, risposte e suggerimenti;
  • flash.events.*: per gestire il caricamento del file XML delle domande, gli input dell'utente e il timer durante il gioco;
  • flash.net.URLLoader e flash.net.URLRequest: per caricare il file XML;
  • import flash.utils.Timer: per gestire il timer.

Ecco quindi il codice con cui iniziare la classe:

Listato 1. Importa i package

package {
  // importazione dei vari package
  import flash.display.*;
  import flash.text.*;
  import flash.events.*;
  import flash.net.URLLoader;
  import flash.net.URLRequest;
  import flash.utils.Timer;

  public class quiz extends MovieClip { }
}

All'interno del nostro quiz avremo diversi elementi in gioco per ogni domanda, oltre ad alcuni valori "generali" quali ad esempio il punteggio; inoltre, poichè vogliamo creare una struttura utilizzabile in diverse occasioni, sfruttiamo alcuni oggetti TextFormat per variare comodamente l'aspetto dei campi di testo relativi a domande, risposte e suggerimenti.

Di seguito è riportato l'intero elenco delle variabili da dichiarare all'inizio della classe, lo scopo di alcune di esse sarà più facilmente comprensibile nel prosieguo dell'articolo.

Listato 2. Variabili da settare

// oggetto contenente le informazioni ricavate dal file XML
private var sorgenteXML:XML;

// oggetti textformat per la formattazione dei testi
private var frmt_domanda:TextFormat;
private var frmt_risposte:TextFormat;
private var formt_suggerimento:TextFormat;

// riferimenti per i campi di testo
private var txt_messaggio:TextField;
private var txt_domanda:TextField;

// Oggetti generali del gioco
private var sprite_gioco:Sprite;
private var sprite_domanda:Sprite;
private var sprite_risposte:Sprite;
private var btn_gioco:Button;
private var btn_suggerimento:Button;
private var clip_tempo:Tempo;

// variabili del gioco
private var numero_domanda:int;
private var risposta_corretta:String;
private var domande_passate:int;
private var risposte_corrette:int;
private var arr_risposte:Array;
private var timer_domanda:Timer;
private var punti_domanda:int;
private var punti:int;

Per facilitare la divisione delle variabili abbiamo usato degli affissi tipo btn per gli oggetti di tipo Button, clip per i MovieClip, sprite per gli Sprite e così via. Non è chiaramente una pratica obbligatoria, tuttavia, avendo molte variabili da gestire può risultare comodo avere delle regole comuni per le variabili dello stesso tipo.

Una volta importati i package e dichiarate le variabili possiamo passare alla scrittura delle funzioni, tramite le quali gestiremo sia gli eventi svolti automaticamente dal sistema (ad esempio il caricamento e la scelta di ogni domanda) sia quelli conseguenti ad azioni dell'utente.

Impostare l'area di gioco

La prima funzione sarà quiz, che chiamerà a sua volta quella che sarà la funzione principale della nostra classe, ovvero impostaPartita; tale funzione si occuperà di impostare le variabili generali di gioco, di creare gli oggetti TextFormat e di mostrare il messaggio di caricamento delle domande, che sarà visibile fino al completo caricamento del file XML. Ecco il codice delle funzioni:

Listato 3. Quiz e impostapartita

public function quiz(){
  impostaPartita()
}

private function impostaPartita():void {
  // creiamo lo sprite di gioco
  sprite_gioco = new Sprite();
  addChild(sprite_gioco);
  // impostiamo i TextFormat dei vari testi
  frmt_domanda = new TextFormat("Arial",24,0x330000,true,false,false,null,null,"center");
  frmt_risposte = new TextFormat("Arial",18,0x330000,true,false,false,null,null,"left");
  frmt_suggerimento = new TextFormat("Arial",14,0x330000,true,false,false,null,null,"center");
  // creiamo il testo di caricamento domande
  txt_messaggio = creaTesto("Caricamento domande in corso...",frmt_domanda,sprite_gioco,0,200,550);
  // impostiamo le variabili generali
  numero_domanda = 0;
  domande_passate = 0;
  risposte_corrette = 0;
  punti = 0;
  
  // carichiamo le domande dal file XML
  caricaDomande();
}

impostaPartita potrà essere richiamata in seguito per iniziare un nuovo quiz senza dover chiudere e riaprire il filmato.

Per prima cosa viene creato lo sprite di gioco (sprite_gioco), che conterrà i vari elementi, quindi vengono impostati i vari TextFormat, dopo di che viene creato un campo di testo (xt_messaggio); per la creazione di quest'ultimi imposteremo una funzione di nome creaTesto che prevederà come parametri il testo da mostrare, il TextFormat da utilizzare, lo sprite dove aggiungere il testo creato, le coordinate x e y a cui posizionare il campo di testo e la sua larghezza.

Listato 4. Crea il testo

public function creaTesto(testo:String, formato:TextFormat, s:Sprite, x,y: Number, width:Number): TextField {
  // creiamo il nuovo campo di testo
  var campo_testo:TextField = new TextField();
  // lo posizioniamo
  campo_testo.x = x;
  campo_testo.y = y;
  // impostiamo la larghezza
  campo_testo.width = width;
  // settiamo il formato
  campo_testo.defaultTextFormat = formato;
  // lo rendiamo non selezionabile, multilinea e con il wordWrap
  campo_testo.selectable = false;
  campo_testo.multiline = true;
  campo_testo.wordWrap = true;
  // impostiamo l'autoSize del campo di testo in base al suo allineamento
  if (formato.align == "left") {
    campo_testo.autoSize = TextFieldAutoSize.LEFT;
  } else {
    campo_testo.autoSize = TextFieldAutoSize.CENTER;
  }
  // scriviamo il testo
  campo_testo.text = testo;
  // aggiungiamo il campo di testo allo sprite
  s.addChild(campo_testo);
  // restituiamo come oggetto il campo di testo creato
  return campo_testo;
}

Possiamo commentare il richiamo alla funzione caricaDomande (che non abbiamo ancora dichiarato) e testare il filmato per vedere il risultato. Notiamo come la scritta creata dinamicamente sia visibile nel filmato; in realtà è presente anche il testo relativo al punteggio, ma poichè al momento è ancora vuoto non è visibile sullo stage.

Figura 5. Schermata iniziale del gioco
Screenshot del filmato

Caricare il set di domande

La scritta di caricamento delle domande sarà una sorta di messaggio di precaricamento: quando il file XML sarà effettivamente stato caricato nel nostro filmato andremo a nascondere questo messaggio e inviteremo l'utente a iniziare la partita.

Analizzeremo in seguito la struttura del file caricato dal nostro quiz; per ora limitiamoci ad impostare la funzione che si occuperà di caricare il file, ovvero caricaDomande. Questa funzione sfrutterà le classi URLRequest e URLLoader per caricare nel file SWF il contenuto di domande.xml, quindi, a caricamento avvenuto (che intercetteremo grazie all'evento Event.COMPLETE), richiamerà la funzione domandeCaricate. Ecco il codice della funzione caricaDomande:

Listato 5. Funzione caricaDomande

private function caricaDomande():void{
  // impostiamo il percorso del file
  var url_file:URLRequest = new URLRequest("domande.xml")
  // carichiamo il file
  var carica_file:URLLoader = new URLLoader(url_file)
  // una volta completato il caricamento avviamo la funzione domandeCaricate
  carica_file.addEventListener(Event.COMPLETE,domandeCaricate)
}

Scopo di domandeCaricate sarà, invece, memorizzare le domande dal file XML e informare l'utente che può iniziare a giocare. Per rendere il gioco più longevo utilizzeremo un XML composto da un certo numero di domande e risposte ma, per ogni partita, ne estrarremo solo alcune; in questo modo anche con uno stesso set di domande l'utente potrebbe trovarsi con quiz differenti tra loro; di questo si occuperà la funzione scegliDomande, che analizzeremo più avanti.

Di seguito è possibile vedere il codice della funzione domandeCaricate.

Listato 6. Codice della funzione domandeCaricate

private function domandeCaricate(evt:Event):void{
  // memorizziamo i dati del file XML
  var dati_xml = XML(evt.target.data)
  // scegliamo 5 domande tra quelle presenti nel file
  sorgenteXML = scegliDomande(dati_xml,5)
  // rimuoviamo il messaggio di caricamento
  sprite_gioco.removeChild(txt_messaggio)
  // creiamo un nuovo messaggio che sostituisca il precedente
  txt_messaggio = creaTesto("Premi il pulsante e inizia a giocare!",frmt_domanda,sprite_gioco,0,200,550);
  // abilitiamo il pulsante "gioca"
  gioca.addEventListener(MouseEvent.CLICK,avviaGioco)
}

Scegliere le domande per la partita

Ad ogni esecuzione del gioco verranno scelte 5 domande tra quelle presenti nel file XML; per eseguire la scelta sfrutteremo le possibilità date dallo standard E4X nella lettura dei file XML, argomento su cui è presente un articolo in questo sito.

Prima di vedere come estrarre casualmente le domande, per ogni partita, è però necessario stabilire la struttura da utilizzare nel file XML.

Struttura del file XML

Come abbiamo detto, il nostro quiz prevederà una domanda con 4 alternative e ci sarà per ogni domanda la possibilità di avere un suggerimento; possiamo facilmente intuire che la domanda, le sue risposte e il suggerimento andranno contenute all'interno di uno stesso oggetto, ma separate tra loro. Avremo quindi una struttura del tipo:

  • oggetto
    • domanda
    • risposte
    • suggerimento
  • fine oggetto

Il file XML conterrà poi più "oggetti", uno per ogni domanda.

Poiché le possibili risposte saranno 4, può essere una buona idea dividere l'oggetto "risposte" in 4 sotto-elementi, uno per ogni alternativa:

  • oggetto
    • domanda
    • risposte
      • risposta
      • risposta
      • risposta
      • risposta
    • suggerimento
  • fine oggetto

Traducendo questa struttura in tag XML, avremmo:

<oggetto>
  <domanda>...</domanda>
  <risposte>
    <risposta>...</risposta>
    <risposta>...</risposta>
    <risposta>...</risposta>
    <risposta>...</risposta>
  </risposte>
  <suggerimento>...</suggerimento>
</oggetto>

Per comodità identificheremo la risposta corretta in base alla sua posizione nel file XML, quindi la prima risposta presente nel file sarà sempre quella corretta.

Una volta stabilita la struttura per ogni domanda possiamo facilmente creare l'intero file XML: di seguito è riportato il codice del file usato nell'esempio:

Listato 7. Struttura del file XML

<quiz>
  <oggetto>
    <domanda>In che anno è nato Roberto Baggio?</domanda>
    <risposte>
      <risposta>1967</risposta>
      <risposta>1971</risposta>
      <risposta>1963</risposta>
      <risposta>1969</risposta>
    </risposte>
    <suggerimento>Ha più di 40 anni</suggerimento>
  </oggetto>
  
  <oggetto>
    <domanda>In che giorno fu ucciso Giulio Cesare?</domanda>
    <risposte>
      <risposta>15 Marzo</risposta>
      <risposta>18 Febbraio</risposta>
      <risposta>3 Aprile</risposta>
      <risposta>5 Maggio</risposta>
    </risposte>
    <suggerimento>Le famose Idi di....</suggerimento>
  </oggetto>
  
  ..//
  
  <oggetto>
    <domanda>Quale tag HTML apre una lista puntata ?</domanda>
    <risposte>
      <risposta><ul></risposta>
      <risposta><li></risposta>
      <risposta><p></risposta>
      <risposta><list></risposta>
    </risposte>
    <suggerimento><li> viene usato per gli elementi della lista</suggerimento>
  </oggetto>
</quiz>

Ora che abbiamo visto la struttura del file possiamo proseguire, analizzando le funzioni che andranno a interagire con i dati caricati da questo file (che nell'esempio si chiama domande.xml)

La funzione scegliDomande

Analizziamo ora la funzione scegliDomande, che con i commenti e dopo aver visto la struttura del file dovrebbe risultare facilmente comprensibile:

Listato 8. Sceglie la domanda

private function scegliDomande(sorgente:XML,quante:int):XML{
  // creiamo l'oggetto XML che conterrà le domande scelte
  var domande_scelte:XML = <quiz></quiz>;
  // finché non abbiamo abbastanza domande, eseguiamo il ciclo
  while(domande_scelte.child("*").length() < quante) {
    // scegliamo una domanda casuale e la copiamo nel nostro XML
    var casuale:int = Math.floor(Math.random()*sorgente.child("*").length());
    domande_scelte.appendChild(sorgente.oggetto[casuale].copy());
    // rimuoviamo la domanda scelta dall'XML sorgente, per evitare doppioni
    delete sorgente.oggetto[casuale];
  }
  // restituiamo l'oggetto XML popolato con le domande scelte
  return domande_scelte;
}

Per prima cosa creiamo un nuovo oggetto XML, domande_scelte: al suo interno inseriremo solamente le domande estrapolate dal file XML completo (che viene passato con il parametro sorgente alla funzione). Tramite un ciclo while facciamo sì che finché le domande sono minori di quelle necessarie venga estratta una domanda casuale; otteniamo tale estrazione andando a generare un numero casuale compreso tra zero a il numero di domande presenti in sorgente: ad ogni estrazione la domanda selezionata viene prima copiata da sorgente a domande_scelte, quindi viene rimossa per evitare la presenza di doppioni.

Una volta che il numero di domande estratte sarà pari a quello richiesto, l'oggetto domande_scelte verrà restituito dalla funzione e quindi nel nostro caso associato alla variabile sorgenteXML.

Avviare il gioco

Quando l'oggetto contenente le domande è pronto, possiamo far partire il gioco vero e proprio, mostrando la prima domanda al giocatore.

Di questo si occuperà la funzione avviaGioco, che abbiamo precedentemente associato alla pressione del pulsante gioca e che andrà a rimuovere dallo stage sia il tasto gioca che il messaggio di avvio partita (txt_messaggio), quindi richiamerà una ulteriore funzione (poniDomanda) che si occuperà di mostrare le varie domande al giocatore e che utilizzeremo quindi per tutto il gioco.

Ecco il codice della funzione avviaGioco:

Listato 9. Avvia il gioco

private function avviaGioco(evt:Event){
  // rimuoviamo il bottone "gioca"
  removeChild(gioca);
  // rimuoviamo il messaggio di avvio partita
  sprite_gioco.removeChild(txt_messaggio);
  poniDomanda()
}

Mostrare le domande

La funzione poniDomanda è sicuramente tra le principali del nostro sistema: essa, infatti, si occuperà di creare la domanda e le risposte e di impostare gli eventi, sia quelli relativi all'interazione con l'utente (richiesta di suggerimento o tentativo di dare la risposta) che quelli automatici (gestione del timer per la risposta).

Anche poniDomanda sarà "supportata" da altre funzioni che assoceremo a determinate operazioni ed eventi, ma possiamo sicuramente considerarla il gestore principale di tutte le domande del nostro quiz.

Per prima cosa la funzione dovrà memorizzare la domanda attuale (il numero della domanda da mostrare è memorizzato nella variabile numero_domanda), quindi ricavare le risposte alla domanda. La domanda e le risposte verranno mostrate in alcuni sprite che andremo a creare in questa funzione.

Listato 10. Prima parte della funzione poniDomanda

private function poniDomanda():void{
  // creiamo un nuovo sprite dove mostrare la domanda
  sprite_domanda = new Sprite();
  sprite_gioco.addChild(sprite_domanda);
  // creiamo il campo di testo contenente la domanda
  var domanda_attuale:String = sorgenteXML.oggetto[numero_domanda].domanda;
  txt_domanda = creaTesto(domanda_attuale,frmt_domanda,sprite_domanda,0,100,550);
  // creiamo uno sprite per le risposte, memorizziamo quella corretta a parte
  sprite_risposte = new Sprite();
  risposta_corretta = sorgenteXML.oggetto[numero_domanda].risposte.risposta[0];
  // memorizziamo tutte le risposte alla domanda
  arr_risposte = new Array(sorgenteXML.oggetto[numero_domanda].risposte.risposta[0],sorgenteXML.oggetto[numero_domanda].risposte.risposta[1],sorgenteXML.oggetto[numero_domanda].risposte.risposta[2],sorgenteXML.oggetto[numero_domanda].risposte.risposta[3]);

Notiamo l'utilizzo della struttura del file XML per ricavare la domanda (sorgenteXML.oggetto[numero_domanda].domanda;)) e le risposte (sorgenteXML.oggetto[numero_domanda].risposte.risposta[x], dove x è il numero della risposta, nel nostro esempio da 0 a 3).

Una volta ricavata la domanda e le risposte (memorizzando a parte quella corretta) possiamo creare i vari campi di testo e le icone, andandoli a disporre sullo stage e possiamo impostare i punti a disposizione per la domanda:

Listato 11. seconda parte della funzione

  // creiamo gli sprite per le risposte
  var posX = 20
  var posY = 200
  for(var i:int=0;i<arr_risposte.length;i++) {
    // memorizziamo il testo della risposta corrente
    var risposta:String = arr_risposte[i];
    // creiamo uno sprite per la risposta
    var sprite_risposta:Sprite = new Sprite();
    // prepariamo la lettera (A, B, C o D) per l'icona
    var lettera_risposta:String = String.fromCharCode(65+i);
    // scriviamo il testo della risposta
    var txt_risposta:TextField = creaTesto(risposta,frmt_risposte,sprite_risposta,60,10,450);
    // creiamo l'icona
    var icona:Icona = new Icona();
    icona.lettera.text = lettera_risposta;
    // posizioniamo lo sprite della risposta
    sprite_risposta.x = posX;
    sprite_risposta.y = posY;
    posX += 230
    if(i == 1){
      posX = 20
      posY += 80
    }
    // aggiungiamo l'icona nello sprite della risposta
    sprite_risposta.addChild(icona);
    // rendiamo lo sprite cliccabile come bottone
    sprite_risposta.addEventListener(MouseEvent.CLICK,rispostaCliccata);
    sprite_risposta.buttonMode = true;
    // aggiungiamo lo sprite della riposta allo sprite "sprite_risposte"
    sprite_risposte.addChild(sprite_risposta);
  }
  // aggiungiamo lo sprite delle risposte nello sprite "sprite_domanda"
  sprite_domanda.addChild(sprite_risposte);
  
  // impostiamo i punti a disposizione per la domanda
  punti_domanda = 100;

Per ogni risposta dell'array arr_risposte andiamo a creare uno sprite (sprite_risposta) che conterrà a sua volta l'icona e il testo; tutti gli sprite delle singole risposte saranno inseriti dentro sprite_risposte che sarà a sua volta posizionato all'interno di sprite_domanda.

Ogni icona delle risposte viene resa cliccabile e quando cliccata richiamerà la funzione rispostaCliccata.

Qualora volessimo testare il filmato potremmo commentare la riga sprite_risposta.addEventListener(MouseEvent.CLICK,rispostaCliccata); (dato che non abbiamo ancora dichiarato la funzione Flash ci restituirebbe un errore), quindi premere Ctrl+Invio.

Figura 6. Domanda caricata nel filmato
Screenshot del filmato

Il codice per mostrare domanda e risposte è completo, ma noi vogliamo inserire nel nostro quiz anche un timer e la possibilità per il giocatore di ricevere un suggerimento: andremo quindi ad aggiungere sullo stage un'istanza della clip Tempo che abbiamo creato nel nostro file FLA, inoltre aggiungeremo dinamicamente anche un pulsante per richiedere il suggerimento.

Listato 12. Aggiunge tempo e suggerimento

// creiamo l'istanza della clip Tempo
clip_tempo = new Tempo();
// lo fermiamo al primo fotogramma
clip_tempo.stop()
clip_tempo.x = 100;
clip_tempo.y = 380;
// lo aggiungiamo a sprite_domanda
sprite_domanda.addChild(clip_tempo);
// creiamo il timer
timer_domanda = new Timer(500,20);
// a ogni ripetizione del timer chiamiamo la funzione aggiornaTimer
timer_domanda.addEventListener(TimerEvent.TIMER,aggiornaTimer);
// avviamo il timer
timer_domanda.start();

// creiamo il bottone per il suggerimento
btn_suggerimento = new Button();
// ne impostiamo la label su "Aiuto"
btn_suggerimento.label = "Aiuto";
// lo posizioniamo
btn_suggerimento.x = 220;
btn_suggerimento.y = 350;
// e lo inseriamo nello sprite di gioco
sprite_gioco.addChild(btn_suggerimento);
// quando clicato, richiamerà la funzione mostraSuggerimento
btn_suggerimento.addEventListener(MouseEvent.CLICK,mostraSuggerimento);

Il timer andrà a richiamare la funzione aggiornaTimer, che si occuperà di mandare la clip al fotogramma desiderato (così da mostrare all'utente il tempo residuo per rispondere): poiché il nostro clip è composto da 20 fotogrammi e vogliamo dare 10 secondi di tempo per rispondere facciamo sì che il timer venga richiamato 20 volte, una ogni mezzo secondo (500 millisecondi). Una volta scaduto il tempo informeremo l'utente e mostreremo un pulsante per passare alla domanda seguente (di questo si occuperà la funzione fineDomanda, che analizzeremo a breve).

Listato 13. Aggiorna il timer

private function aggiornaTimer(evt:Event):void{
  // mandiamo la clip al fotogramma corrispondente al numero di ripetizioni del timer
  clip_tempo.gotoAndStop(evt.target.currentCount)
  // se il tempo è scaduto
  if (evt.target.currentCount == evt.target.repeatCount) {
    // avvisiamo l'utente
    txt_messaggio = creaTesto("Tempo scaduto!",frmt_domanda,sprite_gioco,0,180,550);
    // e consideriamo conclusa la domanda
    fineDomanda();
  }
}

Per quanto riguarda la funzione mostraSuggerimento, questa semplicemente si occuperà di ricavare la frase di aiuto dal file XML e la mostrerà al giocatore, dando però una "penalità" eliminando 30 punti da quelli a disposizione per la domanda. Il pulsante per il suggerimento verrà rimosso e sarà sostituito dalla frase di aiuto. Ecco il codice:

Listato 14. Mostra il suggerimento

private function mostraSuggerimento(evt:Event):void{
  // eliminiamo il bottone di aiuto
  sprite_gioco.removeChild(btn_suggerimento);
  btn_suggerimento = null;
  // diminuiamo i punti in palio
  punti_domanda -= 30;
  // ricaviamo il suggerimento
  var testo_suggerimento:String = sorgenteXML.oggetto[numero_domanda].suggerimento;
  // e lo mostriamo al giocatore
  var txt_suggerimento:TextField = creaTesto(testo_suggerimento,frmt_suggerimento,sprite_domanda,0,340,550);
}

Figura 7. Domanda con timer e tasto di aiuto
Screenshot del filmato

Analizzare la risposta dell'utente

Quando l'utente clicca su una delle risposte dobbiamo confrontare l'alternativa da lui scelta con la risposta corretta (memorizzata, ricordiamo, nella variabile risposta_corretta). In caso di risposta esatta andremo a incrementare il punteggio e ci complimenteremo con il giocatore, altrimenti lo informeremo che la sua risposta è sbagliata. In entrambi i casi considereremo conclusa la domanda, richiamando la funzione fineDomanda.

Listato 15. Restitusce un feedback all'utente

public function rispostaCliccata(evt:MouseEvent):void {
  // ricaviamo la risposta scelta
  var risposta_scelta = evt.currentTarget.getChildAt(0).text;
  // se la risposta è corretta
  if (risposta_scelta == risposta_corretta) {
    // aumentiamo le risposte esatte
    risposte_corrette++;
    // informiamo l'utente
    txt_messaggio = creaTesto("Risposta esatta!",frmt_domanda,sprite_gioco,0,180,550);
    // aumentiamo i punti
    punti += punti_domanda;
  }else{ // se la risposta è errata
    // informiamo l'utente
    txt_messaggio = creaTesto("Risposta errata :(",frmt_domanda,sprite_gioco,0,180,550);
  }
  // consideriamo conclusa la domanda
  fineDomanda();
}

Vediamo allora il codice della funzione fineDomanda, che viene richiamata anche in caso di tempo scaduto. Questa funzione si occuperà molto semplicemente di rimuovere gli elementi visivi relativi alla domanda appena conclusa e di mostrare un pulsante che permetta all'utente di passare alla domanda successiva. Ecco il codice:

Listato 16. Termina la domanda

private function fineDomanda():void{
  // per ogni risposta...
  for(var i:int=0;i<4;i++) {
    // eliminiamo il listener relativo al click
    sprite_risposte.getChildAt(i).removeEventListener(MouseEvent.CLICK,rispostaCliccata);
    // rendiamo invisibile lo sprite
    sprite_risposte.getChildAt(i).visible = false;
  }
  // se presente, rimuoviamo il pulsante di suggerimento
  if (btn_suggerimento != null) {
    sprite_gioco.removeChild(btn_suggerimento);
  }
  // fermiamo il timer
  timer_domanda.stop();
  // impostiamo il numero di domanda
  numero_domanda++;
  // impostiamo il numero di domande a cui si è risposto
  domande_passate++;
  // creiamo il bottone per proseguire
  var btn_continua = new Button()
  btn_continua.label = "Prosegui"
  btn_continua.x = 220
  btn_continua.y = 250
  sprite_gioco.addChild(btn_continua)
  btn_continua.addEventListener(MouseEvent.CLICK,prossimaDomanda)
}

Passare alla domanda successiva

Notiamo per il pulsante btn_continua il richiamo alla funzione prossimaDomanda: questa è una funzione molto importante in quanto controllerà il numero di domande a cui si è già risposto e controllerà quindi se si è risposto all'ultima domanda: in questo caso manderà la timeline al fotogramma di fine gioco e mosterà i punti ottenuti dal giocatore.

Listato 17. Passa alla domanda successiva

private function prossimaDomanda(evt:MouseEvent):void{
  // rimuoviamo la domanda
  sprite_gioco.removeChild(sprite_domanda)
  // rimuoviail il bottone "continua"
  sprite_gioco.removeChild(evt.target as DisplayObject)
  // rimuoviamo il testo informativo
  sprite_gioco.removeChild(txt_messaggio)
  // se abbiamo esaurito le domande
  if(numero_domanda > 4){
    // il gioco è finito
    fineGioco()
  }else{
    // facciamo la prossima domanda
    poniDomanda()
  }
}

Fine del gioco: mostrare i punti

Abbiamo impostato il rilevamento della fine del gioco, quindi ora non ci resta che decidere cosa mostrare all'utente una volta conclusa la partita; innanzitutto manderemo la linea temporale al secondo fotogramma, quindi creeremo un campo di testo con il riepilogo dei punti ottenuti e delle risposte esatte. Andremo poi a impostare la funzione per l'avvio di una nuova partita, funzione che useremo tramite la pressione del pulsante rigioca, a cui andremo ad associare l'evento.

Listato 18. Funzione fine gioco

private function fineGioco():void{
  gotoAndStop(2)
  txt_messaggio = creaTesto("Hai ottenuto " + punti + " punti rispondendo correttamente a " + risposte_corrette + " domande", frmt_domanda, sprite_gioco, 0, 180, 550)
}

Figura 8. Schermata di fine partita
Screenshot del filmato

Ti consigliamo anche