Un puzzle in HTML5 e createJS con Adobe Animate

5
Share:

Cliccando questo link trovate un puzzle in HTML5 e createJS. Si tratta di un instant game molto semplice – in questa prima versione non ancora ottimizzato per i dispositivi mobili – che inaugura una nuova categoria di argomenti presente nella mia miniguida su createJS.
Ad essere sincero, quando qualche annetto fa i primi games in HTML5 e Javascript iniziarono a fare capolino sul web, non mi convinsero più di tanto. Non tutti i browser erano perfettamente compatibili e non mancava qualche problema di prestazione. Ma con il tempo ho cambiato idea. Chiaramente, un gioco gestito da un plugin allo stato attuale resta superiore in termini di performance, ma con il passare del tempo le differenze si stanno velocemente assottigliando  e sempre più spesso mi capita di vedere in giro dei giochi HTML5 che mai avrei reputato possibili fino a qualche tempo fa. Anzi per dirla tutta, molte volte se prima non guardo il codice, non riesco a distinguere i giochi HTML5 dagli altri.
Tornando al nostro articolo, dopo aver illustrato gli eventi, la classe Tween, il trascinamento interattivo e le collisioni, abbiamo tutti gli elementi per realizzare un giochino per il web: vediamo come.

Come funziona

Il gioco prevede un meccanismo iniziale che mostra una foto, la scompone in 24 pezzi che colloca al centro dello stage e infine li rimescola in modo casuale. Il giocatore dovrà quindi agganciare i vari pezzi e ricollocarli nella corretta posizione.
Chiaramente, si tratta solo di una bozza di instant game. Un vero puzzle per essere completo dovrebbe prevedere una difficoltà crescente. Ad esempio quadri più complessi da affrontare strada facendo o un limite di tempo entro il quale ricomporre i pezzi. Inoltre mancano gli effetti sonori, una musica in sottofondo, qualche effetto visivo da mostrare ad ogni aggancio e altre piccole note coreografiche. Infine, dettaglio non secondario, esistono vari modi di impostare un puzzle. Ad esempio, nel mio caso ho scelto la “modalità semplice”, quella in cui i pezzi non si incastrano tra di loro ovunque, ma sono collocabili uno alla volta su un’area ben precisa. Tuttavia, se fate un giretto online, ne troverete molti in cui gli oggetti si agganciano fra di loro in qualunque punto dello stage. Alla luce di queste considerazioni, ho una mezza idea di riprendere il gioco più avanti per aggiungere altre funzionalità man mano che procedo con la guida.

La grafica del gioco

Poiché stiamo usando Animate, la creazione del gioco implica una lavorazione grafica WYSIWYG. Prima di tutto dobbiamo scegliere un’immagine e suddividerla nei vari elementi. Ci sono molti modi per ottenere questo risultato, per cui il metodo che illustro di seguito e solo uno tra i tanti.
Il primo passo consiste nel procurarsi (o creare) un disegno vettoriale che contenga i vari pezzi del puzzle sotto forma di griglia. Se fate una ricerca in rete dovreste trovarne parecchi free da adattare alle vostre esigenze. Tra i sorgenti che è possibile scaricare alla fine dell’articolo ho predisposto anche un file denominato grafica, dove trovate tutti gli elementi per costruire i pezzi da zero. In ogni caso ecco gli step da seguire:

  1. Una volta predisposta la griglia al centro dello stage, bisogna collocare in un livello sottostante una foto che abbia le stesse dimensioni (volendo si può anche ragionare al contrario, si parte dalla foto e si adatta il puzzle). Non dimenticate che la griglia vettoriale deve essere settata in “modalità divisa”: così facendo sarà possibile usarla per tagliare gli oggetti che a loro volta sono stati divisi tramite sovrapposizione. puzzle_fig1

     

  2. Selezionate il fotogramma che contiene il disegno vettoriale e tagliatelo da Modifica > Taglia.
  3. Cliccate sul fotogramma che contiene la foto e trasformate quast’ultima in una bitmap divisa tramite l’opzione Elabora > Dividi.
  4. A questo punto incollate sulla foto il disegno vettoriale tagliato in precedenza tramite Modifica > Incolla in posizione. In questo modo avrete la griglia vettoriale sovrapposta alla foto in un unico livello.
  5. La sovrapposizione tra i due elementi divisi rende ogni singola area selezionabile separatamente. Fate clic sulla parte centrale del primo pezzo in alto a sinistra e convertitelo in clip filmato. dategli come nome simbolo e nome di istanza pezzo1puzzle_fig2

     

  6. Doppio clic sul simbolo per accedere alla linea temporale interna, quindi usate lo strumento Bottiglia di inchiostro per attribuirgli una cornice nera.
  7. Tornale sulla scena principale. Se provate a spostare il clip in punto qualsiasi dello stage, scoprirete di avere creato il primo pezzo del puzzle.
  8. A questo punto bisogna ripetere i passi 5 , 6 e 7 per 24 volte (una per ogni pezzo del puzzle). Lo so è una bella rottura di scatole, ma personalmente non ho trovato metodi più veloci di questo.

Una volta creati i 24 pezzi del puzzle, selezionate la griglia vettoriale e cancellatela. Adesso abbiamo l’occorrente per cominciare.

La struttura del gioco

Il sorgente creato in Animate utilizza gli elementi grafici appena descritti in un mix di grafica statica e animazioni. Di seguito, prima di passare al codice vediamo come sono strutturati i sei livelli dall’alto verso il basso.  

puzzle_fig3

Il primo livello contiene un fotogramma chiave con il codice createJS del gioco. Nel secondo livello  su trova un clip filmato denominato scritta, caratterizzato da una semplice interpolazione movimento, che viene attivato non appena il puzzle è completato dall’utente.
Nel terzo livello abbiamo un clip filmato denominato foto, la cui interpolazione mostra la foto originale animata in dissolvenza. Questa animazione, collocata al centro dello stage, ci consente di far apparire con un effetto il gruppo di pezzi sottostanti (anch’esso collocato centro dello stage) .
Infatti, nel livello quarto livello a partire dall’altro, abbiamo tutti pezzi del puzzle già incastrati tra di loro e con tutti i nomi di istanza regolarmente attribuiti.
Nel quinto livello abbiamo i clip che fungono da “oggetti target” durante il drag and drop. Si tratta degli stessi pezzi posizionati nel livello sottostante nelle stesse posizioni. Hanno solo un nome di istanza  diverso: il clip pezzo1 è stato rinominato pezzo_base1, il clip pezzo2 è stato rinominato pezzo_base2 e così via.  Lo scopo di questi clip è quello di individuare il punto esatto nel quale agganciare gli elementi del puzzle quando il metodo hitTest restituisce true. Un’altra caratteristica di questi oggetti riguarda la loro colorazione. Per sottolineare la loro funzione di bersaglio, e distinguerli dagli elementi trascinabili, tramite il pannello proprietà è stata impostata per ognuno di loro una luminosità del 94%.

puzzle_fig4
Nel sesto e ultimo livello si trova invece il clip filmato base. Si tratta di un simbolo che contiene la foto originale e che inizialmente è reso invisibile tramite codice. Non appena il giocatore aggancia un pezzo del puzzle, sia il pezzo trascinabile che l’elemento target diventano invisibili, mentre invece il clip con la foto denominato base diventa visibile. In altre parole, i pezzi che collidono tra di cloro spariscono e la foto sottostante appare. Si tratta di un trucchetto che ci consente di scoprire gradualmente la foto nella sua versione pulita (ovvero senza linee sovrapposte) man mano che il gioco prosegue.

Il codice createJS

Dopo questa lunga disquisizione sulla struttura del gioco passiamo finalmente al codice. Se avete letto gli articoli precedenti, fatta eccezione per un paio di trucchetti, non c’è niente di nuovo sotto al sole. Ma prima di scendere nel dettaglio diamo uno sguardo al listato. Sono circa 44 righe in tutto:

createjs.Touch.enable(stage);
this.base.visible=false;
var pezzi=0;
function startdrag(e) {
this.base.visible=true;
this.setChildIndex(e.currentTarget,this.numChildren-1); 
var local = stage.globalToLocal(stage.mouseX,stage.mouseY,e.currentTarget);
e.currentTarget.x=local.x;
e.currentTarget.y=local.y;
// 
stage.update();
}
function stopdrag(e){
var local = e.currentTarget.b.localToLocal(0,0,e.currentTarget);
if (e.currentTarget.hitTest(local.x,local.y)) { 
e.currentTarget.x=e.currentTarget.b.x;
e.currentTarget.y=e.currentTarget.b.y;
e.currentTarget.visible=false; 
e.currentTarget.b.visible=false; 
e.currentTarget.removeAllEventListeners("pressmove");
pezzi+=1;
if(pezzi==24){this.scritta.gotoAndPlay(1);}
}
}
function muovi(target,posx,posy,t,tw){
var tween = createjs.Tween.get(target,{loop: false})
.to({x:posx, y:posy,}, t,tw)
}
this.centro=function(){
for(var cl=1; cl<=24; cl++ ){
muovi(this["pezzo"+cl],(stage.canvas.width/2),
(stage.canvas.height/2),2000,createjs.Ease.elasticOut);
}
}
function rn(minimo,massimo){
return Math.round(Math.random()*(massimo-minimo))+minimo;
}
this.rand=function(){
for(var cl=1; cl<=24; cl++ ){
var rx=rn(60,740);
var ry= rn(60,420);
muovi(this["pezzo"+cl],rx,ry,2000,createjs.Ease.cubicOut);
this["pezzo"+cl].on("pressmove", startdrag.bind(this));
this["pezzo"+cl].on("pressup", stopdrag.bind(this));
this["pezzo"+cl].b=this["pezzo_base"+cl];
}
}

La prima riga di codice, come abbiamo visto nell’articolo precedente, serve ad attivare gli eventi per i dispositivi mobili. In realtà, anche se il gioco si vede sul mobile in modalità responsive, non è ancora perfettamente ottimizzato (ma ci torneremo con un articolo a parte).
La seconda riga di codice nasconde la foto sullo sfondo e la terza inizializza la variabile pezzi che ci servirà per contare i pezzi agganciati durante la partita.
Le funzioni startdrag e stopdrag, sono identiche a quelle viste nell’articolo precedente della guida, l’unica differenza è la presenza di un if nella funzione stopdrag. In pratica quando la variabile pezzi assume come valore il numero 24 – e quindi tutti gli elementi sono al loro posto – viene attivata l’animazione con la scritta che annuncia la fine del gioco.
Nel blocco di codice seguente abbiamo le funzioni che attivano il movimento dei pezzi. Si tratta della funzione centro(), la quale colloca tutti i clip al centro dello stage e la funzione rand() che invece li sparpaglia in modo causale. Entrambe sono attivate dai fotogrammi 30 e 60 della linea temporale del clip foto. 

puzzle_fig5

In pratica quando la dissolvenza è ultimata, abbiamo nel fotogramma chiave 30 questa chiamata:

exportRoot.centro();

La funzione centro() che a sua volta innesca la funzione muovi(), individua tutti i 24 clip e li sposta nella parte centrale dello stage tramite un oggetto tween. Per evitare di scrivere 24 istruzioni (una per ogni clip) ho usato il classico trucchetto basato sul ciclo for che compone dinamicamente il nome dell’oggetto per n volte:

this[“nomeoggetto”+n].proprietà;

Dove nomeoggetto è la parte letterale del nome e n il numero che da associare alla fine. Per cui se il numero n vale 2 avremo come nome di istanza nomeoggetto2.
Nel fotogramma 60 abbiamo invece la chiamata alla funzione che mescola i pezzi:

this.stop();
exportRoot.rand();

La funzione rand() utilizza a sua volta la funzione rn(), la quale sfrutta un piccolo algoritmo che ho uso spesso per individuare un numero casuale compreso tra un valore minimo e un valore massimo.

Math.round(Math.random()*(massimo-minimo))+minimo;

Usando il metodo round si approssima il numero casuale generato dal metodo random. I valori che ho usato nella chiamata di funzione li ho calcolati semplicemente spostando i pezzi manualmente sullo stage per poi leggere il valore delle coordinate nel pannello Proprietà. Ad esempio, per mantenere i pezzi sullo stage sull’asse delle x, il valore minimo è 60 e il valore massimo 740.

Qui trovate l’esempio online, mentre potete scaricare i file sorgenti cliccando il link sottostante.

Scarica i sorgenti.

Share:

5 comments

  1. Lisa 18 Luglio, 2017 at 12:30 Reply

    Buongiorno,

    articolo molto interessante. Ho provato a pubblicare da Animate ma non funziona il drag and drop su Chrome, come mai?
    La versione del gioco pubblicata sul sito non è come quella che mi pubblica Animate.

    Grazie
    Lisa

    • bruno doper 18 Luglio, 2017 at 16:52 Reply

      Ciao. In realtà funziona. Il file che vedi online è stato generato con lo stesso sorgente che hai scaricato. Ho appena fatto una prova al volo.
      Purtroppo chrome blocca determinati script in locale per motivi di sicurezza. Per cui, molti file html5 creati con animate, per intenderci quelli che nella barra del browser hanno un percorso del tipo “file:///C:/cartella/ecc” si bloccano. Ma se lo pubblichi online funziona.
      Per testarlo in locale senza metterlo in rete hai solo tre possibilità: lanciare l’anteprima di animate dal programma (senza aprire il browser in separata sede), usare un server simulato come easyphp, settare le regole di sicurezza di chrome. Quest’ultima opzione non l’ho mai provata per motivi di pigrizia. Sbirciando in giro ho visto che la procedura era abbastanza macchinosa, e siccome tramite anteprima simulavo egregiamente quello che poi mettevo online, non ci ho perso tempo. Ma se ne hai voglia, sulla rete trovi la documentazione sulle limitazioni di chrome in locale e i trucchi per aggirarle.

  2. Gabriele 10 Settembre, 2019 at 17:06 Reply

    Ciao,
    ho provato a convertire in automatico questo simpatico puzzle in ActionScript 3.0 ma non riesco a convertire tutto il codice, saresti così gentile da aiutarmi, sempre che la cosa sia fattibile.
    Grazie in ogni caso, articolo davvero interessante.

  3. bruno doper 22 Settembre, 2019 at 20:14 Reply

    Ciao, Gabriele. Prima di tutto scusami per la risposta in ritardo, ma sto rinnovando il blog e per errore la mail di notifica del commento era finita nello spam. L’ho scovata per puro caso.
    Purtroppo per effettuare la conversione non puoi procedere in automatico. Devi rivedere molti aspetti del codice.

Rispondi a bruno doper Annulla risposta

*