这是一个好方法来锁定一个每秒60次循环的循环吗?



我有一款使用Bullet Physics作为物理引擎的游戏,这款游戏是在线多人游戏,所以我想尝试使用Source engine方法来处理网络上的物理同步。所以在客户端我使用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次吗?

p。S

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

如果你想限制渲染到60帧的最大帧数,这是非常简单的:

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

while ( timeLimitedLoop )
{
    float framedelta = ( timeNow - timeLast )
    timeLast = timeNow;
    for each ( ObjectOrCalculation myObjectOrCalculation in allItemsToProcess )
    {
        myObjectOrCalculation->processThisIn60thOfSecond(framedelta);
    }
    render(); // if display needed
}

请注意,如果垂直同步是启用的,渲染将被限制在你的垂直刷新频率,也许50或60赫兹)。

如果,然而,你希望逻辑锁定在60fps,那是另一回事:你将不得不隔离你的显示和逻辑代码,以这样的方式,逻辑运行在60fps的最大值,并修改代码,以便你可以有一个固定的时间间隔循环和一个可变的时间间隔循环(如上所述)。好的资源是"固定时间步长"one_answers"可变时间步长"(链接1链接2和旧的可靠的谷歌搜索)。

代码注释:因为你使用的睡眠是1/60秒的整个持续时间——已经过去的时间,你很容易错过正确的时间,把睡眠改为循环运行,如下所示:

代替

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
        }

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

相关内容

最新更新