Mic*_*LoL 5 c++ windows opengl glfw
我正在尝试使用 C++ 创建一个游戏,我想为 fps 创建限制,但我总是得到比我想要的更多或更少的 fps。当我查看具有 fps 限制的游戏时,它总是精确的帧速率。尝试使用Sleep() std::this_thread::sleep_for(sleep_until). 例如Sleep(0.01-deltaTime),获得 100 fps 但最终得到 +-90fps。当任何睡眠不精确时,这些游戏如何如此精确地处理 fps?我知道我可以使用无限循环来检查时间是否过去,但它使用了 CPU 的全部功率,但我想在没有 VSync 的情况下通过此限制减少 CPU 使用率。
您可以记录开始时的时间点,为其添加固定的持续时间并休眠,直到计算出的时间点出现在每个循环的结束(或开始)。例子:
#include <chrono>
#include <iostream>
#include <ratio>
#include <thread>
template<std::intmax_t FPS>
class frame_rater {
public:
frame_rater() : // initialize the object keeping the pace
time_between_frames{1}, // std::ratio<1, FPS> seconds
tp{std::chrono::steady_clock::now()}
{}
void sleep() {
// add to time point
tp += time_between_frames;
// and sleep until that time point
std::this_thread::sleep_until(tp);
}
private:
// a duration with a length of 1/FPS seconds
std::chrono::duration<double, std::ratio<1, FPS>> time_between_frames;
// the time point we'll add to in every loop
std::chrono::time_point<std::chrono::steady_clock, decltype(time_between_frames)> tp;
};
// this should print ~10 times per second pretty accurately
int main() {
frame_rater<10> fr; // 10 FPS
while(true) {
std::cout << "Hello world\n";
fr.sleep(); // let it sleep any time remaining
}
}
Run Code Online (Sandbox Code Playgroud)
是的,睡眠通常是不准确的。这就是为什么你的睡眠时间少于完成该帧所需的实际时间。例如,如果您还需要 5 毫秒来完成该帧,则休眠 4 毫秒。睡眠后,只需对帧的其余部分进行自旋锁定即可。就像是
float TimeRemaining = NextFrameTime - GetCurrentTime();
Sleep(ConvertToMilliseconds(TimeRemaining) - 1);
while (GetCurrentTime() < NextFrameTime) {};
Run Code Online (Sandbox Code Playgroud)
编辑:如另一个答案所述,应该调用 timeBeginPeriod() 来提高 Sleep() 的准确性。另外,据我所知,如果您之前没有调用,Windows 将在您的进程退出时自动调用 timeEndPeriod() 。