In deze tutorial werken we met het HTML5-canvas en Javascript om een dynamisch tegelwisselspel te maken. Het resultaat is een puzzel die met elke afbeelding werkt en flexibele moeilijkheidsniveaus heeft die gemakkelijk kunnen worden aangepast.
Hier is een snel overzicht van de puzzel die we gaan bouwen:
Een paar opmerkingen:
canvas
element.PUZZLE_DIFFICULTY
, dat bepaalt het aantal stukken. In de bovenstaande demo is dit ingesteld op 4
, een 4x4-puzzel geven. We kunnen dit eenvoudig veranderen - deze versie heeft bijvoorbeeld een PUZZLE_DIFFICULTY
van 10
. Maak een map voor het project om aan de slag te gaan. Plaats een afbeelding in de map die u als uw puzzel wilt gebruiken. Elke webvriendelijke afbeelding zal het doen, en het kan elke gewenste grootte hebben - zorg er gewoon voor dat het in de vouw van het browservenster past.
Open een nieuw bestand met je favoriete teksteditor en sla het op in je projectdirectory, naast je afbeelding. Vul vervolgens deze basis in HTML
sjabloon.
HTML5-puzzel
Het enige wat we hier moeten doen is een standaard maken HTML5
sjabloon met één canvas
tag met de ID kaart
van "canvas". We zullen een schrijven onload
luisteraar in de lichaam
tag die ons zal bellen in het()
functie wanneer ontslagen.
Begin nu met het plaatsen van je cursor in de script
label. Vanaf hier is het alle javascript. Met uitzondering van de beginvariabelen, organiseer ik de secties per functie. Eerst laat je de code zien en vervolgens leg je de logica uit.
Klaar? Laten we erop toezien!
Laten we onze variabelen instellen en een ieder bekijken.
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;
Eerst hebben we een paar constanten: PUZZLE_DIFFICULTY
en PUZZLE_HOVER_TINT
. De PUZZLE_DIFFICULTY
constante bevat het aantal stukjes in onze puzzel. In deze toepassing komen de rijen en kolommen altijd overeen, dus door in te stellen PUZZLE_DIFFICULTY
naar 4
, we krijgen in totaal 16 puzzelstukjes. Door dit te vergroten, vergroot je de moeilijkheidsgraad van de puzzel.
De volgende is een reeks variabelen:
_canvas
en _stadium
bevat een verwijzing naar respectievelijk het canvas en de tekencontext. We doen dit, dus we hoeven niet de hele vraag uit te schrijven telkens we ze gebruiken. En we zullen ze veel gebruiken!_IMG
zal een verwijzing zijn naar de geladen afbeelding, waarvan we pixels van de hele applicatie zullen kopiëren._puzzleWidth
, _puzzleHeight
, _pieceWidth
, en _pieceHeight
wordt gebruikt om de afmetingen van zowel de hele puzzel als elk individueel puzzelstuk op te slaan. We hebben deze één keer ingesteld om te voorkomen dat we ze elke keer opnieuw berekenen wanneer we ze nodig hebben._currentPiece
bevat een verwijzing naar het stuk dat momenteel wordt gesleept._currentDropPiece
bevat een verwijzing naar het stuk dat op dat moment in positie is om op te laten vallen. (In de demo is dit stuk groen gemarkeerd.)_muis
is een verwijzing die de stroom van de muis zal bevatten X
en Y
positie. Dit wordt bijgewerkt wanneer op de puzzel wordt geklikt om te bepalen welk stuk wordt aangeraakt, en wanneer een stuk wordt gesleept om te bepalen welk stuk het zweeft.Nu, op onze functies.
in het()
Functiefunction init () _img = new Image (); _img.addEventListener ( 'load', onImage, false); _img.src = "mke.jpg";
Het eerste dat we willen doen in onze applicatie is om de afbeelding voor de puzzel te laden. Het afbeeldingsobject wordt als eerste geïnstantieerd en op onze ingesteld _IMG
variabel. Vervolgens luisteren we naar de laden
evenement dat ons dan zal ontslaan onImage ()
functie wanneer het beeld klaar is met laden. Ten slotte stellen we de bron van de afbeelding in, waardoor de belasting wordt geactiveerd.
onImage ()
Functiefunction 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 ();
Nu de afbeelding is geladen, kunnen we de meerderheid van de eerder gedeclareerde variabelen instellen. We doen dit hier omdat we nu informatie hebben over de afbeelding en onze waarden op de juiste manier kunnen instellen.
Het eerste dat we doen is de grootte van elk puzzelstuk berekenen. We doen dit door het PUZZLE_DIFFICULTY
waarde door de breedte en hoogte van de geladen afbeelding. We snijden ook het vet van de randen af om ons een aantal mooie even nummers te geven om mee te werken en zorgen ervoor dat elk stuk 'slots' op de juiste manier kan omwisselen met anderen.
Vervolgens gebruiken we onze nieuwe puzzelstukwaarden om de totale grootte van de puzzel te bepalen en deze waarden in te stellen _puzzleWidth
en _puzzleHeight
.
Ten slotte roepen we een aantal functies af - setCanvas ()
en initPuzzle ()
.
setCanvas ()
Functiefunction setCanvas () _canvas = document.getElementById ('canvas'); _stage = _canvas.getContext ('2d'); _canvas.width = _puzzleWidth; _canvas.height = _puzzleHeight; _canvas.style.border = "1px effen zwart";
Nu onze puzzelwaarden compleet zijn, willen we onze canvas
element. Eerst stellen we onze _canvas
variabele om te verwijzen naar onze canvas
element, en _stadium
om te verwijzen naar zijn context
.
Nu hebben we de breedte
en hoogte
van onze canvas
om de grootte van onze getrimde afbeelding te evenaren, gevolgd door enkele eenvoudige stijlen toe te passen om een zwarte rand om ons heen te creëren canvas
om de grenzen van onze puzzel te tonen.
initPuzzle ()
Functiefunction initPuzzle () _pieces = []; _mouse = x: 0, y: 0; _currentPiece = null; _currentDropPiece = null; _stage.drawImage (_img, 0, 0, _puzzleWidth, _puzzleHeight, 0, 0, _puzzleWidth, _puzzleHeight); createTitle ("Click to Start Puzzle"); buildPieces ();
Hier initialiseren we de puzzel. We plaatsen deze functie op een zodanige manier dat we hem later opnieuw kunnen bellen als we de puzzel opnieuw willen spelen. Al het andere dat voorafgaand aan het spelen moet worden ingesteld, hoeft niet opnieuw te worden ingesteld.
Eerst stellen we in _pieces
als een leeg rangschikking
en maak de _muis
object, dat onze muispositie tijdens de hele applicatie zal behouden. Vervolgens stellen we de _currentPiece
en _currentPieceDrop
naar nul
. (Bij het eerste spel zouden deze waarden al zijn nul
, maar we willen er zeker van zijn dat ze worden gereset wanneer de puzzel opnieuw wordt gespeeld.)
Eindelijk is het tijd om te tekenen! Eerst tekenen we de volledige afbeelding om aan de speler weer te geven wat ze zullen maken. Daarna maken we enkele eenvoudige instructies door ons te bellen createTitle ()
functie.
createTitle ()
Functiefunction 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);
Hier maken we een vrij eenvoudig bericht dat de gebruiker opdraagt op de puzzel te klikken om te beginnen.
Ons bericht zal een semi-transparante rechthoek zijn die als achtergrond voor onze tekst zal dienen. Hierdoor kan de gebruiker de afbeelding erachter zien en verzekert hij ook dat onze witte tekst op elke afbeelding leesbaar zal zijn
We zijn gewoon klaar fillStyle
naar zwart en globalAlpha
naar .4
, voordat u een korte zwarte rechthoek onderaan de afbeelding invult.
Sinds globalAlpha
beïnvloedt het hele canvas, we moeten het terugzetten naar 1
(ondoorzichtig) voordat de tekst wordt getekend. Om onze titel in te stellen, hebben we de textAlign
om te 'centreren' en de TextBaseline
naar 'midden'
. We kunnen er ook wat toepassen doopvont
eigenschappen.
Om de tekst te tekenen, gebruiken we de fillText ()
methode. We passeren de msg
variabele en plaats deze in het horizontale midden van de canvas
, en het verticale midden van de rechthoek.
buildPieces ()
Functiefunction buildPieces () var i; var stuk; var xPos = 0; var yPos = 0; voor (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;
Eindelijk is het tijd om de puzzel te bouwen!
Dit doen we door een voorwerp
voor elk stuk. Deze objecten zijn niet verantwoordelijk voor het renderen naar het canvas, maar eerder om referenties te houden over wat te tekenen en waar. Dat gezegd hebbende, laten we er naar toe gaan.
Laten we eerst een paar variabelen declareren die we tijdens de herhaling zullen gebruiken. We willen de lus instellen om het aantal puzzelstukken dat we nodig hebben te herhalen. We krijgen deze waarde door te vermenigvuldigen PUZZLE_DIFFICULTY
alleen, dus in dit geval krijgen we er 16.
voor (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;
Begin door een leeg te maken stuk
voorwerp. Voeg vervolgens de sx
en sy
eigenschappen van het object. In de eerste iteratie zijn deze waarden 0
en vertegenwoordigen het punt in ons beeld waar we beginnen te tekenen. Duw het nu naar de _pieces []
matrix. Dit object bevat ook de eigenschappen xpos
en YPOS
, die ons de huidige positie in de puzzel vertelt waar het stuk moet worden getekend. We zullen de objecten in willekeurige volgorde afspelen voordat deze kunnen worden afgespeeld, dus deze waarden hoeven nog niet helemaal te zijn ingesteld.
Het laatste wat we in elke lus doen, is de lokale variabele verhogen xpos
door _pieceWidth
. Voordat we verder gaan met de lus, bepalen we of we naar de volgende rij stukken moeten gaan door te controleren of xpos
is voorbij de breedte van de puzzel. Als dit het geval is, worden we gereset xpos
terug naar 0 en verhogen YPOS
door _pieceHeight
.
Nu hebben we onze puzzelstukjes allemaal mooi opgeborgen in onze _pieces
matrix. Op dit punt stopt de code uiteindelijk met uitvoeren en wacht op de gebruiker om te communiceren. We hebben een klik luisteraar ingesteld op de document
om de shufflePuzzle ()
functie wanneer geactiveerd, waardoor het spel begint.
shufflePuzzle ()
Functiefunction shufflePuzzle () _pieces = shuffleArray (_pieces); _stage.clearRect (0,0, _puzzleWidth, _puzzleHeight); var i; var stuk; var xPos = 0; var yPos = 0; voor (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;
functie shuffleArray (o) voor (var j, x, i = o.length; i; j = parseInt (Math.random () * i), x = o [- i], o [i] = o [ j], o [j] = x); terug o;
Eerste dingen eerst: schud de _pieces []
matrix. Ik gebruik hier een aardige utiliteitsfunctie die de indices van de array in willekeurige volgorde zal doorlopen. De uitleg van deze functie valt buiten het onderwerp van deze tutorial dus we gaan verder, wetende dat we met succes onze stukken hebben geschud. (Voor een basisinleiding over shuffelen, bekijk deze tutorial.)
Laten we eerst alle afbeeldingen verwijderen die zijn getekend door de canvas
om plaats te maken voor het tekenen van onze stukken. Stel vervolgens de array in op dezelfde manier als bij het maken van onze stukobjecten.
voor (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;
Gebruik om te beginnen de ik
variabele om onze referentie naar het huidige stukobject in de lus in te stellen. Nu vullen we de xpos
en YPOS
eigenschappen die ik eerder heb genoemd, welke zal zijn 0
in onze eerste iteratie.
Eindelijk tekenen we onze stukken.
De eerste parameter van drawImage ()
wijst de bron toe aan de afbeelding waarvan we willen tekenen. Gebruik vervolgens de stukobjecten sx
en sy
eigenschappen, samen met _pieceWidth
en _pieceHeight
, om de parameters in te vullen die het gebied van de afbeelding aanduiden waaruit moet worden getekend. De laatste vier parameters bepalen het gebied van de canvas
waar we willen tekenen. Wij gebruiken de xpos
en YPOS
waarden die we allebei in de lus opbouwen en toewijzen aan het object.
Onmiddellijk hierna tekenen we een snelle slag rond het stuk om het een rand te geven, die het mooi van de andere stukken zal scheiden.
Nu wachten we tot de gebruiker een stuk kan pakken door er een te plaatsen Klik
luisteraar. Deze keer zal het een vuur maken onPuzzleClick ()
functie.
onPuzzleClick ()
Functiefunction 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;
We weten dat er op de puzzel is geklikt; nu moeten we bepalen op welk stuk is geklikt. Deze eenvoudige voorwaarde geeft ons onze muispositie op alle moderne desktopbrowsers die dit ondersteunen canvas
, met een van beide e.layerX
en e.layerY
of e.offsetX
en e.offsetY
. Gebruik deze waarden om onze _muis
object door er een toe te wijzen X
en een Y
eigenschap om de huidige muispositie vast te houden - in dit geval de positie waarop erop is geklikt.
In lijn 112 zetten we dan meteen in _currentPiece
naar de geretourneerde waarde van onze checkPieceClicked ()
functie. We scheiden deze code omdat we deze later willen gebruiken bij het slepen van het puzzelstukje. Ik zal deze functie in de volgende stap uitleggen.
Als de geretourneerde waarde was nul
, we doen gewoon niets, omdat dit impliceert dat de gebruiker niet echt op een puzzelstuk klikte. Als we echter een puzzelstuk ophalen, willen we het aan de muis bevestigen en het een beetje laten vervagen om de onderliggende stukken zichtbaar te maken. Dus hoe doen we dit?
Eerst wissen we de canvas
gebied waar het stuk zat voordat we erop klikten. We gebruiken clearRect ()
nogmaals, maar in dit geval passeren we alleen het gebied verkregen van de _currentPiece
voorwerp. Voordat we het opnieuw tekenen, willen we dat opslaan()
de context van het canvas voordat je verder gaat. Dit zal ervoor zorgen dat alles wat we na het sparen aantrekken niet zomaar iets op zijn weg trekt. We doen dit omdat we het gesleepte stuk iets laten vervagen en de stukken eronder willen zien. Als we niet hebben gebeld opslaan()
, we zouden gewoon afbeeldingen tekenen op de manier - vervaagd of niet.
Nu tekenen we de afbeelding zodat het midden ervan op de muisaanwijzer staat. De eerste 5 parameters van drawImage
zal altijd hetzelfde zijn in de hele applicatie. Wanneer u klikt, worden de volgende twee parameters bijgewerkt om zichzelf te centreren op de muisaanwijzer. De laatste twee parameters, de breedte
en hoogte
tekenen, zal ook nooit veranderen.
Ten slotte noemen we de herstellen()
methode. Dit betekent in feite dat we klaar zijn met de nieuwe alpha-waarde en we willen alle eigenschappen terugzetten naar waar ze waren. Om deze functie af te sluiten, voegen we nog twee luisteraars toe. Een voor wanneer we de muis verplaatsen (het puzzelstuk slepen) en een voor wanneer we loslaten (laat het puzzelstuk vallen).
checkPieceClicked ()
Functiefunction checkPieceClicked () var i; var stuk; voor (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 retourstuk; return null;
Nu moeten we een beetje teruggaan. We hebben kunnen bepalen op welk stuk is geklikt, maar hoe hebben we het gedaan? Het is eigenlijk best simpel. Wat we moeten doen is door alle puzzelstukjes bladeren en bepalen of de klik binnen de grenzen van een van onze objecten lag. Als we er een vinden, retourneren we het gematchte object en beëindigen we de functie. Als we niets vinden, keren we terug nul
.
updatePuzzle ()
Functiefunction 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; var stuk; voor (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 = stuk; _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);
Nu terug naar het slepen. We noemen deze functie wanneer de gebruiker de muis beweegt. Dit is de grootste functie van de toepassing omdat deze verschillende dingen doet. Laten we beginnen. Ik zal het opsplitsen als we gaan.
_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;
Begin met instellen _currentDropPiece
naar nul
. We moeten dit terugzetten naar nul
op update vanwege de kans dat ons stuk terug naar huis werd gesleept. We willen de vorige niet _currentDropPiece
waarde rondhangen. Vervolgens stellen we de _muis
object op dezelfde manier als bij klikken.
_stage.clearRect (0,0, _puzzleWidth, _puzzleHeight);
Hier moeten we alle afbeeldingen op het canvas wissen. In essentie moeten we de puzzelstukjes opnieuw tekenen omdat het object dat erop wordt gesleept hun uiterlijk zal beïnvloeden. Als we dit niet zouden doen, zouden we een aantal zeer vreemde resultaten zien na het pad van ons gesleept puzzelstukje.
var i; var stuk; voor (i = 0; i < _pieces.length;i++)
Begin met het opzetten van onze gebruikelijke stukjes loop.
stuk = _pieces [i]; if (piece == _currentPiece) continue;
Maak onze stuk
referentie zoals gewoonlijk. Controleer vervolgens of het stuk waarnaar we momenteel verwijzen hetzelfde is als het stuk dat we aan het slepen zijn. Als dit het geval is, gaat u verder met de lus. Hierdoor blijft de sleuf van het gesleept stuk leeg.
_stage.drawImage (_img, piece.sx, piece.sy, _pieceWidth, _pieceHeight, piece.xPos, piece.yPos, _pieceWidth, _pieceHeight); _stage.strokeRect (piece.xPos, piece.yPos, _pieceWidth, _pieceHeight);
Als je verder gaat, maak je het puzzelstuk opnieuw met behulp van de eigenschappen op precies dezelfde manier als toen je ze voor het eerst tekende. Je moet ook de rand tekenen.
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 = stuk; _stage.save (); _stage.globalAlpha = .4; _stage.fillStyle = PUZZLE_HOVER_TINT; _stage.fillRect (_currentDropPiece.xPos, _currentDropPiece.yPos, _pieceWidth, _pieceHeight); _stage.restore ();
Omdat we een verwijzing hebben naar elk object in de lus, kunnen we deze gelegenheid ook gebruiken om te controleren of het gesleepte stuk er bovenop staat. We doen dit omdat we de gebruiker feedback willen geven over het onderdeel waarop het kan worden geplaatst. Laten we nu die code eens doornemen.
Eerst willen we zien of deze lus al een druppeldoel heeft geproduceerd. Als dat zo is, hoeven we ons niet druk te maken, omdat er maar één doel kan vallen en elke beweging van een muis. Als niet, _currentDropPiece
zal zijn nul
en we kunnen doorgaan met de logica. Omdat onze muis zich in het midden van het gesleepte stuk bevindt, hoeven we alleen maar te bepalen met welk ander stuk onze muis is geplaatst.
Gebruik vervolgens onze handige checkPieceClicked ()
functie om te bepalen of de muis over het huidige stukobject in de lus zweeft. Als dat zo is, stellen we de _currentDropPiece
verander en teken een gekleurde doos over het puzzelstukje om aan te geven dat dit nu het doel is.
Onthoud om opslaan()
en herstellen()
. Anders krijg je de getinte doos en niet de afbeelding eronder.
_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);
Last but not least moeten we het gesleepte stuk opnieuw tekenen. De code is dezelfde als toen we er voor het eerst op klikten, maar de muis is verplaatst en zijn positie zal worden bijgewerkt.
pieceDropped ()
Functiefunction 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, het ergste is achter de rug. We zijn nu succesvol een puzzelstukje aan het slepen en krijgen zelfs visuele feedback over waar het valt. Nu rest alleen nog het stuk. Laten we eerst de luisteraars meteen verwijderen, omdat er niets wordt gesleept.
Controleer dat vervolgens _currentDropPiece
is niet nul
. Als dat zo is, betekent dit dat we het naar het thuisgebied van het stuk hebben gesleept en niet over een ander slot. Als het dat niet is nul
, we gaan verder met de functie.
Wat we nu doen is simpelweg de xpos
en YPOS
van elk stuk. We maken een snel tijdelijk object als een buffer om een van de waarden van het object in het ruilproces te houden. Op dit punt hebben de twee stukken allebei nieuw xpos
en YPOS
waarden en zullen bij de volgende trekking in hun nieuwe huizen klikken. Dat is wat we nu gaan doen, tegelijkertijd controleren of het spel is gewonnen.
resetPuzzleAndCheckWin ()
Functiefunction resetPuzzleAndCheckWin () _stage.clearRect (0,0, _puzzleWidth, _puzzleHeight); var gameWin = true; var i; var stuk; voor (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);
Nogmaals, wis de canvas
en stel een gameWin
variabele, instellen op waar
standaard. Ga nu verder met onze al te bekende stukjes loop.
De code hier zou er bekend uit moeten zien, dus we zullen er niet overheen gaan. Het trekt gewoon de stukjes terug naar hun originele of nieuwe slots. Binnen deze loop willen we zien of elk stuk in zijn winnende positie wordt getekend. Dit is eenvoudig: we controleren om te zien of onze sx
en sy
eigenschappen komen overeen met xpos
en YPOS
. Zo niet, dan weten we dat we de puzzel en de set niet kunnen winnen gameWin
naar vals
. Als we het luk maakten met iedereen op hun winnende plaatsen, hebben we snel een beslissing genomen time-out
om onze te bellen spel is over()
methode. (We hebben een time-out ingesteld zodat het scherm niet zo drastisch verandert bij het laten vallen van het puzzelstukje.)
spel is over()
Functiefunction gameOver () document.onmousedown = null; document.onmousemove = null; document.onmouseup = null; initPuzzle ();
Dit is onze laatste functie! Hier verwijderen we gewoon alle luisteraars en bellen initPuzzle ()
, die alle noodzakelijke waarden opnieuw instelt en wacht tot de gebruiker opnieuw speelt.
Klik hier om het eindresultaat te bekijken.
Zoals u kunt zien, kunt u in HTML5 veel nieuwe creatieve dingen doen met behulp van geselecteerde bitmapgebieden van geladen afbeeldingen en tekeningen. Je kunt deze applicatie eenvoudig uitbreiden door scoren toe te voegen en misschien zelfs een timer om hem meer te laten spelen. Een ander idee zou zijn om de moeilijkheidsgraad te vergroten en een andere afbeelding te selecteren in de spel is over()
functie, waarbij de spelniveaus worden weergegeven.