Esta pregunta es específica de las simulaciones de plátano reactivo y en tiempo real con un componente físico y visual (por ejemplo, juegos).¿Cómo implementar un bucle de juego en plátano reactivo?
De acuerdo con Fix Your Timestep!, la forma ideal de configurar un bucle de juego (asumiendo que la física necesita ser reproducible), necesita un intervalo de tiempo fijo entre fotogramas. Después de considerar una serie de complicaciones reales, el autor llega a este bucle de juego:
double t = 0.0;
const double dt = 0.01;
double currentTime = hires_time_in_seconds();
double accumulator = 0.0;
State previous;
State current;
while (!quit)
{
double newTime = time();
double frameTime = newTime - currentTime;
if (frameTime > 0.25)
frameTime = 0.25; // note: max frame time to avoid spiral of death
currentTime = newTime;
accumulator += frameTime;
while (accumulator >= dt)
{
previousState = currentState;
integrate(currentState, t, dt);
t += dt;
accumulator -= dt;
}
const double alpha = accumulator/dt;
State state = currentState*alpha + previousState * (1.0 - alpha);
render(state);
}
La sinopsis es que la simulación de la física siempre se alimenta el mismo incremento de tiempo (dt
) para la estabilidad numérica. Organizar para eso debe tener en cuenta que la física y las imágenes se pueden actualizar a diferentes frecuencias y no desea ir demasiado atrás.
Por ejemplo, es posible que desee actualizaciones a una frecuencia de 20 hz, pero una actualización visual con una tasa de fotogramas de 60 hz. Este ciclo realiza la interpolación lineal de la física para compensar la diferencia entre las actualizaciones físicas y las actualizaciones gráficas.
Además, cuando la diferencia en el tiempo entre fotogramas es mucho mayor que dt
, hay un bucle para manejar el paso de las actualizaciones en fragmentos de dt
. La nota sobre la espiral de la muerte solo se refiere a un caso en el que el cálculo de su física simplemente no puede mantenerse al día con la frecuencia deseada de actualizaciones, por lo que le permite omitir algunas actualizaciones.
Para esta discusión, la parte que más me interesa es organizar de modo que la llamada al motor de física (la llamada al integrate
) siempre sea reemplazada por dt
. ¿reactive-banana permite al usuario escribir este ciclo de estilo? ¿Si es así, cómo? Quizás un ejemplo de simulación de física en tiempo real esté en orden (o ya exista)?
No estoy seguro acerca de SDL, pero con OpenGL y GLFW ambos usan el almacenamiento local de subprocesos en el subproceso original del proceso (tiene que ser el subproceso original, la limitación del proveedor). GHCi ejecuta cada comando en un hilo diferente por defecto. Esto significa que las bibliotecas como OpenGL/GLFW (y varias otras bibliotecas gui) no pueden acceder correctamente a su almacenamiento local de subprocesos y se vuelven locas desde GHCi. La solución es agregar -fno-ghci-sandbox al iniciar GHCi. Puede probar esto y ver si soluciona sus problemas con SDL + GHCi: http://www.haskell.org/ghc/docs/7.0.1/html/users_guide/release-7-0-1.html –
Es un poco más difícil que '-fno-ghci-sandbox', me temo. En Mac, SDL necesita compilarse porque redefine 'main' para que sea una macro. Las versiones GLFW tienden a bloquearse en GHCi debido a otras incompatibilidades que no entiendo. –
GLFW-b no debe bloquearse desde GHCi si usa '-fno-ghci-sandbox'. Si lo hace, está pegando un nuevo error así que ¡por favor haga un informe! :) –