unity deteccion colisiones algorithm collision-detection

algorithm - unity - deteccion de colisiones en javascript



colisión círculo-círculo (6)

Como dice cletus, quieres usar la suma de los radios de las dos bolas. Desea calcular la distancia total entre los centros de las bolas, de la siguiente manera:

Ball 1: center: p1=(x1,y1) radius: r1 Ball 2: center: p2=(x2,y2) radius: r2 collision distance: R= r1 + r2 actual distance: r12= sqrt( (x2-x1)^2 + (y2-y2)^2 )

Una colisión ocurrirá cada vez que (r12 <R). Como dice Artelius, en realidad no deberían colisionar con los ejes x / y, colisionan en un ángulo particular. Excepto, en realidad no quieres ese ángulo; quieres el vector de colisión Esta es la diferencia entre los centros de los dos círculos cuando colisionan:

collision vector: d12= (x2-x1,y2-y1) = (dx,dy) actual distance: r12= sqrt( dx*dx + dy*dy )

Tenga en cuenta que ya calculó dx y dy arriba al calcular la distancia real, por lo que también puede realizar un seguimiento de ellos para fines como este. Puede usar este vector de colisión para determinar la nueva velocidad de las bolas: va a terminar escalando el vector de colisión por algunos factores, y agregando eso a las velocidades anteriores ... pero, para volver a la colisión real punto:

collision point: pcollision= ( (x1*r2+x2*r1)/(r1+r2), (y1*r2+y2*r1)/(r1+r2) )

Para descubrir cómo encontrar la nueva velocidad de las bolas (y, en general, para tener más sentido de la situación), probablemente debería encontrar un libro de física de la escuela secundaria, o el equivalente. Lamentablemente, no conozco un buen tutorial web: sugerencias, ¿alguien?

Ah, y si aún quieres seguir con el eje x / y, creo que lo has hecho bien con:

if( abs(dx) > abs(dy) ) then { x-axis } else { y-axis }

En cuanto a por qué podría fallar, es difícil decirlo sin más información, pero es posible que tenga un problema con las bolas que se mueven demasiado rápido y que pasan una al lado de la otra en un solo paso de tiempo. Hay formas de solucionar este problema, pero la forma más sencilla es asegurarse de que no se muevan demasiado rápido ...

Voy a desarrollar un juego de pelota de 2 días donde dos bolas (círculos) colisionan. Ahora tengo el problema de determinar el punto de colisión (de hecho, determinar si colisionan en el eje x / eje y). Tengo una idea de que cuando la diferencia entre la coordenada y de 2 bolas es mayor que la diferencia de coordenadas x, chocan en su eje y, de lo contrario, colisionan en su eje x. Es mi idea correcta? Implementé esto en mis juegos. Normalmente funciona bien, pero a veces falla. ¿Alguien puede decirme si mi idea es correcta? Si no es así, ¿por qué? ¿Hay alguna forma mejor?

Por colisión en el eje x, quiero decir que el 1º, 4º, 5º o 8º octante del círculo, el eje y significa el octavo, tercer, sexto o séptimo octante del círculo.

¡Gracias por adelantado!


El punto en el que colisionan está en la línea entre los puntos medios de los dos círculos, y su distancia desde cualquier punto medio es el radio de ese círculo respectivo.


Este sitio explica la física , deriva el algoritmo y proporciona código para colisiones de bolas 2D.

Calcule el octante después de que esta función calcule lo siguiente: posición del punto de colisión con relación al centro de masa del cuerpo a; posición del punto de colisión con relación al centro de masa del cuerpo a

/** This function calulates the velocities after a 2D collision vaf, vbf, waf and wbf from information about the colliding bodies @param double e coefficient of restitution which depends on the nature of the two colliding materials @param double ma total mass of body a @param double mb total mass of body b @param double Ia inertia for body a. @param double Ib inertia for body b. @param vector ra position of collision point relative to centre of mass of body a in absolute coordinates (if this is known in local body coordinates it must be converted before this is called). @param vector rb position of collision point relative to centre of mass of body b in absolute coordinates (if this is known in local body coordinates it must be converted before this is called). @param vector n normal to collision point, the line along which the impulse acts. @param vector vai initial velocity of centre of mass on object a @param vector vbi initial velocity of centre of mass on object b @param vector wai initial angular velocity of object a @param vector wbi initial angular velocity of object b @param vector vaf final velocity of centre of mass on object a @param vector vbf final velocity of centre of mass on object a @param vector waf final angular velocity of object a @param vector wbf final angular velocity of object b */ CollisionResponce(double e,double ma,double mb,matrix Ia,matrix Ib,vector ra,vector rb,vector n, vector vai, vector vbi, vector wai, vector wbi, vector vaf, vector vbf, vector waf, vector wbf) { double k=1/(ma*ma)+ 2/(ma*mb) +1/(mb*mb) - ra.x*ra.x/(ma*Ia) - rb.x*rb.x/(ma*Ib) - ra.y*ra.y/(ma*Ia) - ra.y*ra.y/(mb*Ia) - ra.x*ra.x/(mb*Ia) - rb.x*rb.x/(mb*Ib) - rb.y*rb.y/(ma*Ib) - rb.y*rb.y/(mb*Ib) + ra.y*ra.y*rb.x*rb.x/(Ia*Ib) + ra.x*ra.x*rb.y*rb.y/(Ia*Ib) - 2*ra.x*ra.y*rb.x*rb.y/(Ia*Ib); double Jx = (e+1)/k * (Vai.x - Vbi.x)( 1/ma - ra.x*ra.x/Ia + 1/mb - rb.x*rb.x/Ib) - (e+1)/k * (Vai.y - Vbi.y) (ra.x*ra.y / Ia + rb.x*rb.y / Ib); double Jy = - (e+1)/k * (Vai.x - Vbi.x) (ra.x*ra.y / Ia + rb.x*rb.y / Ib) + (e+1)/k * (Vai.y - Vbi.y) ( 1/ma - ra.y*ra.y/Ia + 1/mb - rb.y*rb.y/Ib); Vaf.x = Vai.x - Jx/Ma; Vaf.y = Vai.y - Jy/Ma; Vbf.x = Vbi.x - Jx/Mb; Vbf.y = Vbi.y - Jy/Mb; waf.x = wai.x - (Jx*ra.y - Jy*ra.x) /Ia; waf.y = wai.y - (Jx*ra.y - Jy*ra.x) /Ia; wbf.x = wbi.x - (Jx*rb.y - Jy*rb.x) /Ib; wbf.y = wbi.y - (Jx*rb.y - Jy*rb.x) /Ib; }


Estoy de acuerdo con las respuestas proporcionadas, son muy buenas.
Solo quiero señalar un pequeño escollo: si la velocidad de las bolas es alta, puedes perder la colisión, porque los círculos nunca se cruzan para los pasos dados.
La solución es resolver la ecuación del movimiento y encontrar el momento correcto de la colisión.

De todos modos, si implementara su solución (comparaciones en los ejes X e Y) obtendrá el buen viejo ping pong. http://en.wikipedia.org/wiki/Pong
:)


La colisión entre círculos es fácil. Imagina que hay dos círculos:

  • C1 con centro (x1, y1) y radio r1;
  • C2 con centro (x2, y2) y radio r2.

Imagine que hay una línea que corre entre esos dos puntos centrales. La distancia desde los puntos centrales hasta el borde de cualquier círculo es, por definición, igual a sus respectivos radios. Asi que:

  • si los bordes de los círculos tocan, la distancia entre los centros es r1 + r2;
  • cualquier distancia mayor y los círculos no se tocan ni colisionan; y
  • cualquier menos y luego colisionar.

Entonces puedes detectar colisión si:

(x2-x1)^2 + (y1-y2)^2 <= (r1+r2)^2

lo que significa que la distancia entre los puntos centrales es menor que la suma de los radios.

El mismo principio se puede aplicar para detectar colisiones entre esferas en tres dimensiones.

Editar: si desea calcular el punto de colisión, algunos trigonometría básica pueden hacer eso. Tienes un triángulo

(x1,y1) |/ | / | / sqrt((x2-x1)^2 + (y2-y1)^2) = r1+r2 |y2-y1| | / | / | X / (x1,y2) +------+ (x2,y2) |x2-x1|

Las expresiones |x2-x1| y |y2-y1| son valores absolutos Entonces para el ángulo X:

|y2 - y1| sin X = ------- r1 + r2 |x2 - x1| cos X = ------- r1 + r2 |y2 - y1| tan X = ------- |x2 - x1|

Una vez que tenga el ángulo, puede calcular el punto de intersección aplicándolo a un nuevo triángulo:

+ |/ | / b | / r2 | / | X / +-----+ a

dónde:

a cos X = -- r2

asi que

a = r2 cos X

De las fórmulas anteriores:

|x2 - x1| a = r2 ------- r1 + r2

Una vez que tenga a y b, puede calcular el punto de colisión en términos de (x2, y2) compensado por (a, b) según corresponda. Ni siquiera necesita calcular ningún senos, cosenos o senos inversos o cosenos para esto. O cualquier raíz cuadrada para ese asunto. Entonces es rápido.

Pero si no necesita un ángulo exacto o un punto de colisión y solo desea el octante, puede optimizarlo aún más entendiendo algo acerca de las tangentes, que es:

  • 0 <= tan X <= 1 para 0 <= X <= 45 grados;
  • tan X> = 1 para 45 <= X <= 90
  • 0> = tan X> = -1 para 0> = X => -45;
  • tan X <= -1 para -45> = X => -90; y
  • tan X = tan (X + 180) = tan (X-180).

Esos rangos de cuatro grados corresponden a cuatro octantes del cirlce. Los otros cuatro están compensados ​​por 180 grados. Como se demostró anteriormente, la tangente se puede calcular simplemente como:

|y2 - y1| tan X = ------- |x2 - x1|

Pierde los valores absolutos y esta relación te dirá en cuál de los cuatro octantes está la colisión (por los rangos tangentes anteriores). Para calcular el octante exacto, compare x1 y x2 para determinar cuál es el más a la izquierda.

El octante de la colisión en el otro sencillo está desplazado (octante 1 en C1 significa octante 5 en C2, 2 y 6, 3 y 7, 4 y 8, etc.).


Para responder más directamente a tu pregunta: Sí, de acuerdo con las reglas y requisitos que planteas, esas bolas colisionan en el eje Y si la diferencia en Y es mayor que la diferencia en X cuando las bolas se tocan.

Si esto es lo que está implementando, entonces está obteniendo una respuesta correcta a la pregunta "¿Colisión del eje X o Y?". Pero creo que la razón por la que estás obteniendo tantas respuestas aquí que parece que no puedes usar es que

  • estás haciendo una pregunta incorrecta (no aquí, en tu programa); o

  • no estás usando la respuesta correctamente

Estoy seguro de que muchos de nosotros programamos programas de pelotas de rebote, y sospecho que ninguno de nosotros ha intentado modelar colisiones basadas en octantes y hachas. Entonces sospecho que o tienes un nuevo enfoque muy original o simplemente lo estás haciendo mal. Por lo tanto, recomiendo volver y verificar su método y suposiciones.