Creați un puzzle HTML5 pentru placi de tablă

În acest tutorial vom lucra cu panza HTML5 și Javascript pentru a crea un joc dinamic de schimbare a țiglelor. Rezultatul va fi un puzzle care funcționează cu orice imagine dată și are nivele flexibile de dificultate care sunt ușor de ajustat.


Puzzle complet HTML5 Canvas

Iată o fotografie scurtă a puzzle-ului pe care îl vom construi:


Faceți clic pentru a juca

Câteva note:

  • Compatibilitate compatibilă cu browserul: Acest puzzle a fost testat și funcționează în toate versiunile de Safari, Firefox și Chrome care acceptă pânză element.
  • Mobil: Codul furnizat aici funcționează în browserul desktop menționat mai sus și nu este optimizat pentru dispozitive mobile. Puzzle-ul se va încărca și se va face bine, dar din cauza comportamentului atingeți și trageți în browserele mobile, optimizarea este necesară pentru ca acesta să funcționeze corect. Optimizarea acestui puzzle pentru mobil va fi acoperită într-un tutorial viitor.
  • Dificultate reglabilă: Codul conține o constantă, PUZZLE_DIFFICULTY, care determină numărul de bucăți. În demo-ul de mai sus, acesta este setat la 4, oferind un puzzle 4x4. Putem schimba cu ușurință acest lucru - de exemplu, această versiune are o PUZZLE_DIFFICULTY de 10.

Noțiuni de bază

Pentru a începe, creați un director pentru proiect. Plasați o imagine în directorul pe care doriți să-l utilizați ca puzzle. Orice imagine prietenoasă pe web va face, și poate fi orice dimensiune dorința inimii dvs. - asigurați-vă că se potrivește în interiorul ferestrei browserului dvs..


Pasul 1: Crearea șablonului HTML

Deschideți un fișier nou utilizând editorul de text preferat și salvați-l în directorul de proiect, lângă imaginea dvs. Apoi, completați această bază HTML șablon.

    HTML5 Puzzle      

Tot ce trebuie să facem aici este să creeze un standard HTML5 șablon care conține unul pânză eticheta cu id de "pânză". Vom scrie un onload ascultător în corp eticheta care ne va suna init () când este declanșat.

Acum începeți prin plasarea cursorului în interiorul scenariu etichetă. De aici și aici toate javascript. Cu excepția variabilelor inițiale, voi organiza secțiunile după funcție. În primul rând vă arată codul și apoi explicați logica.

Gata? Să mergem direct la asta!


Pasul 2: Configurarea variabilelor noastre

Să ne stabilim variabilele și să aruncăm o privire la fiecare.

 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;

Mai întâi avem câteva constante: PUZZLE_DIFFICULTY și PUZZLE_HOVER_TINT. PUZZLE_DIFFICULTY constantă ține numărul de piese în puzzle-ul nostru. În această aplicație, rândurile și coloanele se potrivesc întotdeauna, prin setare PUZZLE_DIFFICULTY la 4, vom obține 16 piese de puzzle în total. Creșterea acestui fapt crește dificultatea puzzle-ului.

Următoarea este o serie de variabile:

  • _canvas și _etapă va avea o referință la panza și respectiv la contextul de desenare. Facem acest lucru, astfel încât nu trebuie să scriem întreaga interogare de fiecare dată când le folosim. Și le vom folosi foarte mult!
  • _img va fi o referință la imaginea încărcată, pe care o vom copia pixeli din toată aplicația.
  • _puzzleWidth, _puzzleHeight, _pieceWidth, și _pieceHeight va fi folosit pentru a stoca dimensiunile atât a puzzle-ului întreg cât și a fiecărei piese de puzzle individuale. Am stabilit aceste o dată pentru a preveni calcularea lor de peste si peste de fiecare dată când avem nevoie de ele.
  • _currentPiece conține o referință la piesa care este în prezent trasă.
  • _currentDropPiece are o referință la piesa aflată în prezent în poziția de a fi abandonată. (În demo, această piesă este evidențiată în verde.)
  • _șoarece este o referință care va menține curentul mouse-ului X și y poziţie. Aceasta se actualizează atunci când puzzle-ul este apăsat pentru a determina ce piesă este atinsă și când o piesă este târâtă pentru a determina ce piesă se mișcă peste.

Acum, la funcțiile noastre.


Pasul 3: The init () Funcţie

 funcția init () _img = imagine nouă (); _img.addEventListener ( 'încărcare', onImage, fals); _img.src = "mke.jpg"; 

Primul lucru pe care dorim să-l facem în aplicația noastră este să încărcăm imaginea pentru puzzle. Obiectul imaginii este inițial instanțiat și setat pentru a noastră _img variabil. Apoi, ascultăm pentru sarcină eveniment care ne va da foc onImage () atunci când imaginea sa terminat de încărcat. În cele din urmă, setăm sursa imaginii, care declanșează sarcina.


Pasul 4: The onImage () Funcţie

 funcția onImage (e) _pieceWidth = Math.floor (_img.width / PUZZLE_DIFFICULTY) _pieceHeight = Matematică (_img.height / PUZZLE_DIFFICULTY) _puzzleWidth = _pieceWidth * PUZZLE_DIFFICULTY; _puzzleHeight = _pieceHeight * PUZZLE_DIFFICULTY; setCanvas (); initPuzzle (); 

Acum că imaginea este încărcată cu succes, putem seta majoritatea variabilelor declarate anterior. Facem asta aici pentru că acum avem informații despre imagine și putem să ne stabilim valorile în mod corespunzător.

Primul lucru pe care îl facem este să calculam mărimea fiecărei bucăți de puzzle. Noi facem acest lucru împărțind PUZZLE_DIFFICULTY valoare după lățimea și înălțimea imaginii încărcate. De asemenea, eliminăm grăsimea de pe margini pentru a ne oferi niște numere frumoase pentru a lucra și pentru a ne asigura că fiecare piesă poate schimba în mod adecvat "sloturile" cu ceilalți.

Apoi vom folosi noile valori ale puzzle-ului pentru a determina dimensiunea totală a puzzle-ului și a le seta _puzzleWidth și _puzzleHeight.

În cele din urmă, am anula câteva funcții - setCanvas () și initPuzzle ().


Pasul 5: The setCanvas () Funcţie

 funcția setCanvas () _canvas = document.getElementById ('canvas'); _stage = _canvas.getContext ("2d"); _canvas.width = _puzzleWidth; _canvas.height = _puzzleHeight; _canvas.style.border = "1px solid negru"; 

Acum că valorile puzzle-ului sunt complete, vrem să ne înființăm pânză element. Mai întâi ne-am stabilit _canvas variabilă pentru a ne referi pânză element, și _etapă pentru a-i face referire context.

Acum am setat lăţime și înălţime a noastră pânză pentru a se potrivi dimensiunile imaginii tăiate, urmată de aplicarea unor stiluri simple pentru a crea o graniță neagră în jurul nostru pânză pentru a afișa limitele puzzle-ului nostru.


Pasul 6: The initPuzzle () Funcţie

 funcția initPuzzle () _pieces = []; _mouse = x: 0, y: 0; _currentPiece = null; _currentDropPiece = null; _stage.drawImage (_img, 0, 0, _puzzleWidth, _puzzleHeight, 0, 0, _puzzleWidth, _puzzleHeight); createTitle ("Faceți clic pentru a începe Puzzle"); buildPieces (); 

Aici inițializăm puzzle-ul. Am setat această funcție în așa fel încât să o putem numi din nou mai târziu când vrem să reluăm puzzle-ul. Orice altceva care trebuia să fie setat înainte de a juca nu va mai trebui să fie setat din nou.

Mai întâi am stabilit _pieces ca un gol mulțime și creați _șoarece obiect, care va menține poziția mouse-ului pe tot parcursul aplicației. Apoi setăm _currentPiece și _currentPieceDrop la nul. (La prima piesă, aceste valori ar fi deja nul, dar vrem să ne asigurăm că se resetează atunci când redau puzzle-ul.)

În cele din urmă, este timpul să atragem! Mai întâi tragem întreaga imagine pentru a afișa jucătorului ceea ce vor crea. După aceea, vom crea niște instrucțiuni simple sunând la noi createTitle () funcţie.


Pasul 7: The createTitle () Funcţie

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

Aici vom crea un mesaj destul de simplu care instruiește utilizatorul să facă clic pe puzzle pentru a începe.
Mesajul nostru va fi un dreptunghi semi-transparent care va servi ca fundal al textului nostru. Acest lucru permite utilizatorului să vadă imaginea din spatele acestuia și asigură, de asemenea, că textul alb va fi lizibil pe orice imagine

Am stabilit pur și simplu stil de completare la negru și globalAlpha la .4, înainte de a completa un dreptunghi negru scurt în partea de jos a imaginii.

De cand globalAlpha afectează întreaga pânză, trebuie să o readucăm înapoi 1 (opac) înainte de a desena textul. Pentru a configura titlul, setăm aliniere text pentru a "centra" și pentru a textBaseline la 'mijloc'. Putem aplica și altele font proprietăţi.

Pentru a desena textul, folosim fillText () metodă. Trecem în msg variabilă și se plasează la centrul orizontal al pânză, și centrul vertical al dreptunghiului.


Pasul 8: The buildPieces () Funcţie

 funcția buildPieces () var i; var bucată; var xPos = 0; var yPos = 0; pentru (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; 

În cele din urmă, este timpul să construim puzzle-ul!

Noi facem asta prin construirea unui obiect pentru fiecare piesă. Aceste obiecte nu vor fi responsabile pentru redarea pe pânză, ci mai degrabă să țină doar referințe la ceea ce să atragă și unde. Acestea fiind spuse, să ajungem la ele.

În primul rând, să declarăm câteva variabile pe care le vom reutiliza prin buclă. Vrem să setăm bucla pentru a repeta numărul de piese de puzzle de care avem nevoie. Obținem această valoare prin înmulțire PUZZLE_DIFFICULTY de la sine - așa că în acest caz primim 16.

În bucla:

 pentru (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; 

Începeți prin a crea un spațiu gol bucată obiect. Apoi adăugați s x și sy proprietățile obiectului. În prima iterație, aceste valori sunt 0 și reprezintă punctul din imaginea noastră de unde vom începe să tragem. Acum, împingeți-l la _pieces [] matrice. Acest obiect va conține, de asemenea, proprietățile xPos și yPos, care ne va spune poziția actuală în puzzle unde ar trebui să fie desenată piesa. Vom amesteca obiectele înainte de a fi redate, astfel încât aceste valori nu trebuie să fie setate încă.

Ultimul lucru pe care îl facem în fiecare buclă este creșterea variabilei locale xPos de _pieceWidth. Înainte de a continua cu bucla, vom determina dacă trebuie să mergem la următorul rând de bucăți verificând dacă xPos este dincolo de lățimea puzzle-ului. Dacă da, ne reinițializăm xPos înapoi la 0 și măriți yPos de _pieceHeight.

Acum avem piesele noastre de puzzle toate stocate departe frumos în nostru _pieces matrice. În acest moment, codul încetează în cele din urmă să execute și așteaptă ca utilizatorul să interacționeze. Am setat un ascultător de clic pe document pentru a trage shufflePuzzle () atunci când se declanșează, care va începe jocul.


Pasul 9: The shufflePuzzle () Funcţie

 funcția shufflePuzzle () _pieces = shuffleArray (_pieces); _stage.clearRect (0,0, _puzzleWidth, _puzzleHeight); var i; var bucată; var xPos = 0; var yPos = 0; pentru (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; 
 (i), o [i], o [i] = o [i] = o [ j], o [j] = x); retur o; 

Mai intai lucrurile: shuffle _pieces [] matrice. Folosesc aici o funcție utilă de utilitate, care va amesteca indicii matricei introduse în ea. Explicația acestei funcții este dincolo de subiectul acestui tutorial, așa că vom merge mai departe, știind că am reușit să ne amestecăm piesele. (Pentru o introducere de bază a amestecării, aruncați o privire la acest tutorial.)

Să clarificăm mai întâi toate graficele atrase de pânză pentru a face loc pentru desenarea pieselor noastre. Apoi, configurați matricea asemănătoare cu cea pe care am făcut-o când creați mai întâi piesele noastre.

În bucla:

 pentru (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; 

Mai întâi de toate, utilizați eu variabilă pentru a configura referința noastră la piesa curentă a bucății din bucla. Acum vom popula xPos și yPos proprietățile pe care le-am menționat mai devreme, care vor fi 0 în prima noastră iterație.

Acum, în sfârșit, ne desenați piesele.

Primul parametru al lui drawImage () atribuie sursa imaginii de la care vrem să trasăm. Apoi folosiți obiectele piesei s x și sy proprietăți, împreună cu _pieceWidth și _pieceHeight, pentru a popula parametrii care declară aria imaginii în care să se deseneze. Ultimii patru parametri stabilesc aria zonei pânză unde vrem să desenezi. Noi folosim xPos și yPos valori pe care amândoi le construim în bucle și atribuind obiectului.

Imediat după aceasta, tragem o lovitură rapidă în jurul piesei pentru a da o margine, care o va deosebi frumos de celelalte piese.

Acum așteptăm ca utilizatorul să apuce o piesă, stabilind altul clic ascultător. De data asta o să tragă un onPuzzleClick () funcţie.


Pasul 10: The onPuzzleClick () Funcţie

 funcția onPuzzleClick (e) if (e.layerX || e.layerX == 0) _mouse.x = e.layerX - _canvas.offsetLeft; _mouse.y = e.layerY - _canvas.offsetTop;  altfel dacă (e.offsetX || e.offsetX == 0) _mouse.x = e.offsetX - _canvas.offsetLeft; _mouse.y = e.offsetY - _canvas.offsetTop;  _currentPiece = checkPieceClicked (); dacă (_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 = bucatăDropată; 

Știm că a fost făcut clic pe puzzle; acum trebuie să determinăm ce piesă a fost făcută. Această condiție simplă ne va aduce poziția mouse-ului pe toate browserele de desktop moderne care acceptă pânză, folosind fie e.layerX și e.layerY sau e.offsetX și e.offsetY. Utilizați aceste valori pentru a ne actualiza _șoarece obiect prin atribuirea acestuia X și a y proprietatea de a menține poziția actuală a mouse-ului - în acest caz, poziția în care a fost făcut clic.

În linia 112 am stabilit imediat _currentPiece la valoarea returnată din partea noastră checkPieceClicked () funcţie. Separăm acest cod deoarece dorim să îl folosim mai târziu când tragem piesa de puzzle. Voi explica această funcție în pasul următor.

Dacă valoarea returnată a fost nul, pur și simplu nu facem nimic, deoarece acest lucru implică faptul că utilizatorul nu a făcut clic pe o piesă de puzzle. Cu toate acestea, dacă facem să preluăm o piesă de puzzle, vrem să o atașăm la mouse și să o decolăm puțin pentru a dezvălui piesele dedesubt. Deci, cum facem asta??

În primul rând, noi clarificăm pânză zona în care piesa stătea înainte să dăm clic pe ea. Folosim clearRect () încă o dată, dar în acest caz trecem numai în zona obținută de la _currentPiece obiect. Înainte de a ne redresa, vrem să Salvați() contextul panzei înainte de a continua. Acest lucru va asigura că tot ce facem după salvare nu va atrage pur și simplu nimic în calea lui. Facem acest lucru pentru că vom scădea ușor piesa târâtă și vrem să vedem piesele sub ea. Dacă nu am sunat Salvați(), tocmai am tras peste orice grafică în felul ăsta - estompată sau nu.

Acum desenați imaginea astfel încât centrul acesteia să fie poziționat deasupra indicatorului mouse-ului. Primii 5 parametri ai drawImage va fi întotdeauna aceeași în întreaga aplicație. Când faceți clic, următorii doi parametri vor fi actualizați pentru a se centura pe pointerul mouse-ului. Ultimii doi parametri, lăţime și înălţime pentru a desena, nu se va schimba niciodată.

În cele din urmă numim restabili() metodă. Acest lucru înseamnă, în esență, că am terminat folosind noua valoare alfa și doriți să restaurați toate proprietățile înapoi în locul în care se aflau. Pentru a încheia această funcție adăugăm încă doi ascultători. Unul pentru atunci când mutăm mouse-ul (tragerea piesei puzzle-ului), și unul pentru când vom lăsa să plecăm (picătură piesa de puzzle).


Pasul 11: The checkPieceClicked () Funcţie

 funcția checkPieceClicked () var i; var bucată; pentru (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 altceva return piece;  întoarce null; 

Acum trebuie să renunțem puțin. Am reușit să determinăm ce piesă a fost făcută, dar cum am făcut-o? E destul de simplu de fapt. Ceea ce trebuie să facem este să țâșniți prin toate piesele de puzzle și să determinați dacă clicul a fost în limitele oricărui obiect al nostru. Dacă găsim una, vom întoarce obiectul corespunzător și vom termina funcția. Dacă nu găsim nimic, ne întoarcem nul.


Pasul 12: The updatePuzzle () Funcţie

 actualizare functiePuzzle (e) _currentDropPiece = null; dacă (e.layerX || e.layerX == 0) _mouse.x = e.layerX - _canvas.offsetLeft; _mouse.y = e.layerY - _canvas.offsetTop;  altfel dacă (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; var bucată; pentru (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 > (buc.yPos + _pieceHeight)) // NU EXTERN altceva _currentDropPiece = bucată; _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); 

Acum, înapoi la tragere. Apelam această funcție când utilizatorul mișcă mouse-ul. Aceasta este cea mai mare funcție a aplicației, deoarece face mai multe lucruri. Sa incepem. O să-l rup în timp ce mergem.

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

Începeți prin setare _currentDropPiece la nul. Trebuie să reinițializăm acest lucru nul pe actualizare, din cauza șanselor ca piesa noastră să fie târâtă înapoi la casă. Nu vrem pe cei anteriori _currentDropPiece valoare în jurul valorii de agățat. Apoi setăm _șoarece obiect în același mod în care am făcut clic.

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

Aici trebuie să clarificăm toate imaginile de pe panza. Trebuie, în esență, să redesemnăm piesele de puzzle, deoarece obiectul care este tras în sus va avea efectul apariției lor. Dacă nu am face acest lucru, am fi văzut niște rezultate foarte ciudate urmând calea piesei noastre de puzzle trase.

 var i; var bucată; pentru (i = 0; i < _pieces.length;i++)

Începeți prin a configura bucla obișnuită.

În bucla:

 bucata = piesele [i]; dacă (piece == _currentPiece) continue; 

Creați-ne bucată referință ca de obicei. Apoi, verificați dacă piesa pe care o prezentăm în prezent este aceeași cu piesa pe care o trasăm. Dacă da, continuați buclele. Aceasta va menține spațiul liber al casei trase.

 _stage.drawImage (_img, piece.sx, piece.sy, _pieceWidth, _pieceHeight, piece.xPos, piece.yPos, _pieceWidth, _pieceHeight); _stage.strokeRect (bucată.xPos, bucată.Plasă, piesă lățime, piesă de înălțime);

Deplasând-o, retușați piesa de puzzle utilizând proprietățile ei exact așa cum am făcut-o atunci când le-am desenat mai întâi. Va trebui să tragi și frontiera.

 dacă (_currentDropPiece == null) if (_mouse.x < piece.xPos || _mouse.x > (piece.xPos + _pieceWidth) || _mouse.y < piece.yPos || _mouse.y > (buc.yPos + _pieceHeight)) // NU EXTERN altceva _currentDropPiece = bucată; _stage.save (); _stage.globalAlpha = .4; _stage.fillStyle = PUZZLE_HOVER_TINT; _stage.fillRect (_currentDropPiece.xPos, _currentDropPiece.yPos, _pieceWidth, _pieceHeight); _stage.restore (); 

Deoarece avem o referință la fiecare obiect din buclă, putem folosi și această ocazie pentru a verifica dacă piesa trasă este pe partea de sus a acesteia. Facem acest lucru pentru că vrem să oferim utilizatorilor feedback cu privire la ce piesă poate fi abandonată. Hai să intrăm în codul ăsta acum.

Mai întâi vrem să vedem dacă această buclă a produs deja o țintă de scădere. Dacă este așa, nu trebuie să ne deranjăm, deoarece este posibilă o singură atingere și orice mișcare a mouse-ului dat. Dacă nu, _currentDropPiece va fi nul și putem trece în logică. Deoarece mouse-ul nostru se află în mijlocul piesei trase, tot ce trebuie să facem este să determinăm ce altă piesă sa terminat.

Apoi, folosiți-ne la îndemână checkPieceClicked () pentru a determina dacă mouse-ul se află pe obiectul curent în bucla. Dacă da, am setat _currentDropPiece variați și desenați o cutie colorată deasupra piesei puzzle-ului, indicând faptul că aceasta este acum țintă.

A își aminti să Salvați() și restabili(). În caz contrar, veți obține caseta colorată și nu imaginea dedesubt.

În afara buclei:

 _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);

Nu în ultimul rând, trebuie să redesemnăm piesa trasă. Codul este același ca atunci când am făcut clic pentru prima dată, dar mouse-ul sa mutat, astfel încât poziția sa să fie actualizată.


Pasul 13: The pieceDropped () Funcţie

 funcția bucatăDropată (e) document.onmousemove = null; document.onmouseup = null; dacă (_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, cel mai rău este în spatele nostru. Acum reușim să tragem cu succes o piesă de puzzle și chiar să obținem un feedback vizual despre locul în care va fi abandonat. Acum tot ce a mai rămas este să renunți la piesă. Să eliminăm imediat ascultătorii de îndată ce nu se trage nimic.

Apoi, verificați asta _currentDropPiece nu este nul. Dacă este, înseamnă că l-am târât înapoi în zona de acasă a piesei și nu pe alt slot. Dacă nu este nul, vom continua cu funcția.

Ceea ce facem acum este pur și simplu să schimbați xPos și yPos din fiecare bucată. Facem un obiect temp rapid ca tampon pentru a ține una dintre valorile obiectului în procesul de schimbare. În acest moment, cele două piese au și noi xPos și yPos valori, și va intra în noile lor case pe următoarea remiză. Asta vom face acum, verificând simultan dacă jocul a fost câștigat.


Pasul 14: The resetPuzzleAndCheckWin () Funcţie

 resetarea funcțieiPuzzleAndCheckWin () _stage.clearRect (0,0, _puzzleWidth, _puzzleHeight); var gameWin = adevărat; var i; var bucată; pentru (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);  

Încă o dată, eliminați pânză și să înființeze o gameWin variabilă, setându-l la Adevărat în mod implicit. Acum continuați cu bucla noastră de bucăți foarte cunoscute.

Codul aici ar trebui să pară familiar, așa că nu vom trece peste el. Pur și simplu trage piesele înapoi în sloturile originale sau noi. În cadrul acestei bucle, dorim să vedem dacă fiecare piesă este trasă în poziția câștigătoare. Acest lucru este simplu: verificăm dacă ne vom vedea s x și sy proprietățile se potrivesc cu xPos și yPos. Dacă nu, știm că nu am reușit să câștigăm puzzle-ul și să ne fixăm gameWin la fals. Dacă am făcut-o prin buclă cu toată lumea în locurile lor câștigătoare, am stabilit un rapid pauză să ne sunăm joc încheiat() metodă. (Am setat un timeout astfel încât ecranul să nu se schimbe atât de drastic la căderea piesei de puzzle.)


Pasul 15: The joc încheiat() Funcţie

 funcția gameOver () document.onmousedown = null; document.onmousemove = null; document.onmouseup = null; initPuzzle (); 

Aceasta este ultima noastră funcție! Aici eliminăm toți ascultătorii și sunăm initPuzzle (), care resetează toate valorile necesare și așteaptă ca utilizatorul să redea.


Concluzie

Faceți clic aici pentru a vedea rezultatul final.

După cum puteți vedea, puteți realiza o mulțime de lucruri creative noi în HTML5 utilizând zone bitmap selectate de imagini încărcate și desen. Puteți extinde cu ușurință această aplicație prin adăugarea de scoruri și poate chiar de un cronometru pentru a da mai mult gameplay. O altă idee ar fi să sporiți dificultatea și să selectați o altă imagine în joc încheiat() funcție, oferind nivelurile de joc.

Cod