Health, Damage, and Player Death
Now we’ll add actual logic to HealthComponent
.
First, add the following member data:
-
A
float
for the health -
These two callback functions (remember you need to include
<functional>
):std::function<void(const Vector3&)> mOnDamage; std::function<void()> mOnDeath;
We last did callbacks back in Lab 6. One thing that’s a little different this time is the mOnDamage
callback takes in a parameter this time, rather than no parameters.
Then add/change the following functions:
- Make the constructor take in the starting health value (default to a value of 100.0f)
- Add a setter for both callbacks
- Add a
GetHealth
function which returns the health - Add a
IsDead
function which returns if health <= 0.0f - Add a
TakeDamage
function that takes in afloat
for the damage amount as well as aconst Vector3&
for the location the damage is coming from
The code for TakeDamage
is nothing fancy, and pretty similar to what:
- Don’t do anything if already dead
- Subtract the damage amount from the health
- Call the
mOnDamage
callback if it’s set (passing in the location as a parameter) - If dead, call the
mOnDeath
callback if it’s set
Pellets and Death
For the player’s HealthComponent
, set the mOnDeath
callback so that it forces the game to reload the level. Remember that the syntax for setting a callback is like this:
health->SetOnDeath([this] {
// Code you want to run here
});
For the turret’s HealthComponent
, set the mOnDeath
callback so that it calls Die
on the turret.
Now, in Pellet::OnUpdate
:
- If the pellet collides with the player, call
TakeDamage
on the player’sHealthComponent
, passing in 100 for the damage and the pellet’s position as the location - Similarly, when detecting a collision against a collider, if the collider has a
HealthComponent
, first check whether the object is alive:- If it’s dead, ignore the collision (this is so the pellet doesn’t keep hitting a turret that’s dead)
- Otherwise, deal 100 damage with the pellet’s position as the location
Confirm that if you get hit by a pellet, the level reloads. Similarly, confirm that turrets will die when hit by a pellet, and that any subsequent pellets go through the dead turret:
Falling and Death
Change the code in PlayerMove::Update
that checks if the player’s z is too low, and instead of directly reloading the level, cause the health component to take Math::Infinity
damage from the location of the owner.
There is no pit you can fall through in this level, but it’s hard to mess this up so it should be fine!
Turrets and Firing
Now that we actually have health, we can make the turrets do damage!
First, in the helper function that tries to acquire a target, do not acquire a target if it’s health component says it’s already dead.
Next, in UpdateFiring
, if the target is still valid (meaning you didn’t switch to search) and the health component doesn’t say the target is dead, deal damage every 0.05 seconds. Make sure that when you initialy change to the Firing state, you reset the cooldown to 0.05.
Every time the turret deals damage, it should deal 2.5 damage and use the GetWorldPostion()
as the location where the damage is coming from.
Confirm that if you stand in front of a firing turret for a few seconds, you die.
Testing the Input Replay
Finally, confirm that you can pass the input replay validation mode. You’re not required to pass validation mode for an A, but ideally it work so that we can quickly test the main mechanics. For best results, you should start the replay as soon as you load into the game (otherwise you may get unexpectedly killed since the pellets do not reset on starting the replay). It should look like this:
Once you’ve pushed your code, you should review the grading specifications to confirm you’ve satisfied them.