Crea un puzzle di scambio di tessere Canvas HTML5

In questo tutorial lavoreremo con la tela HTML5 e Javascript per creare un gioco dinamico di scambio di tessere. Il risultato sarà un puzzle che funziona con qualsiasi immagine, e ha livelli di difficoltà flessibili facilmente regolabili.


Il puzzle completo Canvas HTML5

Ecco una rapida carrellata del puzzle che costruiremo:


Clicca per giocare

Un paio di note:

  • Compatibilità cross-browser: Questo puzzle è stato testato e funziona in tutte le versioni di Safari, Firefox e Chrome che supportano il tela elemento.
  • Mobile: Il codice fornito qui funziona nel browser desktop sopra menzionato e non è ottimizzato per i dispositivi mobili. Il puzzle verrà caricato e renderizzato correttamente, ma a causa dei comportamenti di trascinamento e tocco nei browser per dispositivi mobili, è necessaria l'ottimizzazione perché funzioni correttamente. L'ottimizzazione di questo puzzle per dispositivi mobili sarà trattata in un futuro tutorial.
  • Difficoltà regolabile: Il codice contiene una costante, PUZZLE_DIFFICULTY, che determina il numero di pezzi. Nella demo sopra, questo è impostato su 4, dando un puzzle 4x4. Possiamo facilmente cambiare questo - per esempio, questa versione ha un PUZZLE_DIFFICULTY di 10.

Iniziare

Per iniziare, crea una directory per il progetto. Inserisci un'immagine nella directory che vuoi utilizzare come puzzle. Qualsiasi immagine web friendly andrà bene e può essere di qualsiasi dimensione il tuo cuore desidera - basta assicurarsi che si adatti alla piega della finestra del browser.


Passaggio 1: creazione del modello HTML

Apri un nuovo file usando il tuo editor di testo preferito e salvalo nella directory del tuo progetto, accanto alla tua immagine. Quindi, completa questa base HTML modello.

    HTML5 Puzzle      

Tutto ciò che dobbiamo fare qui è creare uno standard HTML5 modello contenente uno tela tag con il id di "tela". Scriveremo un onload ascoltatore nel corpo tag che chiamerà il nostro dentro() funzione quando sparato.

Ora inizia posizionando il cursore all'interno del copione etichetta. Da qui in avanti è tutto javascript. Ad eccezione delle variabili iniziali, organizzerò le sezioni per funzione. Per prima cosa ti mostri il codice e poi spieghi la logica.

Pronto? Andiamo subito ad esso!


Passaggio 2: impostazione delle nostre variabili

Impostiamo le nostre variabili e diamo un'occhiata a ciascuna di esse.

 const PUZZLE_DIFFICULTY = 4; const PUZZLE_HOVER_TINT = '# 009900'; var _canvas; var _stage; var _img; var _pieces; var _puzzleWidth; var _puzzleHeight; var _pieceWidth; var _pieceHeight; var _currentPiece; var _currentDropPiece; var _mouse;

Innanzitutto abbiamo un paio di costanti: PUZZLE_DIFFICULTY e PUZZLE_HOVER_TINT. Il PUZZLE_DIFFICULTY costante tiene il numero di pezzi nel nostro puzzle. In questa applicazione, le righe e le colonne corrispondono sempre, quindi impostando PUZZLE_DIFFICULTY a 4, otteniamo 16 puzzle in totale. Aumentando questo aumenta la difficoltà del puzzle.

La prossima è una serie di variabili:

  • _tela e _palcoscenico manterrà un riferimento alla tela e al suo contesto di disegno, rispettivamente. Lo facciamo in modo da non dover scrivere l'intera query ogni volta che li usiamo. E li useremo molto!
  • _img sarà un riferimento all'immagine caricata, che copieremo pixel da tutta l'applicazione.
  • _puzzleWidth, _puzzleHeight, _pieceWidth, e _pieceHeight sarà usato per memorizzare le dimensioni sia dell'intero puzzle sia di ogni singolo pezzo del puzzle. Le impostiamo una volta per impedire di calcolarle più e più volte ogni volta che ne abbiamo bisogno.
  • _currentPiece contiene un riferimento al pezzo attualmente trascinato.
  • _currentDropPiece contiene un riferimento al pezzo attualmente in posizione da lasciare cadere. (Nella demo, questo pezzo è evidenziato in verde.)
  • _topo è un riferimento che manterrà la corrente del mouse X e y posizione. Questo viene aggiornato quando viene cliccato il puzzle per determinare quale pezzo viene toccato e quando un pezzo viene trascinato per determinare quale pezzo è sospeso sopra.

Ora, alle nostre funzioni.


Passaggio 3: The dentro() Funzione

 function init () _img = new Image (); _img.addEventListener ( 'carico', onImage, false); _img.src = "mke.jpg"; 

La prima cosa che vogliamo fare nella nostra applicazione è caricare l'immagine per il puzzle. L'oggetto immagine viene prima istanziato e impostato sul nostro _img variabile. Successivamente, ascoltiamo il caricare evento che poi licenzierà onImage () funzione al termine del caricamento dell'immagine. Infine impostiamo la fonte dell'immagine, che attiva il carico.


Step 4: The onImage () Funzione

 function onImage (e) _pieceWidth = Math.floor (_img.width / PUZZLE_DIFFICULTY) _pieceHeight = Math.floor (_img.height / PUZZLE_DIFFICULTY) _puzzleWidth = _pieceWidth * PUZZLE_DIFFICULTY; _puzzleHeight = _pieceHeight * PUZZLE_DIFFICULTY; setCanvas (); initPuzzle (); 

Ora che l'immagine è stata caricata correttamente, possiamo impostare la maggior parte delle variabili dichiarate in precedenza. Lo facciamo qui perché ora abbiamo informazioni sull'immagine e possiamo impostare i nostri valori in modo appropriato.

La prima cosa che facciamo è calcolare la dimensione di ogni pezzo del puzzle. Lo facciamo dividendo il PUZZLE_DIFFICULTY valore per larghezza e altezza dell'immagine caricata. Abbiamo anche tagliato il grasso dai bordi per darci dei bei numeri pari con cui lavorare e assicurarci che ogni pezzo possa scambiare opportunamente le "fessure" con gli altri.

Successivamente utilizziamo i nostri nuovi valori dei pezzi del puzzle per determinare la dimensione totale del puzzle e impostare questi valori su _puzzleWidth e _puzzleHeight.

Infine, richiamiamo alcune funzioni - setCanvas () e initPuzzle ().


Passaggio 5: The setCanvas () Funzione

 function setCanvas () _canvas = document.getElementById ('canvas'); _stage = _canvas.getContext ('2d'); _canvas.width = _puzzleWidth; _canvas.height = _puzzleHeight; _canvas.style.border = "1px solido nero"; 

Ora che i nostri valori del puzzle sono completi, vogliamo impostare il nostro tela elemento. Per prima cosa impostiamo il nostro _tela variabile per fare riferimento al nostro tela elemento, e _palcoscenico per riferirsi al suo contesto.

Ora impostiamo il larghezza e altezza della nostra tela per abbinare la dimensione della nostra immagine ritagliata, seguita dall'applicazione di alcuni stili semplici per creare un bordo nero intorno al nostro tela per mostrare i limiti del nostro puzzle.


Step 6: The initPuzzle () Funzione

 function initPuzzle () _pieces = []; _mouse = x: 0, y: 0; _currentPiece = null; _currentDropPiece = null; _stage.drawImage (_img, 0, 0, _puzzleWidth, _puzzleHeight, 0, 0, _puzzleWidth, _puzzleHeight); createTitle ("Clicca per iniziare il puzzle"); buildPieces (); 

Qui inizializziamo il puzzle. Impostiamo questa funzione in modo tale da poterla richiamare più tardi quando vogliamo riprodurre il puzzle. Tutto il resto che doveva essere impostato prima di giocare non ha bisogno di essere reimpostato.

Per prima cosa abbiamo impostato _pieces come vuoto schieramento e creare il _topo oggetto, che manterrà la nostra posizione del mouse per tutta l'applicazione. Quindi impostiamo il _currentPiece e _currentPieceDrop a nullo. (Al primo gioco questi valori sarebbero già stati nullo, ma vogliamo assicurarci che vengano ripristinati durante la riproduzione del puzzle.)

Finalmente, è tempo di disegnare! Per prima cosa disegniamo l'intera immagine per mostrare al giocatore ciò che creeranno. Dopodiché creiamo alcune semplici istruzioni chiamando il nostro createTitle () funzione.


Step 7: The createTitle () Funzione

 function createTitle (msg) _stage.fillStyle = "# 000000"; _stage.globalAlpha = .4; _stage.fillRect (100, _puzzleHeight - 40, _puzzleWidth - 200,40); _stage.fillStyle = "#FFFFFF"; _stage.globalAlpha = 1; _stage.textAlign = "center"; _stage.textBaseline = "middle"; _stage.font = "20px Arial"; _stage.fillText (msg, _puzzleWidth / 2, _puzzleHeight - 20); 

Qui creiamo un messaggio abbastanza semplice che indica all'utente di fare clic sul puzzle per iniziare.
Il nostro messaggio sarà un rettangolo semitrasparente che servirà da sfondo del nostro testo. Ciò consente all'utente di vedere l'immagine dietro di esso e assicura anche che il nostro testo bianco sarà leggibile su qualsiasi immagine

Abbiamo semplicemente impostato fillStyle al nero e globalAlpha a .4, prima di riempire un breve rettangolo nero nella parte inferiore dell'immagine.

Da globalAlpha interessa l'intero canvas, dobbiamo impostarlo su 1 (opaco) prima di disegnare il testo. Per impostare il nostro titolo, abbiamo impostato il textAlign a 'centro' e il TextBaseline a 'Middle'. Possiamo anche applicarne alcuni font proprietà.

Per disegnare il testo, usiamo il fillText () metodo. Passiamo nel msg variabile e posizionarlo al centro orizzontale del tela, e il centro verticale del rettangolo.


Step 8: The buildPieces () Funzione

 function buildPieces () var i; pezzo var; var xPos = 0; var yPos = 0; per (i = 0; i < PUZZLE_DIFFICULTY * PUZZLE_DIFFICULTY;i++) piece = ; piece.sx = xPos; piece.sy = yPos; _pieces.push(piece); xPos += _pieceWidth; if(xPos >= _puzzleWidth) xPos = 0; yPos + = _pieceHeight;  document.onmousedown = shufflePuzzle; 

Finalmente è il momento di costruire il puzzle!

Lo facciamo costruendo un oggetto per ogni pezzo. Questi oggetti non saranno responsabili del rendering sulla tela, ma piuttosto semplicemente dei riferimenti su cosa disegnare e dove. Detto questo, arriviamo ad esso.

Innanzitutto, dichiariamo alcune variabili che riutilizzeremo nel ciclo. Vogliamo impostare il ciclo per iterare attraverso il numero di pezzi del puzzle di cui abbiamo bisogno. Otteniamo questo valore moltiplicando PUZZLE_DIFFICULTY da solo - quindi in questo caso otteniamo 16.

Nel loop:

 per (i = 0; i < PUZZLE_DIFFICULTY * PUZZLE_DIFFICULTY;i++) piece = ; piece.sx = xPos; piece.sy = yPos; _pieces.push(piece); xPos += _pieceWidth; if(xPos >= _puzzleWidth) xPos = 0; yPos + = _pieceHeight; 

Inizia creando un vuoto pezzo oggetto. Quindi aggiungere il sx e sy proprietà all'oggetto. Nella prima iterazione, questi valori sono 0 e rappresenta il punto nella nostra immagine da cui inizieremo a disegnare. Ora spingilo al _pieces [] array. Questo oggetto conterrà anche le proprietà xPos e yPos, che ci dirà la posizione corrente nel puzzle in cui il pezzo dovrebbe essere disegnato. Mischeremo gli oggetti prima che siano giocabili, quindi non è necessario impostare ancora questi valori.

L'ultima cosa che facciamo in ogni ciclo è aumentare la variabile locale xPos di _pieceWidth. Prima di continuare con il ciclo, determiniamo se è necessario passare alla fila successiva di pezzi controllando se xPos è oltre la larghezza del puzzle. Se è così, resettiamo xPos torna a 0 e aumenta yPos di _pieceHeight.

Ora abbiamo i nostri pezzi del puzzle tutti ben conservati nel nostro _pieces array. A questo punto, il codice smette di essere in esecuzione e attende che l'utente interagisca. Impostiamo un ascoltatore di clic su documento licenziare il shufflePuzzle () funzione quando attivata, che inizierà il gioco.


Passaggio 9: The shufflePuzzle () Funzione

 function shufflePuzzle () _pieces = shuffleArray (_pieces); _stage.clearRect (0,0, _puzzleWidth, _puzzleHeight); var i; pezzo var; var xPos = 0; var yPos = 0; per (i = 0; i < _pieces.length;i++) piece = _pieces[i]; piece.xPos = xPos; piece.yPos = yPos; _stage.drawImage(_img, piece.sx, piece.sy, _pieceWidth, _pieceHeight, xPos, yPos, _pieceWidth, _pieceHeight); _stage.strokeRect(xPos, yPos, _pieceWidth,_pieceHeight); xPos += _pieceWidth; if(xPos >= _puzzleWidth) xPos = 0; yPos + = _pieceHeight;  document.onmousedown = onPuzzleClick; 
 function shuffleArray (o) for (var j, x, i = o.length; i; j = parseInt (Math.random () * i), x = o [- i], o [i] = o [ j], o [j] = x); return o; 

Per prima cosa: mischia il _pieces [] array. Sto usando qui una bella funzione di utilità che mescolerà gli indici dell'array passato. La spiegazione di questa funzione va oltre l'argomento di questo tutorial, quindi andremo avanti, sapendo di aver mescolato con successo i nostri pezzi. (Per un'introduzione di base allo shuffling, dai un'occhiata a questo tutorial).

Deselezioniamo innanzitutto tutti i grafici disegnati su tela per far posto a disegnare i nostri pezzi. Quindi, imposta l'array in modo simile a come facevamo quando creavamo i nostri oggetti pezzo.

Nel loop:

 per (i = 0; i < _pieces.length;i++) piece = _pieces[i]; piece.xPos = xPos; piece.yPos = yPos; _stage.drawImage(_img, piece.sx, piece.sy, _pieceWidth, _pieceHeight, xPos, yPos, _pieceWidth, _pieceHeight); _stage.strokeRect(xPos, yPos, _pieceWidth,_pieceHeight); xPos += _pieceWidth; if(xPos >= _puzzleWidth) xPos = 0; yPos + = _pieceHeight; 

Prima di tutto, usa il io variabile per impostare il nostro riferimento all'oggetto pezzo corrente nel ciclo. Ora popoliamo il xPos e yPos proprietà che ho menzionato prima, che sarà 0 nella nostra prima iterazione.

Ora, finalmente, disegniamo i nostri pezzi.

Il primo parametro di drawImage () assegna la fonte dell'immagine da cui attingere. Quindi usa gli oggetti pezzo sx e sy proprietà, insieme a _pieceWidth e _pieceHeight, per popolare i parametri che dichiarano l'area dell'immagine in cui attingere. Gli ultimi quattro parametri impostano l'area del tela dove vogliamo disegnare. Noi usiamo il xPos e yPos valori che stiamo entrambi costruendo nel loop e assegnandoci all'oggetto.

Subito dopo, disegniamo un tratto veloce attorno al pezzo per dargli un bordo, che lo separerà bene dagli altri pezzi.

Ora aspettiamo che l'utente prenda un pezzo impostandone un altro clic ascoltatore. Questa volta sparerà un onPuzzleClick () funzione.


Passaggio 10: The onPuzzleClick () Funzione

 function onPuzzleClick (e) if (e.layerX || e.layerX == 0) _mouse.x = e.layerX - _canvas.offsetLeft; _mouse.y = e.layerY - _canvas.offsetTop;  else if (e.offsetX || e.offsetX == 0) _mouse.x = e.offsetX - _canvas.offsetLeft; _mouse.y = e.offsetY - _canvas.offsetTop;  _currentPiece = checkPieceClicked (); if (_currentPiece! = null) _stage.clearRect (_currentPiece.xPos, _currentPiece.yPos, _pieceWidth, _pieceHeight); _stage.save (); _stage.globalAlpha = .9; _stage.drawImage (_img, _currentPiece.sx, _currentPiece.sy, _pieceWidth, _pieceHeight, _mouse.x - (_pieceWidth / 2), _mouse.y - (_pieceHeight / 2), _pieceWidth, _pieceHeight); _stage.restore (); document.onmousemove = updatePuzzle; document.onmouseup = pieceDropped; 

Sappiamo che il puzzle è stato cliccato; ora dobbiamo determinare su quale pezzo è stato fatto clic. Questo semplice condizionale ci porterà la posizione del mouse su tutti i browser desktop moderni che supportano tela, usando entrambi e.layerX e e.layerY o e.offsetX e e.offsetY. Utilizza questi valori per aggiornare il nostro _topo oggetto assegnandolo a X e a y proprietà per mantenere la posizione corrente del mouse - in questo caso, la posizione in cui è stato fatto clic.

Nella riga 112, quindi, impostiamo immediatamente _currentPiece al valore restituito dal nostro checkPieceClicked () funzione. Separiamo questo codice perché vogliamo usarlo in seguito quando trascini il pezzo del puzzle. Spiegherò questa funzione nel prossimo passaggio.

Se il valore restituito era nullo, semplicemente non facciamo nulla, poiché ciò implica che l'utente non ha effettivamente fatto clic su un pezzo del puzzle. Tuttavia, se recuperiamo un pezzo del puzzle, vogliamo collegarlo al mouse e sbiadirlo un po 'per rivelare i pezzi sottostanti. Quindi, come lo facciamo??

Per prima cosa cancelliamo il tela area in cui il pezzo si è seduto prima che l'avessimo fatto clic. Noi usiamo clearRect () ancora una volta, ma in questo caso passiamo solo nell'area ottenuta dal _currentPiece oggetto. Prima di ridisegnarlo, lo vogliamo salvare() il contesto della tela prima di procedere. Ciò assicurerà che tutto ciò che disegniamo dopo il salvataggio non si limiterà a disegnare qualsiasi cosa a suo modo. Lo facciamo perché dovremmo sbiadire leggermente il pezzo trascinato e vogliamo vedere i pezzi sotto di esso. Se non abbiamo chiamato salvare(), disegneremmo su qualsiasi grafica in questo modo - sbiadita o meno.

Ora disegniamo l'immagine in modo che il suo centro sia posizionato sul puntatore del mouse. I primi 5 parametri di drawImage sarà sempre lo stesso per tutta l'applicazione. Facendo clic, i prossimi due parametri verranno aggiornati per centrarsi sul puntatore del mouse. Gli ultimi due parametri, il larghezza e altezza disegnare, non cambierà mai.

Infine chiamiamo il ristabilire() metodo. Questo significa essenzialmente che stiamo usando il nuovo valore alfa e vogliamo ripristinare tutte le proprietà nel punto in cui si trovavano. Per concludere questa funzione aggiungiamo altri due listener. Uno per quando spostiamo il mouse (trascinando il pezzo del puzzle), e uno per quando lasciamo andare (rilascia il pezzo del puzzle).


Step 11: The checkPieceClicked () Funzione

 function checkPieceClicked () var i; pezzo var; per (i = 0; i < _pieces.length;i++) piece = _pieces[i]; if(_mouse.x < piece.xPos || _mouse.x > (piece.xPos + _pieceWidth) || _mouse.y < piece.yPos || _mouse.y > (piece.yPos + _pieceHeight)) // PIECE NOT HIT else return piece;  restituisce null; 

Ora abbiamo bisogno di tornare indietro un po '. Siamo stati in grado di determinare quale pezzo è stato cliccato, ma come lo abbiamo fatto? In realtà è piuttosto semplice. Quello che dobbiamo fare è passare in rassegna tutti i pezzi del puzzle e determinare se il clic fosse all'interno dei limiti di uno qualsiasi dei nostri oggetti. Se ne troviamo uno, restituiamo l'oggetto abbinato e terminiamo la funzione. Se non troviamo nulla, torniamo nullo.


Step 12: The updatePuzzle () Funzione

 function updatePuzzle (e) _currentDropPiece = null; if (e.layerX || e.layerX == 0) _mouse.x = e.layerX - _canvas.offsetLeft; _mouse.y = e.layerY - _canvas.offsetTop;  else if (e.offsetX || e.offsetX == 0) _mouse.x = e.offsetX - _canvas.offsetLeft; _mouse.y = e.offsetY - _canvas.offsetTop;  _stage.clearRect (0,0, _puzzleWidth, _puzzleHeight); var i; pezzo var; per (i = 0; i < _pieces.length;i++) piece = _pieces[i]; if(piece == _currentPiece) continue;  _stage.drawImage(_img, piece.sx, piece.sy, _pieceWidth, _pieceHeight, piece.xPos, piece.yPos, _pieceWidth, _pieceHeight); _stage.strokeRect(piece.xPos, piece.yPos, _pieceWidth,_pieceHeight); if(_currentDropPiece == null) if(_mouse.x < piece.xPos || _mouse.x > (piece.xPos + _pieceWidth) || _mouse.y < piece.yPos || _mouse.y > (piece.yPos + _pieceHeight)) // NOT OVER else _currentDropPiece = piece; _stage.save (); _stage.globalAlpha = .4; _stage.fillStyle = PUZZLE_HOVER_TINT; _stage.fillRect (_currentDropPiece.xPos, _currentDropPiece.yPos, _pieceWidth, _pieceHeight); _stage.restore ();  _stage.save (); _stage.globalAlpha = .6; _stage.drawImage (_img, _currentPiece.sx, _currentPiece.sy, _pieceWidth, _pieceHeight, _mouse.x - (_pieceWidth / 2), _mouse.y - (_pieceHeight / 2), _pieceWidth, _pieceHeight); _stage.restore (); _stage.strokeRect (_mouse.x - (_pieceWidth / 2), _mouse.y - (_pieceHeight / 2), _pieceWidth, _pieceHeight); 

Ora torniamo al trascinamento. Chiamiamo questa funzione quando l'utente muove il mouse. Questa è la più grande funzione dell'applicazione poiché fa diverse cose. Cominciamo. Lo romperò mentre andiamo.

 _currentDropPiece = null; if (e.layerX || e.layerX == 0) _mouse.x = e.layerX - _canvas.offsetLeft; _mouse.y = e.layerY - _canvas.offsetTop;  else if (e.offsetX || e.offsetX == 0) _mouse.x = e.offsetX - _canvas.offsetLeft; _mouse.y = e.offsetY - _canvas.offsetTop; 

Inizia impostando _currentDropPiece a nullo. Dobbiamo resettarlo a nullo in aggiornamento a causa della possibilità che il nostro pezzo sia stato trascinato a casa sua. Non vogliamo il precedente _currentDropPiece valore in giro. Quindi impostiamo il _topo oggetto allo stesso modo in cui lo abbiamo fatto al clic.

 _stage.clearRect (0,0, _puzzleWidth, _puzzleHeight);

Qui abbiamo bisogno di cancellare tutti i grafici sulla tela. In sostanza, abbiamo bisogno di ridisegnare i pezzi del puzzle perché l'oggetto che viene trascinato sopra avrà effetto sul loro aspetto. Se non lo facessimo, vedremmo dei risultati molto strani seguendo il percorso del nostro pezzo di puzzle trascinato.

 var i; pezzo var; per (i = 0; i < _pieces.length;i++)

Inizia impostando il nostro solito ciclo di pezzi.

Nel loop:

 pezzo = _pieces [i]; if (piece == _currentPiece) continua; 

Crea il nostro pezzo riferimento come al solito. Quindi verifica se il pezzo a cui stiamo facendo riferimento è lo stesso del pezzo che stiamo trascinando. Se è così, continua il ciclo. Ciò manterrà lo spazio di casa del pezzo trascinato vuoto.

 _stage.drawImage (_img, piece.sx, piece.sy, _pieceWidth, _pieceHeight, piece.xPos, piece.yPos, _pieceWidth, _pieceHeight); _stage.strokeRect (piece.xPos, piece.yPos, _pieceWidth, _pieceHeight);

Andando avanti, ridisegna il pezzo del puzzle usando le sue proprietà esattamente nello stesso modo in cui lo abbiamo fatto quando le abbiamo disegnate per la prima volta. Dovrai disegnare anche il bordo.

 if (_currentDropPiece == null) if (_mouse.x < piece.xPos || _mouse.x > (piece.xPos + _pieceWidth) || _mouse.y < piece.yPos || _mouse.y > (piece.yPos + _pieceHeight)) // NOT OVER else _currentDropPiece = piece; _stage.save (); _stage.globalAlpha = .4; _stage.fillStyle = PUZZLE_HOVER_TINT; _stage.fillRect (_currentDropPiece.xPos, _currentDropPiece.yPos, _pieceWidth, _pieceHeight); _stage.restore (); 

Dato che abbiamo un riferimento a ciascun oggetto nel ciclo, possiamo anche usare questa opportunità per verificare se il pezzo trascinato è sopra di esso. Lo facciamo perché vogliamo dare all'utente il feedback su quale pezzo può essere lasciato cadere. Analizziamo ora il codice.

Per prima cosa vogliamo vedere se questo ciclo ha già prodotto un obiettivo di rilascio. Se è così, non dobbiamo preoccuparci poiché solo un obiettivo di rilascio può essere possibile e qualsiasi movimento del mouse specificato. Altrimenti, _currentDropPiece sarà nullo e possiamo procedere nella logica. Dato che il nostro mouse si trova nel mezzo del pezzo trascinato, tutto ciò che dobbiamo davvero fare è determinare quale altro pezzo il nostro mouse è finito.

Successivamente, usa il nostro pratico checkPieceClicked () funzione per determinare se il mouse passa con il mouse sopra l'oggetto pezzo corrente nel loop. Se è così, impostiamo il _currentDropPiece variabile e disegna una scatola colorata sopra il pezzo del puzzle, indicando che ora è il bersaglio di caduta.

Ricordati di salvare() e ristabilire(). Altrimenti otterresti la scatola colorata e non l'immagine sottostante.

Fuori dal giro:

 _stage.save (); _stage.globalAlpha = .6; _stage.drawImage (_img, _currentPiece.sx, _currentPiece.sy, _pieceWidth, _pieceHeight, _mouse.x - (_pieceWidth / 2), _mouse.y - (_pieceHeight / 2), _pieceWidth, _pieceHeight); _stage.restore (); _stage.strokeRect (_mouse.x - (_pieceWidth / 2), _mouse.y - (_pieceHeight / 2), _pieceWidth, _pieceHeight);

Ultimo ma non meno importante, dobbiamo ridisegnare il pezzo trascinato. Il codice è lo stesso di quando l'abbiamo fatto clic per primo, ma il mouse si è spostato, quindi la sua posizione verrà aggiornata.


Step 13: The pieceDropped () Funzione

 function pieceDropped (e) document.onmousemove = null; document.onmouseup = null; if (_currentDropPiece! = null) var tmp = xPos: _currentPiece.xPos, yPos: _currentPiece.yPos; _currentPiece.xPos = _currentDropPiece.xPos; _currentPiece.yPos = _currentDropPiece.yPos; _currentDropPiece.xPos = tmp.xPos; _currentDropPiece.yPos = tmp.yPos;  resetPuzzleAndCheckWin (); 

OK, il peggio è dietro di noi. Ora stiamo trascinando con successo un pezzo del puzzle e ottenendo anche un riscontro visivo su dove verrà rilasciato. Ora non resta che lasciare il pezzo. Prima rimuoviamo gli ascoltatori poiché nulla viene trascinato.

Quindi, controlla quello _currentDropPiece non è nullo. Se lo è, significa che l'abbiamo trascinato nell'area del pezzo e non su un altro slot. Se non lo è nullo, continuiamo con la funzione.

Quello che facciamo ora è semplicemente scambiare il xPos e yPos di ogni pezzo. Facciamo un oggetto temporaneo veloce come un buffer per contenere uno dei valori dell'oggetto nel processo di swapping. A questo punto, i due pezzi sono entrambi nuovi xPos e yPos valori, e si inseriranno nelle loro nuove case al sorteggio successivo. Questo è quello che faremo ora, controllando contemporaneamente se il gioco è stato vinto.


Step 14: The resetPuzzleAndCheckWin () Funzione

 function resetPuzzleAndCheckWin () _stage.clearRect (0,0, _puzzleWidth, _puzzleHeight); var gameWin = true; var i; pezzo var; per (i = 0; i < _pieces.length;i++) piece = _pieces[i]; _stage.drawImage(_img, piece.sx, piece.sy, _pieceWidth, _pieceHeight, piece.xPos, piece.yPos, _pieceWidth, _pieceHeight); _stage.strokeRect(piece.xPos, piece.yPos, _pieceWidth,_pieceHeight); if(piece.xPos != piece.sx || piece.yPos != piece.sy) gameWin = false;   if(gameWin) setTimeout(gameOver,500);  

Ancora una volta, cancella il tela e impostare a gameWin variabile, impostandolo su vero per impostazione predefinita. Ora procedi con il nostro loop di pezzi fin troppo familiari.

Il codice qui dovrebbe sembrare familiare, quindi non lo esamineremo. Rimuove semplicemente i pezzi nelle loro slot originali o nuove. All'interno di questo ciclo, vogliamo vedere se ogni pezzo viene disegnato nella sua posizione vincente. Questo è semplice: controlliamo se il nostro sx e sy proprietà corrispondono xPos e yPos. Se no, sappiamo che non potremmo vincere il puzzle e il set gameWin a falso. Se avessimo fatto il giro con tutti i giocatori nei loro luoghi vincenti, avremmo fatto un rapido tempo scaduto chiamare il nostro gioco finito() metodo. (Impostiamo un timeout in modo che lo schermo non cambi in modo così drastico una volta eliminato il pezzo del puzzle.)


Step 15: The gioco finito() Funzione

 function gameOver () document.onmousedown = null; document.onmousemove = null; document.onmouseup = null; initPuzzle (); 

Questa è la nostra ultima funzione! Qui rimuoviamo tutti gli ascoltatori e chiamiamo initPuzzle (), che ripristina tutti i valori necessari e attende che l'utente ricominci.


Conclusione

Clicca qui per vedere il risultato finale.

Come puoi vedere, puoi fare molte nuove cose creative in HTML5 usando aree bitmap selezionate di immagini e disegni caricati. Puoi facilmente estendere questa applicazione aggiungendo punteggio e forse anche un timer per dargli più gameplay. Un'altra idea sarebbe quella di aumentare la difficoltà e selezionare un'immagine diversa in gioco finito() funzione, dando i livelli di gioco.