Introduction

I always loved roguelikes even before I knew what was a roguelike. My first experience with that genre was with Azure Dreams for the PS1, and I spent hundreds of hours struggling level after level of its Monster Tower.

That first experience with a roguelike shaped my tastes for the games to come, choosing Dark Souls or any ‘hardcore’ rpg over any AAA title. It also shaped my process of thought as a game developer.

With that, it was inconceivable that I had never even tried to create a roguelike… and here we are.

With Unity, 3D game programming is far easier than before, leading to interesting possibilities (and why not a 3D roguelike?). So, taking advantage of my first roguelike prototype, I’ll be writing a tutorial with my efforts to help other people tackle the same issues I’ll be facing.

Let’s start!

Edit: HERE’s the unity package for the full project. Take a look as you follow this tutorial.

QuadTree Generation

There are mainly two ways to do dungeons : Design them manually with a 3D modeller, 2D tool, etc; or create it procedurally. The first option let’s you take control of the scenario, its room distribution, design, details and pacing; the second option creates random layouts and procedurally generates a (technically) infinite and unique dungeon. We are clearly doing the 2nd option :D

There are multiple ways for generating your dungeon, but the usual one is using a BSP Tree, like the roguebasin wiki says. We’ll be using a tree, but with 4 childs in each node instead of two, thus making use of a QuadTree. Each zone generated by this QuadTree will be the container for a future room, and later we will connect each room with the neighbour zone room.

Knowing that, let’s look at the code!

Our code will be composed by a series of C# files, as follows:

XY: A [x,y] coordinate.

AABB: A boundary or area definition.

QuadTree: Contains the QuadTree definition and the methods for its generation.

Tile: The tile definition.

DungeonGenerator: The only “script” we’ll use. Attached to any GameObject in the scene. It sets the dungeon generation parameters and starts it.

We’ll go from simple to complex. Our XY class is quite straightforward:

XY.cs

It just contains a float x, float y, and some helper methods. Nothing to see here.

AABB.cs

An AABB is just composed by a 'XY center’ and a 'XY half’. These variables denote its position and dimensions in a 2D space.

QuadTree.cs

Here begins the magic :)

A QuadTree is first construced using an AABB (a boundary of sorts). A QuadTree may be defined as a “sector” which can contain another four smaller sectors, and so on. That means that our QuadTree class can contain four other QuadTree instances.

If we wanted to divide our QuadTree in exact pieces, we could just create four new QuadTrees, one for each quadrant, and repeat the process for each quadrant. That would give us something like this:

Pretty boring, uh?

If we put some random values for each QuadTree’s size things are more interesting.

We calculate a random slice inside the QuadTree boundary. If each quadrant that results from the slice is big enough for our future room’s size, create a new QuadTree on each quadrant. If it’s not, let’s try to calculate a new slice. Do this using some limit on the depth of the QuadTree, add some randomness on when to stop, and you already have the first step of your dungeon generator.

Here’s the result:

Tile.cs

This class is quite empty right now. Our future dungeon will be made of tiles, and the contents of each tile will partly be decided by the results of our QuadTree.

Right now, it contains an 'ID’, and defines two types of tiles: Empty (understood as a wall) and Floor.

DungeonGenerator.cs

This script is attached to one of the scene’s GameObjects, and let’s you start the generation of the QuadTree.

It also contains the definition of the dungeon TileMap, that we’ll fill later with the contents of the QuadTree. It also maps the QuadTree generated “test texture” onto a Plane GameObject in our scene.

And so we end this tutorial!

I’ll write again next week with Part II, where I’ll explain how to place rooms, corridors, and do some neat stuff.

Feel free to ask any questions or give some feedback.

Regards!