Categories
Game Development

Networking friendly game loop with variable length updates and renders

I was reading http://dewitters.koonsolo.com/gameloop.html where the author, Koen Witters, proposes a fixed-update game loop with a variable update render loop using interpolation to find out between-frame render positions. It’s a well written article and his solution is good for single player games. const int TICKS_PER_SECOND = 25; const int SKIP_TICKS = 1000 / TICKS_PER_SECOND; const […]

I was reading http://dewitters.koonsolo.com/gameloop.html where the author, Koen Witters, proposes a fixed-update game loop with a variable update render loop using interpolation to find out between-frame render positions. It’s a well written article and his solution is good for single player games.


const int TICKS_PER_SECOND = 25;
const int SKIP_TICKS = 1000 / TICKS_PER_SECOND;
const int MAX_FRAMESKIP = 5;

DWORD next_game_tick = GetTickCount();
int loops;
float interpolation;

bool game_is_running = true;
while( game_is_running ) {

loops = 0;
while( GetTickCount() > next_game_tick && loops < MAX_FRAMESKIP) { update_game(); next_game_tick += SKIP_TICKS; loops++; } interpolation = float( GetTickCount() + SKIP_TICKS - next_game_tick ) / float( SKIP_TICKS ); display_game( interpolation ); }

However, this has problems with online games. In networking, you often need to extrapolate given a prior position and some amount of time to the current time. For example, I may get a position packet 208 milliseconds ago. If I were to update every 40 milliseconds (25 ticks per second), I would have 8 milliseconds leftover. This moves the problem of left-over ticks to your game objects.

You can either calculate partial ticks, in which case your game objects are slightly out of synch with the fixed-step simulation, or you can ignore them, and just use the least number of ticks you can fit in. If you get frequent updates this is OK, but for objects that are not updated frequently things can get out of place, and a lot faster than 2.4336088699783431e-13.

My solution is variable length game updates with variable length frame updates, with a frequency limit on game updates.

Variable length updates with variable length frame updates:


// Do not skip more than one second (due to debugging)
const int MIN_UPDATE_TIME=1000;
// Do not update more than every 10 milliseconds
const int MAX_UPDATE_TIME=10;
// How much time to render forward
float renderExtrapolationTime;

bool game_is_running = true;
Time lastGameUpdate=GetTimeMS();

// Force the first ever update, before the first ever render
Time elapsedGameTime=MAX_UPDATE_TIME;
while( game_is_running ) {

if (elapsedGameTime >= MAX_UPDATE_TIME) {

if (elapsedGameTime > MIN_UPDATE_TIME)
elapsedGameTime = MIN_UPDATE_TIME;

update_game(elapsedGameTime);
lastGameUpdate=GetTimeMS();
}

renderInterpolationTime = GetTimeMS() - lastGameUpdate;
display_game( renderExtrapolationTime );
elapsedGameTime=GetTimeMS()-lastGameUpdate;
}

Leave a Reply

Your email address will not be published. Required fields are marked *