Casi todo lo que hace interesante a un videojuego depende de saber cuándo dos cosas se tocan. Hoy formalizamos esa pregunta con matemática simple y código reutilizable.
En la lección anterior resolvimos animación de sprites. Antes de eso, en Pong, usamos `SDL_HasIntersection` para detectar cuándo la pelota tocaba una paleta — una solución rápida pero limitada. En esta lección vamos a entender qué hace esa función por dentro, y vamos a construir detección de colisiones que funcione para rectángulos y para círculos, porque no todos los juegos usan solo cajas.
La detección de colisiones es la base de: daño en combate, recolección de ítems, disparos que impactan, personajes que no atraviesan paredes, y prácticamente cualquier interacción física en un juego 2D.
AABB significa "Axis-Aligned Bounding Box" — una caja alineada a los ejes, es decir, sin rotación. Es la forma de colisión más barata de calcular y la más usada en juegos 2D.
La lógica es simple: dos rectángulos NO se superponen si uno está completamente a la izquierda, derecha, arriba o abajo del otro. Si ninguna de esas cuatro condiciones es verdadera, entonces se están tocando.
Esto es exactamente lo que hace `SDL_HasIntersection` internamente. Ahora que lo entiendes, puedes extenderlo — por ejemplo, calculando cuánto se superponen (para resolver la colisión empujando los objetos) en vez de solo saber si chocan.
Para objetos redondos (una pelota, una explosión, un proyectil), la colisión por círculo es más precisa y, sorprendentemente, más simple de calcular: dos círculos colisionan si la distancia entre sus centros es menor que la suma de sus radios.
Nota el truco de rendimiento: comparamos el cuadrado de la distancia contra el cuadrado de la suma de radios, en vez de usar `sqrt()`. La raíz cuadrada es una operación relativamente cara, y aquí es completamente evitable — solo nos interesa saber si una distancia es mayor o menor que otra, no su valor exacto.
Un caso mixto muy común: una pelota redonda contra una plataforma rectangular. La técnica estándar es encontrar el punto del rectángulo más cercano al centro del círculo, y medir la distancia desde ahí.
Ahora podemos reemplazar el `SDL_HasIntersection` improvisado de la lección 3 con nuestra propia función AABB, y usar el solapamiento para decidir si el rebote debe ser horizontal o vertical según en qué lado ocurrió el impacto.
Un bug frecuente: si no separas los objetos después de detectar la colisión, el mismo choque se detecta en varios fotogramas seguidos y el objeto "tiembla" o queda atascado. La solución es empujar los objetos fuera de la zona de solapamiento inmediatamente después de resolver la física.
La geometría de colisiones es un terreno donde los asistentes de IA son particularmente buenos explicando "por qué" funciona una fórmula, no solo "qué" hace. Si la matemática del punto más cercano en colisión círculo-rectángulo no te queda clara del todo, pídele a tu asistente que te la dibuje en ASCII o que te la explique con un caso numérico concreto (por ejemplo, un círculo en `(50, 50)` con radio `10` contra un rectángulo en `(0,0,40,40)`). Ver los números moverse ayuda mucho más que la fórmula sola.
En la próxima lección vamos a usar estas mismas estructuras de datos (posiciones, estados de personajes) como base para algo distinto: un sistema de guardado que le dé memoria persistente a tu juego entre una sesión y la siguiente.
Carlos Montiel es arquitecto de soluciones IA empresarial. Implementa LLMs, Agentes, RAG y orquestadores en empresas de Guatemala y Latinoamérica. Contáctalo para una consultoría.
Contactar a Carlos Montiel