Weird stuttering with fixed-timestep, variable-framerate game loop

| | August 8, 2015

I’ve been trying to set up fixed-timestep loop for my game, using the technique from here. I have no need for the interpolation step as I intend to run the logic at or above vsync speed.

Here is a simplified version of my test code (C#):

const double MILLISECONDS = 1000.0;
const double TARGET_SPEED = 60.0; //Logic tick rate in hertz

const double dt = MILLISECONDS / TARGET_SPEED;

double currentTime;
double accumulator = 0.0;
Stopwatch logicTimer = new Stopwatch();

double theta = 0;
float spinSpeed = 0.005f;

//Game loop:
while (true)
{
    double newTime = logicTimer.ElapsedMilliseconds;
    double frameTime = newTime - currentTime;

    currentTime = newTime;
    accumulator += frameTime;

    while (accumulator >= dt)
    {
        theta = (theta + spinSpeed * dt) % (Math.PI * 2.0);
        accumulator -= dt;
    }


    //Draw sprite, rotated theta radians
    Draw();
}

With TARGET_SPEED at 60Hz on a 60Hz monitor, most of the time it runs smoothly. However, often when I run the test I see periodic jumps in the rotation. The time to complete a revolution does not change, but it appears to stand still for an extra frame or two and then jump ahead to make up the difference. The frequency of these stutters is constant during a run, but subsequent runs with the same settings will stutter at different rates.

I’ve measured how much theta changes each logic step, and it’s rock steady across multiple runs regardless of stuttering.

This leads me to believe the problem is something to do with differences between my game’s clock and my monitor’s refresh clock. However, I can’t figure out anything beyond that.

The problem still happens whether vsync is on or off. It happens less often when TARGET_SPEED is a multiple of 60; for any other value it happens on every run. Increasing TARGET_SPEED past 1000 or 10,000 Hz appears much smoother, but there’s no way I can run a real game that fast. Drawing more or fewer sprites to control the time spent rendering doesn’t seem to have any consistent effect on the problem.

So basically I’m completely stumped. Any idea why this is happening and how I can fix it?

Here’s the full source file for my test project (XNA) if you want to try it for yourself.

One Response to “Weird stuttering with fixed-timestep, variable-framerate game loop”

  1. Maybe the problem lies elsewhere in the code, but if you’re sure it’s contained in the code you pasted, and the stutter is periodic, constant, and only happens in some tests (but constantly throughout the execution), you might be dealing with a rounding error, which would happen only if the initial time gets initialized to a specific value.

    I see you’re using doubles, but the MSDN documentation says that Stopwatch.ElapsedMilliseconds returns long.
    So I’d first change all time variables to long (yes even the dt, round it down to the nearest value), and see if the problem disappears.

    Also, I don’t know about XNA, but the modulo operator is for integers only, and to make it work with floating point values (and PI*2 will be a floating point value), instead of:

    theta = (theta + spinSpeed * dt) % (Math.PI * 2.0);
    

    You want fmod():

    theta = fmod(theta + spinSpeed * dt, Math.PI * 2.0);
    

    Tip: you might want to define a constant for Math.PI * 2.0 to save a couple of CPU cycles.

Leave a Reply