我将 SDL 1.2 和 VS2008 用于较小的类似游戏的应用程序。我最近(在从 SO 上的其他帖子中获得了一些我现在找不到的想法之后,如果您觉得我应该将您的问题链接起来以供参考,非常抱歉)重新编写了我的游戏循环以不使用 Sleep 或 SDL_Delay 进行计时。相反,我以已知频率调用我的游戏逻辑,并根据实际时间步长计算距离和位置。
执行此操作时,我预计 FPS 会被 SDL_Flip 限制为屏幕的帧速率(vsynch?),但我最终在运行 Windows 7 的机器上获得了大约 300 FPS。这可能是什么原因?您可以在监视器 vsynch 之间多次运行整个游戏循环(包括 SDL_Flip)吗?不同机器上的行为是否可能不同,或者 SDL_Flip 永远不应该与 vsynch 同步?我没有看到我期望的不同步屏幕更新的任何闪烁或其他影响。
这是我的游戏循环供参考:
void GraphicsFramework::run()
{
Uint32 last_input_check = 0;
Uint32 last_logics_check = 0;
while(true)
{
Uint32 now = SDL_GetTicks();
if(now - last_input_check > 10) // Every 10 millisecond
{
if(!processEvents())
{
return;
}
last_input_check = now;
}
if(now - last_logics_check > 20) // Every 20 milliseconds
{
handleGameLogics();
last_logics_check = now;
}
draw(); // No FPS limitation
m_Window.flipSurface(); // Calls SDL_Flip(surface)
m_ActualFrameTime = SDL_GetTicks() - now;
}
}
编辑: 固定 FPS 忙等待看起来像这样。代替
m_ActualFrameTime = SDL_GetTicks() - now;
和
do
{
m_ActualFrameTime = SDL_GetTicks() - now;
} while ((Uint32)(1000/m_ActualFrameTime) > getDesiredFPS());
与使用 SDL_Delay 或 Sleep 相比,这提供了一种更稳定的结果,至少在我的机器上,您会得到一些可变的 FPS。两者当然都打破了示例中 processEvents() 的时间安排。
还添加了 SDL_Delay 变体以确保完整性:
Sint32 timeToSleep = (Uint32)(1000/getDesiredFPS()) - m_ActualFrameTime;
if(timeToSleep > 0)
{
SDL_Delay((Uint32)timeToSleep);
}