c++ - 这是将循环锁定为每秒 60 个循环的好方法吗?

标签 c++ algorithm loops timer

我有一个游戏 Bullet Physics作为物理引擎,该游戏是在线多人游戏,所以我想试试 Source Engine approach处理网络上的物理同步。所以在客户端我使用 GLFW所以默认情况下 fps 限制在那里工作。 (至少我认为这是因为 GLFW)。但是在服务器端没有图形库,所以我需要“锁定”模拟世界并将物理引擎步进到每秒 60 个“滴答”的循环。

这是将循环锁定为每秒运行 60 次的正确方法吗? (又名 60“fps”)。

void World::Run()
{
    m_IsRunning = true;

    long limit = (1 / 60.0f) * 1000;
    long previous = milliseconds_now();

    while (m_IsRunning)
    {
        long start = milliseconds_now();
        long deltaTime = start - previous;
        previous = start;

        std::cout << m_Objects[0]->GetObjectState().position[1] << std::endl;

        m_DynamicsWorld->stepSimulation(1 / 60.0f, 10);

        long end = milliseconds_now();
        long dt = end - start;

        if (dt < limit)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(limit - dt));
        }
    }
}

可以使用 std::thread 来完成这个任务吗?

这种方式是否足够高效?

物理模拟会每秒步进 60 次吗?

附言

milliseconds_now() 看起来像这样:

long long milliseconds_now()
{
    static LARGE_INTEGER s_frequency;
    static BOOL s_use_qpc = QueryPerformanceFrequency(&s_frequency);
    if (s_use_qpc) {
        LARGE_INTEGER now;
        QueryPerformanceCounter(&now);
        return (1000LL * now.QuadPart) / s_frequency.QuadPart;
    }
    else {
        return GetTickCount();
    }
}

取自:https://gamedev.stackexchange.com/questions/26759/best-way-to-get-elapsed-time-in-miliseconds-in-windows

最佳答案

如果要将渲染限制在最大 FPS 60,非常简单:

每一帧,只是检查游戏是否运行得太快,如果是就等待,例如:

while ( timeLimitedLoop )
{
    float framedelta = ( timeNow - timeLast )
    timeLast = timeNow;

    for each ( ObjectOrCalculation myObjectOrCalculation in allItemsToProcess )
    {
        myObjectOrCalculation->processThisIn60thOfSecond(framedelta);
    }

    render(); // if display needed
}

请注意,如果启用了垂直同步,渲染将被限制为垂直刷新频率,可能是 50 或 60 Hz。

但是,如果您希望逻辑锁定在 60fps,那就另当别论了:您必须隔离显示和逻辑代码,使逻辑以最大 60fps 运行,并修改代码,以便你可以有一个固定的时间间隔循环和一个可变的时间间隔循环(如上所述)。值得关注的好来源是“固定时间步长”和“可变时间步长”(Link 1 Link 2 和旧的可信赖的 Google 搜索)。

请注意您的代码: 因为您在 1/60 秒的整个持续时间内都在使用 sleep - 已经过去的时间,您很容易错过正确的时间,请将 sleep 更改为循环运行,如下所示:

代替

if (dt < limit)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(limit - dt));
        } 

改为

while(dt < limit)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(limit - (dt/10.0)));
            // or 100.0 or whatever fine-grained step you desire
        }

希望这对您有所帮助,但如果您需要更多信息,请告诉我:)

关于c++ - 这是将循环锁定为每秒 60 个循环的好方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22613245/

相关文章:

javascript - 在 JavaScript 循环中声明相同的变量名

java - 如何删除数组元素

arrays - Perl循环遍历单个元素的数组哈希

c++ - 有没有可以查看XPS文档的C++代码?

c++ - QTableWidget 中的 QComboBox 和 QSpinBox 具有适当的对齐方式

c++ - 模板类实例化如何与类继承一起工作?

algorithm - 以间隔合并范围

c - 高效迭代转置矩阵的连续元素(通过位运算符)

c++ - 如何在 Linux 中验证主机名\域名 - C++

c# - 可以使光线转换仅检测物体的侧面吗?