Tuesday, September 5, 2017

Game loop and multi-threading in game programming

In most of games, the game status will change in every moment, even if there is no user input.

So game program must have game loop, which updates internal status time by time.

The game loop looks like this.

#include <chrono>
#include <thread>

using namespace std::chrono;

void game_loop()
{
    while(true)
    {
        steady_clock::time_point begin = steady_clock::now();

        input();            // receive and store user input.
        update();           // update game.
        draw_screen();      // draw.

        steady_clock::time_point end = steady_clock::now();

        constexpr fps = milliseconds(1000/60); // 60 frames per second
        milliseconds elapsed_time = duration_cast<milliseconds>(end - begin);

        if( fps > elapsed_time ) {
            std::this_thread::sleep_for( fps - elapsed_time ); // wait for next frame
        }
    }
}

Each loop is called 'frame'. In this example each frame is intended to be called 60 times per second.
If one frame takes more than 1/60 second, the game will get slower.

So, we have to take care not to take 1/60 second in one frame.

In game program, tipical long-time task is loading resource(3D models, texture, database, etc.).
If the program execute loading resource in 'update()', the game will stop at the frame.

Multi-threading is used to solve this kind of problem.
In 'update()', when the program desides to load some resource, create loading request to other thread.
The thread loads the resource, and send the data back to main thread.

The game loop will be going, even when loading resource.


It&#39;s magic! std::bind

'std::bind' is a powerful helper for working around 'std::function'. 'std::bind' makes a instance of 'std::fun...