我一直在努力寻找关于如何在使用SDL 2的游戏中实现稳定的60 fps的行业标准的信息,在阅读了一堆文章之后,我迭代了不同的想法,直到我能够在我的游戏中测量60(+-0. 1)fps。
下面是我目前的方法,我正在寻找验证,这是不是完全错误/纠正实际游戏(2D)如何做到这一点。
const float TARGET_FPS = 60.04f;
const float SCREEN_TICKS_PER_FRAME = 1000.0f / static_cast<float>(TARGET_FPS);
...
class Timer{
public:
Uint64 started_ticks = 0;
Timer()
:started_ticks{SDL_GetPerformanceCounter()}
{}
void restart() {
started_ticks = SDL_GetPerformanceCounter();
}
float get_time() {
return (static_cast<float>(SDL_GetPerformanceCounter() - started_ticks) / static_cast<float>(SDL_GetPerformanceFrequency()) * 1000.0f);
}
};
...
float extra_time{0};
Timer fps_cap_timer{};
while(game_loop_condition){
fps_cap_timer.restart();
...
render();
while((fps_cap_timer.get_time() + extra_time) < SCREEN_TICKS_PER_FRAME) {
SDL_Delay(1); // I am aware of the issues with delay on different platforms / OS scheduling
}
if (fps_cap_timer.get_time() < (SCREEN_TICKS_PER_FRAME)) {
extra_time -= SCREEN_TICKS_PER_FRAME - fps_cap_timer.get_time();
}
else {
extra_time += fps_cap_timer.get_time() - SCREEN_TICKS_PER_FRAME;
}
}
字符串
使用这种方法,总是有一点额外的时间在0 - 1 ms之间波动,这导致FPS略低于60,因此我将目标FPS调整为60.04,我得到60±0.1 FPS。
那么.这是真的可行还是我搞砸了什么,应该做更多的阅读的主题?
1条答案
按热度按时间5rgfhyps1#
注意事项:通常不依赖FPS,而是测量自上一帧以来的时间,并将其用作游戏对象移动距离的乘数。
虽然在某些情况下可能需要一个相当精确的FPS,但由于您在每次循环迭代中重新启动计时器,它会漂移。我建议只需向计时器添加固定的持续时间并等待直到时间点发生。仅使用标准库类和函数,它可能看起来像这样:
字符串
忙碌的等待是为了使FPS尽可能准确,但它会消耗CPU,所以你想让它尽可能短。100µs可能太多了,所以你可以让它更短,甚至删除它,如果你发现没有它的准确性足够好。
然后你的游戏循环将是:
型