WEBVTT

00:00.180 --> 00:00.960
Hello again!

00:01.020 --> 00:04.500
In this video, we are going to have an overview of the entity manager.

00:04.500 --> 00:08.160
So this is going to be the second stage of our code refactoring.

00:10.020 --> 00:16.050
We are going to take all the code which is related to entities out of the game loop, and put it into

00:16.050 --> 00:17.010
its own class.

00:17.490 --> 00:24.150
So if the game loop needs to do anything which involves entities. Such as creating a new entity object,

00:24.180 --> 00:29.370
updating all the entities, drawing them and so on, it will now call a member function of the entity

00:29.370 --> 00:29.970
manager.

00:30.720 --> 00:36.690
And the idea of this is to simplify the game loop, and also to provide better abstraction.

00:36.840 --> 00:44.130
So if we want to change the game by creating more entity objects or even adding new types of entities,

00:44.250 --> 00:46.260
then this should make it easier.

00:48.150 --> 00:51.060
The entity manager is going to use polymorphism.

00:51.330 --> 00:56.880
It is going to store the entity objects as pointers to the base class, to the entity class.

00:57.570 --> 01:04.080
And operations will involve calling virtual functions, through these pointers to base. At runtime,

01:04.080 --> 01:10.020
these will resolve to the correct member functions for the actual type of the entity in the game.

01:10.950 --> 01:15.120
It will also provide an interface for performing operations on entities.

01:15.300 --> 01:17.340
And there are two types of operations.

01:17.550 --> 01:20.970
There are operations which will affect all the entities in the game.

01:21.180 --> 01:28.110
For example, destroying all the entities when we reset the game. And operations which will only affect

01:28.110 --> 01:29.540
one type of entity.

01:29.550 --> 01:32.850
So for example, if we want to change the colour of all the bricks.

01:35.330 --> 01:40.430
The entity manager is responsible for managing the lifetime of all the entities in the game.

01:40.430 --> 01:48.980
So the entity manager will create all the objects. And, when necessary, it will delete them. On each iteration

01:48.990 --> 01:49.950
through the game loop,

01:49.970 --> 01:54.920
the manager is going to scan through all the entities. And, if there are any instances which have been

01:54.920 --> 01:58.400
marked as destroyed, then the manager will delete them.

02:01.380 --> 02:08.380
The class will have two data members and these provide different views of the entities. With all_entities,

02:08.400 --> 02:14.040
this will have all the entities in the game, as a vector, and the elements of this vector will be a

02:14.040 --> 02:16.650
unique pointer to the base class.

02:17.520 --> 02:23.850
There is also a grouped_entities which has all the entities, but this time grouped by their type.

02:24.330 --> 02:26.370
And we are going to use a map for this.

02:26.610 --> 02:32.760
The key of the map will depend on the type of the entity, and the value of the map will be a vector

02:32.790 --> 02:36.570
of pointers to entity objects. Again, to the base class.

02:36.780 --> 02:46.080
So this will be all the objects which have the same type as the key. And these are going to be aliases,

02:46.080 --> 02:47.690
or references, if you like.

02:47.700 --> 02:51.240
If this was Java or C#, then these really would be references.

02:51.240 --> 02:54.960
But in C++ you cannot have a container with references.

02:55.020 --> 02:56.670
So we have to use pointers.

02:57.180 --> 03:03.810
And this is actually one of the rare occasions in C++, where it is advisable to use traditional pointers.

03:03.810 --> 03:06.660
Because they are referring to an object which is owned by someone else.

03:06.690 --> 03:09.810
In this case, the object is owned by the unique pointer.

03:11.660 --> 03:13.580
So this is how it will look.

03:13.610 --> 03:18.080
I have got a very simple game with just one ball object and one brick object.

03:18.950 --> 03:25.070
The all_entities vector has unique pointers to all the objects in the game.

03:26.090 --> 03:31.520
grouped_entities, with key ball, will have a vector of pointers to all the ball objects.

03:31.520 --> 03:32.870
So that is just this one.

03:33.410 --> 03:39.140
And with the brick as the key, it will be a vector with pointers to the brick objects.

03:40.550 --> 03:46.220
The unique pointer will allocate memory for the ball object, and then call the constructor for the ball.

03:46.730 --> 03:52.220
When this unique pointer is destroyed, then it will destroy the ball object and release the memory.

03:52.940 --> 03:54.410
And the same goes for the brick.

03:55.550 --> 03:59.840
These pointers here are just pointers which have the raw address.

03:59.960 --> 04:03.830
So if these [unique] pointers go away, then these pointers are going to be invalid.

04:04.130 --> 04:09.800
So when we delete things, we need to make sure that we delete from the grouped_ entities first.

04:09.800 --> 04:13.370
So we get rid of these pointers, so we cannot use them by accident.

04:13.670 --> 04:17.990
And then we delete these pointers which will actually destroy the object.

04:20.940 --> 04:23.850
And then finally the interface to the class.

04:24.420 --> 04:31.770
The create() member function will create an entity object of a given type, and it will update the data members.

04:31.920 --> 04:37.410
So it is going to add it to the vector which has all the entities, and it is going to add it to the map

04:37.410 --> 04:40.450
element which has all the elements of that type.

04:40.470 --> 04:44.280
The rest of the member functions are fairly self-explanatory, really.

04:44.580 --> 04:46.800
refresh() will redraw all the entities.

04:47.010 --> 04:52.590
clear() will destroy everything. get_all() will return all the entities which have a given type.

04:53.070 --> 04:55.470
And then there is this apply_all() function.

04:56.070 --> 05:01.890
This will take a callable object, and then it will iterate over all the entities which have a given type.

05:01.890 --> 05:07.400
And it will call this function with each of the entity objects of that type as its argument.

05:07.410 --> 05:10.970
So this is a bit like an algorithm call really, with a predicate.

05:10.980 --> 05:14.430
So we're going to iterate and then call this function on every element.

05:14.850 --> 05:20.550
And then the update() and draw() member functions are basically the same as we had before, in the game loop.

05:20.920 --> 05:22.500
Okay, so that is it for this video.

05:22.530 --> 05:27.180
In the next video, I will go into the entity manager class in more detail with the implementation, but

05:27.180 --> 05:28.080
that is all for now.

05:28.590 --> 05:29.400
I will see you next time,

05:29.400 --> 05:31.590
but until then, keep coding!
