Estoy desarrollando un motor de física para un juego de plataformas en 2D. Estoy usando el teorema del eje de separación para la detección de colisiones. La superficie del suelo se construye a partir de cuadros delimitadores orientados, con el jugador como un cuadro delimitador alineado con el eje. (Específicamente, estoy usando el algoritmo del libro "Detección de colisión en tiempo real" que realiza la detección de colisión barrida para OBBs usando SAT). Estoy usando un coeficiente de restitución bastante pequeño (cercano a cero) en la respuesta de colisión, para asegurar que los objetos dinámicos no penetren en el entorno.
El motor en su mayoría funciona bien, es solo que me preocupan algunos casos extremos que podrían ocurrir. Por ejemplo, en el diagrama, A, B y C son la superficie del suelo. El jugador se dirige hacia la izquierda a lo largo de B hacia A. Me parece que debido a la inexactitud, la casilla del jugador podría estar ligeramente debajo de la casilla B a medida que continúa hacia arriba y hacia la izquierda. Cuando llega a A, por lo tanto, la esquina inferior izquierda del jugador podría colisionar con el lado derecho de A, lo que sería indeseable (ya que la intención es que el jugador se mueva suavemente sobre la parte superior de A). Parece que podría ocurrir un problema similar cuando el jugador está en la parte superior de la casilla C, moviéndose a la izquierda hacia B: el punto más extremo de B podría chocar con el lado izquierdo del jugador, en lugar de que la esquina inferior izquierda del jugador se deslice hacia arriba y hacia la izquierda por encima de B.
Box2D parece manejar este problema almacenando información de conectividad para sus formas de borde, pero no estoy realmente seguro de cómo usa esta información para resolver el problema, y después de mirar el código, realmente no entiendo lo que está haciendo.
Cualquier sugerencia sería muy apreciada.
Respuestas:
Plataformas y Física
Estos casos extremos son numerosos. Los juegos de plataformas buenos y divertidos no se comportan de ninguna manera físicamente precisa, y el control y el comportamiento que los jugadores esperan después de años de juegos de plataformas "perfectos" como Mario son increíblemente difíciles de implementar con técnicas generales como las que obtienes con Box2D u otros motores de física. La mayoría de los buenos plataformas no usan ningún tipo de física genérica o respuesta de colisión en sus controladores de jugador.
Generar cascos
Con respecto a su pregunta específica, la mejor solución es dejar de usar cajas como base. Use una serie de segmentos de línea conectados (un casco). Eso permite que el motor de detección de colisión se enfoque solo en las superficies realmente transitables y no mire el borde "falso" que existe entre AB y BC. Eso es lo que hace Box2D, de hecho. Las formas se utilizan para generar las superficies exteriores, que se unen para formar un casco.
Necesitas esto incluso en juegos basados en fichas, o en situaciones en las que tienes dos objetos AABB junto a otros que actúan como piso. El motor de colisión recogerá esos bordes verticales y hará que el jugador los atrape. Hay hacks que pueden ayudar, pero no eliminan el problema. La solución es tener un solo segmento de línea que represente la superficie en lugar de un cuadro 2D completo.
Puede generar los cascos en el caso genérico recortando los polígonos entre sí y uniendo los puntos de recorte en una lista de bordes.
Superficies inclinadas
Dado que su ejemplo incluye una pendiente y está mencionando la restitución y otras propiedades físicas, señalaré algunos otros problemas que notará pronto, lo que ilustra aún más por qué la detección y respuesta de colisión genérica no funciona bien para los juegos de plataformas. Primero, intenta pararte en la plataforma en ángulo, salta y luego aterriza. Probablemente notarás que el personaje se "deslizará" un poco al aterrizar. El problema es que el contacto normal que está generando generalmente estará señalando desde la superficie en ángulo. Luego, al resolver la colisión, el jugador es empujado en esa dirección. A pesar de que el personaje cayó hacia abajo, lo empujarán hacia arriba y un poco hacia la derecha al aterrizar, lo que provocará el deslizamiento. Esto puede ser pirateado teniendo en cuenta las velocidades relativas,
El segundo problema que notará, que es mucho más difícil de solucionar, es lo que sucede cuando intenta correr rápidamente por una rampa. El jugador va a "saltar" por la rampa. Esto es muy visible incluso en la mayoría de los juegos AAA de hoy. No solo parece una tontería, sino que si tu juego requiere que el jugador esté parado en el suelo para saltar, hace que sea difícil correr por una rampa y saltar a mitad de camino, porque el jugador solo está en contacto con la rampa durante una pequeña porción del tiempo dedicado a bajarlo. Una solución más simple es simplemente hacer algunos lanzamientos de rayos cuando el jugador se mueve, y ajustar la posición del jugador hacia la superficie más cercana (si está muy cerca del jugador) si el jugador no está saltando y estaba previamente en el suelo.
También puede encontrar que el jugador se lanza al aire cuando corre por una rampa si intenta modelar la velocidad, la fricción y la restitución en el jugador como si fuera un cuerpo rígido normal. El movimiento del jugador debe limitarse al movimiento horizontal a menos que caiga / salte. Por supuesto, si juegas plataformas de edad dorada más antiguas, puedes notar que la velocidad horizontal del jugador a menudo es constante entre las superficies horizontales e inclinadas. Esto también debe tenerse en cuenta al subir / bajar pendientes.
Habrá una serie de otros casos de esquina extraños con los que eventualmente también se encontrará. Si está tratando de hacer un buen juego de plataformas, realmente es mejor implementar un controlador de jugador de plataformas separado de la física y codificar el comportamiento de movimiento y control que desea, en lugar de confiar en la física genérica y el algoritmo de respuesta a colisiones.
fuente
Creo que ambos problemas podrían resolverse tratando sus cajas, con fines de respuesta de colisión, como si tuvieran esquinas redondeadas (de un radio similar a su error numérico). Esto hará que la superficie combinada efectiva de las esquinas de reunión entre A y B, y B y C, sea más suave.
Por lo tanto, si el JUGADOR que se mueve hacia la izquierda golpea la esquina de A, la colisión normal sería diagonal en lugar de puramente hacia la derecha, permitiendo así la continuación del movimiento hacia la izquierda y hacia arriba.
Sin embargo, una solución más típica, al revisar lo que sé de física de plataformas, es hacer que el jugador tenga una forma más redondeada y dejar el terreno solo. En particular, considere hacer que la forma del jugador sea una cápsula (círculo estirado en el medio (2D) / esfera (3D)), entonces sus normales de colisión serán naturalmente verticales, eliminando cualquier problema de captura.
Dice que está utilizando un algoritmo de colisión específicamente para OBB, pero aún así debería poder, después de encontrar una colisión OBB-OBB, usar una prueba adicional contra una forma que esté completamente dentro del OBB.
fuente