APRENDE JAVASCRIPT CREANDO 7 JUEGOS RETRO EN 2025
Introducción a la programación de juegos retro con JavaScript
JavaScript es un pilar fundamental del desarrollo web, y una de las formas más efectivas y entretenidas de aprenderlo es mediante la creación de proyectos interactivos. Desarrollar juegos retro no solo permite practicar conceptos clave como manipulación del DOM, eventos y animaciones, sino que también fomenta la creatividad y el pensamiento lógico. Este tutorial te guiará paso a paso para construir clones de siete juegos clásicos: Piedra, Papel o Tijeras, Juego de Memoria, Whac-a-Mole, Breakout, Frogger, Connect Four y Space Invaders. Cada sección incluye explicaciones detalladas y ejemplos de código para que puedas implementar estos proyectos en tu entorno de desarrollo. No se requieren conocimientos avanzados, pero es útil tener una base en HTML, CSS y JavaScript básico. Al final, habrás creado aplicaciones jugables que podrás personalizar y compartir.
Configuración del entorno de desarrollo
Antes de comenzar, necesitas un entorno de desarrollo simple. Todo lo que requieres es un editor de código como Visual Studio Code, un navegador web moderno y una carpeta para tus proyectos. Crea una estructura básica para cada juego con los siguientes archivos:
proyecto-juego/
├── index.html
├── styles.css
├── script.js
El archivo index.html contendrá la estructura de la página, styles.css definirá los estilos visuales y script.js incluirá la lógica del juego. A continuación, un ejemplo de index.html básico:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Juego Retro</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<canvas id="gameCanvas"></canvas>
<script src="script.js"></script>
</body>
</html>
Este código establece un lienzo HTML5 (<canvas>) donde se renderizarán los gráficos de los juegos. Asegúrate de que todos los archivos estén en la misma carpeta y ábrelos en el navegador para verificar que funcionan.
Piedra, Papel o Tijeras
El juego Piedra, Papel o Tijeras es un excelente punto de partida para aprender lógica condicional y manejo de eventos. El objetivo es que el usuario elija una opción, la computadora genere una elección aleatoria y se determine un ganador. La interfaz puede ser tan simple como tres botones y un área para mostrar el resultado.
Primero, crea la interfaz en index.html:
<div id="game">
<button onclick="play('piedra')">Piedra</button>
<button onclick="play('papel')">Papel</button>
<button onclick="play('tijeras')">Tijeras</button>
<p id="result"></p>
</div>
En script.js, implementa la lógica para comparar elecciones y mostrar resultados:
function play(userChoice) {
const choices = ["piedra", "papel", "tijeras"];
const computerChoice = choices[Math.floor(Math.random() * 3)];
let result = "";
if (userChoice === computerChoice) {
result = "Empate";
} else if (
(userChoice === "piedra" && computerChoice === "tijeras") ||
(userChoice === "papel" && computerChoice === "piedra") ||
(userChoice === "tijeras" && computerChoice === "papel")
) {
result = "¡Ganaste!";
} else {
result = "Perdiste";
}
document.getElementById(
"result"
).innerText = `Tú: ${userChoice} | Computadora: ${computerChoice} | ${result}`;
}
Este código utiliza una función play que toma la elección del usuario, genera una elección aleatoria para la computadora y evalúa el resultado con condicionales. Practica conceptos como funciones, arrays y manipulación del DOM mientras construyes un juego interactivo.
Juego de Memoria
El Juego de Memoria desafía al usuario a emparejar cartas idénticas en un tablero. Este proyecto introduce el uso de arrays bidimensionales, temporizadores y manejo de estados. La interfaz consiste en una cuadrícula de cartas que se voltean al hacer clic.
En index.html, crea una cuadrícula simple:
<div id="memoryGame" class="grid"></div>
En styles.css, define el estilo de la cuadrícula:
.grid {
display: grid;
grid-template-columns: repeat(4, 100px);
gap: 10px;
}
.card {
width: 100px;
height: 100px;
background: #ccc;
cursor: pointer;
}
En script.js, genera las cartas y maneja los clics:
const cards = ["A", "A", "B", "B", "C", "C", "D", "D"];
cards.sort(() => Math.random() - 0.5);
const grid = document.querySelector(".grid");
let firstCard = null;
cards.forEach((symbol, index) => {
const card = document.createElement("div");
card.classList.add("card");
card.dataset.symbol = symbol;
card.addEventListener("click", () => flipCard(card));
grid.appendChild(card);
});
function flipCard(card) {
if (!firstCard) {
firstCard = card;
card.innerText = card.dataset.symbol;
} else {
card.innerText = card.dataset.symbol;
if (
firstCard.dataset.symbol === card.dataset.symbol &&
firstCard !== card
) {
firstCard = null;
} else {
setTimeout(() => {
firstCard.innerText = "";
card.innerText = "";
firstCard = null;
}, 1000);
}
}
}
Este código crea un tablero de 4x2 cartas, las baraja aleatoriamente y permite al usuario voltearlas. Si las cartas no coinciden, se ocultan tras un segundo. Este proyecto refuerza el manejo de eventos y la lógica de estado.
Whac-a-Mole
El juego Whac-a-Mole simula un arcade donde los jugadores golpean topos que aparecen aleatoriamente. Este proyecto enseña a trabajar con temporizadores en JavaScript, animaciones y puntajes.
En index.html, crea una cuadrícula para los topos:
<div id="whacAMole">
<p>Puntuación: <span id="score">0</span></p>
<div class="grid"></div>
</div>
En styles.css:
.grid {
display: grid;
grid-template-columns: repeat(3, 100px);
gap: 10px;
}
.hole {
width: 100px;
height: 100px;
background: #333;
}
.mole {
background: url("mole.png");
}
En script.js, implementa la lógica:
const holes = 9;
const grid = document.querySelector(".grid");
let score = 0;
for (let i = 0; i < holes; i++) {
const hole = document.createElement("div");
hole.classList.add("hole");
hole.addEventListener("click", () => {
if (hole.classList.contains("mole")) {
score++;
document.getElementById("score").innerText = score;
hole.classList.remove("mole");
}
});
grid.appendChild(hole);
}
function showMole() {
const holes = document.querySelectorAll(".hole");
holes.forEach((h) => h.classList.remove("mole"));
const randomHole = holes[Math.floor(Math.random() * holes.length)];
randomHole.classList.add("mole");
}
setInterval(showMole, 1000);
El topo aparece en un agujero aleatorio cada segundo, y el jugador suma puntos al hacer clic en él. Este proyecto mejora tu comprensión de intervalos y eventos de clic.
Breakout
El juego Breakout consiste en una paleta que rebota una pelota para destruir ladrillos. Este proyecto utiliza el elemento <canvas> para renderizar gráficos y manejar colisiones.
En index.html:
<canvas id="gameCanvas" width="480" height="320"></canvas>
En script.js:
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
const ballRadius = 10;
let x = canvas.width / 2;
let y = canvas.height - 30;
let dx = 2;
let dy = -2;
const paddleHeight = 10;
const paddleWidth = 75;
let paddleX = (canvas.width - paddleWidth) / 2;
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
drawPaddle();
x += dx;
y += dy;
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
dx = -dx;
}
if (y + dy < ballRadius) {
dy = -dy;
} else if (y + dy > canvas.height - ballRadius) {
if (x > paddleX && x < paddleX + paddleWidth) {
dy = -dy;
} else {
document.location.reload();
}
}
requestAnimationFrame(draw);
}
document.addEventListener("mousemove", (e) => {
const relativeX = e.clientX - canvas.offsetLeft;
if (relativeX > 0 && relativeX < canvas.width) {
paddleX = relativeX - paddleWidth / 2;
}
});
draw();
Este código renderiza una pelota y una paleta, detecta colisiones y mueve la paleta con el ratón. Practica el uso del canvas y la animación fluida con requestAnimationFrame.
Frogger
El juego Frogger requiere que una rana cruce una carretera evitando obstáculos. Este proyecto introduce sprites y colisiones más complejas.
En index.html:
<canvas id="gameCanvas" width="480" height="480"></canvas>
En script.js:
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
const gridSize = 48;
let frog = { x: 5 * gridSize, y: 9 * gridSize };
const cars = [
{ x: 0, y: 7 * gridSize, speed: 2 },
{ x: 3 * gridSize, y: 6 * gridSize, speed: -2 },
];
function drawFrog() {
ctx.fillStyle = "green";
ctx.fillRect(frog.x, frog.y, gridSize, gridSize);
}
function drawCars() {
ctx.fillStyle = "red";
cars.forEach((car) => {
ctx.fillRect(car.x, car.y, gridSize, gridSize);
car.x += car.speed;
if (car.x > canvas.width) car.x = -gridSize;
if (car.x < -gridSize) car.x = canvas.width;
});
}
function checkCollision() {
for (let car of cars) {
if (frog.x === car.x && frog.y === car.y) {
frog.x = 5 * gridSize;
frog.y = 9 * gridSize;
}
}
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawFrog();
drawCars();
checkCollision();
requestAnimationFrame(draw);
}
document.addEventListener("keydown", (e) => {
if (e.key === "ArrowUp" && frog.y > 0) frog.y -= gridSize;
if (e.key === "ArrowDown" && frog.y < canvas.height - gridSize)
frog.y += gridSize;
if (e.key === "ArrowLeft" && frog.x > 0) frog.x -= gridSize;
if (e.key === "ArrowRight" && frog.x < canvas.width - gridSize)
frog.x += gridSize;
});
draw();
La rana se mueve con las teclas de flecha, y los coches circulan horizontalmente. Si hay una colisión, la rana vuelve al inicio. Este proyecto mejora tu manejo de entrada de teclado y animaciones.
Connect Four
El juego Connect Four es un tablero donde dos jugadores alternan para alinear cuatro fichas. Este proyecto enseña lógica de turnos y detección de victorias.
En index.html:
<div id="connectFour">
<div class="board"></div>
</div>
En styles.css:
.board {
display: grid;
grid-template-columns: repeat(7, 50px);
}
.cell {
width: 50px;
height: 50px;
background: #fff;
border: 1px solid #000;
border-radius: 50%;
}
.red {
background: red;
}
.yellow {
background: yellow;
}
En script.js:
const board = Array(6)
.fill()
.map(() => Array(7).fill(null));
const cells = document.querySelector(".board");
let currentPlayer = "red";
for (let row = 0; row < 6; row++) {
for (let col = 0; col < 7; col++) {
const cell = document.createElement("div");
cell.classList.add("cell");
cell.dataset.col = col;
cell.addEventListener("click", () => dropPiece(col));
cells.appendChild(cell);
}
}
function dropPiece(col) {
for (let row = 5; row >= 0; row--) {
if (!board[row][col]) {
board[row][col] = currentPlayer;
const cell = document.querySelector(
`.cell:nth-child(${row * 7 + col + 1})`
);
cell.classList.add(currentPlayer);
if (checkWin(currentPlayer)) {
alert(`${currentPlayer} gana!`);
document.location.reload();
}
currentPlayer = currentPlayer === "red" ? "yellow" : "red";
break;
}
}
}
function checkWin(player) {
// Lógica de victoria (horizontal, vertical, diagonal)
for (let row = 0; row < 6; row++) {
for (let col = 0; col < 4; col++) {
if (
board[row][col] === player &&
board[row][col + 1] === player &&
board[row][col + 2] === player &&
board[row][col + 3] === player
)
return true;
}
}
// Agrega lógica para vertical y diagonal
return false;
}
Este código crea un tablero 6x7, permite a los jugadores alternar turnos y verifica victorias horizontales. Amplía la función checkWin para incluir victorias verticales y diagonales.
Space Invaders
El juego Space Invaders involucra una nave que dispara a alienígenas en movimiento. Este proyecto combina canvas en HTML5, disparos y enemigos.
En index.html:
<canvas id="gameCanvas" width="480" height="320"></canvas>
En script.js:
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
const player = {
x: canvas.width / 2,
y: canvas.height - 30,
width: 40,
height: 20,
};
const bullets = [];
const enemies = Array(5)
.fill()
.map((_, i) => ({
x: 50 + i * 60,
y: 50,
width: 30,
height: 30,
}));
let rightPressed = false;
let leftPressed = false;
document.addEventListener("keydown", (e) => {
if (e.key === "ArrowRight") rightPressed = true;
if (e.key === "ArrowLeft") leftPressed = true;
if (e.key === " ")
bullets.push({
x: player.x + player.width / 2,
y: player.y,
width: 5,
height: 10,
});
});
document.addEventListener("keyup", (e) => {
if (e.key === "ArrowRight") rightPressed = false;
if (e.key === "ArrowLeft") leftPressed = false;
});
function drawPlayer() {
ctx.fillStyle = "green";
ctx.fillRect(player.x, player.y, player.width, player.height);
}
function drawBullets() {
ctx.fillStyle = "white";
bullets.forEach((bullet) => {
ctx.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
bullet.y -= 5;
});
}
function drawEnemies() {
ctx.fillStyle = "red";
enemies.forEach((enemy) => {
ctx.fillRect(enemy.x, enemy.y, enemy.width, enemy.height);
});
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawPlayer();
drawBullets();
drawEnemies();
if (rightPressed && player.x < canvas.width - player.width) player.x += 5;
if (leftPressed && player.x > 0) player.x -= 5;
enemies.forEach((enemy) => (enemy.x += 1));
if (enemies.some((e) => e.x > canvas.width - e.width)) {
enemies.forEach((e) => {
e.x -= 10;
e.y += 40;
});
}
bullets.forEach((bullet, bIndex) => {
enemies.forEach((enemy, eIndex) => {
if (
bullet.x > enemy.x &&
bullet.x < enemy.x + enemy.width &&
bullet.y > enemy.y &&
bullet.y < enemy.y + enemy.height
) {
enemies.splice(eIndex, 1);
bullets.splice(bIndex, 1);
}
});
});
requestAnimationFrame(draw);
}
draw();
La nave se mueve con las teclas de flecha, dispara con la barra espaciadora y los enemigos avanzan. Este proyecto refuerza animaciones, colisiones y entrada de teclado.
Conclusiones
Crear juegos retro con JavaScript es una forma poderosa de aprender programación web. A través de estos siete proyectos, has practicado manipulación del DOM, eventos, animaciones, colisiones y lógica de juego. Cada juego introduce conceptos únicos: desde condicionales simples en Piedra, Papel o Tijeras hasta animaciones complejas en Space Invaders. Te recomendamos personalizar estos juegos agregando sonidos, mejores gráficos o nuevas mecánicas para profundizar tu aprendizaje. Además, subir tus proyectos a GitHub y compartirlos en plataformas como CodePen puede ayudarte a construir un portafolio sólido. Continúa explorando frameworks como Phaser para proyectos más avanzados y mantente actualizado con las últimas características de JavaScript en 2025.