WEBVTT

00:00.180 --> 00:04.260
Hello again! In this video, we are going to add some more features to our game.

00:05.310 --> 00:10.710
We are going to add some lives, player lives. So the player can win or lose the game.

00:11.070 --> 00:15.150
And we are also going to give some text messages, so we can communicate with the player.

00:16.680 --> 00:18.090
SFML has a text

00:18.090 --> 00:25.170
class. This represents graphical text, which can be drawn on a render target. Such as our game window.

00:25.950 --> 00:27.870
And it also has a font class.

00:28.350 --> 00:33.720
A Text object will have a Font object associated with it, and that will control how the characters

00:33.720 --> 00:34.890
appear on the screen.

00:37.860 --> 00:44.880
This is quite similar to sprites and textures. So we start off by loading the font from disk. And this

00:44.880 --> 00:46.050
can be problematical.

00:48.030 --> 00:52.140
The first problem is that different systems provide different fonts.

00:52.140 --> 00:55.140
So it may be that your system does not actually have this font.

00:55.800 --> 00:58.980
And also different systems keep their fonts in different places.

00:58.980 --> 01:02.850
So the font may be available, but not in the directory where your program expects it.

01:03.090 --> 01:08.880
So if you are going to be distributing your game to other people, then a good thing to do is to copy

01:08.880 --> 01:15.240
the fonts file into the same directory as the images. So your program will be able to find it easily.

01:15.570 --> 01:18.630
And I should add that there are copyright issues with some fonts.

01:20.450 --> 01:25.880
So assuming that you have loaded up your Font objects, you can then associate it with a Text object.

01:25.880 --> 01:33.380
So you call setFont(). And then setString() will populate the Text object with some characters. And then

01:33.380 --> 01:36.980
you can draw the text, and display on the window as usual.

01:39.020 --> 01:39.890
In the game manager,

01:39.890 --> 01:43.070
we are going to add a member for the number of lives the player has.

01:43.580 --> 01:48.680
Each time the ball hits the bottom of the screen, the player is going to lose a life. And if they

01:48.680 --> 01:52.340
lose all their lives, then the game is over and the player has lost.

01:53.000 --> 01:58.220
On the other hand, if the player manages to destroy all the bricks, then they win the game.

01:59.030 --> 02:04.880
We have two more values for the game state enumeration: game over, player losing, and the player

02:04.880 --> 02:05.360
winning.

02:06.620 --> 02:12.230
And we are also going to have some members which are SFML text objects. And those will be used for displaying

02:12.230 --> 02:13.490
messages to the player.

02:15.180 --> 02:18.870
We need to change how the ball reacts, when it hits the bottom of the window.

02:19.110 --> 02:21.280
In the update() member function of ball.

02:21.300 --> 02:25.770
So far, we have been bouncing off the bottom of the window, back into the window. But we do not want to

02:25.770 --> 02:26.670
do that anymore.

02:27.360 --> 02:29.160
We are going to destroy the ball.

02:29.160 --> 02:33.450
So that will make it look as though the ball has disappeared off the bottom of the window.

02:34.710 --> 02:37.890
And then, in the game loop, we can check if the ball has been destroyed.

02:37.890 --> 02:40.410
And that will tell us that the player has lost a life.

02:42.790 --> 02:45.330
In constants, we have a new parameter.

02:45.340 --> 02:50.200
This is the number of lives the player has, at the start of the game. So the player will have three

02:50.200 --> 02:52.480
opportunities to demolish all the bricks.

02:55.020 --> 02:56.040
In the game class,

02:56.040 --> 02:59.670
we have the extra members for the game_state enumeration.

03:00.420 --> 03:04.200
We have the objects for the fonts and the text messages.

03:04.380 --> 03:10.530
text_state will tell the player about the state of the game, and text_lives will tell the player how

03:10.530 --> 03:11.820
many lives they have left.

03:13.730 --> 03:18.560
And we also have a member function which will keep track of how many lives the player has left. And

03:18.560 --> 03:21.810
the initial value will be the total number of lives they have.

03:21.830 --> 03:23.090
So that would be three.

03:25.080 --> 03:26.400
In the game constructor,

03:26.400 --> 03:29.010
we need to initialize these text objects.

03:29.160 --> 03:33.690
So we start off by loading the font. We call loadFromFile().

03:34.260 --> 03:38.040
I chose one which is available on Windows, to make life easier.

03:39.690 --> 03:44.970
If you're using a Unix system or Mac, then the path will look something like that.

03:45.480 --> 03:47.610
webfonts is in fact a package,

03:47.610 --> 03:52.770
I think. This is FreeBSD, so Verdana is not part of the default X installation.

03:52.980 --> 03:59.310
So you could use another font if you want, or just install this one. And then we can configure the objects.

03:59.310 --> 04:01.470
So we set the font to be Verdana.

04:01.890 --> 04:07.770
We search the position, which is going to be near the middle of the screen. And, as usual, this is just

04:07.770 --> 04:08.460
trial and error.

04:08.910 --> 04:14.520
Then we can set the size of the characters and their colour. And then we provide some characters for

04:14.520 --> 04:18.840
the text object. And similar for the text_lives.

04:19.290 --> 04:23.220
And the characters will give the number of lives that the player has left.

04:23.220 --> 04:27.600
So we are using C++11's to_string(), to convert this int to a string.

04:29.640 --> 04:33.150
If we restart the game, then we want the player to have all their lives back.

04:33.150 --> 04:36.210
So we set the lives member back to the maximum.

04:40.440 --> 04:41.310
In the game loop,

04:41.310 --> 04:46.500
we have these extra states. So we need to change the logic slightly. And we also need to display the

04:46.500 --> 04:47.400
text messages.

04:48.480 --> 04:52.950
If the game is paused, then we draw the entities, but we do not update them.

04:53.790 --> 04:57.660
If the game is not running, then we tell the user what the state is.

04:57.840 --> 05:00.570
So this could be paused, game over or player wins.

05:00.960 --> 05:05.010
And I have made these all the same size, with some padding spaces.

05:06.720 --> 05:09.690
And then we draw the text objects on the window.

05:12.020 --> 05:15.380
Otherwise, if the game is running, then we update the entities.

05:15.410 --> 05:18.740
But, before we do that, we need to check some things.

05:19.520 --> 05:22.460
We need to check if the ball has been destroyed.

05:22.490 --> 05:27.350
If it has, then the entity manager will have a vector of ball entities, which is empty.

05:27.860 --> 05:36.050
So we decrement the player lives. And we also create a new ball, so the player can continue playing. And

05:36.050 --> 05:40.850
we set the game state to paused, so the player has some time to recover from their state of shock!

05:43.080 --> 05:47.460
If all the bricks have been destroyed, then the entity manager will have a vector of brick entities

05:47.460 --> 05:48.300
which is empty.

05:48.570 --> 05:50.700
So the player has won.

05:53.040 --> 05:56.580
If the player has no lives left, then they have lost the game.

05:57.630 --> 06:01.770
Then we update the text_lives, so it has the correct number of lives.

06:02.070 --> 06:06.750
And then we do the usual: update manager, handle collision, refresh, draw and display.

06:10.250 --> 06:10.990
So there we are.

06:11.000 --> 06:14.390
We know that the game is paused and we have three lives.

06:16.460 --> 06:17.960
And now I have two lives!

06:17.960 --> 06:20.690
So when the ball goes off the bottom, I lose a life.

06:27.100 --> 06:27.330
(Huh!)

06:27.860 --> 06:28.930
Now I lose another one.

06:30.450 --> 06:31.040
And that is it.

06:31.070 --> 06:31.760
Game over!

06:32.120 --> 06:32.680
(Boo hoo!)

06:34.250 --> 06:40.570
If you want to test the case where the player wins, then you do not have to actually win the game and

06:40.580 --> 06:41.750
destroy all the bricks.

06:41.960 --> 06:43.370
You can take a shortcut.

06:43.490 --> 06:50.270
If you go up to the reset member function, this line here will populate the entity manager's brick vector.

06:50.720 --> 06:56.210
So if we comment this out, then the entity manager will have an empty vector of bricks.

06:56.540 --> 07:00.620
So when we start playing, there are no bricks and the player has won.

07:06.880 --> 07:11.920
One other thing that is worth knowing, and perhaps I should have mentioned earlier. If there is an error

07:11.920 --> 07:18.400
in this loadFromFile() function, so that could be either sprites or fonts, then SFML will print

07:18.400 --> 07:20.340
a message to standard output.

07:20.350 --> 07:26.260
So if you are running in a command line, or your development environment has a console, then you will see

07:26.260 --> 07:31.300
that if you're running in a standalone window like I am, then you will not be able to see that.

07:31.510 --> 07:33.820
So here is how to do this for Visual Studio.

07:33.820 --> 07:40.210
So go into Project Properties, and then Linker, System. And this is controlled by Subsystem.

07:40.240 --> 07:41.980
So currently it is Windows.

07:42.550 --> 07:48.040
If I change this to console, then I will get a console when I start playing the game.

07:49.840 --> 07:54.430
So obviously, that is not something you want when you are releasing your application, but it is useful

07:54.430 --> 07:56.200
for testing and debugging.

07:56.830 --> 08:00.640
For example, if I change this so the load file will fail.

08:03.180 --> 08:05.010
And there we are, we get an error message.

08:05.580 --> 08:05.850
Okay.

08:05.850 --> 08:07.080
So that is it for this video.

08:07.440 --> 08:08.550
So I will see you next time.

08:08.550 --> 08:11.070
But until then, keep coding!
