当前位置: 动力学知识库 > 问答 > 编程问答 >

c++ - Is this a good way to lock a loop on 60 loops per second?

问题描述:

I have a game with Bullet Physics as the physics engine, the game is online multiplayer so I though to try the Source Engine approach to deal with physics sync over the net. So in the client I use GLFW so the fps limit is working there by default. (At least I think it's because GLFW). But in the server side there is no graphics libraries so I need to "lock" the loop which simulating the world and stepping the physics engine to 60 "ticks" per second.

Is this the right way to lock a loop to run 60 times a second? (A.K.A 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));

}

}

}

Is it ok to use std::thread for this task?

Is this way is efficient enough?

Will the physics simulation will be steped 60 times a second?

P.S

The milliseconds_now() looks like this:

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();

}

}

Taken from: http://gamedev.stackexchange.com/questions/26759/best-way-to-get-elapsed-time-in-miliseconds-in-windows

网友答案:

If you want to limit the rendering to a maximum FPS of 60, it is very simple :

Each frame, just check if the game is running too fast, if so just wait, for example:

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

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

    render(); // if display needed
}

Please note that if vertical sync is enabled, rendering will already be limited to the frequency of your vertical refresh, perhaps 50 or 60 Hz).

If, however, you wish the logic locked at 60fps, that's different matter: you will have to segregate your display and logic code in such a way that the logic runs at a maximum of 60 fps, and modify the code so that you can have a fixed time-interval loop and a variable time-interval loop (as above). Good sources to look at are "fixed timestep" and "variable timestep" ( Link 1 Link 2 and the old trusty Google search).

Note on your code: Because you are using a sleep for the whole duration of the 1/60th of a second - already elapsed time you can miss the correct timing easily, change the sleep to a loop running as follows:

instead of

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

change to

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
        }

Hope this helps, however let me know if you need more info:)

分享给朋友:
您可能感兴趣的文章:
随机阅读: