I'm using C++ with raylib to create a game. I'm running Windows x64 compiling with MinGW in Eclipse.
For the game loop, the normal tutorials give you something like this:
int main()
{
InitWindow(800, 600, ("Window Title").c_str());
SetWindowState(FLAG_VSYNC_HINT);
while (!WindowShouldClose())
{
Update(); // your function to do game update logic
BeginDrawing();
ClearBackground((Color){0, 0, 0, 255});
Draw(); // your function to do game drawing
EndDrawing();
}
}
However, this is bad practice. So it sets the VSYNC flag to make sure the drawing only happens at the same rate as the monitor refresh rate. That's fine but if you insert your update logic into the same loop, then your update rate is locked to the draw rate.
This is foolish because different users have different refresh rates. Mines uses 60 Hz, in Europe they use 50 Hz, and lots of people use 120, 144, 240, or any custom refresh rate they want.
So that means the game will run at very different speeds. Not what I want.
What I want instead is the update logic to always be 60 FPS (actually 16 ms intervals so it's 62.5 FPS), while the draw logic runs on the VSYNC loop.
So here's what I tried next:
std::thread ULT(scr_run_updateloop); // spawn a new thread that calls scr_run_updateloop() immediately
while (!WindowShouldClose())
{
// no more Update() call in the draw loop!
BeginDrawing();
ClearBackground((Color){0, 0, 0, 255});
Draw(); // your function to do game drawing
EndDrawing();
}
and the function called by the thread...
void scr_run_updateloop()
{
auto time_current = chrono::steady_clock::now();
auto time_last = time_current;
uint64_t time_d;
while (true)
{
time_current = chrono::steady_clock::now();
time_d = duration_cast<milliseconds>(time_current - time_last).count();
if (time_d >= 16) // 16 ms interval is 62.5 FPS
{
Update();
time_last = time_current;
}
}
}
This code works. However, that thread is hogging CPU like crazy. My task manager says 25% and I'm on a 4-core system.
What can I do? I've read about sleep and thread::sleep_for but the problem is the sleep time is not guaranteed and can be off by many milliseconds because the OS could be busy with whatever.
Note: I don't need the thread to sync with the main thread at all. The Update loop can be completely separate from the Draw Loop, AFAIK they will never need to share a locked resource.
I've also read about a completely alternate approach where your time between Updates is NOT fixed, but uses deltaTime. Then you interpolate positions, speeds and other stuff to make sure things happen at the same overall speed. That seems extraordinarily overcomplicated and unnecessary. If you can VSYNC to a draw refresh rate than I don't see why you can't set up a custom loop to call once every fixed interval. There must be a way to do this, but how?