Version Beta
This commit is contained in:
commit
a978d0b7a5
BIN
assets/Tetris.mp3
Normal file
BIN
assets/Tetris.mp3
Normal file
Binary file not shown.
284
game.js
Normal file
284
game.js
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
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`;
|
||||
}
|
||||
34
index.html
Normal file
34
index.html
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<title>Tetris</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="gui">
|
||||
<canvas id="tablero" width="200" height="400"></canvas>
|
||||
<div id="marcador">
|
||||
<h2>Tetris</h2>
|
||||
<p>Score: <span id="score">0</span> </p>
|
||||
<div id="leyendaTeclas">
|
||||
<div><span style="font-size: 24px;">➡️</span> Cursor derecha</div>
|
||||
<div><span style="font-size: 24px;">⬅️</span> Cursor izquierda</div>
|
||||
<div><span style="font-size: 24px;">⬇️</span> Cursor abajo</div>
|
||||
<div><span style="font-size: 24px;">🔄</span> Barra espaciadora</div>
|
||||
<div><span style="font-size: 24px;">1️⃣</span> Ventana debug</div>
|
||||
</div>
|
||||
<div style="font-size: 8px;">Esc - Salir partida</div>
|
||||
<button id="startButton" onclick="iniciarPartida()">Start</button>
|
||||
</div>
|
||||
</div>
|
||||
<textarea id="debug" cols="30" rows="10"></textarea>
|
||||
<audio id="musica" src="./assets/Tetris.mp3" loop></audio>
|
||||
<script src="game.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
67
style.css
Normal file
67
style.css
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
* {
|
||||
box-sizing: border-box;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: linear-gradient(to bottom right, #0f2027, #203a43, #2c5364);
|
||||
min-height: 100vh;
|
||||
min-width: 100vw;
|
||||
color: white;
|
||||
font-family: "Press Start 2P", cursive;
|
||||
}
|
||||
|
||||
#gui {
|
||||
padding-top: 2%;
|
||||
width: fit-content;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
#tablero {
|
||||
border: 4px solid white;
|
||||
background-color: #282829;
|
||||
height: 80vh;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
#marcador {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
textarea {
|
||||
position: absolute;
|
||||
top: 2%;
|
||||
left: 1rem;
|
||||
background-color: transparent;
|
||||
color: white;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#leyendaTeclas {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
button {
|
||||
font-size: 16px;
|
||||
background-color: #4caf50;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
margin: 4px 2px;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user