Me pregunto cómo se diseñan típicamente los mecanismos de manipulación del tiempo en los juegos. Estoy particularmente interesado en invertir el tiempo (algo así como en el último SSX o Prince of Persia).
El juego es un tirador 2D de arriba hacia abajo.
El mecanismo que estoy tratando de diseñar / implementar tiene los siguientes requisitos:
1) Las acciones de entidades aparte del personaje del jugador son completamente deterministas.
- La acción que realiza una entidad se basa en los marcos progresados desde el inicio del nivel y / o la posición del jugador en la pantalla
- Las entidades se generan a la hora establecida durante el nivel.
2) El tiempo inverso funciona retrocediendo en tiempo real.
- Las acciones del jugador también se invierten, reproduce a la inversa lo que realizó el jugador. El jugador no tiene control durante el tiempo inverso.
- No hay límite en el tiempo invertido en revertir, podemos revertir todo el camino hasta el comienzo del nivel si lo desea.
Como ejemplo:
Cuadros 0-50: el jugador se mueve hacia adelante 20 unidades durante este tiempo. El enemigo 1 se genera en el cuadro 20 El enemigo 1 se mueve hacia la izquierda 10 unidades durante el cuadro 30-40 El jugador dispara una bala en el cuadro 45 La bala viaja 5 hacia adelante (45-50) y mata al enemigo 1 en marco 50
Revertir esto se reproduciría en tiempo real: el jugador se mueve hacia atrás 20 unidades durante este tiempo. El enemigo 1 revive en el cuadro 50 La bala vuelve a aparecer en el cuadro 50 La bala se mueve hacia atrás 5 y desaparece (50-45) El enemigo se mueve hacia la izquierda 10 (40-30) Enemigo eliminado en marco 20.
Solo mirando el movimiento tenía algunas ideas sobre cómo lograr esto, pensé en tener una interfaz que cambiara el comportamiento cuando el tiempo avanzaba o retrocedía. En lugar de hacer algo como esto:
void update()
{
movement += new Vector(0,5);
}
Haría algo como esto:
public interface movement()
{
public void move(Vector v, Entity e);
}
public class advance() implements movement
{
public void move(Vector v, Entity e)
{
e.location += v;
}
}
public class reverse() implements movement
{
public void move(Vector v, Entity e)
{
e.location -= v;
}
}
public void update()
{
moveLogic.move(new vector(5,0));
}
Sin embargo, me di cuenta de que esto no sería un rendimiento óptimo y rápidamente se volvería complicado para acciones más avanzadas (como un movimiento suave a lo largo de caminos curvos, etc.).