tetris Tailwind Templates

Tetris

Tetris realizado con Javascript, Canvas y Tailwind.

Sitio web

馃敽 TETRIS 馃敽

Descripci贸n general del proyecto.

Se ha utilizado vanilla Javascript, Canvas para la animaci贸n y Tailwind para los estilos. El proyecto consiste en el tradicional juego del tetris:

Tareas realizadas

鉁旓笍 Dibujo del tablero y su matriz.
鉁旓笍 Funcion que dibuje cada ficha.
鉁旓笍 Descenso autom谩tico de las piezas (animaci贸n).
鉁旓笍 Colores aleatorios en cada partida.
鉁旓笍 Movimiento con A-W-S-D y flechas.
鉁旓笍 Creaci贸n de la clase 'Bolsa' para la gesti贸n de fichas aleatorias.
鉁旓笍 Gesti贸n de colisiones.
鉁旓笍 Rotaci贸n de las piezas.
鉁旓笍 L贸gica para borrar filas con casillas ocupadas.
鉁旓笍 Score sin vista.
鉁旓笍 Gesti贸n de la velocidad.
鉁旓笍 Sonido.
鉁旓笍 Creaci贸n de la web con Tailwind.
鉁旓笍 Dise帽o de niveles, botones de sonido, play, selecci贸n en Tailwind.
鉁旓笍 Score con vista.
鉁旓笍 Mostrar la siguiente ficha dentro de la bolsa.
鉁旓笍 Dificultad HARD.
鉁旓笍 Desplazamiento aleatorio
鉁旓笍 Dise帽o adaptativo a m贸vil
鉁旓笍 Ventana del Game Over
鉁旓笍 localStorage + tabla de puntuaci贸n

Dificultades

El juego cuenta con 2 tipos de dificultades:

  • Normal
  • Hard

Hard

  • Mayor velocidad
  • Efecto blurr
  • Controles invertidos

Descripci贸n de algunas funcionalidades.

Tableros y piezas de diferentes colores.

El tetris trae una paleta de colores por defecto, pero gracias a la propiedad FILTER y al efecto hue-rotate() es posible hacer que cada partida tenga una apariencia diferente a la anterior.

Creaci贸n del Tablero.

Para la creaci贸n de un tablero 'gen茅rico' se ha utilizado POO (programaci贸n orientada a objetos) y CANVAS. En este caso, existe una clase llamada Tablero:

Esta clase tambi茅n tiene un m茅todo llamado setTablero() que realiza 2 funciones:

  • Por un lado, dibuja el tablero en el HTML.
  • Por otro lado, crea una matriz interna que representa ese tablero.

Comprobar la creaci贸n del tablero:

 1. Inspeccionar y seleccionar 'Fuentes'
 2. Crear un punto de ruptura en la linea 43 del main.js
 3. Recargar

Bolsa virtual de piezas.

La bolsa representa un conjunto de PIEZAS de la cual se va obteniendo una FICHA hasta quedar completamente vac铆a. Una vez vac铆a, se rellena autom谩ticamente con otro conjunto de PIEZAS aleatorias. Esto evita la repetici贸n de una misma ficha varias veces. La 煤nica vez que se da el caso de repetici贸n es cuando coincide la 煤ltima ficha de la primera bolsa con la primera ficha de la siguiente bolsa.

M茅todo que genera el array 'bolsa'.

PIEZAS es un array predefinido de las 7 piezas que tienen una letra y color. Ejemplo:

const PIEZAS = [
  ['T', "#E71D36"],
  ['Z', "#FF44FF"],
  ['S', "#F46036"],
  ['J', "yellow"],
  ['L', "#00FF00"],
  ['I', "cyan"],
  ['O', "white"]
]

Se hace una copia de la matriz PIEZAS y a partir del length de 'copia' se va sacando un n煤mero aleatorio.

En la primera vuelta el n煤mero ser谩 de 0 a 6, como splice muta la matriz, en la siguiente vuelta tendr谩 una longitud de 6 y el n煤mero aleatorio ser谩 de 0 a 5.

M茅todo que saca una ficha de la bolsa y la elimina.

Como el array 'bolsa' ya esta desordenado gracias al m茅todo anterior, basta con comprobar si quedan piezas en la bolsa y hacer un .splice() para sacar la ficha.

Despu茅s, he ampliado el m茅todo para saber cual va ser la siguiente pieza por salir. Al eliminar la pieza 'actual' con splice, si volvemos a llamar a this.piezasAleatorias[0] obtendremos la pr贸xima ficha.

Asimismo, podemos sacar la letra del array y concatenarla para crear una URL para la etiqueta <img>.

Borrar filas

Para borrar filas, cuando una pieza colisiona con otra o el tablero, cambia su valor interno de '1' a '2'. De esta forma, es posible iterar sobre el tablero y comprobar si una fila tiene todos sus valores a '2'.

En este caso es posible usar la funci贸n every() que nos devuelve true si todos los valores cumplen el valor especificado y false si no es as铆. La ventaja de usar este m茅todo es que, en el momento que no coincida un 煤nico valor para de buscar coincidencias, devuelve false y pasa a la siguiente fila.

Para insertar una nueva fila tambi茅n podemos usar:

  const fila = [0,0,0,0,0,0,0,0,0,0]

Selecci贸n aleatoria entre controles normales/invertidos

En un principio la dificultad HARD invert铆a los controles de movimiento hacia la derecha/izquierda para a帽adirle ese plus de dificultad. Sin embargo, si sigues jugando hay un momento en el que te acostumbras a la 'inversi贸n'.

Para evitar que esta funcionalidad solo sirva como 'sorpresa' he a帽adido un m茅todo adicional que, a partir de la segunda partida, seleccionar谩 de forma aleatoria entre controles invertidos y controles tradicionales. De esta forma, el jugador nunca sabr谩 si la partida va a tener los controles invertidos o no hasta que empiece a jugar.

Para implementar esta funcionalidad he usado sessionStorage que permite crear variables y guardarlas como clave/valor. Estos datos sobreviven a la recarga de p谩gina. Tambi茅n existe localStorage, que permite una persistencia de datos superior (sobrevive a recargas de p谩gina, a la apertura de la web en diferentes pesta帽as del navegador e incluso al cierre del mismo). En este caso, me interesaba que solo se mantuvieran durante el refresco de p谩gina para asegurar que la primera experiencia con el modo HARD siempre fuera con los controles invertidos.

M谩s informaci贸n aqu铆.

C贸digo del m茅todo

  1. Creamos una funci贸n para sacar un n煤mero aleatorio entre 0 y 10.
  2. Creamos la variable de session y la inicializamos con el valor 0.
  3. Como todos los datos se convierten a "String" es necesario hacer un parseInt para aumentar el valor del contador.
  4. Comparamos con IF-ELSE y asignamos el evento seg煤n el n煤mero de recargas web && el n煤mero aleatorio.

Esta funci贸n se ejecuta despu茅s de seleccionar el modo hard y jugar una partida.

Ejemplo de 'X' recargas y selecci贸n de controles 'normales'.

Ejemplo de 'X' recargas y selecci贸n de controles 'invertidos'.

Puntuaci贸n persistente sin BDD

El juego define 2 variables de localStorage para guardar el numero de partidas y la puntuaci贸n de la partida actual.

Al unir ambos, tendriamos el numero de la partida y los datos (puntuaci贸n) de la misma. Ejemplo:

  • partida 1, 3000 puntos
  • partida 2, 0 puntos
  • partida 3, 200 puntos

Despu茅s, se recorre todo el objeto y se imprime din谩micamente con Javascript en una tabla.

La raz贸n por la que se usa el .subString() es porque las claves o keys no pueden contener espacios en blanco. Es decir, puedes tener partida1, pero no partida 1.

Colisiones

Uno de los grandes desaf铆os de este juego es sin duda sus colisiones. Hay 3 tipos de colisiones que debes de manejar:

  • La colisi贸n con el final del tablero y fichas en el eje Y.
  • La colisi贸n con las fichas a tu izquierda y derecha.
  • La colisi贸n con los l铆mites del tablero a tu izquierda y derecha.

Para comprobar, por ejemplo, la colisi贸n con las fichas en el eje Y tienes que ver si la posici贸n actual de la ficha esta rellena y la posici贸n siguiente es una casilla ocupada o final del tablero.

La rotaci贸n de las piezas tambi茅n influye en este apartado. Por ejemplo, para calcular la posici贸n correcta de la pieza "I" tuve que ver si en su siguiente posici贸n no este fuera del tablero y las posiciones que fuera a ocupar la fila de esa ficha estuvieran libres (valor != 2).

Animaci贸n + EventHandler

Por un lado, el juego tiene una animaci贸n que desplaza la ficha una casilla en el eje Y cada segundo. Esta animaci贸n se realiza de forma autom谩tica mediante requestAnimation. Por otro lado, el jugador puede mover la ficha dentro de los l铆mites del tablero con (A-W-S-D o las flechas). Este evento lo gestiona exclusivamente el addEventListener.

Muchos de los problemas de pintado, superposici贸n de fichas y errores de colisi贸n ocurren por la desincronizaci贸n de estos dos m茅todos.

La soluci贸n para que tanto los eventos como las animaciones funcionen en armon铆a es usar algoritmos que calculen el tiempo entre las diferentes llamadas de forma precisa. Es decir, no podemos depender de setTimeout().

Utilizaremos la clase Date y calcularemos el tiempo que pasa entre la ejecuci贸n de funciones.

Adem谩s, esta f贸rmula tambi茅n permite evitar el desplazamiento autom谩tico de la pieza mientras el jugador la mueva o rote.

Recursos

Licencia

Tetris Game by Dmitry Poldnev is licensed under CC BY 4.0

Top categories

Loading Svelte Themes