Limit while loop to run at 30 “FPS” using a delta

2019-07-04 01:54发布

I basically need a while loop to only run at 30 "FPS". I was told to do this: "Inside your while loop, make a deltaT , and if that deltaT is lesser than 33 miliseconds use sleep(33-deltaT) ."

But I really wasn't quite sure how to initialize the delta/what to set this variable to. I also couldn't get a reply back from the person that suggested this.

I'm also not sure why the value in sleep is 33 instead of 30.

Does anyone know what I can do about this?

This is mainly for a game server to update players at 30FPS, but because I'm not doing any rendering on the server, I need a way to just have the code sleep to limit how many times it can run per second or else it will process the players too fast.

3条回答
再贱就再见
2楼-- · 2019-07-04 02:09

You basically need to do something like this:

int now = GetTimeInMilliseconds();
int lastFrame = GetTimeInMilliseconds();

while(running)
{
    now = GetTimeInMilliseconds();
    int delta = now - lastFrame;
    lastFrame = now;

    if(delta < 33)
    {
        Sleep(33 - delta);
    }

    //...
    Update();
    Draw();
}

That way you calculate the amount of milliseconds passed between the current frame and last frame, and if it's smaller than 33 millisecods (1000/30, 1000 milliseconds in a second divided by 30 FPS = 33.333333....) then you sleep until 33 milliseconds has passed. Has for GetTimeInMilliseconds() and Sleep() function, it depends on the library that you're using and/or the platform.

查看更多
聊天终结者
3楼-- · 2019-07-04 02:22

c++11 provides a simple mechanism for that:

#include <chrono>
#include <thread>
#include <iostream>

using namespace std;
using namespace std::chrono;

void doStuff(){
    std::cout << "Loop executed" << std::endl;
}

int main() {

    time_point<system_clock> t = system_clock::now();

    while (1) {
        doStuff();
        t += milliseconds(33);
        this_thread::sleep_until(t);
    }
}

The only thing you have to be aware of though is that if one loop iteration takes longer than the 33ms, the next two iterations will be executed without a pause in between (until t has caught up with the real time), which may or may not be what you want.

查看更多
神经病院院长
4楼-- · 2019-07-04 02:33

Glenn Fiedler has written a nice article on this topic a few years ago. Hacking with sleep() is not very precise, instead you want to run your physics a fixed number of times per second, let your graphics run freely, and between frames, you do as many fixed timesteps as time has passed.

The code that follows looks intimidating at first, but once you get the idea, it becomes simple; it's best to read the article completely.

Fix Your Timestep

double t = 0.0;
double dt = 0.01;

double currentTime = hires_time_in_seconds();
double accumulator = 0.0;

State previous;
State current;

while ( !quit )
{
    double newTime = hires_time_in_seconds();
    double frameTime = newTime - currentTime;
    if ( frameTime > 0.25 )
        frameTime = 0.25;
    currentTime = newTime;

    accumulator += frameTime;

    while ( accumulator >= dt )
    {
        previousState = currentState;
        integrate( currentState, t, dt );
        t += dt;
        accumulator -= dt;
    }

    const double alpha = accumulator / dt;

    State state = currentState * alpha + 
        previousState * ( 1.0 - alpha );

    render( state );
}

If it goes offline, there should be several backups available; however, I remember Gaffer on Games for many years already.

查看更多
登录 后发表回答