¿Cómo lidiar con colisiones de esquinas en 2D?

22

Estoy escribiendo un juego 2D XNA de arriba hacia abajo. Desde que es mi primera vez, intento escribir sobre física y material de colisión para aprenderlo.

Cada vez que el personaje sprite de mi jugador intenta moverse a una posición donde sus límites se cruzan con el borde de una pared, descubro un ángulo de rebote (ángulo de incidencia = ángulo de reflexión) y hago que el jugador rebote de la pared y evite la colisión. .

Tengo problemas para descubrir cómo lidiar con la situación de mi sprite que se cruza con dos bordes de la pared simultáneamente, por ejemplo, golpea una esquina.

colisión de esquina

Mi código actualmente me dice que se han cruzado dos bordes de la pared, pero no qué borde golpearía primero y, por lo tanto, qué borde rebotar.

¿Cuál es la prueba matemática para elegir qué borde rebotar? Es fácil de ver al mirarlo, pero estoy luchando por resolver la prueba de matemáticas.

TerryB
fuente
Gracias Tetrad Vi esa pero parecía que la pelota se comportaría de manera diferente a mi problema rectangular. En el caso ilustrado arriba, el sprite rectangular habría golpeado el borde inferior de la pared y rebotado. El borde lateral de la pared nunca habría entrado en la ecuación. Simplemente no sé cómo expresar eso en código y tomar esa decisión.
TerryB

Respuestas:

9

Si se calcula hasta qué punto en el Wallla Player Spriteha movido, es probable que pueda basar en el delta del coordenadas X e Y de las esquinas que se cruzan. Espero que tenga sentido, no puedo pensar en una mejor manera de decirlo.

Entonces, por ejemplo, si miras tu diagrama. Tome el xvalor de la esquina superior izquierda de Player Sprite(después del movimiento) y reste el xvalor de la esquina inferior derecha de Wall. Haga lo mismo para los yvalores y luego vea cuál es más grande. La clave es que si uno es más grande que el otro, Player Spriteprobablemente se crucen en ese lado.

Aquí hay un ejemplo de imagen (esta es una subsección de su imagen con mis propias líneas agregadas):

ejemplo de intersección

Ahora, ves aquí que la línea azul es más grande que la línea verde. En este caso, la línea azul también está del lado del Player Spriteque se esperaría que rebote.

Si los dos valores son iguales, golpean justo en la esquina.

Ahora, hay un pequeño problema al hacerlo de esta manera. Si Player Spriteviaja muy rápido o la colisión está muy cerca de la esquina, es posible que Player Spriteavance más en la Walldirección equivocada. En ese caso, probablemente tendrá que verificar la velocidad del objeto en movimiento. (Ver la respuesta de Nathan Reed ).

Nota: Creo que estoy tratando esencialmente de describir la detección de colisión SAT que mencionó @Blau, pero he pasado mucho tiempo escribiendo esto, así que lo publicaré de todos modos. Espero que te ayude un poco.

Richard Marskell - Drackir
fuente
Gracias Drackir! Y supongo que si mi pared gira con respecto al sprite, es un poco más complicado, pero se aplica el mismo principio. Busque el vector de desplazamiento de longitud mínima que significaría que el sprite no colisionaría con la pared. Luego use la pared que es normal para ese vector como la mía para rebotar.
TerryB
@TerryB: la rotación le agrega un poco más de complejidad. Es posible que desee leer en los cuadros delimitadores alineados a los ejes (AABB). Básicamente, todavía utiliza el mismo principio que el anterior al probar la caja más pequeña en la que se ajustará el objeto girado, pero cuyos ejes están alineados con los ejes cartesianos. Imagínese si tuviera un cuadrado y lo girara 45 grados para convertirlo en un diamante. Calcular la colisión en eso sería difícil y costoso, así que primero verifique si el objeto está incluso cerca de él utilizando el AABB, que sería un cuadrado donde cada punto del diamante toca cada lado en el medio.
Richard Marskell - Drackir
Luego, cuando sepa que está cerca, puede hacer los cálculos más costosos para ver si se cruzan en ángulos (lo que probablemente debería ser otra pregunta por completo :)).
Richard Marskell - Drackir
1
-1 ya que el desplazamiento mínimo no siempre da la respuesta correcta a "qué borde colisionó primero"; mira mi respuesta
Nathan Reed
@NathanReed - Es por eso que mencioné verificar la velocidad en mi párrafo "Ahora, hay un pequeño problema al hacerlo de esta manera".
Richard Marskell - Drackir
15

El desplazamiento mínimo no siempre da la respuesta correcta para qué borde se golpeó primero. Considere este caso:

caso que rompe el algoritmo de desplazamiento más corto

Esto sucede cuando la velocidad es lo suficientemente alta como para que el bloque se mueva bastante lejos durante un cuadro. Para detectar correctamente qué borde se golpeó primero, deberá configurar una ecuación lineal para resolver el tiempo de colisión con cada borde. En este caso descrito en el diagrama del OP, las ecuaciones relevantes son:

timeXCollision = (player.left - wall.right) / -player.velocity.x
timeYCollision = (wall.bottom - player.top) / player.velocity.y

(Esto supone un sistema de coordenadas X-derecha, Y-arriba). En general, tendrías que usar los signos de los componentes X e Y de player.velocity para determinar qué par de bordes necesitan ser probados. De todos modos, una vez que haya calculado los tiempos de colisión, el primero de los dos es la colisión que debe manejar.

Nathan Reed
fuente
1
¿Podría dar un ejemplo de cómo se podrían implementar sus dos variables?
BjarkeCK
1

Necesita detección de colisión SAT

Básicamente, debe buscar el vector de desplazamiento mínimo que se resta a uno de los objetos para que no se crucen.

En su imagen, el desplazamiento mínimo es el segmento naranja.

ingrese la descripción de la imagen aquí

Blau
fuente
44
-1 ya que el desplazamiento mínimo no siempre da la respuesta correcta a "qué borde colisionó primero"; mira mi respuesta
Nathan Reed
quien pregunta eso?
Blau
La pregunta es eso. "Mi código actualmente me dice que se han cruzado dos bordes de la pared, pero no qué borde golpearía primero y, por lo tanto, qué borde rebotaría".
Nathan Reed
¿primero? el problema no es cuál es el primero, choca con los dos bordes al mismo tiempo, ... lo importante es qué borde rebotar, debes elegir un método que sea bueno para ti, he elegido un método que es bueno para mí, ambos son válidos
Blau
1
Si desea tomar una decisión de diseño para dejar que los objetos se deslicen entre sí de esa manera, como si estuvieran redondeados o biselados en las esquinas, esa es su decisión, y puede ser lo correcto para su juego. Pero no creo que la pregunta sea sobre una decisión de diseño; está preguntando matemáticamente cómo hacer rebotar rectángulos alineados entre ejes. Esto no es una cuestión de interpretación; Este problema matemático tiene una respuesta clara y correcta a qué borde rebotar.
Nathan Reed
0

Respondí una pregunta similar aquí

Es posible que desee considerar verificar posiciones anteriores

Por ejemplo: si su lado izquierdo estaba previamente a la derecha de su lado derecho y está colisionando, entonces ha ocurrido una colisión con la mano derecha.

Si hace esto, solo resuelva las colisiones del eje y, compruebe si está colisionando con algo, luego resuelva las colisiones del eje x.

ultifinitus
fuente