[Archives] Learning Random Generation

Archives, Game Development

Little Ghost Flower was both a technical experiment (I wanted to test a certain feature in Construct using masks, and it turned into a game) and also an opportunity to learn something I had never done before: random map generation.

I learned a lot, but I also did a lot of things poorly, so let’s dive in and see how things went.

I started by creating bounds within which the spawn point would be created, and moved that randomly each time a new map was generated.  I placed the Church sprite directly above that, so the player will always know where they spawned (and where the ghosts will come from)
I then created a “creator” block that would move around in a random direction, with the tendency to stay facing the direction it was currently moving.  Every time it completed a movement, it would spawn a “path” block in its place.  It does this until there are 100 “path” blocks. Here’s where things started to go sour: I was creating a lot of objects.


Each “path” block would, when created, spawn four “wall” blocks; one on each side.  These would later become the collision blocks for the characters.  Each “wall” block would destroy itself if it were overtop of a path (because we don’t want random invisible walls on paths), and then spawn “ghostwall” blocks in a specific formation to allow for a mechanic I will explain later.

Obviously this is WAY TOO MANY OBJECTS to just be lying around acting as walls.  To remedy this, I created a TileMap object, which is like one big object containing lots of small sprites, which you can paint into place like pixels.  These are really good for backgrounds, since they’re optimized in order to cause less draw calls and collision calls.  If you want to read more about that, Scirra has a blog post on the subject.  
As soon as 100 “path” blocks were created and the loop spawning paths was over, each path block would change the tile on its position on the TileMap to be a path sprite.  These sprites would then sort themselves in order to create the outlines at the edges and corners of each path.  The “path” block would then destroy itself, having served its purpose.


For a while it stayed like this, until I realized I could make another tilemap for the ghostwalls, since tilemaps calculate collisions in a much better way than lots of individual sprites.  Tilemap tiles that don’t have a block set to them are empty, and do not have a collision, while tiles that have a block set will find nearby set blocks and group them together for one collision rectangle.  So for each ghostwall, I set the tile at the position of the ghostwall to be full, and all others are unset.  This cut down on hundreds of individual objects, condensing them into one tilemap.
Unfortunately I could not do the same for the regular walls, as these depend on the positions of the objects to calculate collisions.  I should have experimented with a much better way to do this, but in the end it did not impact performance too much, so I left it.

The ghost walls are spawned in such a way that they will prevent the ghosts from leaving the same path as the human characters, except in the case of being directly next to a flower. When the player plants a flower next to the edge of a path, it deletes the blocks directly around the flower so the ghosts can find a way to each side of the flower.  However, if the flower is in a corner, this leaves the possibility of opening up a hole in the wall.  So the ghostwalls also spawn at a diagonal between walls.  This leaves some straggling walls floating out in space, but it also prevents holes from being opened up when a flower is planted in a corner.


Continue to Page 2 for more.