44. Colisiones entre círculos

Las colisiones circulares convierten una prueba geométrica sencilla en una respuesta física completa: distancia, normal, penetración, velocidad relativa, impulso y conservación del movimiento.

44.1 Introducción

Los círculos son regiones de colisión naturales para pelotas, partículas, ruedas, planetas, campos de alcance y personajes aproximadamente redondos. Su simetría hace que la orientación no afecte la prueba.

La misma información usada para detectar el contacto permite separar los cuerpos y calcular un rebote.

44.2 Representación

Cada círculo se describe con un centro y un radio:

A=(CA,rA)   ·   B=(CB,rB)

Los radios deben ser no negativos. Para colisiones físicas también se agregan velocidad, masa, restitución y, opcionalmente, fricción.

44.3 Condición de colisión

Los círculos se tocan o solapan cuando la distancia entre centros no supera la suma de radios:

|CB−CA| ≤ rA+rB

Si la distancia es mayor, existe separación. Si es igual, hay contacto tangencial; si es menor, existe penetración.

44.4 Comparar distancias cuadráticas

Para detectar sin calcular raíces:

dx=Bx−Ax   ·   dy=By−Ay
d²=dx²+dy²
d²≤(rA+rB)²

Esta forma es ideal cuando solo necesitamos un booleano. Para obtener la profundidad y la normal sí necesitaremos la distancia real.

44.5 Estados geométricos

d>rA+rB
separados
d=rA+rB
contacto tangencial
d<rA+rB
penetración
d=0
centros coincidentes

En código se usa una tolerancia para distinguir el contacto de una diferencia decimal mínima.

44.6 Normal de contacto

La normal apunta desde A hacia B:

n=(CB−CA)/|CB−CA|

Es un vector unitario. Si los centros coinciden, la división no está definida; debe elegirse una normal alternativa basada en la velocidad relativa o una dirección fija.

44.7 Profundidad de penetración

penetración=rA+rB−d

Un valor positivo indica cuánto debe aumentar la distancia entre centros para eliminar la superposición. El vector mínimo de traslación es n multiplicado por esa profundidad.

44.8 Punto de contacto aproximado

Cuando los círculos apenas se tocan, el punto de contacto sobre A es:

Q=CA+n·rA

Si ya penetraron, las dos superficies producen puntos distintos. Puede usarse un punto intermedio o corregir primero las posiciones y calcularlo después.

44.9 Corrección posicional

Si A y B tienen la misma movilidad, cada uno se separa la mitad de la profundidad:

CA'=CA−n·penetración/2
CB'=CB+n·penetración/2

Con masas diferentes se reparte según las masas inversas. Un cuerpo inmóvil tiene masa inversa cero y no recibe desplazamiento.

44.10 Velocidad relativa

Antes de aplicar un rebote calculamos cómo se aproxima B respecto de A:

vrel=vB−vA
vn=vrel·n

Si vn>0 los cuerpos ya se separan; aplicar otro impulso los aceleraría incorrectamente. Solo se responde cuando vn<0.

44.11 Impulso de colisión

Para masas inversas invA e invB y restitución e:

j=−(1+e)(vrel·n)/(invA+invB)

Después se aplican impulsos opuestos:

vA'=vA−j·invA·n
vB'=vB+j·invB·n

e=1 representa un choque perfectamente elástico; e=0 elimina la velocidad relativa normal.

44.12 Colisiones continuas

Un círculo rápido puede atravesar otro entre fotogramas. La detección continua estudia el movimiento relativo y resuelve el instante t donde:

|(CA−CB)+(vA−vB)t|²=(rA+rB)²

La ecuación es cuadrática. La menor raíz válida dentro del fotograma indica el primer impacto.

44.13 Simulación interactiva

Mueve el círculo B y modifica los radios. La escena muestra la línea de centros, la normal, el punto de contacto y la profundidad.

AB
Estadopenetración
Distancia / suma0 / 0
Normal(1,0)
Penetración0

44.14 Detección en JavaScript

function colisionCirculos(a,b) {
  const dx=b.x-a.x, dy=b.y-a.y;
  const suma=a.radio+b.radio;
  return dx*dx+dy*dy <= suma*suma;
}

const A={x:0,y:0,radio:3};
const B={x:4,y:1,radio:2};
console.log("¿Colisionan?",colisionCirculos(A,B));

La salida es true. No se calcula ninguna raíz porque solo se necesita comparar.

44.15 Datos del contacto

function contactoCirculos(a,b) {
  const dx=b.x-a.x, dy=b.y-a.y;
  const distancia=Math.hypot(dx,dy);
  const suma=a.radio+b.radio;
  if (distancia>suma) return null;
  const normal=distancia>1e-9
    ? {x:dx/distancia,y:dy/distancia}
    : {x:1,y:0};
  return {
    normal,
    profundidad:suma-distancia,
    punto:{x:a.x+normal.x*a.radio,y:a.y+normal.y*a.radio}
  };
}

console.log(contactoCirculos(
  {x:0,y:0,radio:3},{x:4,y:0,radio:2}
));

El caso de centros coincidentes recibe una normal alternativa para evitar una división por cero.

44.16 Impulso elástico en JavaScript

function aplicarImpulso(a,b,n,restitucion=1) {
  const rv={x:b.vx-a.vx,y:b.vy-a.vy};
  const velocidadNormal=rv.x*n.x+rv.y*n.y;
  if (velocidadNormal>=0) return;
  const invA=1/a.masa, invB=1/b.masa;
  const j=-(1+restitucion)*velocidadNormal/(invA+invB);
  a.vx-=j*invA*n.x; a.vy-=j*invA*n.y;
  b.vx+=j*invB*n.x; b.vy+=j*invB*n.y;
}

const A={vx:3,vy:0,masa:1};
const B={vx:-1,vy:0,masa:1};
aplicarImpulso(A,B,{x:1,y:0});
console.log("Velocidades:",A.vx,B.vx);

Para masas iguales y restitución 1, los cuerpos intercambian sus velocidades normales.

44.17 Aplicación animada: reactor de partículas

Las partículas se mueven con velocidades y masas diferentes. Cada contacto corrige la penetración y aplica un impulso elástico; el destello señala el último choque.

Choques detectados: 0 · energía: 0

44.18 Aplicaciones, errores y conclusión

Las colisiones circulares se usan en juegos de billar, partículas, ruedas, campos de fuerza, alcance de sensores, multitudes, moléculas y aproximaciones de personajes.

  • Comparar la distancia cuadrática con la suma de radios sin elevarla al cuadrado.
  • Normalizar un vector de longitud cero.
  • Aplicar un impulso cuando los cuerpos ya se separan.
  • Corregir toda la penetración moviendo también un cuerpo inmóvil.
  • Confundir radio con diámetro.
  • Aplicar repetidamente un rebote sin corregir la superposición.
  • Ignorar la tunelización de círculos rápidos.
  • Usar restitución mayor que 1 sin intención de agregar energía.

Recuerda: compara d² con (rA+rB)²; la normal une los centros; la penetración produce el MTV; y el impulso solo actúa si la velocidad relativa apunta hacia el contacto.

En el próximo tema estudiaremos interpolación y movimiento suave.