Maquetación Web Dinámica / Canvas y videojuegos 2D
Colisiones: AABB y por distancia
"¿La nave chocó con el asteroide?" "¿El jugador recogió la moneda?" "¿La pelota tocó la paleta?" Todo juego se reduce, una y otra vez, a la misma pregunta: ¿estas dos cosas se están tocando? Responderla se llama detección de colisiones, y con dos técnicas — una para cajas, otra para círculos — cubres casi todo. La matemática es de secundaria; lo valioso es saber cuál usar.
AABB: ¿se solapan dos cajas?
AABB significa "Axis-Aligned Bounding Box" — caja alineada a los ejes (sin rotar). Es la reina de las colisiones por lo barata y lo simple.
function colisionan(a, b) {
return a.x < b.x + b.w && // el borde izq de A está antes del der de B
a.x + a.w > b.x && // el borde der de A está después del izq de B
a.y < b.y + b.h && // (lo mismo en vertical)
a.y + a.h > b.y;
}
// a y b son cajas { x, y, w, h }. Si las 4 son verdad → se tocan.Las cuatro condiciones deben cumplirse a la vez (&&): basta que UNA falle
para que haya "escapatoria" y no haya choque. Es toda la colisión que
necesita un plataformero, un Breakout o un Pong. Cuatro comparaciones,
cero raíces cuadradas: baratísima incluso con cientos de objetos.
Pruébala
<canvas id="aabb" width="340" height="220"></canvas>body { font-family: system-ui; padding: 16px; background: #f8fafc; }
canvas { background: white; border: 1px solid #e2e8f0; border-radius: 12px; cursor: none; }const canvas = document.getElementById("aabb");
const ctx = canvas.getContext("2d");
const meta = { x: 140, y: 90, w: 60, h: 60 };
const jugador = { x: 40, y: 40, w: 44, h: 44 };
let dentro = false;
canvas.addEventListener("mousemove", (e) => {
const r = canvas.getBoundingClientRect();
jugador.x = e.clientX - r.left - jugador.w / 2;
jugador.y = e.clientY - r.top - jugador.h / 2;
});
canvas.addEventListener("mouseleave", () => { jugador.x = -100; });
function colisionan(a, b) {
return a.x < b.x + b.w && a.x + a.w > b.x &&
a.y < b.y + b.h && a.y + a.h > b.y;
}
function loop() {
dentro = colisionan(jugador, meta);
ctx.clearRect(0, 0, canvas.width, canvas.height);
// la meta cambia de color si hay choque
ctx.fillStyle = dentro ? "#22c55e" : "#e2e8f0";
ctx.fillRect(meta.x, meta.y, meta.w, meta.h);
// el jugador (sigue al mouse)
ctx.fillStyle = "#6d28d9";
ctx.fillRect(jugador.x, jugador.y, jugador.w, jugador.h);
if (dentro) {
ctx.fillStyle = "#15803d";
ctx.font = "700 18px system-ui";
ctx.textAlign = "center";
ctx.fillText("¡Colisión!", canvas.width / 2, 30);
}
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);Mueve el mouse sobre el canvas: el cuadro violeta te sigue y la meta se
pone verde en cuanto las dos cajas se tocan — la función colisionan en
acción, evaluada cada fotograma.
Por distancia: círculos y radios de acción
Para cosas redondas (o para un "radio de acción"), AABB es tosco — las esquinas de la caja invisible detectan choques donde no los hay. La técnica correcta es medir la DISTANCIA entre centros:
function chocanCirculos(a, b) {
const dx = a.cx - b.cx;
const dy = a.cy - b.cy;
const distancia = Math.hypot(dx, dy); // teorema de Pitágoras, en una línea
return distancia < a.r + b.r;
}Math.hypot(dx, dy) es la distancia en línea recta entre los centros (la
hipotenusa). Truco de rendimiento pro, para cuando tengas MILES de
comprobaciones: la raíz cuadrada de hypot es cara, así que se compara la
distancia al cuadrado con (a.r + b.r)² y se evita la raíz. No lo
necesitas todavía; guárdalo para cuando el profiler te lo pida.
En tu juego de naves, la colisión con AABB marca 'choque' cuando el asteroide redondo todavía está claramente separado de la nave, por una esquina. ¿Qué conviene?
Mini-reto
Convierte el demo en un mini-juego de "recoger": dibuja 5 monedas (círculos) en posiciones fijas y, cuando tu cuadro-jugador colisione con una (usa AABB tratando la moneda como una cajita, o distancia si la tratas como círculo), haz que DESAPAREZCA y suma 1 a un puntaje que dibujas arriba. Acabas de programar el bucle central de medio catálogo de videojuegos: mover, detectar, recoger, puntuar.
Qué sigue
Ya sabes cuándo dos cosas se tocan. La próxima lección multiplica los objetos por mil: SISTEMAS DE PARTÍCULAS — confeti, nieve, chispas, humo. Cientos de partículas diminutas, cada una con su física, naciendo y muriendo. El efecto que hace que un juego se sienta espectacular.