【问题标题】:Why is SDL_Flip not limiting the FPS to match screen frequency?为什么 SDL_Flip 不限制 FPS 以匹配屏幕频率?
【发布时间】:2014-05-03 10:57:54
【问题描述】:

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

【问题讨论】:

    标签: c++ visual-c++ sdl game-loop sdl-1.2


    【解决方案1】:

    SDL_Flip 只是将表面上的内容推送到屏幕上。它与fps无关。不,你不应该在同一个循环中多次使用 SDL_Flip,你应该在更新你的表面并准备好在屏幕上显示它之后再做。

    我认为管理 fps SDL_Delay(简单地称为睡眠)是你最好的选择。

    【讨论】:

    • SDL_Delay 使 Windows 切换出您的进程,并且无法保证何时切换回来,因此对于控制 FPS 来说不是很好。我多次执行 SDL_Flip 的意思是游戏循环将在监视器 vsynch 之间运行多次。我会在问题中澄清。
    • 是的,这就是现代多任务操作系统中的生活。你猜怎么着——如果你返回你的时间片,操作系统会仍然进入并从你的进程中夺取控制权,没有保证什么时候回来。因为这就是现代抢占式多任务操作系统的生活,现在大多数都是这样。
    • 看看这里msdn.microsoft.com/en-us/library/windows/desktop/…。您应该使用此功能,以便睡眠时间准确(尽可能)。在stackoverflow中寻找时间问题,有很多好的答案;)(顺便说一句,如果你没有看到任何闪烁,那么我认为这很好。有些游戏可以选择vsync,所以你可以打开/关闭它. 所以这应该不是问题。您可能只是想放慢速度,这样您就不会使用太多的cpu,并且可以控制不依赖于deltaTime的基本物理)
    • jofra,你怎么可能提出这个要求。 SDL_Flip() 应该 wait 等待 VSYNC 并且 waiting 应该会影响 fps。
    • “SDL_Flip() 交换屏幕缓冲区”来自 wiki。它只是交换缓冲区,我很确定与 vsync 无关。
    猜你喜欢
    • 2015-03-15
    • 2015-03-12
    • 1970-01-01
    • 2018-05-17
    • 2013-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多