ruk·si

🕹️ Game Development
Game Loop

Updated at 2013-04-12 13:30

This note is about the technical game loop. Most games or game engines have a main game loop that is used to separate input, operations and rendering. But there are multiple ways to model a game loop. This note is not about the user-interface or design kind of a game loop.

Command-based game loop. Text games have command based game loop. Command is a line of text.

while (true)
{
    char* command = readCommand();
    handleCommand(command);
}

Event-based game loop. Simple graphical games have event based game loop. Event is e.g. a key press, mouse movement or mouse click.

while (true)
{
    Event* event = waitForEvent();
    dispatchEvent(event);
}

Fixed time step game loop with no synchronization. Modern games have event based game loop, which keeps on running without user input. Event is a key press, mouse movement or mouse click.

while (true)
{
    processInput();
    update();
    render();
}

Fixed time step game loop with synchronization. But the game will run differently on different machines.

while (true)
{
    double start = getCurrentTime();
    processInput();
    update();
    render();
    sleep(start + MS_PER_FRAME - getCurrentTime());
}

Variable time step game loop. Determines how much real time passed since last update, and telling the game that how much has passed, so the game can advance the game world by that amount.

double lastTime = getCurrentTime();
while (true)
{
    double current = getCurrentTime();
    double elapsed = current - lastTime;
    processInput();
    update(elapsed);
    render();
    lastTime = current;
}

Fixed update time step game loop with variable rendering. But this causes problems with multiple players that have different kind of machines.

double previous = getCurrentTime();
double lag = 0.0;
while (true)
{
    double current = getCurrentTime();
    double elapsed = current - previous;
    previous = current;
    lag += elapsed;

    processInput();

    while (lag >= MS_PER_UPDATE)
    {
        update();
        lag -= MS_PER_UPDATE;
    }

    // To estimate next update when rendering between update()s
    render(lag / MS_PER_UPDATE);
}

Game world may contain a collection of game objects. Each of these game objects implement update method that simulates the behavior of the game object. But there can be different kinds of loops called in different points of the game loop. For example, fixedUpdate() usually is a function that is called after each physics calculation.

class GameObject
{
public:
    GameObject()
    : x(0), y(0)
    {}

    virtual ~GameObject() {}
    virtual void update() = 0;

protected:
    double x;
    double y;
};
class World
{
public:
    World()
    : numGameObjects_(0)
    {}

    void World::gameLoop()
    {
        while (true)
        {
            // Handle user input...
            // Update each entity.
            for (int i = 0; i < numGameObjects_; i++)
            {
                gameObjects_[i]->update();
            }
            // Physics and rendering...
        }
    }

private:
    GameObject* gameObjects_[MAX_GAME_OBJECTS];
    int numGameObjects_;
};

Sources