Esta pregunta es una pregunta de "seguimiento" de la anterior, con respecto a la detección y resolución de colisiones, que puede encontrar aquí .
Si no desea leer la pregunta anterior, aquí hay una breve descripción de cómo funciona mi motor de física:
Cada entidad física se almacena en una clase llamada SSSPBody.
Solo se admiten AABB.
Cada SSSPBody se almacena en una clase llamada SSSPWorld, que actualiza cada cuerpo y maneja la gravedad.
Cada cuadro, SSSPWorld actualiza cada cuerpo.
Cada cuerpo actualizado busca cuerpos cercanos en un hash espacial, comprueba si necesitan detectar colisiones con ellos. En caso afirmativo, invocan un evento de "colisión" y comprueban si necesitan resolver colisiones con ellos. En caso afirmativo, calculan el vector de penetración y la superposición direccional, luego cambian su posición para resolver la penetración.
Cuando un cuerpo choca con otro, transfiere su velocidad al otro simplemente ajustando la velocidad del cuerpo a la suya.
Un cuerpo con velocidad se establece en 0 cuando no ha cambiado de posición desde el último fotograma. Si también choca con un cuerpo móvil (como un elevador o una plataforma móvil), calcula la diferencia de movimiento del elevador para ver si el cuerpo no se ha movido desde su última posición.
Además, un cuerpo invoca un evento "aplastado" cuando todas sus esquinas AABB se superponen a algo en un marco.
Este es el código fuente COMPLETO de mi juego. Está dividido en tres proyectos. SFMLStart es una biblioteca simple que maneja entradas, dibujos y actualizaciones de entidades. SFMLStartPhysics es el más importante, donde se encuentran las clases SSSPBody y SSSPWorld. PlatformerPhysicsTest es el proyecto del juego, que contiene toda la lógica del juego.
Y este es el método de "actualización" en la clase SSSPBody, comentado y simplificado. Puede ver esto solo si no tiene ganas de mirar todo el proyecto SFMLStartSimplePhysics. (E incluso si lo haces, aún deberías echarle un vistazo a esto ya que está comentado).
El .gif muestra dos problemas.
- Si los cuerpos se colocan en un orden diferente, se producen resultados diferentes. Las cajas de la izquierda son idénticas a las cajas de la derecha, solo colocadas en orden inverso (en el editor).
- Ambas cajas deben ser impulsadas hacia la parte superior de la pantalla. En la situación de la izquierda, no se impulsan cajas. A la derecha, solo uno de ellos es. Ambas situaciones son involuntarias.
Primer problema: orden de actualización
Esto es bastante simple de entender. En la situación de la izquierda, la caja superior se actualiza antes que la otra. Incluso si la caja en la parte inferior "transfiere" la velocidad a la otra, necesita esperar al siguiente cuadro para moverse. Como no se movió, la velocidad de la caja inferior se establece en 0.
No tengo idea de cómo solucionar esto. Prefiero que la solución no dependa de "ordenar" la lista de actualizaciones, porque siento que estoy haciendo algo mal en todo el diseño del motor de física.
¿Cómo manejan los principales motores de física (Box2D, Bullet, Chipmunk) el orden de actualización?
Segundo problema: solo una caja se impulsa hacia el techo
Todavía no entiendo por qué sucede esto. Lo que hace la entidad de "resorte" es establecer la velocidad del cuerpo en -4000 y reubicarla en la parte superior del resorte. Incluso si desactivo el código de reubicación, el problema aún ocurre.
Mi idea es que cuando la caja inferior choca con la caja superior, su velocidad se establece en 0. No estoy seguro de por qué sucede esto.
A pesar de la posibilidad de parecer alguien que se rinde ante el primer problema, publiqué todo el código fuente del proyecto arriba. No tengo nada que lo demuestre, pero créanme, intenté arreglar esto, pero no pude encontrar una solución y no tengo experiencia previa en física y colisiones. Llevo más de una semana intentando resolver estos dos problemas y ahora estoy desesperado.
No creo que pueda encontrar una solución por mi cuenta sin quitar muchas funciones del juego (transferencia de velocidad y resortes, por ejemplo).
Muchas gracias por el tiempo dedicado a leer esta pregunta, y más aún si intentas encontrar una solución o una sugerencia.