125 lines
3.0 KiB
JavaScript
125 lines
3.0 KiB
JavaScript
const canvas = document.getElementById('pong');
|
|
const ctx = canvas.getContext('2d');
|
|
const scoreDiv = document.getElementById('score');
|
|
const restartBtn = document.getElementById('restart-btn');
|
|
|
|
const w = canvas.width, h = canvas.height;
|
|
const paddleHeight = 80, paddleWidth = 14;
|
|
let playerY = h/2 - paddleHeight/2, aiY = h/2 - paddleHeight/2;
|
|
let playerScore = 0, aiScore = 0;
|
|
|
|
let ball = {
|
|
x: w/2, y: h/2,
|
|
size: 12,
|
|
speed: 5,
|
|
velX: 5,
|
|
velY: -4
|
|
};
|
|
|
|
let up = false, down = false;
|
|
let running = true;
|
|
|
|
// Dibujo de todo (juego, paletas, bola, marcador)
|
|
function draw() {
|
|
ctx.clearRect(0, 0, w, h);
|
|
ctx.fillStyle = "#f2e9e4";
|
|
// Jugador (izq)
|
|
ctx.fillRect(16, playerY, paddleWidth, paddleHeight);
|
|
// AI (der)
|
|
ctx.fillRect(w-16-paddleWidth, aiY, paddleWidth, paddleHeight);
|
|
// Bola
|
|
ctx.beginPath();
|
|
ctx.arc(ball.x, ball.y, ball.size, 0, 2 * Math.PI);
|
|
ctx.fillStyle = "#f6c90e";
|
|
ctx.fill();
|
|
// Red central
|
|
for(let i=15;i<h;i+=30){
|
|
ctx.fillRect(w/2-2,i,4,14);
|
|
}
|
|
// Score
|
|
scoreDiv.innerHTML = `<b>Tú:</b> ${playerScore} | <b>Máquina:</b> ${aiScore}`;
|
|
}
|
|
|
|
function gameLoop() {
|
|
if (!running) return;
|
|
|
|
// Jugador
|
|
if (up) playerY -= 7;
|
|
if (down) playerY += 7;
|
|
playerY = Math.max(0, Math.min(h-paddleHeight, playerY));
|
|
// AI: sigue la bola
|
|
if (aiY + paddleHeight/2 < ball.y - 12) aiY += 5;
|
|
else if (aiY + paddleHeight/2 > ball.y + 12) aiY -= 5;
|
|
aiY = Math.max(0, Math.min(h-paddleHeight, aiY));
|
|
|
|
// Bola
|
|
ball.x += ball.velX;
|
|
ball.y += ball.velY;
|
|
|
|
// Colisión con pared arriba/abajo
|
|
if (ball.y - ball.size < 0 || ball.y + ball.size > h) ball.velY *= -1;
|
|
|
|
// Colisión con paleta jugador
|
|
if (
|
|
ball.x - ball.size < 16 + paddleWidth &&
|
|
ball.y > playerY && ball.y < playerY + paddleHeight
|
|
) {
|
|
ball.velX = Math.abs(ball.velX);
|
|
ball.velY += (Math.random() - 0.5) * 2.5;
|
|
}
|
|
|
|
// Colisión con paleta AI
|
|
if (
|
|
ball.x + ball.size > w-16-paddleWidth &&
|
|
ball.y > aiY && ball.y < aiY + paddleHeight
|
|
) {
|
|
ball.velX = -Math.abs(ball.velX);
|
|
ball.velY += (Math.random() - 0.5) * 2.5;
|
|
}
|
|
|
|
// Gol jugador
|
|
if (ball.x - ball.size < 0) {
|
|
aiScore++;
|
|
resetBall();
|
|
}
|
|
// Gol máquina
|
|
if (ball.x + ball.size > w) {
|
|
playerScore++;
|
|
resetBall();
|
|
}
|
|
|
|
draw();
|
|
requestAnimationFrame(gameLoop);
|
|
}
|
|
|
|
function resetBall() {
|
|
ball.x = w/2; ball.y = h/2;
|
|
ball.velX = (Math.random() > 0.5 ? 5 : -5);
|
|
ball.velY = (Math.random() - 0.5) * 7;
|
|
running = false;
|
|
setTimeout(() => {
|
|
running = true;
|
|
requestAnimationFrame(gameLoop);
|
|
}, 900);
|
|
}
|
|
|
|
document.addEventListener('keydown', e => {
|
|
if (e.key === 'ArrowUp') up = true;
|
|
if (e.key === 'ArrowDown') down = true;
|
|
});
|
|
document.addEventListener('keyup', e => {
|
|
if (e.key === 'ArrowUp') up = false;
|
|
if (e.key === 'ArrowDown') down = false;
|
|
});
|
|
|
|
restartBtn.onclick = () => {
|
|
playerScore = aiScore = 0;
|
|
playerY = h/2 - paddleHeight/2;
|
|
aiY = h/2 - paddleHeight/2;
|
|
resetBall();
|
|
running = true;
|
|
requestAnimationFrame(gameLoop);
|
|
};
|
|
|
|
draw();
|
|
gameLoop(); |