1
00:00:00,006 --> 00:00:02,000
- [Narrator] Hi.

2
00:00:02,000 --> 00:00:04,004
This video is about
building the game engine.

3
00:00:04,004 --> 00:00:06,007
In the last video, we learned structuring

4
00:00:06,007 --> 00:00:08,006
the Thomas Was Late code.

5
00:00:08,006 --> 00:00:10,003
In this video, we're going to take a look

6
00:00:10,003 --> 00:00:14,008
at reusing the texture
holder class coding engine.h

7
00:00:14,008 --> 00:00:17,004
and coding engine.cpp.

8
00:00:17,004 --> 00:00:20,000
As suggested in the previous discussion,

9
00:00:20,000 --> 00:00:22,002
we will code a class called engine

10
00:00:22,002 --> 00:00:23,008
that will control and bind together

11
00:00:23,008 --> 00:00:26,009
the different parts of
the Thomas Was Late game.

12
00:00:26,009 --> 00:00:30,000
The first thing we will do is
make the texture holder class

13
00:00:30,000 --> 00:00:33,004
from the previous project
available in this one.

14
00:00:33,004 --> 00:00:35,004
The texture holder class that we discussed

15
00:00:35,004 --> 00:00:37,002
and coded for the zombie arena game

16
00:00:37,002 --> 00:00:39,008
will also be useful in this project.

17
00:00:39,008 --> 00:00:41,008
While it is possible to add the files,

18
00:00:41,008 --> 00:00:45,004
texture holder.h and texture holder.cpp

19
00:00:45,004 --> 00:00:47,001
directly from a previous project

20
00:00:47,001 --> 00:00:50,004
without recoding them or
re-creating the files.

21
00:00:50,004 --> 00:00:51,006
I don't want to make the assumption

22
00:00:51,006 --> 00:00:54,005
that you haven't jumped
straight to this project.

23
00:00:54,005 --> 00:00:55,009
I'll guide you through few steps

24
00:00:55,009 --> 00:00:57,009
along with the complete code listing

25
00:00:57,009 --> 00:01:01,005
to create the texture holder class.

26
00:01:01,005 --> 00:01:04,001
To create the texture
holder class from scratch,

27
00:01:04,001 --> 00:01:07,006
right-click header files
in the solution Explorer

28
00:01:07,006 --> 00:01:10,001
and select add new item.

29
00:01:10,001 --> 00:01:14,000
In the add new item
window, click header file.h

30
00:01:14,000 --> 00:01:17,005
and then in the name
field, type texture holder.

31
00:01:17,005 --> 00:01:20,008
So the name is texture holder.h.

32
00:01:20,008 --> 00:01:24,004
Finally, click the add button.

33
00:01:24,004 --> 00:01:28,002
Now add this code to texture holder.h.

34
00:01:28,002 --> 00:01:30,005
Notice that we have an include directive

35
00:01:30,005 --> 00:01:33,000
for map from the STL.

36
00:01:33,000 --> 00:01:36,004
Then we declare a map
that holds string and SFML

37
00:01:36,004 --> 00:01:38,006
texture keyvalue pairs.

38
00:01:38,006 --> 00:01:41,007
This map is called m_textures.

39
00:01:41,007 --> 00:01:44,003
Now, this line of code
is quite interesting.

40
00:01:44,003 --> 00:01:47,000
Here we are declaring a static pointer

41
00:01:47,000 --> 00:01:53,001
to an object of type texture
holder called m_s_instance.

42
00:01:53,001 --> 00:01:55,008
This means that the texture holder class

43
00:01:55,008 --> 00:01:59,002
has an object that is
the same type as itself.

44
00:01:59,002 --> 00:02:01,004
Not only that, but because it is static

45
00:02:01,004 --> 00:02:03,005
it can be used with the class itself

46
00:02:03,005 --> 00:02:06,002
without an instance of the class.

47
00:02:06,002 --> 00:02:08,005
When we code the related.cpp file

48
00:02:08,005 --> 00:02:10,008
we will see how we use this.

49
00:02:10,008 --> 00:02:13,000
Now, in the public part of the class

50
00:02:13,000 --> 00:02:16,001
we have the prototype for
the constructor function,

51
00:02:16,001 --> 00:02:17,005
texture holder.

52
00:02:17,005 --> 00:02:20,009
The constructor takes no
arguments and as usual,

53
00:02:20,009 --> 00:02:22,007
has no return type.

54
00:02:22,007 --> 00:02:26,002
This is the same as the
default constructor.

55
00:02:26,002 --> 00:02:28,004
We're going to override
the default constructor

56
00:02:28,004 --> 00:02:30,009
with a definition that
makes our singleton work

57
00:02:30,009 --> 00:02:32,004
how we want it to.

58
00:02:32,004 --> 00:02:35,003
We have another function
called get texture.

59
00:02:35,003 --> 00:02:37,003
Let's look at the signature again,

60
00:02:37,003 --> 00:02:39,008
and analyze exactly what is happening.

61
00:02:39,008 --> 00:02:42,003
First, notice that the function returns

62
00:02:42,003 --> 00:02:43,008
are referenced to a texture.

63
00:02:43,008 --> 00:02:47,000
This means that get texture
will return a reference

64
00:02:47,000 --> 00:02:49,003
which is efficient because
it avoids making a copy

65
00:02:49,003 --> 00:02:51,009
of what could be a fairly large graphic.

66
00:02:51,009 --> 00:02:55,000
Also, notice the function
is declared as static.

67
00:02:55,000 --> 00:02:57,000
This means the function can be used

68
00:02:57,000 --> 00:02:59,004
without an instance of the class.

69
00:02:59,004 --> 00:03:00,006
The function takes a string

70
00:03:00,006 --> 00:03:03,003
as a constant reference as a parameter.

71
00:03:03,003 --> 00:03:05,000
The effect of this is twofold.

72
00:03:05,000 --> 00:03:07,000
Firstly, the operation is efficient

73
00:03:07,000 --> 00:03:09,007
and secondly, because
the reference is constant

74
00:03:09,007 --> 00:03:11,005
it can't be changed.

75
00:03:11,005 --> 00:03:15,006
Now, let's create texture holder.cpp file.

76
00:03:15,006 --> 00:03:18,001
Right-click source files
in the solution Explorer

77
00:03:18,001 --> 00:03:20,006
and select add new item.

78
00:03:20,006 --> 00:03:25,006
In the add new item
window, click C++ file.cpp

79
00:03:25,006 --> 00:03:29,001
and then in the name
field, type texture holder.

80
00:03:29,001 --> 00:03:31,006
Lastly, click the add button.

81
00:03:31,006 --> 00:03:34,007
Add this highlighted code to the file.

82
00:03:34,007 --> 00:03:37,000
See, this is the whole code.

83
00:03:37,000 --> 00:03:40,003
In the code, first we
initialize our pointer

84
00:03:40,003 --> 00:03:43,004
to type texture holder to null PTR.

85
00:03:43,004 --> 00:03:45,009
This is a constructor function.

86
00:03:45,009 --> 00:03:48,000
Inside the constructor function,

87
00:03:48,000 --> 00:03:52,004
this line of code
ensures that M_S_instance

88
00:03:52,004 --> 00:03:54,008
equals null PTR.

89
00:03:54,008 --> 00:03:57,003
If it doesn't, the game
will exit execution.

90
00:03:57,003 --> 00:04:01,008
Then M_S_instance equals to this

91
00:04:01,008 --> 00:04:04,006
assigns the pointer to this instance.

92
00:04:04,006 --> 00:04:07,004
Now, consider where this
code is taking place.

93
00:04:07,004 --> 00:04:09,004
The code is in constructor.

94
00:04:09,004 --> 00:04:12,002
The constructor is the
way we create instance

95
00:04:12,002 --> 00:04:13,007
of an object from classes.

96
00:04:13,007 --> 00:04:17,007
So effectively, we now have
pointer to a texture holder

97
00:04:17,007 --> 00:04:21,005
that points the one and
only instance of itself.

98
00:04:21,005 --> 00:04:26,001
In this line of code, we get
a reference to M_textures.

99
00:04:26,001 --> 00:04:30,001
Then we attempt to get an
iterator to keyvalue pair

100
00:04:30,001 --> 00:04:32,004
using the past in filename.

101
00:04:32,004 --> 00:04:35,003
If we find a matching
key, we return the texture

102
00:04:35,003 --> 00:04:37,002
using this line of code.

103
00:04:37,002 --> 00:04:40,006
Otherwise, first we
create a new keyvalue pair

104
00:04:40,006 --> 00:04:43,008
using the filename and
then we had texture to map

105
00:04:43,008 --> 00:04:46,003
and at last we return
it to the calling code

106
00:04:46,003 --> 00:04:48,008
with the help of return texture.

107
00:04:48,008 --> 00:04:52,002
Texture holder class introduced
lots of new concepts.

108
00:04:52,002 --> 00:04:55,005
Singleton, static functions,
constant references,

109
00:04:55,005 --> 00:04:57,007
auto keyword and syntax.

110
00:04:57,007 --> 00:05:01,003
We can now get on with
our new engine class.

111
00:05:01,003 --> 00:05:03,008
As usual we will start
with the header file

112
00:05:03,008 --> 00:05:07,003
which holds the function
declarations and member variables.

113
00:05:07,003 --> 00:05:10,003
Note that we will revisit this
file throughout the project

114
00:05:10,003 --> 00:05:13,002
to add more functions
and member variables.

115
00:05:13,002 --> 00:05:15,000
For now, we will just add the code

116
00:05:15,000 --> 00:05:17,008
that is necessary at this stage.

117
00:05:17,008 --> 00:05:20,006
Right-click header files
in the solution Explorer

118
00:05:20,006 --> 00:05:22,009
and select add new item.

119
00:05:22,009 --> 00:05:27,001
In the add new item
window click header file.h

120
00:05:27,001 --> 00:05:30,001
and then in the name field, type engine.

121
00:05:30,001 --> 00:05:31,008
Then click the add button.

122
00:05:31,008 --> 00:05:34,007
Add this highlighted code to the file.

123
00:05:34,007 --> 00:05:37,005
This code consists of
various member variables

124
00:05:37,005 --> 00:05:40,000
as well as the function declarations.

125
00:05:40,000 --> 00:05:42,007
Take note of the function
and variable names

126
00:05:42,007 --> 00:05:45,004
as well as whether they
are private or public.

127
00:05:45,004 --> 00:05:49,002
Let's go through all of the
private variables and functions.

128
00:05:49,002 --> 00:05:52,002
Texture holder TH, the
one and only instance

129
00:05:52,002 --> 00:05:54,003
of the texture holder class.

130
00:05:54,003 --> 00:05:58,001
Tile size, a useful constant to remind us

131
00:05:58,001 --> 00:06:01,008
that each tile in the
spreadsheet is 50 pixels wide

132
00:06:01,008 --> 00:06:03,007
and 50 pixels high.

133
00:06:03,007 --> 00:06:06,007
Verts in quad, a useful constant

134
00:06:06,007 --> 00:06:10,007
to make our manipulation of a
vertex array less error-prone.

135
00:06:10,007 --> 00:06:13,007
There are in fact for vertices in a quad.

136
00:06:13,007 --> 00:06:15,004
Now we can't forget it.

137
00:06:15,004 --> 00:06:18,005
Gravity, an instant INT value

138
00:06:18,005 --> 00:06:20,004
representing the number of pixels

139
00:06:20,004 --> 00:06:23,000
by which the game characters
will be pushed outward

140
00:06:23,000 --> 00:06:24,001
each second.

141
00:06:24,001 --> 00:06:25,007
This is quite a fun value to play with

142
00:06:25,007 --> 00:06:27,003
once the game is done.

143
00:06:27,003 --> 00:06:30,004
We initialize it to 300 as this works well

144
00:06:30,004 --> 00:06:32,009
for our initial level designs.

145
00:06:32,009 --> 00:06:37,006
M_window, the usual render window object

146
00:06:37,006 --> 00:06:40,003
like we've had in all of our projects.

147
00:06:40,003 --> 00:06:42,009
Look at these SF ML view objects.

148
00:06:42,009 --> 00:06:48,003
M_main view, M_left view, M_right view,

149
00:06:48,003 --> 00:06:53,001
M_BG main view, M_BG left view,

150
00:06:53,001 --> 00:06:57,002
M_BG right view and M_HUD view.

151
00:06:57,002 --> 00:07:01,006
The first three view
objects that is M_main view

152
00:07:01,006 --> 00:07:03,004
is for the full-screen view.

153
00:07:03,004 --> 00:07:07,006
M_left view is for left split screen.

154
00:07:07,006 --> 00:07:12,008
And M_right view right split
screen views of the game.

155
00:07:12,008 --> 00:07:16,005
Now these three SF ML view objects

156
00:07:16,005 --> 00:07:18,001
will draw the background behind.

157
00:07:18,001 --> 00:07:21,005
The last view object M_HudView

158
00:07:21,005 --> 00:07:24,003
will be drawn on top of
the appropriate combination

159
00:07:24,003 --> 00:07:27,002
of the other six views
to display the score,

160
00:07:27,002 --> 00:07:29,009
the remaining time, and any
messages to the players.

161
00:07:29,009 --> 00:07:33,004
Having seven different view
objects might imply complexity

162
00:07:33,004 --> 00:07:35,005
but when you see how we deal with them

163
00:07:35,005 --> 00:07:36,008
as the section progresses,

164
00:07:36,008 --> 00:07:39,003
you will see they are
quite straightforward.

165
00:07:39,003 --> 00:07:41,001
We will have the whole split screen

166
00:07:41,001 --> 00:07:45,000
full-screen conundrum sorted
out by the end of the section.

167
00:07:45,000 --> 00:07:50,009
Sprite M_background Sprite and
texture M_background texture

168
00:07:50,009 --> 00:07:54,001
this combination of SF
ML Sprite and texture

169
00:07:54,001 --> 00:07:56,008
will be for showing and
holding the background graphic

170
00:07:56,008 --> 00:07:58,007
from the graphics assets folder.

171
00:07:58,007 --> 00:08:03,004
M_playing, this boolean will
keep the game engine informed

172
00:08:03,004 --> 00:08:05,005
about whether the level has started yet

173
00:08:05,005 --> 00:08:07,001
by pressing the enter key.

174
00:08:07,001 --> 00:08:09,008
The player does not have
the option to pause the game

175
00:08:09,008 --> 00:08:11,004
once they've started it.

176
00:08:11,004 --> 00:08:14,006
Now, we have set M_playing to false.

177
00:08:14,006 --> 00:08:19,004
M_character one, when
the screen is full-screen

178
00:08:19,004 --> 00:08:20,008
should it center on Thomas,

179
00:08:20,008 --> 00:08:23,003
M_character one equal to true

180
00:08:23,003 --> 00:08:27,003
or Bob M_character one equal to false.

181
00:08:27,003 --> 00:08:32,002
Initially, it is initialized
to true to center on Thomas.

182
00:08:32,002 --> 00:08:35,008
M_split screen is the game
currently being played

183
00:08:35,008 --> 00:08:37,007
in split screen mode are not.

184
00:08:37,007 --> 00:08:40,001
We will use this variable
to decide how exactly to use

185
00:08:40,001 --> 00:08:43,006
all the view objects we
declared a few steps ago.

186
00:08:43,006 --> 00:08:46,001
M_time remaining variable.

187
00:08:46,001 --> 00:08:49,005
This float variable holds
how much time is remaining

188
00:08:49,005 --> 00:08:51,009
to get to the goal of the current level.

189
00:08:51,009 --> 00:08:54,004
We have set it to 10 for
the purposes of testing

190
00:08:54,004 --> 00:08:58,001
until we actually get to set a
specific time for each level.

191
00:08:58,001 --> 00:09:01,006
M_gametime total variable.

192
00:09:01,006 --> 00:09:04,008
This variable is an SF ML time object.

193
00:09:04,008 --> 00:09:07,009
It keeps track of how long
the game has been played for.

194
00:09:07,009 --> 00:09:12,000
M_new level required boolean variable.

195
00:09:12,000 --> 00:09:14,009
This variable keeps a
check on whether the player

196
00:09:14,009 --> 00:09:16,009
has just completed or failed the level.

197
00:09:16,009 --> 00:09:19,006
We can then use it to trigger
the loading of the next level

198
00:09:19,006 --> 00:09:21,009
or the restarting of the current level.

199
00:09:21,009 --> 00:09:23,006
We have set it to true.

200
00:09:23,006 --> 00:09:24,009
The input function.

201
00:09:24,009 --> 00:09:28,000
This function will handle
all the players input

202
00:09:28,000 --> 00:09:30,005
which in this game is
entirely from the keyboard.

203
00:09:30,005 --> 00:09:32,002
At first glance, it would appear

204
00:09:32,002 --> 00:09:34,008
that it handles all the
keyboard input directly.

205
00:09:34,008 --> 00:09:38,002
In this game however, we will
be handling keyboard input

206
00:09:38,002 --> 00:09:40,004
that directly affects Thomas or Bob

207
00:09:40,004 --> 00:09:43,005
within the Thomas and
Bob classes directly.

208
00:09:43,005 --> 00:09:45,003
We will call the input function

209
00:09:45,003 --> 00:09:48,002
and this function will
directly handle keyboard inputs

210
00:09:48,002 --> 00:09:51,000
such as quitting,
switching to split screen

211
00:09:51,000 --> 00:09:53,006
and any other keyboard input.

212
00:09:53,006 --> 00:09:55,003
The update function.

213
00:09:55,003 --> 00:09:58,003
This function will do all the
work that we previously did

214
00:09:58,003 --> 00:10:00,002
in the update section
of the main function.

215
00:10:00,002 --> 00:10:02,004
We will also call some other functions

216
00:10:02,004 --> 00:10:03,009
from the update function

217
00:10:03,009 --> 00:10:05,008
in order to keep the code organized.

218
00:10:05,008 --> 00:10:07,008
If you look back at the code,

219
00:10:07,008 --> 00:10:10,000
you will see that it
receives a float parameter

220
00:10:10,000 --> 00:10:11,008
which will hold the fraction of a second

221
00:10:11,008 --> 00:10:14,000
that has passed since the previous time.

222
00:10:14,000 --> 00:10:16,000
This of course is just what we need

223
00:10:16,000 --> 00:10:18,004
to update all our game objects.

224
00:10:18,004 --> 00:10:22,005
The draw function, this
function will hold all the code

225
00:10:22,005 --> 00:10:25,004
that used to go in the drawing
section of the main function

226
00:10:25,004 --> 00:10:26,007
in previous projects.

227
00:10:26,007 --> 00:10:28,009
We will however have some drawing code

228
00:10:28,009 --> 00:10:30,009
that is not kept in this function

229
00:10:30,009 --> 00:10:34,000
when we look at other
ways to draw with SF ML.

230
00:10:34,000 --> 00:10:37,000
Let's run through all public
constructor functions.

231
00:10:37,000 --> 00:10:39,000
The engine constructor function.

232
00:10:39,000 --> 00:10:42,000
As we've come to expect,
this function will be called

233
00:10:42,000 --> 00:10:44,004
when refers declare an instance of engine.

234
00:10:44,004 --> 00:10:47,004
It will do all the setup and
initialization of the class.

235
00:10:47,004 --> 00:10:52,000
We will see exactly what when
we code the engine.cpp file.

236
00:10:52,000 --> 00:10:53,005
The run function.

237
00:10:53,005 --> 00:10:56,001
This is the only public
function that we need to call.

238
00:10:56,001 --> 00:10:59,008
It will trigger the execution
of input, update and draw

239
00:10:59,008 --> 00:11:01,004
which will do all the work.

240
00:11:01,004 --> 00:11:04,001
Next we'll see the definition
of all these functions

241
00:11:04,001 --> 00:11:08,001
and some of the variables in action.

242
00:11:08,001 --> 00:11:10,002
Let's get started by coding engine

243
00:11:10,002 --> 00:11:12,007
and run it in engine.cpp.

244
00:11:12,007 --> 00:11:15,007
Right-click source files
in the solution Explorer

245
00:11:15,007 --> 00:11:17,007
and select add new item.

246
00:11:17,007 --> 00:11:23,001
In the add new item
window, click C++ file.cpp

247
00:11:23,001 --> 00:11:25,006
and then in the name field, type engine.

248
00:11:25,006 --> 00:11:27,006
Finally click the add button.

249
00:11:27,006 --> 00:11:30,002
In this file, add this entire code.

250
00:11:30,002 --> 00:11:33,009
We will add constructor engine
and public run function.

251
00:11:33,009 --> 00:11:37,004
All other functions will
go in their own .cpp file

252
00:11:37,004 --> 00:11:40,006
with a name that makes it clear
which function goes where.

253
00:11:40,006 --> 00:11:42,004
This will not be a problem for compiling

254
00:11:42,004 --> 00:11:45,004
as long as we had
appropriate include directive

255
00:11:45,004 --> 00:11:49,002
hash include engine.h
at the top of all files

256
00:11:49,002 --> 00:11:52,006
that contain function
definition from engine class.

257
00:11:52,006 --> 00:11:57,001
We are now ready to code the
.cpp file for the engine class.

258
00:11:57,001 --> 00:12:00,005
The code for this function
will be in the engine.cpp file

259
00:12:00,005 --> 00:12:01,009
we just created.

260
00:12:01,009 --> 00:12:06,002
Here we are adding necessary
include directives.

261
00:12:06,002 --> 00:12:08,001
Much of the code we have seen before.

262
00:12:08,001 --> 00:12:10,008
For example, there are
the usual lines of code

263
00:12:10,008 --> 00:12:12,002
to get the screen resolution

264
00:12:12,002 --> 00:12:14,005
as well as to create a render window.

265
00:12:14,005 --> 00:12:17,000
At the end of this code, we
use the now familiar code

266
00:12:17,000 --> 00:12:20,001
to load a texture and
assign it to a Sprite.

267
00:12:20,001 --> 00:12:21,005
In this case, first

268
00:12:21,005 --> 00:12:23,009
we are loading the background.PNG texture

269
00:12:23,009 --> 00:12:27,003
and assigning it to M_background Sprite.

270
00:12:27,003 --> 00:12:29,003
In this code in between,

271
00:12:29,003 --> 00:12:31,009
the four calls to the
set viewport function

272
00:12:31,009 --> 00:12:33,009
that needs some explanation.

273
00:12:33,009 --> 00:12:36,009
The set viewport function
assigns a portion of the screen

274
00:12:36,009 --> 00:12:39,001
to an SF ML view object.

275
00:12:39,001 --> 00:12:42,003
It doesn't work using
pixel coordinates however.

276
00:12:42,003 --> 00:12:44,002
It works using a ratio

277
00:12:44,002 --> 00:12:47,004
where one is the entire
screen, width or height.

278
00:12:47,004 --> 00:12:50,005
The first two values in
each call to set viewport

279
00:12:50,005 --> 00:12:53,007
are the starting position
horizontally and vertically.

280
00:12:53,007 --> 00:12:56,002
And the last two are the ending position.

281
00:12:56,002 --> 00:13:01,006
Notice that the M_left
view and M_BG left view

282
00:13:01,006 --> 00:13:03,007
are placed in exactly the same place

283
00:13:03,007 --> 00:13:08,002
starting at virtually the
far left, 0.001 of the screen

284
00:13:08,002 --> 00:13:12,006
and ending two 1000s
from the center, 0.498.

285
00:13:12,006 --> 00:13:17,000
The M_right view and M_BG right view

286
00:13:17,000 --> 00:13:19,003
are also in exactly the same position,

287
00:13:19,003 --> 00:13:23,003
starting just left of the
previous two view objects 0.5

288
00:13:23,003 --> 00:13:26,003
and extending to almost
the far right-hand side,

289
00:13:26,003 --> 00:13:28,003
0.998 of the screen.

290
00:13:28,003 --> 00:13:32,005
Furthermore, all the views
leave a tiny sliver of a gap

291
00:13:32,005 --> 00:13:34,008
at the top and bottom of the screen.

292
00:13:34,008 --> 00:13:37,005
When we draw these view
objects on the screen

293
00:13:37,005 --> 00:13:39,000
on top of a white background,

294
00:13:39,000 --> 00:13:41,005
it will have the effect
of splitting the screen

295
00:13:41,005 --> 00:13:44,008
with a thin white line between
the two sides of the screen

296
00:13:44,008 --> 00:13:47,004
as well as a thin white
border around the edges.

297
00:13:47,004 --> 00:13:50,007
I've tried to represent
this effect in this diagram.

298
00:13:50,007 --> 00:13:54,001
The best way to understand
it is to finish this section,

299
00:13:54,001 --> 00:13:56,008
run the code and see it in action.

300
00:13:56,008 --> 00:14:00,000
Let's take a look at coding
the run function definition.

301
00:14:00,000 --> 00:14:04,001
Add this highlighted code in engine.cpp

302
00:14:04,001 --> 00:14:06,001
just after the constructor code.

303
00:14:06,001 --> 00:14:09,001
The run function is the
center of our engine.

304
00:14:09,001 --> 00:14:10,008
It initiates all the other parts.

305
00:14:10,008 --> 00:14:13,007
First, we declare a clock object.

306
00:14:13,007 --> 00:14:17,003
Next, we have the familiar
while window is open loop

307
00:14:17,003 --> 00:14:18,009
which creates the game loop.

308
00:14:18,009 --> 00:14:23,002
Inside this while loop, we
restart clock and save the time

309
00:14:23,002 --> 00:14:26,000
that the previous loop took in DT.

310
00:14:26,000 --> 00:14:28,006
Then, we keep track of
the total time elapsed

311
00:14:28,006 --> 00:14:31,004
in M_gametime total.

312
00:14:31,004 --> 00:14:34,003
Here declare and initialize a float

313
00:14:34,003 --> 00:14:36,005
to represent the fraction
of a second that elapsed

314
00:14:36,005 --> 00:14:38,001
during the previous frame.

315
00:14:38,001 --> 00:14:40,007
Next, we call input function.

316
00:14:40,007 --> 00:14:43,009
Then we call update passing
in the elapsed time,

317
00:14:43,009 --> 00:14:46,001
DT as seconds.

318
00:14:46,001 --> 00:14:49,005
And at last, we call draw function.

319
00:14:49,005 --> 00:14:51,002
All of this should look very familiar.

320
00:14:51,002 --> 00:14:54,005
What is new is that is
wrapped in the run function.

321
00:14:54,005 --> 00:14:59,004
Now let's move on to coding
the input function definition.

322
00:14:59,004 --> 00:15:02,004
Right-click source files
in the solution Explorer

323
00:15:02,004 --> 00:15:03,009
and select add.

324
00:15:03,009 --> 00:15:06,003
In that, click on new item.

325
00:15:06,003 --> 00:15:10,008
Now we have to select C++ file.cpp

326
00:15:10,008 --> 00:15:12,009
and then in the name field type input.

327
00:15:12,009 --> 00:15:16,001
So the name is now input.cpp.

328
00:15:16,001 --> 00:15:18,000
Finally, click the add button.

329
00:15:18,000 --> 00:15:20,008
We're now ready to code
the input function.

330
00:15:20,008 --> 00:15:23,005
Now we have to add this highlighted code.

331
00:15:23,005 --> 00:15:26,003
The code for this function
will go in its own file.

332
00:15:26,003 --> 00:15:28,005
This is the entire highlighted code

333
00:15:28,005 --> 00:15:31,009
that we have to add in the input.cpp file.

334
00:15:31,009 --> 00:15:34,006
In this highlighted
code, first we will use

335
00:15:34,006 --> 00:15:37,004
hash include engine.h

336
00:15:37,004 --> 00:15:40,000
and prefix the function
signature with engine

337
00:15:40,000 --> 00:15:43,000
to make sure the compiler
is aware of our intentions.

338
00:15:43,000 --> 00:15:45,009
As usual, when the escape key is pressed

339
00:15:45,009 --> 00:15:48,007
it closes the window
and the game will quit.

340
00:15:48,007 --> 00:15:50,008
That is whenever we press escape key,

341
00:15:50,008 --> 00:15:52,004
the game will be closed.

342
00:15:52,004 --> 00:15:57,009
When enter key is pressed,
it sets M_playing to true

343
00:15:57,009 --> 00:15:59,003
and eventually this will have the effect

344
00:15:59,003 --> 00:16:00,008
of starting a level.

345
00:16:00,008 --> 00:16:05,005
The cube keypress alternates
the value of M_character one

346
00:16:05,005 --> 00:16:06,009
between true and false.

347
00:16:06,009 --> 00:16:09,009
This key only has an
effect in full-screen mode.

348
00:16:09,009 --> 00:16:12,000
It will switch between Thomas and Bob

349
00:16:12,000 --> 00:16:13,008
being the center of the main view.

350
00:16:13,008 --> 00:16:17,007
When E key is pressed, it
switches M_split screen

351
00:16:17,007 --> 00:16:19,000
between true and false.

352
00:16:19,000 --> 00:16:21,008
This will have the effect of
switching between fullscreen

353
00:16:21,008 --> 00:16:23,006
and split screen views.

354
00:16:23,006 --> 00:16:25,008
The majority of this
keyboard functionality

355
00:16:25,008 --> 00:16:28,006
will be fully working by
the end of the section.

356
00:16:28,006 --> 00:16:31,003
We're getting close to being
able to run our game engine.

357
00:16:31,003 --> 00:16:34,001
Next, let's code update function.

358
00:16:34,001 --> 00:16:37,009
As usual, right-click source
files in the solution Explorer

359
00:16:37,009 --> 00:16:40,000
and select add new item.

360
00:16:40,000 --> 00:16:44,006
In the add new item
window, click C++ file.cpp

361
00:16:44,006 --> 00:16:47,001
and then in the name field type update.

362
00:16:47,001 --> 00:16:49,001
Lastly, click the add button.

363
00:16:49,001 --> 00:16:52,003
We're now ready to write some
code for the update function.

364
00:16:52,003 --> 00:16:54,005
Now add this highlighted code.

365
00:16:54,005 --> 00:16:58,003
The code for update
function goes in update.cpp.

366
00:16:58,003 --> 00:17:03,000
Just as we did earlier, we
will use hash include engine.h

367
00:17:03,000 --> 00:17:05,003
and prefix the function
signature with engine

368
00:17:05,003 --> 00:17:08,006
to make sure the compiler
is aware of our intentions.

369
00:17:08,006 --> 00:17:11,002
Notice that the update
function receives the time

370
00:17:11,002 --> 00:17:13,003
the previous frame took as a parameter.

371
00:17:13,003 --> 00:17:16,002
This of course will be essential
for the update function

372
00:17:16,002 --> 00:17:17,007
to fulfill its role.

373
00:17:17,007 --> 00:17:21,001
Then it checks the if
condition M is playing.

374
00:17:21,001 --> 00:17:24,009
If yes, then it subtracts the
time the previous frame took

375
00:17:24,009 --> 00:17:27,001
from M_time remaining.

376
00:17:27,001 --> 00:17:29,003
It checks whether time has run out,

377
00:17:29,003 --> 00:17:33,006
and if it has, it sets M_new
level required to true.

378
00:17:33,006 --> 00:17:36,007
All this code is wrapped
in an if statement

379
00:17:36,007 --> 00:17:39,009
that only executes when M_playing is true.

380
00:17:39,009 --> 00:17:42,007
The reason for this is because
as with the previous projects

381
00:17:42,007 --> 00:17:46,002
we don't want time advancing
and objects updating

382
00:17:46,002 --> 00:17:47,009
when the game is not started.

383
00:17:47,009 --> 00:17:51,003
We will build on this code
as the project continues.

384
00:17:51,003 --> 00:17:55,002
Lastly, let's code the
draw function definition

385
00:17:55,002 --> 00:17:58,002
right-click source files
in the solution Explorer

386
00:17:58,002 --> 00:18:00,006
and select add new item.

387
00:18:00,006 --> 00:18:03,007
Then select C++ file.cpp

388
00:18:03,007 --> 00:18:05,008
and then in the name field, type draw.

389
00:18:05,008 --> 00:18:09,000
Now the name is draw.cpp.

390
00:18:09,000 --> 00:18:10,008
Then click the add button.

391
00:18:10,008 --> 00:18:14,002
We are now ready to add some
code to the draw function.

392
00:18:14,002 --> 00:18:16,005
Now we'll add this code to the file

393
00:18:16,005 --> 00:18:18,003
to implement the draw function.

394
00:18:18,003 --> 00:18:21,001
The code for draw function
will go in its own file.

395
00:18:21,001 --> 00:18:26,004
You can see we will use hash
include engine.h here also

396
00:18:26,004 --> 00:18:29,000
and prefix the function
signature with engine.

397
00:18:29,000 --> 00:18:32,005
In this highlighted line of
code we clear the screen.

398
00:18:32,005 --> 00:18:35,007
In this project, we clear
the screen with white.

399
00:18:35,007 --> 00:18:38,007
What is new is the way the
different drawing options

400
00:18:38,007 --> 00:18:40,004
are separated by a condition

401
00:18:40,004 --> 00:18:44,000
which checks whether the screen
is currently split or full.

402
00:18:44,000 --> 00:18:45,008
If the screen is not split,

403
00:18:45,008 --> 00:18:48,002
we draw the background
sprite in the background view

404
00:18:48,002 --> 00:18:50,009
that is M_BG main view,

405
00:18:50,009 --> 00:18:54,008
and then switch to the main
full-screen, view M_main view.

406
00:18:54,008 --> 00:18:56,007
Note that at the moment,

407
00:18:56,007 --> 00:18:59,008
we don't actually do any
drawing in M_main view.

408
00:18:59,008 --> 00:19:02,002
On the other hand, if the screen is split

409
00:19:02,002 --> 00:19:04,008
the code in the else block is executed

410
00:19:04,008 --> 00:19:07,005
and we draw M_BG left view

411
00:19:07,005 --> 00:19:10,004
with the background sprite
on the left of the screen

412
00:19:10,004 --> 00:19:13,008
followed by switching to M_left view.

413
00:19:13,008 --> 00:19:18,006
Then still in the else block,
we draw M_BG right view

414
00:19:18,006 --> 00:19:20,009
with the background sprite
on the right of the screen

415
00:19:20,009 --> 00:19:24,001
followed by switching to M_right view.

416
00:19:24,001 --> 00:19:27,004
Outside the if else structure,

417
00:19:27,004 --> 00:19:30,000
we run to M_HUD view.

418
00:19:30,000 --> 00:19:32,007
At this stage, we're not
actually drawing anything

419
00:19:32,007 --> 00:19:34,008
in M_HUD view.

420
00:19:34,008 --> 00:19:37,005
At last, we call the display function

421
00:19:37,005 --> 00:19:39,005
to show everything we have just drawn.

422
00:19:39,005 --> 00:19:41,005
As with the other two input update

423
00:19:41,005 --> 00:19:44,000
of the three most significant functions

424
00:19:44,000 --> 00:19:46,005
we will be back here at
the draw function often.

425
00:19:46,005 --> 00:19:49,005
We will add new elements of
our game that need to be drawn.

426
00:19:49,005 --> 00:19:51,005
You'll notice that each time we do,

427
00:19:51,005 --> 00:19:53,007
we'll add code into each of the main,

428
00:19:53,007 --> 00:19:55,003
left and right sections.

429
00:19:55,003 --> 00:19:57,006
Let's quickly recap the engine class

430
00:19:57,006 --> 00:19:58,009
and then we can fire it up.

431
00:19:58,009 --> 00:20:02,005
What we have achieved is the
abstraction of all the code

432
00:20:02,005 --> 00:20:04,004
that used to be in the main function

433
00:20:04,004 --> 00:20:07,001
into the input, update and draw functions.

434
00:20:07,001 --> 00:20:09,001
The continuous looping of these functions

435
00:20:09,001 --> 00:20:12,001
as well as the timing is
handled by the run function.

436
00:20:12,001 --> 00:20:18,009
As you can see here, input.cpp,
update.cpp and draw.cpp tabs

437
00:20:18,009 --> 00:20:20,006
open in Visual Studio.

438
00:20:20,006 --> 00:20:22,006
I've organized them in order.

439
00:20:22,006 --> 00:20:24,006
We will revisit each of these functions

440
00:20:24,006 --> 00:20:27,005
throughout the course of the
project to add more code.

441
00:20:27,005 --> 00:20:29,006
Now that we have the basic structure

442
00:20:29,006 --> 00:20:31,003
and functionality the engine class,

443
00:20:31,003 --> 00:20:34,002
we can create an instance
of it in the main function

444
00:20:34,002 --> 00:20:35,007
and see it in action.

445
00:20:35,007 --> 00:20:38,009
In this video, we've looked
at building the game engine.

446
00:20:38,009 --> 00:20:41,005
Great, in the next video,

447
00:20:41,005 --> 00:20:44,001
we'll learn coding the main function.

