285 lines
6.3 KiB
JavaScript
285 lines
6.3 KiB
JavaScript
const audio = document.getElementById("musica");
|
|
const startButton = document.getElementById("startButton");
|
|
const debugTextArea = document.getElementById("debug");
|
|
const canvas = document.getElementById("tablero");
|
|
const ctx = canvas.getContext("2d");
|
|
ctx.scale(20, 20);
|
|
const marcador = document.getElementById("score");
|
|
const FILAS = 20;
|
|
const COLUMNAS = 10;
|
|
const FPS = 60;
|
|
|
|
const PIEZAS = [
|
|
[[1, 1, 1, 1]],
|
|
[
|
|
[2, 2, 2],
|
|
[0, 0, 2],
|
|
],
|
|
[
|
|
[3, 3, 3],
|
|
[3, 0, 0],
|
|
],
|
|
[
|
|
[4, 4],
|
|
[4, 4],
|
|
],
|
|
[
|
|
[5, 5, 0],
|
|
[0, 5, 5],
|
|
],
|
|
[
|
|
[0, 6, 6],
|
|
[6, 6, 0],
|
|
],
|
|
[
|
|
[7, 7, 7],
|
|
[0, 7, 0],
|
|
],
|
|
];
|
|
const COLORES_PIEZAS = {
|
|
0: "#282829", // Fondo oscuro
|
|
1: "#FFFFFF", // Blanco para cyan
|
|
2: "#FFA500", // Naranja
|
|
3: "#FFFF00", // Amarillo
|
|
4: "#00FF00", // Verde
|
|
5: "#FF0000", // Rojo
|
|
6: "#800080", // Púrpura
|
|
7: "#0000FF", // Azul
|
|
};
|
|
|
|
const KEYDOWNHANDLER = (event) => {
|
|
if (event.key === "ArrowDown") {
|
|
moverPiezaAbajo();
|
|
} else if (event.key === "ArrowLeft") {
|
|
moverPiezaIzquierda();
|
|
} else if (event.key === "ArrowRight") {
|
|
moverPiezaDerecha();
|
|
} else if (event.key === " ") {
|
|
rotarPieza();
|
|
} else if (event.key === "1") {
|
|
toggleDebug();
|
|
} else if (event.key === "Escape") {
|
|
gameOver();
|
|
}
|
|
};
|
|
|
|
let debugFlag = false;
|
|
let lineasVelocidad = 10;
|
|
let velocidadCaida = 400;
|
|
let intervalBuclePrincipal;
|
|
let tiempoUltimoMovimiento = 0;
|
|
let tablero = [];
|
|
let puntuacion = 0;
|
|
let piezaJugador;
|
|
let piezaJugadorX;
|
|
let piezaJugadorY;
|
|
|
|
audio.preload = "auto";
|
|
|
|
function generaPiezaAleatoria() {
|
|
const indice = Math.floor(Math.random() * PIEZAS.length);
|
|
return PIEZAS[indice];
|
|
}
|
|
|
|
function dibujaPiezaEnTablero(pieza, offsetX, offsetY) {
|
|
pieza.forEach((fila, y) => {
|
|
fila.forEach((valor, x) => {
|
|
if (valor) {
|
|
dibujarCuadro(x + offsetX, y + offsetY, valor);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function soltarNuevaPieza() {
|
|
piezaJugador = generaPiezaAleatoria();
|
|
piezaJugadorX = Math.floor(COLUMNAS / 2) - 1;
|
|
piezaJugadorY = 0;
|
|
}
|
|
|
|
function dibujarTablero() {
|
|
for (let fila = 0; fila < FILAS; fila++) {
|
|
for (let columna = 0; columna < COLUMNAS; columna++) {
|
|
dibujarCuadro(columna, fila, tablero[fila][columna]);
|
|
}
|
|
}
|
|
}
|
|
|
|
function dibujarCuadro(x, y, color) {
|
|
ctx.fillStyle = COLORES_PIEZAS[color];
|
|
ctx.fillRect(x, y, 1, 1);
|
|
}
|
|
|
|
function actualizaMarcador() {
|
|
marcador.textContent = puntuacion;
|
|
}
|
|
|
|
function inicializarTablero() {
|
|
for (let fila = 0; fila < FILAS; fila++) {
|
|
tablero[fila] = [];
|
|
for (let columna = 0; columna < COLUMNAS; columna++) {
|
|
tablero[fila][columna] = 0;
|
|
}
|
|
}
|
|
puntuacion = 0;
|
|
dibujarTablero();
|
|
actualizaMarcador();
|
|
soltarNuevaPieza();
|
|
}
|
|
|
|
function moverPiezaAbajo() {
|
|
piezaJugadorY++;
|
|
if (colisiona(piezaJugador, piezaJugadorX, piezaJugadorY)) {
|
|
if (piezaJugadorY <= 1) {
|
|
gameOver();
|
|
}
|
|
piezaJugadorY--;
|
|
fijarPiezaTablero();
|
|
soltarNuevaPieza();
|
|
}
|
|
}
|
|
|
|
function moverPiezaIzquierda() {
|
|
piezaJugadorX--;
|
|
if (colisiona(piezaJugador, piezaJugadorX, piezaJugadorY)) {
|
|
piezaJugadorX++; // Deshacer el movimiento si hay colisión
|
|
}
|
|
}
|
|
|
|
function moverPiezaDerecha() {
|
|
piezaJugadorX++;
|
|
if (colisiona(piezaJugador, piezaJugadorX, piezaJugadorY)) {
|
|
piezaJugadorX--; // Deshacer el movimiento si hay colisión
|
|
}
|
|
}
|
|
|
|
function rotarPieza() {
|
|
const piezaRotada = [];
|
|
for (let y = 0; y < piezaJugador[0].length; y++) {
|
|
piezaRotada[y] = [];
|
|
for (let x = 0; x < piezaJugador.length; x++) {
|
|
piezaRotada[y][x] = piezaJugador[piezaJugador.length - 1 - x][y];
|
|
}
|
|
}
|
|
if (!colisiona(piezaRotada, piezaJugadorX, piezaJugadorY)) {
|
|
piezaJugador = piezaRotada;
|
|
}
|
|
}
|
|
|
|
function colisiona(pieza, offsetX, offsetY) {
|
|
for (let y = 0; y < pieza.length; y++) {
|
|
for (let x = 0; x < pieza[y].length; x++) {
|
|
if (
|
|
pieza[y][x] &&
|
|
(tablero[y + offsetY] && tablero[y + offsetY][x + offsetX]) !== 0
|
|
) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function fijarPiezaTablero() {
|
|
piezaJugador.forEach((fila, y) => {
|
|
fila.forEach((valor, x) => {
|
|
if (valor) {
|
|
tablero[piezaJugadorY + y][piezaJugadorX + x] = valor;
|
|
}
|
|
});
|
|
});
|
|
revisarLineasCompletas();
|
|
}
|
|
|
|
function revisarLineasCompletas() {
|
|
let lineasCompletas = 0;
|
|
for (let y = FILAS - 1; y >= 0; y--) {
|
|
let filaCompleta = true;
|
|
for (let x = 0; x < COLUMNAS; x++) {
|
|
if (tablero[y][x] === 0) {
|
|
filaCompleta = false;
|
|
break;
|
|
}
|
|
}
|
|
if (filaCompleta) {
|
|
tablero.splice(y, 1);
|
|
tablero.unshift(Array(COLUMNAS).fill(0));
|
|
y++;
|
|
lineasCompletas++;
|
|
}
|
|
}
|
|
if (lineasCompletas) {
|
|
lineasVelocidad -= lineasCompletas;
|
|
if (lineasVelocidad <= 0) {
|
|
lineasVelocidad = 10;
|
|
velocidadCaida -= 10;
|
|
}
|
|
switch (lineasCompletas) {
|
|
case 1:
|
|
puntuacion += 10;
|
|
break;
|
|
case 2:
|
|
puntuacion += 40;
|
|
break;
|
|
case 3:
|
|
puntuacion += 60;
|
|
break;
|
|
case 4:
|
|
puntuacion += 80;
|
|
break;
|
|
}
|
|
actualizaMarcador();
|
|
}
|
|
}
|
|
|
|
function actualizar() {
|
|
const ahora = Date.now();
|
|
const deltaTiempo = ahora - tiempoUltimoMovimiento;
|
|
|
|
if (deltaTiempo > velocidadCaida) {
|
|
tiempoUltimoMovimiento = ahora;
|
|
moverPiezaAbajo();
|
|
}
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
dibujarTablero();
|
|
dibujaPiezaEnTablero(piezaJugador, piezaJugadorX, piezaJugadorY);
|
|
debugLog();
|
|
}
|
|
|
|
function iniciarPartida() {
|
|
startButton.blur();
|
|
startButton.style.visibility = "hidden";
|
|
document.addEventListener("keydown", KEYDOWNHANDLER);
|
|
musica.play();
|
|
inicializarTablero();
|
|
intervalBuclePrincipal = setInterval(actualizar, 1000 / FPS);
|
|
}
|
|
|
|
function gameOver() {
|
|
clearInterval(intervalBuclePrincipal);
|
|
document.removeEventListener("keydown", KEYDOWNHANDLER);
|
|
startButton.style.visibility = "visible";
|
|
musica.pause();
|
|
musica.currentTime = 0;
|
|
startButton.focus();
|
|
}
|
|
|
|
function toggleDebug() {
|
|
if (debugFlag) {
|
|
debugFlag = false;
|
|
debugTextArea.style.display = "none";
|
|
} else {
|
|
debugFlag = true;
|
|
debugTextArea.style.display = "block";
|
|
}
|
|
}
|
|
|
|
function debugLog() {
|
|
debugTextArea.value =
|
|
`Filas: ${FILAS}\n` +
|
|
`Columnas: ${COLUMNAS}\n` +
|
|
`PosX: ${piezaJugadorX} - PosY: ${piezaJugadorY} \n` +
|
|
`Lineas hasta aumento de velocidad: ${lineasVelocidad}\n` +
|
|
`Velocidad ms/fila: ${velocidadCaida}\n`;
|
|
}
|