tetromino/game.js
2024-03-09 12:14:14 +01:00

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`;
}