- [Instructor] Hey!
This is the last video of this section, Collision Detection.
Previously, we looked at updating the game engine.
In this video, we'll be coding the detectCollisions
function.
We will handle collision detection using rectangle
intersection and the SFML intersects function.
What will be different in this project is that we will
abstract the collision detection code into is own
function and Thomas and Bob as we have already seen,
have multiple rectangles: m underscore Head,
m underscore Feet, m underscore Left, m underscore Right,
that we need to check for collisions.
Let's start coding the detectCollisions function.
To be clear, this function is part of the engine class.
Open up the engine dot h file and add a declaration for
a function called detectCollisions.
You have to add the declaration after void loadLevel
function.
Write a comment.
Run will call all the private functions.
Then bool detectCollisions, playable character,
ampersand character.
Notice from the signature that the detectCollision
function takes a polymorphic argument.
A player character object.
As we know, playable character is abstract and can
never be instantianated.
We do, however, inherit from it with the Thomas and
Bob classes.
We'll be able to pass either m underscore Thomas
or m underscore Bob to detect collisions.
Now create a dot CPP file for detecting collisions.
Right click source files in the solution explorer,
and select add new item.
Then click C plus plus file and then in the name field
type detect collisions.
Lastly, click add.
We are now ready to code the detectCollisions function.
Add this highlighted code to detectCollisions dot
CPP file.
Note that this is just the first part of the function.
The first thing that happens is that we declare a
boolean called reachedGoal.
This is the value that the detectCollisions function
returns to the calling code.
It is initialized to false.
Next, we declare a FloatRect called detectionZone
and initialize it with the same rectangle that
represents the entire rectangle of the character Sprite.
Note that we will not actually do intersection tests
with this rectangle.
After that we declare nother FoatRect called block.
We initialize block as a 50 by 50 rectangle.
We will see block in use shortly.
Next, we see how we will use detectionZone.
We initialize four int variables: startX, startY,
endX and endY, by expanding the area around
detectionZone a few blocks.
In the four if statements that follow, we check that
it is not possible to try and do collisionDetection
on a tile that does not exist.
We achieve this by making sure we never check positions
less than zero or greater than the value returned
by getLevelSize dot x or dot y.
Now, all this highlighted code creates an area with
which to do collision detection.
There is no point doing collision detection on a block
that is hundreds or thousands of pixels away from
the character.
In addition, if we try and do collision detection where
an array position doesn't exist, less than zero or
greater than getLevelSize, the game will crash.
Next, add this highlighted code, which handles the player
falling out of the level.
For a character to stop falling, it must collide with
a platform.
Therefore, if the player moves out of the map, where
there are no platforms, it will continuously fall.
This code checks whether the character does not intersect
with the FloatRect level.
If it doesn't not, then it has fallen out of the
level and the spawn function sends it back to the start.
Now, add this highlighted code right after the previous
code we added.
It's quite large, I must say, but don't worry.
We'll go through it and see what it does.
This code does three things using the same techniques.
It loops through all the values contained between startX
endX and startY endY.
For each pass, it checks some conditions.
First, has the character burned or drowned?
This line of code determines if the current position
being checked is a fire or water tile.
If the character's head intersects with one of these tiles,
the player is respawned.
We also code an empty if else block,
in preparation for adding sound in the next section.
Next, has the character touched a regular tile?
This line determines if the current position being
checked holds a regular tile.
If it intersects with any of the rectangles that
represent the various body parts of the character,
the related function is called stopRight,
stopLeft, stopFalling and stopJump.
The value that is passed to each of these functions and
how the function uses the value to reposition the
character is quite nuanced.
While it is not necessary to closely examine these
values to understand the code, you might like to look
at the values passed in and then refer back to the
appropriate function of the playable character class
in the previous section.
This will help you appreciate exactly what is going on.
Has the character touched the goal tile?
This is determined by this highlighted line of code.
All we need to do is set reachedGoal to true.
The update function of the engine class will keep
track of whether both characters, Thomas and Bob,
have reached the goal simultaneously.
We will write this code in update in just a moment.
Now, write the last line of code to detect collisions
function.
Add a comment.
All done, return, whether or not a new level might be
required.
Then write return reachedGoal.
The highlighted line of code returns reachedGoal,
so that the calling code can keep track and respond
appropriately if both characters reach the goal
simultaneously.
All we need to do now is call the detectCollision
function once per character per frame.
Open the update dot CPP file, and inside
m underscore playing and after Update Bob,
we have to add a code.
Add this highlighted code I've shown.
This code calls the detectCollision function,
and checks if both Bob and Thomas have simultaneously
reached the goal.
If they have, the next level's prepared by setting
m underscore NewLevelRequired to true.
Otherwise, it runs Bobs collisionDetection.
You can run the game by clicking on local Windows
debugger button.
You can now walk on the platforms.
You can reach the goal and start a new level.
Also, for the first time, the jump buttons will work.
Bob can jump with the up arrow key and Thomas can
jump with the w key.
If you reach the goal the next level will load.
If you reach the goal of the last level, then the first
level will load with a 10% reduced time limit.
Of course, there is no visual feedback for the time
or the current level, because we haven't built a
HUD yet.
We will do so in the next section.
Let's see some more collisionDetection.
You have to add this highlighted code just after the
previous code you added in the update dot CPP file.
Within the if m underscore PlayingSecion.
This code helps Bob and Thomas jump on each other's heads.
You can run the game again by clicking the local Window
debugger button.
And you can stand on the heads of Thomas and Bob
to get to the hard to reach places that were previously
not attainable.
You can see how Bob is jumping on the head of Thomas.
Also, Thomas can jump on the head of Bob.
Awesome!
In this video, we have learned collision detection.
Cool!
That marks the end of this section.
We started this section by designing levels in a
text file.
We then built a level manager class, and coded
load level function.
Then we updated the game engine to use level manager,
and lastly, we coded a polymorphic function to handle
the collision detection for Bob and Thomas.
In the next section, we'll take a look at sound,
spatialization and HUD.