This article continues on our previous article (which can be seen here: http://www.duckbridge.nl/a-spawning-system-that-keeps-our-game-interesting-p1/ ). I recommend that you check that one out before this one, because it goes over the general idea of our spawning system for 15min Max (http://www.newgrounds.com/portal/view/641800).
(I do recommend checking out the first article and the game, so that you can get a general idea of the spawning system)
In this article I will talk more in-depth about our spawning system and provide some (pseudo) code with explanations to give you an idea of how it was implemented, the pseudo code given is not all the code, but it is the code that is more or less needed to get this to work.
So as I mentioned in part 1 there are three spawners; the base spawner, the normal spawner and the override spawner. I’ll start with the base spawner, this spawner serves as a base class for the other spawners (normal & override).
For those who don’t know : the list with all the rooms is public because we use Unity, and Unity allows you to fill the objects in the list from the editor.
This class is the Spawner class, and is the base class for the spawner(s) in our game, many of the functions are virtual because that allows the sub-classes to override them (but I will get into that later).
The interesting part of this class is the Spawn function; the Spawn is the only function that is not virtual. This is because the spawning should work the same for all spawners. Only some details of the spawning can be tweaked (hence the virtual GetRandomRoomType and FindRoomForRoomType).
But what the Spawn function actually does is, it uses the two functions to find a random Room Type and use that Room Type to find a Room object that belongs to it.
If (for some reason) a Room cannot be found with that room type by using the FindRoomForType then it just tries all the rooms and tries to find one that matches (this was very usefull during development because we didn’t have all rooms and stuff).
After it finds the room it basically spawns the room inside the game and it unloads old rooms.
The Room class is the class that belongs to all the rooms that Max runs through in 15minMax. The class itself is actually quite simple. It does contains some variables which are used by the sub-spawners so I’ll go over the Room class now.
You can see that the room level for each room can be set in the editor but also the score that they require to be spawnable.
The most interesting parts of this class are the OnRoomEntered() and OnPlayerExittedDoor() functions (these allow for custom behaviour (because they call the ExtraOnExit/Enter functions, which are virtual) . One way we use this is to control the behaviour of the clicking in each Room.
So now on to the first spawner, the ‘normal’ spawner, this spawner is the spawner that is used in the game (when we’re not testing). This class is a bit bigger so it will be exlained in parts.
The Normal Spawner can be seen above and the FindRoomForRoomType function is overriden and finds the score for the roomType that is given (You can implement this any way you’d like, we use the ‘RoomTypeManager’).
After we found the Room with that RoomType use the LinQ funciton of C# to find a Room within the list of allRooms with the same RoomType and a requiredScore higher than the room.minimumScoreRequired and lower than the room.maximumScoreRequired.
The GetRandomRoomType function is a bit more complex (or messy ha^^), but it does some interesting stuff.
At first we use the chooseRoomTypeThatStillNeedsToBeUnlocked to randomize the choice to:
- return a random room type that we have already unlocked
- return the newlyUnlockedRoomType, which is a new RoomType which has not been unlocked yet.This value is set somewhere else, we’ll get into that soon.
- return a random roomType which is already unlocked, if the randomRoomType is stil not set (which can happen when the spawner wants to spawn a newlyUnlockedRoomType but it has not been set. (a.k.a bugfix)
The last function of the NormalSpawner is the OnRoomExitted function, which is called when a room is exitted. The OnRoomExitted function is quite tricky/long so I’ll try to go over it as good as possible.
At first the RoomType that has just been exitted is removed from the Rooms that still need to be unlocked (remember the ‘unlocking system’ from part 1?). All the Rooms that need to be unlocked are removed from the roomTypesLeft list untill there no roomTypesLeft left.
When that happens all the RoomTypes that are already unlocked are removed from list with the RoomTypes that still need to be unlocked.
Then if there are RoomTypes left in the roomTypesLeft list, then a new roomType is randomly chosen between them, otherwise a random room type is just selected.
If the chosenRandomRoomType is not unlocked already (so it’s a new RoomType that the player has not seen yet). Then the newlyUnlockedRoomType (which is used in the GetRandomRoomType() ) and that’s it.
(Maybe the code explains it better than words ^^)
So the last component is the Override Spawner which is used during testing to allow us to specify which roomType we want to spawn and from which roomLevel we would like it to start spawning.
And after seeing the code for this you can see that the two virtual functions are very usefull and allow for many different spawning behaviours (Without changing the core implementation).
You can see that this spawner is very small in comparison to the Normal Spawner, the reason for this is quite simple, because we provide the roomLEvelToOverride and randomRoomTypeToOverride through the editor. (Because we already know what we want to spawn, so we don’t need any crazy behaviour for that)
And this made testing SO MUCH EASIER and you can see that the code change is very minimal. And this is how it looks in the editor.
So that’s it! I hope you learned something and can use some of the techniques we applied for our spawner for your own spawner!
I guess that the best part of the Spawner is that the Spawn() function is very core to the Spawner but its behaviour can be tweaked without chaning the core implementation! This will allow for many different kind of spawners and just subclass Spawner and code the functions correctly! (And then you could have some ‘SpawnManager’ which swaps between Spawners and stuff.
Well that’s it! Thanks for reading and if you have any questions/comments, just post them in the comments below, contact us at duckbridge.dev[@]gmail.com or tweet at us : @Duckbridge. (We also have facebook^^)
PS: We’ll release the game to mobile soon, so follow us to stay updated!