2010-10-10 19 views
6

Estoy trabajando en un juego basado en mosaicos 3D y estoy usando la detección de colisiones AABB. Por cada cubo que el jugador se cruza, encuentro que el eje a lo largo del cual el jugador está intersectando el cubo es el que menos, y empujo al jugador fuera del cubo a lo largo de ese eje.Colisión AABB deslizante: atascarse en los bordes

Dependiendo del orden en que se revisen los cubos, esto puede causar problemas al deslizarse a lo largo del borde de varios cubos. He creado un diagrama que debe explicar el problema:

http://imgur.com/mmK0W.png

  • Flecha # 1 es el intento de movimiento del jugador. Las otras flechas son la respuesta de colisión.
  • En el diagrama de la izquierda, la colisión se prueba primero contra el cubo derecho, lo que hace que el jugador sea empujado hacia la izquierda y luego hacia arriba. (malo)
  • En el diagrama de la derecha, la colisión se prueba primero contra el cubo izquierdo, haciendo que el jugador sea empujado hacia arriba, en cuyo punto el jugador ya no se está cruzando con el otro cubo. (buena)

¿Alguna idea sobre lo que la forma más eficiente para resolver esto podría ser? ¿O alguna forma mejor de manejar la respuesta de colisión?

Gracias.

+3

Tal comprobar todas las colisiones y anotar el tiempo (o distancia) de la colisión. Aplique solo la colisión que ocurra lo más pronto posible. Opcionalmente continúe el proceso por el resto del paso de tiempo. –

+0

Así que si clasifiqué todos los cubos con los que el jugador se cruzaba por la distancia del jugador, y luego los consideraba uno a la vez, eso podría funcionar. Estoy pensando que sería mejor evitar tener que ordenar las cosas en cada fotograma, pero no estoy seguro de que importe mucho, ya que el jugador solo podría estar colisionando con hasta? 7? bloques a la vez. ¿Crees que hay algo de qué preocuparse? – Jeff

Respuesta

4

Una implementación discreta te obliga a inyectar algunos cálculos matemáticos continuos en el sistema, solo cuando sea necesario (cubos/direcciones superpuestas).

Para cada cubo c1, c2 ... ci con la que el cubo de usuario (UC ) se cruza en el momento de la verificación, que desea saber qué cubo fue "tocado" primera - solo hay uno, como en la vida real. Considere la dirección de d uc, y, tomando la cantidad de uc ci en (superposición) encontrar la posición del cu en el momento en que "tocado" ci .

determinar qué cubo era "tocado" primera cj (la que requiere el máximo de reversión en el eje d - cuanto antes en el tiempo) y utilizar sólo éste para calcular la reacción de colisión.

No solo alcanzará la precisión. pero ayudará si todos los cubos se mueven, tienen diferentes velocidades, etc.

+0

+1. Hice algo así una vez, aunque es un esfuerzo implementarlo y depurarlo. Puede tener problemas al usar este enfoque cuando el movimiento de objetos de un cuadro al siguiente no es a lo largo de una línea lineal, pero de lo contrario, funciona muy bien. Tendrá que recordar la posición anterior (y tal vez la velocidad previa) de cada objeto que se puede mover para que pueda calcular la posición y la velocidad de los objetos en un momento dado entre dos cuadros. – Cameron

+0

Tengo problemas para entender lo que dices, pero creo que esta respuesta también tendría un problema si el jugador intentara entrar en una esquina de la habitación. Creo que sería necesario tener más de un bloque en cuenta. Tal vez podría ordenar todos los bloques con los que el jugador está chocando, pero no estoy seguro de si sería mejor evitar tener que ordenar las cosas. – Jeff

+0

La pared de la habitación debe tratarse del mismo modo que otros cubos: este es un caso particular (más fácil): se comprueba si el cubo está fuera de los límites y, usando el mismo algoritmo, se determina qué parte del cubo está fuera, luego verifica las colisiones con otros cubos. Una vez más, el primer "tocado" (otro cubo o la pared) tiene que ser tratado con la reacción de colisión. Wall es simplemente un objeto particular no móvil y más grande con el que el cubo puede colisionar. –

0

En su diagrama, parece que desea el movimiento más pequeño que minimice la superposición entre el jugador y los cubos. Cada cubo con superposición intentará "empujar" al jugador en dos direcciones ortogonales. ¿Puedes hacer algo como elegir la presión mínima de los empujes máximos en cada dirección?

+0

Creo que eso causaría problemas si el jugador se acerca a una esquina. En ese caso, necesito empujar al jugador hacia atrás a lo largo de 2 ejes. – Jeff

+0

Bien; pensando en 2D, el empuje debe tener un componente vertical y horizontal. Cada cubo superpuesto puede impartir un empuje en dos direcciones desde {N, S, E, W}. Si hay múltiples cubos superpuestos, entonces debe considerar el máximo de empujes en las direcciones {N, S} y {E, W} (cualquier cosa menos se superpondrá, pero puede ser posible ignorar, digamos, un empuje NS porque un empuje EW hará el trabajo). Hay como máximo ocho posibilidades. ¿Puedes probar los ocho en orden de magnitud y elegir el primero que despeje al jugador de los cubos? – Rafe

+0

Desafortunadamente, habría aún más conjuntos posibles en 3 dimensiones. Probablemente sería más eficiente clasificar inicialmente los bloques según la distancia, como sugirió Tom. – Jeff

0

Puede implementar un tipo de fase ancha híbrida cuando sus dos (o más) cubos estacionarios en una fila se pueden combinar en un rectángulo más grande. Pruebe primero contra el rectángulo más grande. Le dará los resultados de su marca de verificación verde y será más rápido que comprobar cada cubo de todos modos. Luego, después de eso, solo si es necesario, verifique los cubos individuales.

+0

Estoy tratando de pensar cómo aplicar esto a 3 dimensiones. Si tuviera una forma como una 'L' que estaba de pie, podría combinar 2 bloques horizontal o verticalmente. Pero creo que el orden en el que debería aplicar la respuesta dependerá de la posición del jugador o de la dirección del movimiento. – Jeff

0

Una colisión puede empujar un objeto solo en 1 eje. Para determinar el eje a presionar:

else -- not this 
elseif -- change to this 

if w > h then 
    push x 
elseif h > w then 
    push y 
end 

Esto funciona si sus mosaicos están alineados.

Usa círculos para evitar el bastón en los azulejos no alineados

Cuestiones relacionadas