Questa domanda è specifica per le simulazioni di banana reattiva e in tempo reale con una componente fisica e visiva (ad es. Giochi).Come implementare un loop di gioco in banana reattiva?
In base allo Fix Your Timestep! il modo ideale per impostare un loop di gioco (supponendo che la fisica debba essere riproducibile), è necessario un intervallo di tempo fisso tra i frame. Dopo aver considerato una serie di complicazioni reali, l'autore arriva a questo ciclo di gioco:
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 sinossi è che la simulazione fisica è sempre alimentato lo stesso incremento di tempo (dt
) per la stabilità numerica. Organizzare per questo deve considerare che fisica e immagini possono essere aggiornate a frequenze diverse e non si vuole essere troppo indietro.
Ad esempio, è possibile che si desiderino aggiornamenti a una frequenza di 20 hz, ma un aggiornamento visivo con un framerate di 60 hz. Questo ciclo interpola linearmente la fisica per compensare la differenza tra gli aggiornamenti di fisica e gli aggiornamenti grafici.
Inoltre, quando la differenza di tempo tra i frame è molto maggiore di dt
, esiste un ciclo per gestire l'aggiornamento degli aggiornamenti in blocchi di dt
. La nota sulla spirale della morte si riferisce solo a un caso in cui il calcolo della fisica semplicemente non riesce a tenere il passo con la frequenza desiderata di aggiornamenti, quindi gli consenti di saltare alcuni aggiornamenti.
Per questa discussione, la parte che mi interessa di più è organizzare in modo che la chiamata al motore fisico (la chiamata a integrate
) venga sempre preceduta da dt
. banana reattiva consente all'utente di scrivere questo ciclo di stile? Se é cosi, come? Forse un esempio di simulazione fisica in tempo reale è in ordine (o esiste già)?
Non sono sicuro di SDL, ma con OpenGL e GLFW entrambi utilizzano la memorizzazione locale dei thread sul thread originale del processo (deve essere il thread originale, la limitazione del fornitore). GHCi esegue ciascun comando in un thread diverso per impostazione predefinita. Ciò significa che le librerie come OpenGL/GLFW (e molte altre librerie gui) non possono accedere correttamente alla loro memoria locale dei thread e andare in giro da GHCi. La soluzione è aggiungere -fno-ghci-sandbox all'avvio di GHCi. Potresti provare questo e vedere se corregge i tuoi guai SDL + GHCi: http://www.haskell.org/ghc/docs/7.0.1/html/users_guide/release-7-0-1.html –
È un po ' più difficile di '-fno-ghci-sandbox', temo. Su Mac, SDL deve essere compilato perché ridefinisce 'main' come macro. Le versioni GLFW tendono a bloccarsi in GHCi a causa di altre incompatibilità che non capisco. –
GLFW-b non dovrebbe bloccarsi da GHCi se si utilizza '-fno-ghci-sandbox'. Se lo fa, stai colpendo un nuovo bug quindi per favore fai un rapporto! :) –