The main game loop
We need a way to stay in the program until the player wants to quit. At the same time, we should clearly mark out where the different parts of our code will go as we progress with Timber!!!. Furthermore, if we are going to stop our game from exiting, we had better provide a way for the player to exit when they are ready; otherwise, the game will go on forever!
Add the following highlighted code to the existing code and then we will go through it and discuss it all:
int main() { // Create a video mode object VideoMode vm(1920, 1080); // Create and open a window for the game RenderWindow window(vm, “Timber!!!”, Style::Fullscreen); while (window.isOpen()) { /* **************************************** Handle the players input **************************************** */ if (Keyboard::isKeyPressed(Keyboard::Escape)) { window.close(); } /* **************************************** Update the scene **************************************** */ /* **************************************** Draw the scene **************************************** */ // Clear everything from the last frame window.clear(); // Draw our game scene here // Show everything we just drew window.display(); } return 0; }
While loops
The very first thing we saw in the new code is as follows:
while (window.isOpen()) {
The very last thing we saw in the new code is a closing }
. We have created a while loop. Everything between the opening ({
) and closing (}
) brackets of the while
loop will continue to execute, over and over, potentially forever.
Look closely between the parentheses (...)
of the while
loop, as shown here:
while (window.isOpen())
The full explanation of this code will have to wait until we discus loops and conditions in Chapter 4, Loops, Arrays, Switches, Enumerations, and Functions – Implementing Game Mechanics. What is important for now is that when the window
object is set to closed, the execution of the code will break out of the while
loop and move on to the next statement. Exactly how a window is closed is covered soon.
The next statement is, of course, return 0;
, which ends our game.
We now know that our while
loop will whiz round and round, repeatedly executing the code within it, until our window object is set to closed.
C-style code comments
Just inside the while
loop, we can see what, at first glance, might look a bit like ASCII art:
/* **************************************** Handle the player’s input **************************************** */
Important note
ASCII art is a niche but fun way of creating images with computer text. You can read more about it here: https://en.wikipedia.org/wiki/ASCII_art.
The previous code is simply another type of comment. This type of comment is known as a C-style comment. The comment begins with (/*
) and ends with (*/
). Anything in between is just for information and is not compiled. I have used this slightly elaborate text to make it absolutely clear what we will be doing in each part of the code file. And of course, you can now work out that any code that follows will be related to handling the player’s input.
Skip over a few lines of code and you will see that we have another C-style comment, announcing that in that part of the code, we will be updating the scene.
If you jump to the next C-style comment, it will be clear where we will be drawing all the graphics.
Input, update, draw, repeat
Although this first project uses the simplest possible version of a game loop, every game will need these phases in the code. Let’s go over the steps:
- Get the player’s input (if any).
- Update the scene based on things such as artificial intelligence, physics, or the player’s input.
- Draw the current scene.
- Repeat these steps at a fast-enough rate to create a smooth, animated game world.
Now, let’s look at the code that actually does something within the game loop.
Detecting a key press
Firstly, within the section that’s identifiable by the comment with the Handle the player’s input
text, we have the following code:
if (Keyboard::isKeyPressed(Keyboard::Escape)) { window.close(); }
This code checks whether the Esc key is currently being pressed. If it is, the highlighted code uses the window
object to close itself. Now, the next time the while
loop begins, it will see that the window
object is closed and jump to the code immediately after the closing curly brace of the while
loop and the game will exit. We will discuss if
statements more fully in Chapter 2, Variables, Operators, and Decisions – Animating Sprites.
Clearing and drawing the scene
Currently, there is no code in the Update the scene
section, so let’s move on to the Draw the scene
section.
The first thing we will do is rub out the previous frame of animation using the following code:
window.clear();
What we would do now is draw every object from the game. However, we don’t have any game objects.
The next line of code is as follows:
window.display();
When we draw all the game objects, we are drawing them to a hidden surface ready to be displayed. The window.display()
code flips from the previously displayed surface to the newly updated (previously hidden) one. This way, the player will never see the drawing process as the surface has all the sprites added to it. It also guarantees that the scene will be complete before it is flipped. This prevents a graphical glitch known as tearing. This process is called double buffering.
Also note that all this drawing and clearing functionality is performed using our window
object, which was created from the SFML RenderWindow
class.
Running the game
Run the game and you will get a blank, full screen window that remains open until you press the Esc key.
That is good progress. At this stage, we have an executing program that opens a window and loops around, waiting for the player to press the Esc key to exit. Now, we are able to move on to drawing the background image of the game.