Game Loop
Create a fixed time step Game Loop
Game Loop
What’s a Game Loop ? If you’ve read the tutorials Graphics Window and OpenGL Window, you know about the Infinite Loop that maintains your game window visible. Most of your game will happen inside that loop, this is why we call it the Game Loop. Inside that loop, you perform three actions at each frame of your game
- Capture the user Inputs
- Update the Game
- Render the Game
- First, the game will capture your inputs (pressing on the right-arrow of the D-Pad).
- Then, the game will update Mario’s position and animation to make it move to the right.
- Finally, the game will draw Mario at its new position with the correct animation pose.
bool gameRunning = true; while(gameRunning) { captureInputs(); //Keyboard, Mouse, GamePad, etc. updateGame(); //update object position, animations, health bar, etc. renderGame(); //draw all game objects }
Fixed Time Step
- Step 1 : Let’s suppose we want to run our game at 60 FPS, which means each frame should last 1/60 seconds (or 0.0166). We call that time Fixed Time
- Step 2 : We start a clock and measure the time that passes and store it into a variable called Time Passed.
- Step 3 : When Time Passed equals Fixed Time (1/60 seconds here), we perform the game loop operations (capture inputs, update, and render)
- Step 4 : Then we set Time Passed at zero and repeat the process again and again.
- Step 3 : When Time Passed is superior to Fixed Time (1/60 seconds here), we perform the game loop operations (capture inputs, update and render)
- Step 4 : We subtract Fixed Time from Time Passed in order to get the time overflow, this overflow is reported to the next frame. For example, if Time Passed is 0.018 seconds, it’s superior to Fixed Time (0.0166), we update the game, then we compute the overflow (0.018 – 0.0166 = 0.0014). Those 0.0014 seconds will be counted for the next frame.
//Start a clock Clock clock; clock.start(); //Save the time that passes Time timePassed = 0; bool gameRunning = true; while(gameRunning) { //Get the time measure by the clock Time clockTime = clock.getTime(); clock.reset(); //Accumulate the time that passes timePassed += clockTime; //When the time that passes is over the Fixed Time, perform the game operations if(timePassed > FIXED_TIME) { //remove FIXED_TIME and keep the overflow for the next frame timePassed - FIXED_TIME; captureInputs(); //Keyboard, Mouse, GamePad etc updateGame(FIXED_TIME); //update object position, animations, health bar etc. renderGame(); //draw all game objects } }
More about Game Loops
There isn’t a single way to create a Game Loop. Depending on your needs a Game Loop can be really simple or become complicated. If you want to learn more about Game Loops, you can read this article : Game Loop Patterns. In this article, the authors present different Game Loop techniques and how to choose between them:
- Pattern 1 : Run, run as fast as you can (Our oversimplified game loop)
- Pattern 2 : Take a little nap (Pattern 1 with sleep)
- Pattern 3 : One small step, one giant step (Use a clock, resemble the one we created above)
- Pattern 4 : Play catch up (Use a clock, resemble the one we created above but more complicated)
SFML Game Loop
Let’s create an actual Game Loop with SFML. We will use the pattern presented above (Fixed Time Step) but with a little difference. Only the first two game loop operations (Capture Inputs and Update) will happen at Fixed Time (60 FPS in this case). The Render operation will happen as fast as the computer running the game can handle it. This is the Game Loop that we will be using during the rest of this Tutorial Series
//Create our fixed time for 60 FPS (0.0166 seconds) sf::Time FIXED_FRAME_TIME = sf::seconds(1/60.f); //Variable to store the time that passes sf::Time timePassed = sf::Time::Zero; //Create a clock, the clock starts automatically sf::Clock clock; //Entering the game loop while(graphicsWindow.isOpen()) { //Retrieve the clock time and reset the clock at the same time sf::Time clockTime = clock.restart(); //Accumulate the time passing in our variable (this happens at each cycle of the while loop) timePassed += clockTime; //When the time passing is over our Fixed Time only Capture Inputs and Update the Game while(timePassed > FIXED_FRAME_TIME) { //Remove (0.0166) seconds from the passing time //Only the overflow will remain for the next frame timePassed -= FIXED_FRAME_TIME; //capture the user inputs using SFML Events handleEvent(); //update the game at the fixed time frame of (0.0166 second) update(FIXED_FRAME_TIME); } //Render the game //We do not render the game at 60 FPS, only the update happens at 60 FPS render(); }