Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm trying to make my game's server thread run at a fixed 30Hz but can't figure out how. Basically, before I just had a stupid while(1) { //do everything as fast as you can} which means that for my computer, with client and server on localhost, results in sending ~30,000(!) packets per second. which of course, is way, way too much.

Which is all because it's burning as fast as it can, and since the player position is being changed extremely quickly, it will send out those packets just as quickly.

It's based off of the infamous fixed timestep: http://gafferongames.com/game-physics/fix-your-timestep/ but I'm trying to use C++11's chrono features, but anything I try to do still doesn't slow down the server. Either it won't ever run the inner while loop, or it will do so (like it does right now with the code below), super super fast-like.

The problem's definitely something simple/stupid, but I can't tell what.

Thanks.

std::chrono::system_clock::time_point currentTime = std::chrono::high_resolution_clock::now();
double accumulator = 0.0;
const double dt = (1.0 / 30.0) / 1000.0 / 1000.0; // runs at 30 hz
double t = 0.0;

while (1) {

    std::chrono::system_clock::time_point newTime = std::chrono::high_resolution_clock::now();
    double frameTime = std::chrono::duration_cast<std::chrono::nanoseconds>(newTime - currentTime).count();

    if ( frameTime > 1.0/15.0 / 1000.0 / 1000.0) {
        frameTime = 1.0/15.0 / 1000.0 / 1000.0;   // note: max frame time to avoid spiral of death
    }
    currentTime = newTime;


    accumulator += frameTime;

    while ( accumulator >= dt )
    {
        m_world->update(dt);
        poll();

        t += dt;
        accumulator -= dt;
    }

    const double alpha = accumulator / dt;

    // do network shit
}
share|improve this question
3  
Have you tried breakpoints or benchmarking? –  Shotgun Ninja Mar 20 '13 at 20:30
add comment

closed as too localized by Sean Middleditch, bummzack, Josh Petrie, Byte56, John McDonald Apr 5 '13 at 17:19

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.If this question can be reworded to fit the rules in the help center, please edit the question.

1 Answer

up vote 5 down vote accepted

Your game loop code is correct, but your units are all mixed up -- you are effectively setting to your timestep to .00000003 nanoseconds!

Your clock is counting in nanoseconds, so your dt should be in nanoseconds. If a clock ticks 30 times a second, it will tick every .033 seconds. There are many nanoseconds in a second, so it will take more nanoseconds to tick (* 1000.0), not fewer (/ 1000.0). Your code should work if you change your dt to this:

const double dt = (1.0 / 30) * 1000 * 1000 * 1000;   // 1000ms in s, 1000μs in ms, 1000ns in μs

and make a similar change for your max frame cap:

if ( frameTime > 1.0/15.0 * 1000.0 * 1000.0 * 1000.0) {
    frameTime = 1.0/15.0 * 1000.0 * 1000.0 * 1000.0;   // note: max frame time to avoid spiral of death
}
share|improve this answer
    
okay, this makes a lot of sense now. But i printed my frametime and it's something like 50 nanoseconds. which sure as hell isn't running at 30 hz..which is odd –  user148459 Mar 20 '13 at 23:21
    
I tried switching it to milliseconds, because that makes more sense really, by switching the duration cast to ::milliseconds and instead doing 1.0/15.0 *1000.0 and then 1.0/30.0 * 1000.0 for the dt. But then the inner while loop doesn't get run even once. what's going on here? –  user148459 Mar 20 '13 at 23:23
    
frameTime isn't the fixed 30Hz time, but instead it is the amount of time that has passed since the previous iteration through the loop. So, we expect frameTime to be different. dt is the fixed 30Hz time (notice that's what you pass to your update function), so that's the value that should remain the same. The loop basically accumulates frameTime into fixed dt chunks. –  Mike Welsh Mar 21 '13 at 0:53
    
The reason that you are getting 0 when switching to milliseconds is a little more complex. std::chrono::milliseconds is defined as std::chrono::duration< int_64t, std::milli > -- that is, it is clamped to an integer! Therefore, your resulting frameTime is 0 (because the loop always executes in faster than an ms). You can fix this by using duration_cast< std::chrono::duration<double, std::milli> >, which will allow it use a double. –  Mike Welsh Mar 21 '13 at 0:53
    
Finally, you should probably put the thread to sleep at the end of the loop to prevent your game from hogging 100% of the CPU. After your tick loop, you can do something like: std::chrono::milliseconds timeTilNextFrame( int( dt - accumulator ) ); std::this_thread::sleep_for(timeTilNextFrame); –  Mike Welsh Mar 21 '13 at 1:01
show 2 more comments

Not the answer you're looking for? Browse other questions tagged or ask your own question.