2011-09-09 12 views
10

Tratando de entender los conceptos de establecer velocidad constante en el loop del juego. Me duele la cabeza. Leí el deWiTTERS page, pero no puedo ver el por qué/cómo ... cuando lo tengo ... resbala.Loop basado en tiempo y Loop basado en Frame

while(true) 
{ 
     player->update() ; 
     player->draw() ; 
} 

Esto funcionará lo más rápido posible según lo rápido que sea un procesador ... Lo entiendo.

Para correr a la misma velocidad en todas las computadoras, la lógica es lo que no entiendo. Si estoy tratando de correr a 60 fps, significa que por cada 16ms los objetos se mueven por un marco, ¿sí? Lo que no entiendo es que el update() o el draw() pueden ser demasiado lentos.

deWiTTERS ejemplo (utilicé 60):

const int FRAMES_PER_SECOND = 60; 
const int SKIP_TICKS = 1000/FRAMES_PER_SECOND; 

DWORD next_game_tick = GetTickCount(); 
// GetTickCount() returns the current number of milliseconds 
// that have elapsed since the system was started 

int sleep_time = 0; 

bool game_is_running = true; 

while(game_is_running) { 
    update_game(); 
    display_game(); 

    next_game_tick += SKIP_TICKS; 
    sleep_time = next_game_tick - GetTickCount(); 
    if(sleep_time >= 0) { 
     Sleep(sleep_time); 
    } 
    else { 
     // Shit, we are running behind! 
    } 
} 

No entiendo por qué se obtiene la hora actual antes de que comience el bucle. Y cuando aumenta en SKIP_TICKS, entiendo que se incrementa al siguiente intervalo de 16 ms. Pero no entiendo esta parte así:

sleep_time = nextgametick - GetTickCount() 

¿Qué significa Sleep(sleep_time)? El procesador abandona el ciclo y hace algo más? ¿Cómo logra ejecutar 60 fps?

+0

http://msdn.microsoft.com/en-us/library/ms686298%28v=vs.85%29.aspx – Lucian

+0

http://msdn.microsoft.com/en-us/library/ms724408%28v = vs.85% 29.aspx – Lucian

+0

Gracias, se supone que GetTickCount() regresa entre 10-16ms o menos, ¿sí? Pero, en cambio, estoy viendo cosas como 324505599 como resultado ... ¿Qué significa "La resolución de la función GetTickCount está limitada a la resolución del temporizador del sistema, que normalmente está en el rango de 10 milisegundos a 16 milisegundos", entonces? –

Respuesta

5

En los casos donde las funciones update_game() y display_game() se completan en menos tiempo que un solo intervalo de fotogramas en 60FP, el bucle intenta asegurarse de que el siguiente fotograma no se procesa hasta que ese intervalo está activo. el hilo) fuera del tiempo de fotograma sobrante. Parece que está intentando garantizar que la velocidad de fotogramas esté limitada a 60 FPS, y no más.

El procesador no 'abandona el ciclo', sino que el hilo en el que se ejecuta el ciclo está bloqueado (no se puede continuar la ejecución de su código) hasta que se agote el tiempo de espera. Luego continúa en el siguiente cuadro. En un motor de juego de subprocesos múltiples, dormir el hilo del bucle principal del juego de esta manera le da tiempo a la CPU para ejecutar código en otros hilos, que pueden administrar física, inteligencia artificial, mezcla de audio, etc., dependiendo de la configuración.

¿Por qué se llama a GetTickCount() antes de que se inicie el ciclo? Sabemos por el comentario en su código que GetTickCount() devuelve los milisegundos desde el inicio del sistema.

lo que permite decir que el sistema ha estado funcionando durante 30 segundos (30,000ms) al iniciar el programa, Y digamos que no lo hicimos GetTickCount llamada() antes de entrar en el bucle, pero en vez inicializado next_game_tick a 0.

hacemos la actualización y el consumo de las llamadas (como ejemplo, se llevan de 6 ms) y luego:

next_game_tick += SKIP_TICKS; // next_game_tick is now 16 
sleep_time = next_game_tick - GetTickCount(); 

// GetTickCount() returns 30000! 
// So sleep_time is now 16 - 30000 = -29984 !!! 

como nos (sensatez), sólo dormir cuando sleep_time es positiva, el juego lazo correría tan rápido s posible (potencialmente más rápido que 60FPS), que no es lo que desea.

+0

Pero si ambas funciones se completan en menos de 16 ms, es posible que no se quede inactiva porque es posible que el if (tiempo de espera> 0) no sea cierto ...? –

+1

No estoy seguro de entender su pregunta de seguimiento, así que tomemos el primer fotograma como ejemplo, y supongamos que next_game_tick comienza en 0. Ahora, digamos que la actualización y visualización se realizan en 6 ms. next_game_tick se incrementa a 16. Ahora sleep_time es 16 - GetTickCount() = 16 - 6 = 10. Así que tenemos 10 milisegundos para dormir, antes de pasar al siguiente fotograma. –

+1

Por cierto, el valor de retorno de GetTickCount() se explica en un comentario en su código ;-) '... milisegundos desde que se inició el sistema', es decir, el tiempo transcurrido desde el inicio de su máquina. –