My First Ludum Dare Part 2 - Map Generation

This is going to be a bit more of a technical dive on the map generation in Cacophony.

I got a bit carried away so this post is a bit long but I hope its informative!

Map Generation

Procedural generation of maps is arguably one of the most iconic properties of roguelike games, because of this we had to make sure we got it right. As I had some experience creating a similar script in a previous unity project this task fell on me.

So I got to work.

The generation in our game is based on the methodology from a popular roguelike tutorial using a python library called libtcod. The basic process followed by this tutorial is as follows:

  1. Fill the specified area with walls
  2. Carve rooms out of this area by deleting walls and placing floors in rectangles
  3. Connect the current room with hallways
  4. Determine what type of room has been generated and place the proper extra characteristics within the room
  5. Repeat for the specified number of rooms

There was, however a few issues with using this tutorial namely:

  1. This tutorial is meant for python, not C# and especially not Unity
  2. This tutorial represented every wall with the same “Sprite” (really a character in most cases)
  3. While I am sure they get to it eventually, the section I read did not have different types of rooms generated

traditionalRogue.png         More traditional roguelike couresty of my co-developer Scott

ourMap.png One of our generated maps

Our Implementation

There are 3 main classes involved in the generation of maps in our game

GridGenerator.cs – Handles the generation aspect

MapInfo.cs – This is a scriptural object that contains variables used to generate the map, stores information such as the x and y bounds, the current tileset, and the list of enemies to be spawned in this map

Map.cs – This class contains static dictionaries used to reference the different tile layers using their (x,y) coordinate as a key. This class is responsible for populating these dictionaries after the game has been loaded.

If you’re interested in seeing the code in full for these classes click here

There is also a Rect class that handles some aspects of the room generation, but I don’t feel this is a good implementation in its current form and would recommend against our current setup.

GridGenerator.cs

For the most part, this class follows the tutorial linked above to a tee. Below is some of the code that had to be handmade to have our display work properly. Essentially all this does is place the proper sprites on the edges of the room so that they can visually look better than just having a flat wall sprite.

gridgen.png

It’s game jam code, go easy on me

Further down, in the GenerateMap() function we have another slight deviation from the tutorial script. We wanted to generate different types of rooms so we could have stores, traps, exits to a further floor, etc. The counter is basically a hacky way of making sure that we always generate one and only one kitchen, store, and exit.

the room variable is the room we are currently generating, this function will be called after the room has been carved out and hallways generated.

roomGen.png

I can’t explain why the usage of that counter – switch statement combo feels wrong but it does…

The functions being called on the room object belong to the Rect class, I am not sure is the best way to break up this code but it’s what we came up with in the time allotted.

I’ll only show a few examples so you can get an idea, because this is most likely the messiest code in the entire project.

diffRooms.png

Believe it or not, this is some of the better code from this section

Now, if you’re reading this in hopes to learn how to do some map generation please do not copy and paste this code, it is ugly ugly ugly and one of the first things I will be refactoring but it got the job done for the time we had.

MapInfo.cs

MapInfo is a Scriptable Object class, if you don’t know what that means I spent my first post on this blog talking about them! Alternatively, you can go straight to the resources I learned from this excellent blog post by Daniel Ilett.

To sum it up real quickly scriptable objects are a Unity class that are very good for storing data independent of game objects and with very easy serialization.

Here’s what our usage of them looks like:

mapinfo.png

The entirety of this class

The first section of variables lines 9-15 contains some general information about the map that will be useful to players,enemies and the grid generator.

All of the variables here are pretty self explanatory, the tiles and enemies are fed into the grid generator so that it knows what tiles to use and the boundaries determine where the map starts and stops generating.

What this allows us to do is create a Unity asset entirely in the editor for each different tileset and set the enemies and dimensions in there without changing any code at all!

unity.png

An example of what this object looks like in the Unity inspector

This is one of the better design choices we made during the jam as it allowed our map generation to be flexible even for our team members who did not know how to code.

Map.cs

This is the class that glues this whole thing together to work in our project.

It contains two dictionaries with every relevant tile that we can then access using the tiles (x,y) coordinates. This is how we handle movement, combat, and interaction with special objects.

What this class does is quite simple but the implementation can seem a bit confusing.

getTiles.png Thank God for stackoverflow

What happens is the tilemap object has a collider that scales when a tile is placed, we use this to get the x,y bounds of an this object and then we iterate every x,y position in world space and create a MapTile object (This is a data class that I will likely rewrite soon) and store it in the dictionary.

Most of the time when we reference this dictionary we are checking whether the requested tile is a floor or a wall.

Wrapping Up

All in all, I don’t think this seems like the most complex take on map generation I have ever seen and it is really a stringing together of different tutorials until we had something manageable. But it worked well for our game and most importantly we were able to get it done in the time frame we had.

This is a section of the code I spent a lot of Ludum Dare working on, and as we continue to develop the game I have no doubts this will continue to be the case.

Yes you read that right, we are going to continue developing Cacophony because we’re all having so much fun working on it.

The first update will release the same day Ludum Dare voting ends May 12th.

space.PNG

Cacophony: The Ballad of the Celestial Goblin-King is a procedurally-generated roguelike dungeon crawler created in 72 hours for Ludum Dare.

The first update to Cacophony will be released May 12th.

You can try the game in your browser here.