Crear un rompecabezas de intercambio de azulejos de lona HTML5

En este tutorial, trabajaremos con el lienzo HTML5 y Javascript para crear un juego dinámico de intercambio de fichas. El resultado será un rompecabezas que funciona con cualquier imagen dada y tiene niveles de dificultad flexibles que se ajustan fácilmente.


El puzzle completo de lienzo HTML5

Aquí está un tiro rápido del rompecabezas que estaremos construyendo:


Dele "click" para jugar

Un par de notas:

  • Compatibilidad entre navegadores: Este rompecabezas fue probado y funciona en todas las versiones de Safari, Firefox y Chrome que son compatibles con lona elemento.
  • Móvil: El código proporcionado aquí funciona en el navegador de escritorio mencionado anteriormente y no está optimizado para dispositivos móviles. El rompecabezas se cargará y se procesará bien, pero debido a los comportamientos de toque y arrastre en los navegadores móviles, se requiere optimización para que funcione correctamente. La optimización de este rompecabezas para dispositivos móviles se tratará en un futuro tutorial..
  • Dificultad Ajustable: El código contiene una constante., PUZZLE_DIFICULTAD, Eso determina el número de piezas. En la demostración anterior, esto se establece en 4, Dando un puzzle 4x4. Podemos cambiar esto fácilmente, por ejemplo, esta versión tiene una PUZZLE_DIFICULTAD de 10.

Empezando

Para empezar, crea un directorio para el proyecto. Coloque una imagen en el directorio que desea utilizar como su rompecabezas. Cualquier imagen compatible con la web servirá, y puede ser de cualquier tamaño que su corazón desee, solo asegúrese de que se ajuste al pliegue de la ventana de su navegador..


Paso 1: Creando la plantilla HTML

Abra un nuevo archivo con su editor de texto favorito y guárdelo en el directorio de su proyecto, al lado de su imagen. A continuación, rellene este básico HTML modelo.

    Puzzle HTML5      

Todo lo que necesitamos hacer aquí es crear un estándar. HTML5 plantilla que contiene uno lona etiqueta con el carné de identidad de “lienzo”. Escribiremos un onload oyente en el cuerpo etiqueta que llamará nuestra en eso() funciona cuando se dispara.

Ahora comienza colocando el cursor dentro de la guión etiqueta. De aquí en adelante es todo javascript. Con la excepción de las variables iniciales, organizaré las secciones por función. Primero mostrándote el código y luego explicando la lógica.

Listo? Vamos a hacerlo bien!


Paso 2: Configuración de nuestras variables

Configuremos nuestras variables y echemos un vistazo a cada una..

 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;

Primero tenemos un par de constantes: PUZZLE_DIFICULTAD y PUZZLE_HOVER_TINT. los PUZZLE_DIFICULTAD constante mantiene el número de piezas en nuestro rompecabezas. En esta aplicación, las filas y columnas siempre coinciden, por lo que al configurar PUZZLE_DIFICULTAD a 4, Conseguimos 16 piezas de rompecabezas en total. Aumentar esto aumenta la dificultad del rompecabezas..

A continuación hay una serie de variables:

  • _lona y _escenario mantendrá una referencia al lienzo y a su contexto de dibujo, respectivamente. Hacemos esto para no tener que escribir la consulta completa cada vez que los usamos. Y los estaremos usando mucho.!
  • _img será una referencia a la imagen cargada, de la que copiaremos píxeles en toda la aplicación.
  • _puzzleWidth, _puzzleHeight, _pieceWidth, y _pieceHeight se utilizará para almacenar las dimensiones de todo el rompecabezas y cada pieza individual del rompecabezas. Los configuramos una vez para evitar que se calculen una y otra vez cada vez que los necesitemos..
  • _currentPiece Mantiene una referencia a la pieza que actualmente está siendo arrastrada..
  • _currentDropPiece contiene una referencia a la pieza actualmente en posición para ser colocada. (En la demo, esta pieza está resaltada en verde).
  • _ratón Es una referencia que mantendrá la corriente del ratón. X y y posición. Esto se actualiza cuando se hace clic en el rompecabezas para determinar qué pieza se toca, y cuando se arrastra una pieza para determinar en qué pieza se está moviendo..

Ahora, a nuestras funciones..


Paso 3: El en eso() Función

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

Lo primero que queremos hacer en nuestra aplicación es cargar la imagen para el rompecabezas. El objeto de imagen se crea una primera instancia y se establece en nuestro _img variable. A continuación, escuchamos la carga evento que luego disparará nuestra onImage () Funciona cuando la imagen ha terminado de cargarse. Por último, establecemos la fuente de la imagen, que activa la carga..


Paso 4: El onImage () Función

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

Ahora que la imagen se ha cargado correctamente, podemos establecer la mayoría de las variables declaradas anteriormente. Hacemos esto aquí porque ahora tenemos información sobre la imagen y podemos establecer nuestros valores de manera apropiada.

Lo primero que hacemos es calcular el tamaño de cada pieza del rompecabezas. Hacemos esto dividiendo el PUZZLE_DIFICULTAD Valor por el ancho y alto de la imagen cargada. También recortamos la grasa de los bordes para darnos algunos números pares para trabajar y asegurarnos de que cada pieza pueda intercambiar apropiadamente las "ranuras" con otras.

A continuación, utilizamos nuestros nuevos valores de piezas de rompecabezas para determinar el tamaño total del rompecabezas y establecer estos valores en _puzzleWidth y _puzzleHeight.

Por último, cancelamos algunas funciones. - setCanvas () y initPuzzle ().


Paso 5: El setCanvas () Función

 función setCanvas () _canvas = document.getElementById ('lienzo'); _stage = _canvas.getContext ('2d'); _canvas.width = _puzzleWidth; _canvas.height = _puzzleHeight; _canvas.style.border = "1px negro sólido"; 

Ahora que nuestros valores de rompecabezas están completos, queremos configurar nuestro lona elemento. Primero ponemos nuestro _lona variable para hacer referencia a nuestra lona elemento, y _escenario para hacer referencia a su contexto.

Ahora configuramos el anchura y altura de nuestro lona para coincidir con el tamaño de nuestra imagen recortada, seguido de la aplicación de algunos estilos simples para crear un borde negro alrededor de nuestra lona para mostrar los límites de nuestro rompecabezas.


Paso 6: El initPuzzle () Función

 function 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 (); 

Aquí inicializamos el puzzle. Configuramos esta función de tal manera que podamos volver a llamarla más tarde cuando deseamos volver a jugar el rompecabezas. Cualquier otra cosa que haya que configurar antes de jugar no tendrá que volver a configurarse.

Primero nos ponemos _piezas como un vacío formación y crea el _ratón Objeto, que mantendrá la posición de nuestro ratón en toda la aplicación. A continuación ponemos la _currentPiece y _currentPieceDrop a nulo. (En la primera jugada estos valores ya estarían nulo, pero queremos asegurarnos de que se reinicien al volver a jugar el rompecabezas.)

Finalmente, es hora de dibujar! Primero dibujamos la imagen completa para mostrar al jugador lo que van a crear. Después de eso creamos algunas instrucciones simples llamando a nuestro createTitle () función.


Paso 7: El createTitle () Función

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

Aquí creamos un mensaje bastante simple que indica al usuario que haga clic en el rompecabezas para comenzar.
Nuestro mensaje será un rectángulo semitransparente que servirá como fondo de nuestro texto. Esto permite al usuario ver la imagen detrás de ella y también asegura que nuestro texto en blanco será legible en cualquier imagen

Simplemente establecemos estilo de relleno a negro y globalAlpha a .4, antes de rellenar un rectángulo negro corto en la parte inferior de la imagen.

Ya que globalAlpha afecta a todo el lienzo, tenemos que volver a ponerlo en 1 (opaco) antes de dibujar el texto. Para configurar nuestro título, configuramos el texto alineado al 'centro' y al textBaseline a 'medio'. También podemos aplicar algunos fuente propiedades.

Para dibujar el texto, usamos el fillText () método. Pasamos en el msg variable y colóquelo en el centro horizontal de la lona, y el centro vertical del rectángulo.


Paso 8: El buildPieces () Función

 function buildPieces () var i; pieza de var var xPos = 0; var yPos = 0; para (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 es hora de construir el puzzle.!

Hacemos esto construyendo un objeto para cada pieza. Estos objetos no serán responsables de la representación en el lienzo, sino de mantener referencias sobre qué dibujar y dónde. Dicho esto, vamos a ello.

En primer lugar, declaremos algunas variables que reutilizaremos a través del bucle. Queremos configurar el bucle para recorrer el número de piezas de rompecabezas que necesitamos. Obtenemos este valor multiplicando PUZZLE_DIFICULTAD por sí mismo - por lo que en este caso obtenemos 16.

En el lazo:

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

Comience creando un vacío trozo objeto. A continuación agregue el sx y sy Propiedades al objeto. En la primera iteración, estos valores son 0 y representar el punto en nuestra imagen de donde comenzaremos a dibujar. Ahora empújalo a la _piezas[] formación. Este objeto también contendrá las propiedades. xPos y yPos, lo que nos dirá la posición actual en el rompecabezas donde se debe dibujar la pieza. Vamos a barajar los objetos antes de poder reproducirlos, por lo que no es necesario configurar estos valores todavía..

Lo último que hacemos en cada bucle es aumentar la variable local. xPos por _pieceWidth. Antes de continuar con el ciclo, determinamos si necesitamos pasar a la siguiente fila de piezas al verificar si xPos está más allá del ancho del rompecabezas. Si es así, restablecemos xPos volver a 0 y aumentar yPos por _pieceHeight.

Ahora tenemos nuestras piezas de rompecabezas almacenadas muy bien en nuestro _piezas formación. En este punto, el código finalmente deja de ejecutarse y espera a que el usuario interactúe. Configuramos un oyente de clic en el documento para disparar el shufflePuzzle () Funciona cuando se activa, lo que comenzará el juego..


Paso 9: El shufflePuzzle () Función

 function shufflePuzzle () _pieces = shuffleArray (_pieces); _stage.clearRect (0,0, _puzzleWidth, _puzzleHeight); var i; pieza de var var xPos = 0; var yPos = 0; para (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); retorno o; 

Lo primero es lo primero: baraja la _piezas[] formación. Estoy usando una buena función de utilidad aquí que mezclará los índices de la matriz que se le pasa. La explicación de esta función está más allá del tema de este tutorial, así que seguiremos adelante, sabiendo que hemos barajado con éxito nuestras piezas. (Para obtener una introducción básica a la reproducción aleatoria, eche un vistazo a este tutorial).

Primero aclaremos todos los gráficos dibujados a la lona Para dar paso al dibujo de nuestras piezas. A continuación, configure la matriz de manera similar a como lo hicimos al crear nuestros objetos de pieza por primera vez.

En el lazo:

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

En primer lugar, use el yo Variable para configurar nuestra referencia al objeto pieza actual en el bucle. Ahora poblamos el xPos y yPos propiedades que mencioné anteriormente, que serán 0 en nuestra primera iteración.

Ahora, por fin, dibujamos nuestras piezas..

El primer parámetro de drawImage () Asigna la fuente de la imagen de la que queremos dibujar. Luego usa los objetos de la pieza. sx y sy propiedades, junto con _pieceWidth y _pieceHeight, para rellenar los parámetros que declaran el área de la imagen en la que se dibuja. Los últimos cuatro parámetros establecen el área del lona donde queremos dibujar. Usamos el xPos y yPos Valores que ambos estamos construyendo en el bucle y asignando al objeto..

Inmediatamente después de esto, hacemos un trazo rápido alrededor de la pieza para darle un borde, que la separará muy bien de las otras piezas..

Ahora esperamos que el usuario agarre una pieza configurando otra hacer clic oyente. Esta vez disparará un onPuzzleClick () función.


Paso 10: El onPuzzleClick () Función

 funcion 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; 

Sabemos que se hizo clic en el rompecabezas; Ahora necesitamos determinar en qué pieza se hizo clic. Este condicional simple nos dará la posición de nuestro mouse en todos los navegadores de escritorio modernos que admiten lona, usando cualquiera e.layerX y e.layerY o e.offsetX y e.offsetY. Utilice estos valores para actualizar nuestros _ratón objeto asignándole una X y un y propiedad para mantener la posición actual del mouse - en este caso, la posición donde se hizo clic.

En la línea 112 nos ponemos inmediatamente _currentPiece al valor devuelto de nuestro checkPieceClicked () función. Separamos este código porque queremos usarlo más adelante al arrastrar la pieza del rompecabezas. Explicaré esta función en el siguiente paso..

Si el valor devuelto era nulo, simplemente no hacemos nada, ya que esto implica que el usuario no hizo clic en una pieza del rompecabezas. Sin embargo, si recuperamos una pieza del rompecabezas, queremos unirla al mouse y desvanecerla un poco para revelar las piezas que se encuentran debajo. Entonces como hacemos esto?

Primero limpiamos el lona Área donde se sentó la pieza antes de hacer clic. Usamos clearRect () Una vez más, pero en este caso pasamos solo en el área obtenida de la _currentPiece objeto. Antes de redibujarlo, queremos salvar() El contexto del lienzo antes de proceder. Esto asegurará que cualquier cosa que dibujemos después de guardar no se limitará a dibujar nada en su camino. Hacemos esto porque estaremos desvaneciendo un poco la pieza arrastrada y queremos ver las piezas debajo de ella. Si no llamáramos salvar(), Acabábamos de dibujar sobre cualquier gráfico en el camino, descolorido o no.

Ahora dibujamos la imagen para que su centro quede posicionado en el puntero del mouse. Los primeros 5 parámetros de dibujar imagen Siempre será el mismo en toda la aplicación. Al hacer clic, los dos parámetros siguientes se actualizarán para centrarse en el puntero del mouse. Los dos últimos parámetros, el anchura y altura dibujar, tampoco cambiará nunca..

Por último llamamos al restaurar() método. Básicamente, esto significa que hemos terminado de usar el nuevo valor alfa y queremos restaurar todas las propiedades a donde estaban. Para concluir esta función añadimos dos oyentes más. Una para cuando movemos el mouse (arrastrando la pieza del rompecabezas) y otra para cuando soltamos (soltamos la pieza del rompecabezas).


Paso 11: El checkPieceClicked () Función

 función checkPieceClicked () var i; pieza de var para (i = 0; i < _pieces.length;i++) piece = _pieces[i]; if(_mouse.x < piece.xPos || _mouse.x > (piece.xPos + _pieceWidth) || _pardusco < piece.yPos || _mouse.y > (piece.yPos + _pieceHeight)) // PIECE NOT HIT else return piece;  devolver nulo; 

Ahora tenemos que retroceder un poco. Pudimos determinar en qué pieza se hizo clic, pero ¿cómo lo hicimos? Es bastante simple en realidad. Lo que debemos hacer es recorrer todas las piezas del rompecabezas y determinar si el clic estuvo dentro de los límites de cualquiera de nuestros objetos. Si encontramos uno, devolvemos el objeto coincidente y finalizamos la función. Si no encontramos nada, volvemos. nulo.


Paso 12: El updatePuzzle () Función

 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; pieza de var para (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) || _pardusco < 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); 

Ahora volvemos al arrastre. Llamamos a esta función cuando el usuario mueve el mouse. Esta es la función más importante de la aplicación, ya que está haciendo varias cosas. Vamos a empezar. Lo desglosaré a medida que avanzamos.

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

Empezar por la configuración _currentDropPiece a nulo. Necesitamos restablecer esto de nuevo a nulo en la actualización debido a la posibilidad de que nuestra pieza haya sido arrastrada a su hogar. No queremos lo anterior. _currentDropPiece valor que cuelga alrededor. A continuación ponemos la _ratón objeto de la misma manera que hicimos en clic.

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

Aquí tenemos que hacer claros todos los gráficos en el lienzo. Básicamente necesitamos volver a dibujar las piezas del rompecabezas porque el objeto que se arrastra hacia arriba afectará su apariencia. Si no hiciéramos esto, veríamos algunos resultados muy extraños siguiendo el camino de nuestra pieza de rompecabezas arrastrada.

 var i; pieza de var para (i = 0; i < _pieces.length;i++)

Empieza configurando nuestro habitual bucle de piezas..

En el lazo:

 pieza = _pieces [i]; if (pieza == _currentPiece) continuar; 

Crear nuestro trozo referencia como de costumbre. A continuación, compruebe si la pieza a la que estamos haciendo referencia actualmente es la misma que estamos arrastrando. Si es así, continúa el bucle. Esto mantendrá la ranura de inicio de la pieza arrastrada vacía..

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

Continuando, vuelva a dibujar la pieza del rompecabezas usando sus propiedades exactamente de la misma manera que lo hicimos cuando las dibujamos por primera vez. Tendrás que dibujar el borde también.

 if (_currentDropPiece == null) if (_mouse.x < piece.xPos || _mouse.x > (piece.xPos + _pieceWidth) || _pardusco < 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 (); 

Ya que tenemos una referencia a cada objeto en el bucle, también podemos usar esta oportunidad para verificar si la pieza arrastrada está encima de él. Hacemos esto porque queremos dar retroalimentación al usuario sobre qué pieza se puede colocar. Vamos a profundizar en ese código ahora.

Primero queremos ver si este bucle ya ha producido un objetivo de caída. Si es así, no debemos molestarnos, ya que solo es posible un objetivo de lanzamiento y cualquier movimiento del mouse. Si no, _currentDropPiece estarán nulo y podemos proceder a la lógica. Ya que nuestro mouse está en el medio de la pieza arrastrada, todo lo que necesitamos hacer es determinar en qué otra pieza está nuestro mouse..

A continuación, utilice nuestro práctico checkPieceClicked () función para determinar si el mouse se desplaza sobre el objeto de pieza actual en el bucle. Si es así, establecemos la _currentDropPiece variable y dibuja un cuadro teñido sobre la pieza del rompecabezas, lo que indica que ahora es el objetivo de caída.

Recuerda salvar() y restaurar(). De lo contrario, obtendrías la caja teñida y no la imagen debajo..

Fuera de la lupa:

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

Por último, pero no menos importante, tenemos que volver a dibujar la pieza arrastrada. El código es el mismo que cuando hicimos clic en él por primera vez, pero el mouse se movió para que su posición se actualice.


Paso 13: El pieceDropped () Función

 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, lo peor está detrás de nosotros. Ahora estamos arrastrando con éxito una pieza del rompecabezas e incluso obteniendo retroalimentación visual sobre dónde se dejará caer. Ahora todo lo que queda es dejar caer la pieza. Primero eliminemos a los oyentes de inmediato, ya que no se está arrastrando nada..

A continuación, compruebe que _currentDropPiece no es nulo. Si es así, esto significa que lo arrastramos de nuevo a la zona de inicio de la pieza y no a otra ranura. Si no es nulo, continuamos con la función.

Lo que hacemos ahora es simplemente cambiar la xPos y yPos de cada pieza. Hacemos un objeto temporal rápido como un búfer para mantener uno de los valores del objeto en el proceso de intercambio. En este punto, las dos piezas tienen nuevas xPos y yPos valores, y se ajustarán a sus nuevos hogares en el próximo sorteo. Eso es lo que haremos ahora, verificando simultáneamente si el juego ha sido ganado..


Paso 14: El resetPuzzleAndCheckWin () Función

 function resetPuzzleAndCheckWin () _stage.clearRect (0,0, _puzzleWidth, _puzzleHeight); var gameWin = true; var i; pieza de var para (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);  

Una vez más, borra el lona y configurar un juegoWin variable, configurándolo para cierto por defecto. Ahora proceda con nuestro bucle de piezas muy familiar.

El código aquí debería ser familiar para que no lo revisemos. Simplemente dibuja las piezas de nuevo en sus ranuras originales o nuevas. Dentro de este bucle, queremos ver si cada pieza se está dibujando en su posición ganadora. Esto es simple: verificamos si nuestro sx y sy propiedades coinciden con xPos y yPos. Si no, sabemos que posiblemente no podríamos ganar el rompecabezas y poner juegoWin a falso. Si superamos el ciclo con todos en sus lugares ganadores, configuramos un rápido se acabó el tiempo para llamar a nuestro juego terminado() método. (Establecemos un tiempo de espera para que la pantalla no cambie tan drásticamente al soltar la pieza del rompecabezas).


Paso 15: El juego terminado() Función

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

¡Esta es nuestra última función! Aquí solo eliminamos a todos los oyentes y llamamos. initPuzzle (), que restablece todos los valores necesarios y espera a que el usuario vuelva a jugar.


Conclusión

Haga clic aquí para ver el resultado final..

Como puede ver, puede hacer muchas cosas creativas nuevas en HTML5 utilizando áreas de mapa de bits seleccionadas de imágenes cargadas y dibujos. Puede extender esta aplicación fácilmente agregando puntuación y quizás incluso un temporizador para darle más juego. Otra idea sería aumentar la dificultad y seleccionar una imagen diferente en el juego terminado() Función, dando los niveles de juego..