Hello again.
In this video, we are going to look at the game manager.
We have implemented the basic features of our game.
Obviously, there is still a lot more that we could add.
But before we go any further, we need to think about the organization of our code.
Our main() function is too long.
Ideally, a function should fit into a single screen, so you can see all the code without having to do
any scrolling.
And also, there is a lot of code which is duplicated across the program.
So we are going to step aside for a minute and refactor the code. And we are going to start off, in this
video, by moving the code from the main() function into a new class which will manage the game.
This class will have the game window as a data member, and also all the entities from the game.
It will have a constructor, to start things off, and a run() member function, which will perform the game
loop.
There is also going to be a new feature, reset().
So this will reinitialize the entities. So we can use that to allow the user to restart the game.
And we are also going to allow the user to pause the game.
So this means that the ball will appear to stop moving.
The user cannot move the paddle across the screen, and so on.
So the entities are not being updated.
However, the entities are still redrawn.
So if we cover up the game window and then uncover it, it will still look normal.
We need to know what the game's current state is.
So we are going to have a member for that. And we are going to use a class enum, which is another
C++11 feature.
In the class definition, we need to include the headers for all the entities, and also the constants.
Then we have all the members, so we have the game window, the background and so on. And we are using
in-place initialization.
And we can do this because all these constants are constant expressions, they are constexpr. If they
were just normal const, we could not do this.
So this means that when we create an object of game, then by default, game window will have these dimensions
and that title, the ball will have these dimensions and so on.
You will notice that I had to change this to a C string literal and not a C++ string, because C++ strings
cannot be constexpr. At least, not in this version of C++.
And we also need to have the vector initialized separately, because vectors are not constexpr either.
Or, not yet.
Then we have our class enum with the game's states, and then we have the member.
So initially, we assume that the game is going to be running. And then we have the declaration of the
member functions.
In the game constructor,
we do not need to provide an initialization list, because the class already has sensible initial values.
If we did put anything in here, it would just override the default values.
But we do not need to do that.
All we need to do, is to populate the vector of bricks, the same code as we had before, and to set the
frame rate for the window. In the reset() member function,
we want to restore all the bricks to their original position. So all the destroyed bricks will be drawn
again.
They will come back to life, if you like.
And the easiest way to do that is just to draw everything again.
And then we have the one member function with the game loop.
I will come back to this in a minute. But the basic loop is the same.
So we clear the screen, check for events. (Skip ahead a bit)
Then we update all the entities.
We handle collisions.
We erase all the removed bricks.
And then we draw the updated graphics.
So that is all the same code that you have seen before, with just a couple of little extra features.
The first one is that we only do the updates if the game state is not "paused".
So we do not do any of this update, collision handling and erasing, but we do display the graphics.
And then we have this code for the pause and reset. The reset is very simple: we just check for the
user pressing the 'r' key, and then we call the reset() function.
We check for the user pressing the 'p' key.
If they press it when the game is running, it will pause it. And if they press the key again, then the game
will resume.
So we just invert the state of the game.
There is a complication here, because if the user holds down the key, then it is going to send an event
on every iteration, until the user releases the key.
So we could have a situation where the user presses the key, and that pauses the game.
Then they hold it down.
The next iteration gets the key again, so it resumes the game. Then the next iteration pauses and
so on.
So we have this kind of "whipsaw" effect, and we want to avoid that.
So we put in a check to see if the key has already been pressed.
So that is the purpose of this variable.
So initially, the key has not been pressed. And then, the first time, this variable will be false.
So we go into this, and we invert the state of the game. And then we set the flag to true.
And then the next time, if the user holds the key down, then this will be true.
So we skip over this. And if the user releases the key, or presses some other key, then we go into here.
And this will set the flag to false.
And finally, in the main() function, this is now very simple.
We just create an object of the game.
The game manager.
So this will initialize everything.
And then we call the run() member function and that will start up the game loop.
So that will keep on running.
And when the game loop terminates, then this function call will return, and we exit the program.
So, there we are.
I am busy playing this game, rather badly!
And then the phone rings.
(Just put this over here)
(I do not want anyone to know I'm playing this game!)
(Okay)
(The phone call is over) And you can see the window looks normal.
We do not have any busy cursor, or black screen, or "window not responding" message.
And then we can continue.
And then...
If I want to restart, then I just press the "r" key.
And then all the bricks reappear.
I suppose I should really make the ball go back to the initial position, and the paddle, but that would
require some changes to the entity.
But if you want to do that, if you want to make the ball and the paddle go back to the initial positions
when the user resets the game, then that would be a useful exercise.
Okay, so that is it for this video.
I will see you next time.
But until then, keep coding.