Implementación del clásico Tetris en JavaScript vanilla, usando HTML5 Canvas y CSS. Sin dependencias externas, sin frameworks, sin proceso de build: solo abrir y jugar.
Es una versión jugable del Tetris clásico con todas las mecánicas que esperarías:
- Tablero de 10 × 20 celdas.
- Las 7 piezas estándar (I, O, T, S, Z, J, L) con colores diferenciados.
- 5 piezas especiales no estándar que aparecen ocasionalmente (ver Piezas especiales).
- Rotación con wall kicks básicos (pequeños desplazamientos para que la pieza pueda rotar pegada a la pared).
- Soft drop (bajada acelerada) y hard drop (caída instantánea).
- Pieza fantasma (ghost piece): muestra dónde aterrizará la pieza actual.
- Vista previa de la siguiente pieza.
- Sistema de puntuación clásico de Tetris (100 / 300 / 500 / 800 multiplicado por nivel).
- Niveles que aumentan cada 10 líneas y aceleran la caída.
- Pausa y Game Over con opción de reinicio.
Además de las 7 piezas clásicas, el juego incluye 5 piezas no estándar:
| Pieza | Bloques | Forma | Cuándo aparece |
|---|---|---|---|
| + (rosa) | 5 | .#. / ### / .#. |
Pool de especiales |
| U (turquesa) | 5 | #.# / ### |
Pool de especiales |
| Y (índigo) | 5 | ..#. / .##. / ..#. / ..#. |
Pool de especiales |
| 3×3 hueca (marrón) | 8 | ### / #.# / ### |
Pool de especiales |
| 1×1 (blanca) | 1 | # |
Recompensa tras eliminar 4 líneas |
- Cada vez que se genera una pieza hay un 8 % de probabilidad de que salga una del pool de especiales (
+,U,Yo hueca), desde el nivel 1. - El bloque 1×1 no entra en el sorteo: se otorga como recompensa al hacer un Tetris (4 líneas de golpe). Se entrega como la siguiente pieza, así que aparece primero en la vista previa.
- La 3×3 hueca deja un agujero en el centro que solo puede rellenarse con piezas posteriores: es la pieza más difícil del juego.
Los pentominós de 5 bloques rompen a propósito la aritmética del Tetris clásico, donde toda pieza ocupa exactamente 4 celdas.
No hay nada que instalar ni compilar. Tienes dos opciones:
open index.html # macOS
xdg-open index.html # Linux
start index.html # WindowsCualquier servidor estático funciona. Algunos ejemplos:
# Con Python 3
python3 -m http.server 8000
# Con Node.js (npx)
npx serve .
# Con PHP
php -S localhost:8000Después abre http://localhost:8000 en el navegador.
| Tecla | Acción |
|---|---|
← / → |
Mover la pieza horizontalmente |
↑ o X |
Rotar la pieza en sentido horario |
↓ |
Soft drop (bajar más rápido) |
Espacio |
Hard drop (caída instantánea) |
P |
Pausar / reanudar |
El juego se compone de tres archivos que cooperan:
Define la estructura visual:
- Un
<canvas id="board">de 300 × 600 píxeles donde se renderiza el tablero. - Un panel lateral con
SCORE,LINES,LEVEL, vista de la siguiente pieza y la lista de controles. - Un overlay para los estados PAUSA y GAME OVER.
Aporta el aspecto visual con estética dark / retro arcade: fondo oscuro, tipografía monoespaciada para los marcadores y backdrop blur en los overlays.
Contiene toda la lógica del juego. A grandes rasgos:
- Modelo del tablero: una matriz
ROWS × COLSdonde cada celda guarda0(vacía) o un índice de color (1–12) que identifica la pieza. - Piezas: definidas como matrices cuadradas. Para rotar se calcula la transposición + reverso de filas (
rotateCW). - Generación de piezas (
pickType): si hay una recompensa pendiente devuelve el bloque 1×1; si no, sortea una especial con probabilidadSPECIAL_CHANCEy en caso contrario una de las 7 estándar. - Detección de colisiones (
collide): comprueba que ninguna celda de la pieza salga del tablero ni se solape con bloques ya fijados. - Wall kicks (
tryRotate): si la rotación choca, intenta desplazar la pieza ±1 y ±2 columnas antes de descartar el giro. - Game loop (
loop): basado enrequestAnimationFrame, acumula el tiempo transcurrido y baja la pieza una fila cuando se superadropInterval. - Limpieza de líneas (
clearLines): recorre el tablero de abajo hacia arriba; cada fila completa se elimina y se inserta una vacía en la cima. - Puntuación: usa la tabla clásica
[0, 100, 300, 500, 800]multiplicada por el nivel actual; el hard drop suma 2 puntos por celda recorrida y el soft drop 1 punto por fila. - Nivel y velocidad: el nivel sube cada 10 líneas; la velocidad de caída se calcula como
max(100, 1000 − (level − 1) × 90)milisegundos. - Ghost piece (
ghostY): proyecta la posición final de la pieza actual hacia abajo y la dibuja conglobalAlpha = 0.2.
init()
├─ createBoard() → matriz vacía
├─ next = randomPiece()
├─ spawn() → mueve next a current y genera nueva next
└─ requestAnimationFrame(loop)
↓
loop(timestamp)
├─ acumula dt
├─ si dt ≥ dropInterval → baja la pieza o llama a lockPiece()
├─ draw() (grid + tablero + ghost + pieza actual)
└─ requestAnimationFrame(loop)
keydown → mover / rotar / soft-drop / hard-drop / pausa
Cuando una pieza recién generada ya colisiona al aparecer (spawn), se dispara endGame() y se muestra el overlay de Game Over.
- HTML5 — marcado y dos elementos
<canvas>(tablero y vista previa). - CSS3 — flexbox, variables de color,
backdrop-filterybox-shadow. - JavaScript (ES6+) vanilla —
const/let, arrow functions, spread operator,Array.from, template literals… - Canvas 2D API — para todo el renderizado del juego.
requestAnimationFrame— para el bucle de juego sincronizado con el navegador.
Sin dependencias. No hay package.json, ni bundler, ni transpilador.
03-tetris/
├── index.html # Estructura del DOM y canvas
├── style.css # Estilos del juego (dark theme)
├── game.js # Toda la lógica del Tetris (~300 líneas)
└── README.md
Algunos parámetros fáciles de tunear en game.js:
| Constante | Significado | Por defecto |
|---|---|---|
COLS |
Columnas del tablero | 10 |
ROWS |
Filas del tablero | 20 |
BLOCK |
Tamaño en píxeles de cada celda | 30 |
COLORS |
Paleta de colores por tipo de pieza | 12 colores |
LINE_SCORES |
Puntos por 1, 2, 3 o 4 líneas eliminadas | [0,100,300,500,800] |
dropInterval |
Velocidad inicial de caída en ms | 1000 |
SPECIAL_CHANCE |
Probabilidad de que salga una pieza especial | 0.08 |
SPECIAL_TYPES |
Tipos que entran en el sorteo de especiales | [8, 9, 10, 12] |
Si cambias
COLS,ROWSoBLOCK, recuerda ajustar tambiénwidthyheightdel<canvas id="board">enindex.htmlpara que coincida (COLS × BLOCK×ROWS × BLOCK).
Proyecto de uso libre con fines educativos y de práctica.