Ok vamos a dar un poco más de contexto.
Mi algoritmo está basado en este paper que describe un algoritmo para detección de colisiones en 3D de elipsoides contra triangulos. Simplemente lo he reducido a dos dimensiones.
El jugador está representado por un "Mobile": un vector posición, un vector velocidad y un radio. En cada tick del juego, si no hay colisiones, la nueva posicion del jugador es simplemente:
new_pos = old_pos + velocity;
Las paredes están representadas por segmentos. Un segmento no es más que un punto inicial y un punto final, representados por vectores.
Hasta ahora, los únicos structs importantes:
typedef struct Vector {
double x, y;
} Vector;
typedef struct Mobile {
Vector pos, vel;
double radius;
} Mobile;
typedef struct Segment {
Vector start, end;
} Segment;
A vista de pájaro el algoritmo tiene dos fases, Deteccion y Respuesta.
Detección:
Dado un Mobile y un array de Segments, obtener el Segment con el que menos distancia hay que recorrer para colisionar, y el punto de colisión.
Respuesta:
Moverse un poquito menos que la distancia hasta la colisión (para evitar meterse por accidente en la pared), calcular la velocidad restante.
Calcular la tangente al círculo del Mobile en el punto de colisión, y proyectar la velocidad restante sobre esta dirección.
Repetir el proceso (deteccion y respuesta) con esta nueva velocidad, hasta que no haya colisiones o la velocidad sea muy pequeña.
Esta teoría funciona perfectamente excepto en el caso del gif. Tiene que ser culpa de la fase de respuesta porque si la reduzco a "si hay colision -> no te muevas", nunca me cuelo por nada.
Se que es mucha tela, he posteado más que nada por frustración xD llevo bastantes horas dandome cabezazos con esto, y ni si quiera he conseguido crear un test que me reproduzca el fallo.