In which we spawn enemies, and have them die when out of health
Up until now, we’ve only had a single Walking Enemy and Trap Enemy each, hard-coded in our “Game” class. Not only do we have no means of spawning more, but the Walking Enemies don’t die when they run out of health.
In this lesson, we’ll change that.
Once again, this is mostly game-logic, which I intend to skim over.
To start with, two minor changes in “GameObject.py”. These simply have the Walking Enemy play a “spawn” animation when its constructed, and skip the behaviour in “runLogic” until the “spawn” animation is done:
Now, on to “Game.py”.
First, delete the code related to “self.tempEnemy” and “self.tempTrap”, in both the “__init__” and “update” methods.
What we’re going to do is keep a few lists: one of enemies, one of traps, one of “dead enemies” (so that we can clean them up, but only after they’ve finished animating), and one of spawn-points for enemies.
The spawn-points will simply be positions spaced evenly along the walls, and when spawning an enemy, we’ll randomly choose one as the location for the new enemy.
Traps will be placed at the start of the level. They’ll similarly use a list of positions, but, to prevent the placement of two traps in the same spot, we’ll remove positions as we choose them.
We’ll also create a new “startGame” method to contain the logic for the spawning of traps, creation of the player, and a few other things. While not terribly useful just yet, it will come in handy once we add the ability to restart the game when the player-character dies.
Next, we’ll add a method to clean up a level once we’re done with it.
Furthermore, it might be a good idea to clean up not only when starting a new level, but also when exiting the game. To that end, we’ll tell Panda that, when the user indicates that they want to quit, we want to run a custom exit-function. This function will run our new clean-up method, then quit.
If we run the game now, we’ll be able to move around as before, and we’ll have traps scattered randomly around the walls. The traps won’t, however, move. (Because they’re not being updated–yet.)
Next, we’ll add a method to spawn an enemy. This is pretty straightforward: pick a spawn-point, create an enemy at that point, and add the new enemy to our list of enemies:
And finally, we’ll implement the logic to make it all do something. In short, the logic looks something like this:
If the player isn’t “None”, and has health, run this logic.
Update the player.
Count down the spawn-timer; if it finishes, attempt to spawn an enemy, and reset the timer.
Update the enemies and traps.
Find enemies that have just died. For each of those:
Exclude them from the list of enemies
Remove their colliders
Award to the player their score-value
And add them to the list of “dead enemies”
If there were any dead enemies, update the player’s score-UI.
Check the “dead enemies” to see if any have finished animating their “die” animation; if so, remove them and clean them up.
And finally, run the difficulty timer down; if it finishes, make the game a little more difficult by increasing the maximum number of enemies, and decreasing the time between spawns.
In code form:
And now we have something like a real game! Enemies spawn and attack us! Traps destroy player-character and enemy alike! We can even gain points for each enemy defeated! And when at last we fall to the endless horde, play stops!
It… is all a bit quiet, however, isn’t it? Perhaps some sound and music would help…