miércoles, 4 de abril de 2012

Cuestiones de FPS

Dado la pequeña modificación que hice en uno de los proyectos (concretamente en el de minisoccer), me gustaría comentar el tema del control de tiempo en las aplicaciones a tiempo real.

Hasta ahora, siempre había hecho uso de una determinada velocidad constante de juego y FPS. Es decir, el simple bucle que en cada iteración hace un "sleep" si dicha iteración se realiza en muy poco tiempo. Esto nos asegura que el juego se reproduzca a la misma velocidad en cualquier ordenador (no es del todo cierto), pero el renderizado se realiza las mismas veces que la física del juego.

const int FPS = 60;
const int DT = 1000 / FPS;
int lastTime, frameTime;

bool running = true;
while (running) {
    lastTime = getTicks();

    update();
    render();

    frameTime = getTicks() - lastTime;
    if (frameTime < DT)
        sleep(DT - frameTime);
}

Pero de este modo, limitamos las capacidades de un buen hardware cuando seguramente podría ser capaz de ejecutar el juego a una velocidad mayor. Por eso a menudo los programadores usan el tiempo de cada frame (frameTime) para actualizar la física usando lógicas parecidas a esta:

x = x + speed * frameTime

Así se aplica la integración de Euler. Pero no es eso a lo que quiero llegar. Gracias a los excelentes artículos publicados en esta y esta otra página web podemos llegar a implementar un bucle en el que la velocidad del juego es totalmente independente de los FPS. En ese caso la física podríamos calcularla 25 veces por segundo (está estudiado que generalmente es suficiente, incluyendo chequeo de collisones etc.) mientras que el renderizado se realiza en cada frame.

No voy a entrar en la implementación ya que no tiene mucha complicación y las fuentes aportadas tienen suficiente información para entenderlo (en inglés). Cabe destacar que en la renderización se hace uso de un nuevo valor que se usa para interpolar la posición correcta de las instancias y así se consigue una animación realmente suave. Yo mismo he conseguido un excelente resultado asi que animo a hacer uso de este método a todo programador, cualquier duda podeis consultarmelo.

Fuentes:
Koonsolo
Gafferongames

P.D: Las dos páginas usan métodos distintos para calcular el valor usado para la interpolación; personalmente prefiero el método usado por gafferongames que calcula dicho valor mediante el uso del estado anterior y actual de las instancias.

No hay comentarios:

Publicar un comentario