Capítulo 04

Pelota, rebotes y colisiones

Objetivo: mover la pelota, resolver rebotes contra paredes y detectar contacto con las paletas.

1. Movimiento de la pelota

La pelota usa velocidad independiente en X e Y. En cada frame, la posición se incrementa con esa velocidad.

Pelota desplazándose
Actualizar posición
ball.x += ball.vx;
ball.y += ball.vy;

ball.vx desplaza horizontalmente. ball.vy desplaza verticalmente. Si vx es positivo, la pelota avanza a la derecha; si es negativo, avanza a la izquierda. Si vy es positivo, baja; si es negativo, sube.

2. Rebote contra techo y piso

La pelota debe invertir su dirección vertical al tocar el borde superior o inferior.

Rebote contra borde superior/inferior
Rebote vertical
if (ball.y - ballR < 0 || ball.y + ballR > H) {
    ball.vy *= -1;
}

ball.y - ballR representa el borde superior de la pelota. ball.y + ballR representa el borde inferior. Luego de detectar el contacto, se resuelve la consecuencia invirtiendo vy.

3. Colisión con la paleta del jugador

La pelota colisiona con la paleta izquierda cuando su borde izquierdo alcanza el borde derecho de la paleta, su centro vertical está dentro del rango de la paleta y la pelota se mueve hacia la izquierda.

Pelota rebotando en paleta
Pelota contra jugador
if (ball.x - ballR < player.x + paddleW &&
    ball.y > player.y &&
    ball.y < player.y + paddleH &&
    ball.vx < 0) {
    ball.vx *= -1.08;
    let offset = (ball.y - (player.y + paddleH / 2)) / (paddleH / 2);
    ball.vy = offset * 5;
    score += 10;
    ctx.onScore(score);
}

La condición ball.vx < 0 confirma que la pelota se mueve hacia la paleta izquierda. Luego de detectar la colisión, ball.vx *= -1.08 invierte la dirección horizontal y aumenta la velocidad. offset calcula el punto de contacto dentro de la paleta.

4. Cálculo del ángulo de salida

offset produce un valor aproximado entre -1 y 1. Cerca del centro vale 0. Cerca del borde superior es negativo. Cerca del borde inferior es positivo.

Ángulo por offset
let offset = (ball.y - (player.y + paddleH / 2)) / (paddleH / 2);
ball.vy = offset * 5;

ball.y es el centro vertical de la pelota. player.y + paddleH / 2 es el centro vertical de la paleta. La resta mide si el golpe ocurrió arriba o abajo del centro. Dividir por paddleH / 2 normaliza ese valor.

5. Colisión con la CPU

La paleta derecha usa la misma regla, pero se revisa el borde derecho de la pelota y se exige que la pelota avance hacia la derecha.

Pelota contra CPU
if (ball.x + ballR > computer.x &&
    ball.y > computer.y &&
    ball.y < computer.y + paddleH &&
    ball.vx > 0) {
    ball.vx *= -1.05;
    let offset = (ball.y - (computer.y + paddleH / 2)) / (paddleH / 2);
    ball.vy = offset * 5;
}

ball.x + ballR representa el borde derecho de la pelota. computer.x representa el borde izquierdo de la paleta derecha. ball.vx > 0 evita procesar una colisión cuando la pelota ya se aleja.