使用 delta 变量 C++ 将 while 循环限制为 运行 at 30 "FPS"
Limit while loop to run at 30 "FPS" using a delta variable C++
我基本上需要一个 while 循环才能在 30 "FPS" 处仅 运行。
有人告诉我这样做:
"Inside your while loop, make a deltaT , and if that deltaT is lesser than 33 miliseconds use sleep(33-deltaT) ."
但我真的不太确定如何初始化 delta/what 以将此变量设置为。我也无法从提出此建议的人那里得到回复。
我也不确定为什么 sleep 中的值是 33 而不是 30。
有人知道我能做些什么吗?
这主要是为了让游戏服务器以 30FPS 的速度更新玩家,但是因为我没有在服务器上进行任何渲染,所以我需要一种方法让代码休眠以限制它可以运行的次数 运行 每秒,否则它会处理玩家太快。
你基本上需要做这样的事情:
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()
功能,这取决于您使用的库 and/or 平台。
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 多年的游戏了。
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 赶上实时) ,这可能是也可能不是您想要的。
我基本上需要一个 while 循环才能在 30 "FPS" 处仅 运行。 有人告诉我这样做: "Inside your while loop, make a deltaT , and if that deltaT is lesser than 33 miliseconds use sleep(33-deltaT) ."
但我真的不太确定如何初始化 delta/what 以将此变量设置为。我也无法从提出此建议的人那里得到回复。
我也不确定为什么 sleep 中的值是 33 而不是 30。
有人知道我能做些什么吗?
这主要是为了让游戏服务器以 30FPS 的速度更新玩家,但是因为我没有在服务器上进行任何渲染,所以我需要一种方法让代码休眠以限制它可以运行的次数 运行 每秒,否则它会处理玩家太快。
你基本上需要做这样的事情:
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()
功能,这取决于您使用的库 and/or 平台。
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 多年的游戏了。
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 赶上实时) ,这可能是也可能不是您想要的。