使用delta变量C ++限制while循环以30“FPS”运行

时间:2015-01-18 09:55:29

标签: c++ loops frame-rate delta

我基本上需要一个while循环才能以30“FPS”运行。 有人告诉我这样做: “在你的while循环中,做一个deltaT,如果deltaT小于33毫秒,则使用sleep(33-deltaT)。”

但我真的不太确定如何初始化delta /将此变量设置为什么。我也无法得到建议此人的回复。

我也不确定为什么睡眠中的值是33而不是30。

有谁知道我能做些什么呢?

这主要是为了让游戏服务器以30FPS更新播放器,但由于我没有在服务器上进行任何渲染,我需要一种方法让代码休眠以限制它每秒运行的次数或否则它会过快地处理玩家。

3 个答案:

答案 0 :(得分:5)

你基本上需要做这样的事情:

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

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

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

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

这样你计算当前帧和最后一帧之间传递的毫秒数,如果它小于33毫秒(1000 / 30,1000毫秒,一秒除以30 FPS = 33.333333 ....)那么你睡到33毫秒过去了。对于GetTimeInMilliseconds()Sleep()功能,它取决于您正在使用的库和/或平台。

答案 1 :(得分:2)

几年前格伦·费德勒(Glenn Fiedler)写了一篇关于这个话题的好文章。使用sleep()进行黑客攻击并不十分精确,相反,您希望每秒运行物理一次固定次数,让图形自由运行,并且在帧之间,您可以执行与时间一样多的固定时间步长。

下面的代码起初看起来令人生畏,但是一旦你明白了,它就会变得简单;最好完全阅读这篇文章。

  

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 );
}

如果它脱机,应该有几个备份可用;但是,我已经多年记得Gaffer on Games。

答案 2 :(得分:2)

c ++ 11为此提供了一种简单的机制:

#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);
    }
}

唯一需要注意的是,如果一个循环迭代需要的时间超过33毫秒,那么接下来的两个迭代将在两个迭代之间执行而不会暂停(直到t赶上实时),可能是也可能不是你想要的。