I figured I should give a brief explanation as to how I’m generating the levels in RetroRaider.
This might become a regular series, so if you find this stuff interesting, be sure to let me know in the comments or email or twitter or whatever..
For RetroRaider, the map is split into an 8×8 grid, and each of those are split into a top and bottom. For the sake of making things easier on myself, I decided to make an 8×16 grid.
Within each of the grid positions, I’ve created 3 sections. A left, a middle and a right.
Each of those can hold a single item, be it a wall, a hole to the floor beneath, a ladder to climb up, an enemy spawn point, a collectable, or anything else that I might throw in.
This means, onscreen, there’s a maximum of 6 objects at a time.
I know this isn’t a lot, but this game doesn’t need a lot of things onscreen!
Everything is plopped into a simple array.
An X reference, a Y reference, and then 3 splits inbetween.
( (y*8) +x ) *10
The y being our y reference, multiplied by how wide the world is (8), add an x reference, and then multiply it so we have 10 value slots per grid reference.
Those values are currently (as I type this..)
0 = Background sprite
1,2,3 = Object within each of the 3 split areas.
4,5,6 = A slight randomiser to offset the x-position of the objects, so that they look a bit more random than always being stuck in the same static position.
7,8 = Reserved for possible future usage!?
and 9 = Whether the player has been in this room. (Which I use when drawing the minimap, later.)
Filling the Grid
So, with all this in place, I start by emptying the map completely, then doing a first pass of walls.
Each y layer gets a random number of walls, up to 4.
for y=0 to 15 ' Layer
LayerBackground=Rand(0,8) ' Random Background for the whole layer.
for n=0 to 3 ' Number of walls.
grid[(((y*8)+x)*10)+x2]=1 ' Where 1 is a Wall!
After the wall-pass, I do a second pass for adding holes, where holes can exist anywhere where there’s not a wall beneath, and also avoiding adding holes to the bottom-most layer.
Next is ladders, which are again placed avoiding anything above them, and ignoring the top-most layer.
All three added together makes for a nice sprinkling of rooms, with layers that match up, and everything fitting together well.
Running the Grid
Once done, I create a random player which starts from the main player’s position, and runs around the map at random. He/she runs in direction D, randomly turns around at specific intervals, turns around at walls, and randomly decides whether to use holes and ladders to move up and down the level.
The pseudo player’s path is recorded, and after a predetermined number of moves a rough score is awarded, based on how much area the player’s been able to move around.
If the player ends up getting stuck between two walls, for example, the score will be low.
Too low, and the whole process restarts, with a brand new level being built, and another pseudo player running around.
If the score is high enough, the level is determined to be “playable”, and that’s when the generator starts to sprinkle in the enemies, the pickups and other such objects.
All in all, it’s an incredibly simple process, and isn’t anywhere near as complicated as I’ve previously worried it might be. (The main reason I haven’t previously tackled automated levels in a RetroRaider game.)
Whether it makes “good” levels or not, remains to be seen.
I still haven’t finished off the generation to the point where full levels are playable, or have a proper goal.
I might add extra walls around the levels to ensure the player sticks to the pseudo-player’s path, or maybe I’ll leave it as a freely roam-able arena.
As with most AGameAWeek things, the end result will depend entirely on how it actually plays.
Anyway, I thought I should post this. It’s an example of something seemingly complicated being much simpler when looked at in the correct way.
I’ve built a lot of these generators over the past few years, so if you understood what I’ve been waffling on about, and if you’d like to see more of these types of posts, let me know!
I hope this was helpful to someone!!