- Hi, welcome to Building the Playable Character Class.
Previously, we looked at abstract classes,
virtual and pure virtual functions.
In this video, we're going to look at coding
Playable Character.h and Playable Character.cpp.
Now that we know the basics about inheritance,
polymorphism, and pure virtual functions,
let's put them to use.
We will build a Playable Character Class
that has the vast majority of the functionality
that any character from our game is going to need.
It will have one pure virtual function, handle input.
The handle input function will need to be quite
different in the sub-classes, this makes sense,
as Playable Character will have a pure virtual function.
It will be an abstract class,
and no objects of it, will be possible.
We will then build the both Thomas and Bob Classes,
which will inherit from Playable Character,
implement the definition of the pure virtual function,
and allow us to instantiate Bob and Thomas objects
in our game.
Let's start with coding Playable Character.h
Right click Header Files in the Solution Explorer,
and select, Add New Item.
In the Add New Item window, click Header File.h,
and then, in the name field, type Playable Character.
So, now the name is Playable Character.h.
Lastly, click the Add button.
We are now ready to code the Header File,
for the Playable Character Class.
Add this highlighted code in the file.
As usual, when creating a class, we will start off with
the Header File, that will contain the member variables,
and function declarations.
What is new, is that in this class, we will declare some
protected member variables.
Remember, that protected variables can be used,
as if they are public by classes,
which inherit from the class with the protected variables.
We will add, and discuss, the contents of the
Playable Character.h file in three sections.
First, the protected section, followed by private,
then public.
The first thing to notice in the code we just wrote,
is that all the variables are protected.
This means that when we extend the class,
all the variables we just wrote, will be accessible
to those classes that extended.
We will extend this class with Thomas and Bob Classes.
Apart from the protected access specification,
there's nothing new, or complicated, about this code.
It is worth paying attention to some of the details however.
Then, it will be easy to understand how the class works,
as we progress.
So, let's run through those protected variables,
one at a time.
First of all, we have our, somewhat predictable,
Sprite, m_Sprite.
That is, we are declaring an object of Sprite,
called m_Sprite.
We have a float called m_JumpDuration,
which will hold the value representing the time that the
character is able to jump for.
The greater the value, the higher the character will be
able to jump.
Next, we have boolean, m_ IsJumping,
which is true when the character is jumping,
and falls otherwise.
This will be useful for making sure that the character
can't jump while in mid-air.
The m_ IsFalling variable, has a similar use,
to m_IsJumping.
It will be useful to know when a character is falling.
It's also a bolean variable.
Next we have two boolean's, which would be true,
if the character's left or right keyboard buttons,
are currently being pressed.
These are relative, depending upon the character.
Keys, A and D for Thomas, left and right arrow keys for Bob.
How we respond to these booleans, will be seen in the
Thomas and Bob Classes.
The m_TimeThisJump float variable, is updated,
each and every frame, the m_IsJumping is true.
We can then know when m_Jump duration has been reached.
The final protected variable, is the boolean m_JustJumped,
this will be true if a jump was initiated,
in the current frame.
It will be useful for knowing
when to play a jump sound effect.
As of now, we have set m_JustJumped, to false.
Next, at this highlighted code, where we are adding
private variables to the Playable Character.h file.
We have some interesting private variables here.
Remember that these variables will only be directly
accessible to the code, in the Playable Character Class.
The Thomas and Bob classes, will not be able to
access them directly.
The m_Gravity variable, will hold the number of pixels
per second that the character will fall.
The m_Speed variable, will hold the number of pixels
per second that the character can move left, or right.
The Vector2f m_Position variable,
is the position in the world, not the screen,
where the center of the character is.
The next four float rect objects, are important to discuss.
When we did collision detection in the Zombie Arena game,
we simply checked to see if,
two float rect objects intersected.
Each float rect object, represented an entire character,
a pick up, or a bullet.
For the non-rectangular shaped objects,
zombies and the player,
this was a little bit inaccurate.
In this game, we will need to be more precise.
The m_Feet, m_Head, m_Right and m_Left float rect objects,
will hold the co-ordinates of the different parts
of a character's body.
These co-ordinates will be updated,
in each and every frame.
Through these co-ordinates, we will be able to tell exactly
when a character lands on a platform, bumps his head
during a jump or, rubs shoulders with a tile to his side.
Lastly, we have texture, that is,
we declare an object of type texture,
called m_Texture.
Texture is private, as it is not used directly,
by the Thomas or Bob Classes,
but as we saw, Sprite is protected,
because it is used directly.
Now, add all the public functions to the
Playable Character.h file,
this is the entire highlighted code to be added.
Let's talk about each of the function declarations
that we just added.
This will make coding their definitions, easier to follow.
First, the Spawn function receives a vector2f called,
Start Position, and a float called Gravity.
As the name suggests, Start Position will be the
co-ordinates in the level at which the character will start,
and Gravity will be the number of pixels per second,
at which the character will fall.
The bool virtual handle input = 0,
is, of course, our pure virtual function.
As Playable Character has this function,
any class that extends it, if we want to instantiate it,
must provide a definition for this function.
Therefore, when we write all the function definitions for
Playable Character in the minute,
we will not provide a definition for handle input.
There will, of course, need to be definitions,
in both the Thomas and Bob Classes.
The Get Position function, returns a float rect,
that represents the position of the whole character.
The Get Feet function, as well as Get Head,
Get Right and Get Left, each return a float rect,
that represents the location of a specific part
of the character's body.
This is just what we need, for detailed collision detection.
The Get Sprite function, as usual, returns a copy
of m_Sprite, to the calling code.
The StopFalling, StopRight and StopLeft,
receive a single float value.
Which the function will use, to reposition the
character, and stop it walking or jumping,
through a solid tile.
The StopJump function, will stop the character,
from jumping through a solid tile.
The GetCenter function, returns a vector2f,
to the calling code, to let it know exactly where
the center of the character is.
This value is, of course, held in m_Position.
We will see later, that it is used by the Engine Class,
to center the appropriate view around
the appropriate character.
The update function, we have seen many times before,
and, as usual, it takes float parameter,
which is the fraction of a second,
that the current frame is taken.
This update function, will need to do more work,
than previous update functions, from other projects.
However, it will need to handle jumping,
as well as updating the float rect objects that
represent the head, feet, left and right.
Now, we can write the definitions for all the functions,
except, of course, handle input.
Now, let's move on to coding Playable Character.cpp.
Just like we always do, right click Source Files,
in the Solution Explorer, and select Add New Item.
Click, c++ File.cpp, and then in the name field,
type Playable Character, and click Add.
We are now ready to code the .cpp file,
for the Playable Character Class.
We will break up the code, and discussion,
into a number of chunks.
First, add the Include Directives, and the definition
of the Spawn function.
The Spawn function, initializes m_Position,
with the past in position.
That is, m_Positionx = StartPositionx and,
m_Positiony = StartPositiony.
It also initializes m_Gravity, and this final line of code,
moves m_Sprite, to it's starting position.
Next, add the definition for the Update function.
Add this entire highlighted code immediately after
the preceding code.
Here, first we check whether m_RightPressed is true.
If it is, m_Position is changed, using this formula,
m_Speed into elapse time.
The same is done for m_LeftPressed, in case it's true,
it changes m_Position using this formula.
Then, we see whether or not the character,
is currently executing a jump.
If this if statement is true,
the code first updates m_TimeThisJump, with elapse time.
Then, it checks if m_TimeThisJump is still less than,
m_JumpDuration, if it is,
change the y co-ordinate of m_Position by
twice Gravity multiplied by the elapse time.
In the else clause, it executes when m_TimeThisJump is,
not lower than m_JumpDuration,
then m_Falling is set to true.
Also, m_Jumping is set to false.
This prevents the code we have just been discussing,
from executing.
As if m_IsJumping, is now false.
Next, if m_IsFalling block moves m_Position down each frame,
it is moved, using the current value of m_Gravity
and the elapse time.
That is, using the current value of m_Gravity,
and the elapse time.
This code, which is almost all of the remaining code,
updates the body parts of the character,
relative to the current position of the Sprite, as a whole.
Take a look at this diagram,
to see how the code calculates the position,
of the virtual head, feet, left and right sides,
of the character.
This final line of code, uses the set position of
function, to move the Sprite to it's corrected
location after all the possibilities of the update function.
Now, add this code, right after the previous one.
Here we are adding the definition for the Get Position,
GetCenter, GetFeet, GetHead, GetLeft, GetRight and
GetSprite functions.
The GetPosition function, returns a float rect,
that wraps the entire Sprite and Get Center returns
a vector2f, which contains the center of the Sprite.
Notice, that we divide the height and width of the Sprite,
by two, in order to dynamically arrive at this result.
This is because Thomas and Bob,
will be at different heights.
The GetFeet, GetHead, GetLeft and GetRight functions,
return the float rect objects that represent the
body parts of the character, that we update each frame,
in the update function.
The Get Sprite function, as usual,
returns a copy of m_Sprite.
Finally, for the Playable Character Class,
add the definitions for the, StopFalling, StopRight,
StopLeft and StopJump functions.
Note that to do so, immediately after the previous code.
Each of these function receive a value, as a parameter,
that is used to reposition either the top,
bottom, left or right of the Sprite.
Exactly what these values are, and how they are obtained,
will be seen later.
Each of the previous functions also repositions the Sprite.
The final function is the StopJump function,
that will also be used in collision detection.
It sets the necessary values for m_IsJumping and,
m_IsFalling, to end a jump.
Here we have set m_IsJumping to false,
and m_IsJumping to true.
In this video, we have learned,
Building the Playable Character Class.
Cool.
In the next video, we will see building the
Thomas and Bob Classes.