Un aspecto importante a la hora de desarrollar un juego es lograr sincronizar el motor gráfico, el motor de física, y la lógica del juego, de manera que este se comporte de manera similar en diferentes máquinas.
Por un lado, el motor gráfico cuanto más fluido funcione mejor, aunque nunca viene mal ajustar su velocidad con la tasa de refresco del monitor, con lo que aliviamos un poco el procesador. El motor de física y la lógica del juego suelen consumir bastantes recursos, por lo que también es buena idea regular a la velocidad que se actualizan.
Hasta la versión 0.0.5 de Project Football (incluida), el motor gráfico y el de física corrían a sus anchas, y la lógica del juego tenía como límite una actualización por cada tres veces que se actualizara la física. Esto tiene el inconveniente de que consume muchos recursos y que dependiendo de la máquina, el juego funciona más rápido o más lento. La única opción hasta el momento era activar la sincronización con el monitor (opción VSYNC en el fichero ProjectFootball.ini), que disminuye bastante el uso de recursos, pero aún así, no todos los monitores tienen la misma frecuencia de actualización, por lo que el juego seguirá funcionando a diferente velocidad dependiendo de la máquina.
Para tratar este tema, he creado una clase llamada CTimer, cuyos objetos harán las funciones de reloj según sea necesario. Esta clase aprovecha la información que nos da el motor
Ogre, en los objetos registrados como "FrameListener", del tiempo que ha pasado desde el anterior frame. Para crear un reloj CTimer sólo hay que pasarle la frecuencia en Herzios, y al llamar a la función "nextTick" nos dirá si ha pasado el tiempo equivalente a un Herzio o no. Para ver esto con más claridad, os pongo como queda el método de actualización del simulador:
if(m_logicTimer->nextTick()) {
     std::vector::iterator it;
     m_referee->update();
     for(it = m_homePlayers.begin(); it!=m_homePlayers.end(); it++) {
         (*it)->update();
     }
     for(it = m_awayPlayers.begin(); it!=m_awayPlayers.end(); it++) {
         (*it)->update();
     }
}
if(m_physicsTimer->nextTick()) {
     m_simWorld->update();
}
Como veis, queda muy simple: si el reloj de lógica avisa, actualizamos la lógica, y si el reloj de física avisa, actualizamos el motor de físicas. El reloj de lógica lo he configurado a 30 Hz y el de física a 60 Hz, que en código quedaría así:
m_logicTimer = new CTimer(30);
m_physicsTimer = new CTimer(60);
Con esto, tanto la física como la lógica se actualizarán con esta frecuencia independientemente de la máquina en la que se juegue, siempre y cuando esta sea capaz de realizar los cálculos a tiempo. Si la máquina es demasiado lenta, simplemente funcionará a máximo rendimiento.