Today I am going to talk about how my spawning system has evolved. It first started with a Spawn object, who’s main job is to display spawning related information to the player; such as where the enemies will be spawning from. The key thing to note is that the Spawn object does not spawn enemies. It is given a spawning component which tells the game when it is time to spawn an Enemy object; I will talk more about components in a future post. I pick this design because I wanted a lot of flexibility when it comes to spawning enemies.
My first spawning component was the easiest thing that I could think of. Basically it would spawn a Enemy object of type X, at a regular interval. Example: spawn weak Enemy, every half a second. The goal was to get something playable very quickly; knowing I would improve this later.
For my second iteration, I wanted something similar to other tower defense games. Such as spawning waves, notification that enemies will appear, and indicator of what type of enemies will be spawning. I created a SpawnWave component that held a collection of Wave objects. The Wave object holds a collection of enemies that would get spawned and some metadata about the Wave. The SpawnWave component would go through and figure out when a Wave should start, and then the Wave object would iterate through its collections of enemies and spawn them. The SpawnWave object would hold a bunch of Wave objects, and remove them when they are finished.
This worked well at first, but as time progressed I wanted more control over spawning. I had an vague idea of what I wanted, but wasn’t sure if it would be worth the time. It was only when I was trying to fix a bug in SpawnWave, that I decided that this code was a bit too complex and that I should try the new idea. My thinking was some type of a event based system, where I have a collection of events that are fired when their time is ready.
For my third iteration, I created a SpawnEvent component that holds a collection of Event objects. Event objects has a spawn time as well as a method to be called when it was time to be activated. I was surprised how simple and smaller the SpawnEvent code was compared to SpawnWave. Note for the design pattern junkies this is command (Event) and event queue (SpawnEvent) patterns.
At first I only had one Event, which spawned an Enemy object. I shortly realized that it could do much more. A Event could spawn a group of enemies, it could display a message to the player, it could give the player money, or even cause them to win the game. The possibilities are basically endless, and so far fairly easy to implement (hopefully it will continue to be so).
But all is not great in event system land, with power comes responsibility. In giving the designer this level of control, it also means they have to keep track of more stuff. Such as making sure Events fire at the right time or making sure they don’t forget to add a important Event. I had one issue where enemies would be spawning perfectly, and then all of a sudden a bunch enemies would spawn on top of each other, looking as if only one enemy had spawned. Can you guess what the problem was?
The problem was I had a bunch of Events in the middle of the SpawnEvent collection who’s spawn time said they should spawn at the start of the level. Since they where in the middle of the collection, SpawnEvent would see a bunch of Events, where spawn time was less then simulation time and trigger them all at once.
Overall I am pleased with how the spawning system has turned out. The components allowed me to quickly test ideas. I was able to come up with a really simple and easy to use code. Makes me wonder why I didn’t think of this at first. Maybe that is a sign of good design?