We have all sorts of enemies flying at our hero and if he hits them they disappear. Now we need to incentivize him to NOT run into all the bad guys.
Our next steps are to make enemies damage our hero when he runs into them, give him the ability to shoot the enemies before they reach him, and give the player points whenever they successfully destroy an enemy.
Since all of our enemies and our player are Characters in our game, we can handle keeping track of their health in our Character class.
To do so we will add a health field and give each enemy and the player some starting health and a maximum amount of health.
Now we need to change our game creation code and our enemy generator to pass in health for our player and enemies.
Now that characters have health, we should give them the ability to take damage.
Let’s change the OnObjectCollisionMethod to cause the player and enemies to damage each other when they run into each other.
In our character class we are going to add a method that handles units taking damage. Then we will call it from the character Update method.
And in our OnUpdate method, we will make some changes to handle updating characters to damage them and destroy them.
Now when you run the game, when the player runs into an enemy it causes damage instead of outright destroying them. Enemies with more than 1 health won’t be destroyed. And after the player takes too much damage, they will no longer damage enemies. Eventually we will add a GAME OVER or lost life for this case but that will come later.
Now that we have characters taking damage, lets give our player the ability to shoot at enemies and destroy them. We will start by making a projectile class and a projectile type class. Create a new file called projectile.monkey that we can start making projectiles from. It will have a constructor and an update method.
and a file called projectile_type.monkey
Projectiles have a variety of attributes. First of all they have a box that can collide with enemies, and when we make enemies that shoot, with the player. Next they have power. This is done so that powerups can make the player’s projectiles stronger.
We also give the projectiles maximum speed, range, and acceleration. This is also for handling upgrades and how different weapons on different player ships or characters will work. We can have a short range, fast moving projectile. We can have a long range projectile that starts slow but speeds up over time which we handle with the Projectile’s Update method. Whatever we want.
The reason we separate the projectile type attributes out is so that we can store each character’s projectile type in their character class.
Now we want our player to be able to make some kind of projectile when the space bar is pressed. We are going to give the player character a type of projectile to fire and limit their fire rate. The idea is that whenever the fire key or button is pressed, we will true to the game engine and it will create a new projectile at the player’s location.
First we need to pass in a ProjectileType as part of the Character class constructor.
And modify the Character class to have a ProjectileType
Now we are going to add a projectile creation function for our game, and set up the SPACE bar to be our firing control.
You should be able to “fire” bullets now. Currently we are not restricting how fast you can fire, which means you can use bullets to draw a line on the screen. Our next step is to limit the players fire rate. We will do that by giving characters a last fired time as well as giving projectile types a rate of fire.
Start by updating the ProjectileType class.
Then in the Character class, lets add a method that determines whether or not a character can fire.
Finally, add the check for whether the player character can fire or not in our games OnUpdate method. Also we are going to make some small modifications to the CreateProjectile method
Your player’s character should now be firing little light blue bullets about every half second if they hold down the space bar.
Projectile Collision and Damage
Now that we can fire projectiles, we want them to actually hit the enemies and do damage to them. This means we need to modify our CustomEngine Class OnObjectCollision method to tell enemies to be damaged by projectiles and to set projectiles to destroyed when they hit enemies. While we do that, we will also refactor our other collision code to make it cleaner.
We also need to remove all projectiles that hit enemies from the game, so they don’t hit enemies twice. And since we are not currently calling the projectile’s Update method each loop, acceleration will not work yet. Let’s add that in as well as we loop over the projectiles.
When you run the game now, bullets that hit enemies should disappear and enemies that take enough damage should be destroyed (at this point red enemies take 1 damage, green take 2, and blue ones take 3).
For the final part of this section, we are going to give the player points whenever he destroys an enemy. To do this we need to assign each enemy a point value, we don’t want those tougher enemies to be worth the same as the weak ones.
To do this, we are going to store a point value in the Character class. The player character won’t use it and that is just fine. We will also make a method for increasing the points earned. Then whenever an enemy with 0 health is destroyed we will give the player that many points. The reason we are checking the health is that soon we will be removing enemies that fly off the screen to keep game performance up.
Now we need to modify the Enemy and player creation code to include point values in the constructors.
Now lets add a check in OnUpdate when we destroy an Enemy to increase the player’s score if the enemy’s health is 0 or less.
Now whenever we destroy and enemy, our players score will get updated. But we can’t see what the score is right now. Our next step will be to draw the player’s score on the screen. We will do that my adding a text draw to our OnRender method to draw the player’s score in the upper left hand corner of the screen.
That wraps up projectiles and scoring for now. Our next step is to be able to actually end the game when the player takes too much damage and to add some other game states.