top of page

Randomized Generation of 2D Dungeons

1
2
3
4
5
6
7
8
Image Not Found

Procedural Generation of the dungeon:

 

The core of the game is based upon procedural generation of the path on which player can play. So, the player faces different maze each time. Procedural Generation is explained in the following section in detail.

 

 

What things are procedurally Generated?

  • The playground and inner walls of the map

  • The rooms (rooms are technically absence of a wall)

  • The hallways connecting between every two rooms

  • Player start

  • Player destination

  • Resource encounters(Mushrooms pickups)

 

 

Let's see each thing in detail:

 

  1. Playground and inner walls:

The generation begins with laying down of a grid. The grid by default is 100 units x 100 units. This gives us around 10000 vertices to play with.

The grid is internally a 2D Array. The square in each grid has a center point. The walls are made of a 2D sprite and each wall sprite is spawned on this center point. The placement of grid starts from the origin (0,0) and moves in +x and +y direction, i.e. in positive quadrant of a graph.

 

 

  2. Rooms

 

The rooms are technically absence of walls in 3D space. However, in 2D space, it is a series of textures in roughly rectangular shape. Each room is held in a custom data structure like a struct.

This data structure contains info about each of the rooms. The information includes following.

  • Rooms starting location in X and Y coordinate.

  • Size of the room (width and height)

  • A direction for the next hallway (North/East/West/South)

 

The minimum and the maximum number of rooms is given by the player. The number is taken as a range and a random number is generated between those 2 integers and it's our final room count.

First room nearly starts in the middle of the playground. This avoids rooms and hallways running out of the playable area. After first room’s location is randomized then according to its height and weight, the rooms floor tiles start to spawn from that location until height and width of the room are not filled.

Core loop of rooms placements:

 

     void SetTilesValuesForRooms()

         {   

             for (int i = 0; i < rooms.Length; i++)

             {

                 RoomData currentRoom = rooms[i];   

                 for (int j = 0; j < currentRoom.roomWidth; j++)

                 {

                     int xCoord = currentRoom.xPos + j;         

                     for (int k = 0; k < currentRoom.roomHeight; k++)

                     {

                         int yCoord = currentRoom.yPos + k;                 

                         tiles[xCoord][yCoord] = TileType.Floor;

                     }

                 }

             }

         }

    3. Hallways

 

Hallways are entrances and corridors connecting two rooms. After rooms are placed, one of the 4 directions is chosen randomly (North/East/South/West). After the direction is chosen, the hallway sets its starting position to the edge of the “previous” room and then continues in only either “X” or “Y” direction. While moving forward it lays down the same floor tile as a room. This gives us an effect of a corridor in an art-friendly way (because we don’t need special art for corridors if we are using the same tile as a room).

 

 

Core loop for corridors chosing direction:

 

   void SetTilesValuesForCorridors()

    {

        for (int i = 0; i < corridors.Length; i++)

        {

            Hallway currentCorridor = corridors[i];        

            for (int j = 0; j < currentCorridor.corridorLength; j++)

            {          

                int xCoord = currentCorridor.startXPos;

                int yCoord = currentCorridor.startYPos;

                switch (currentCorridor.direction)

                {

                    case Direction.North:

                        yCoord += j;

                        break;

                    case Direction.East:

                        xCoord += j;

                        break;

                    case Direction.South:

                        yCoord -= j;

                        break;

                    case Direction.West:

                        xCoord -= j;

                        break;

                }           

                tiles[xCoord][yCoord] = TileType.Floor;

            }

        }

    }

 

 

 

4. Player Start, player destination and resource allocation

The player start is calculated based on the number of rooms being drawn. Usually, the player will be chosen to spawn while the first 20% of rooms are being drawn. The player destination, however, is calculated when the rooms are almost done drawing. Usually the castle, which is the player's destination will be spawned after 80% of the rooms are drawn.

Resource allocation is a little bit tricky. Current procedural generation cannot guarantee a fun and noncomplex maze. Thus, I have made plentiful resources available for now. Each room has a 30% chance of spawning a single mushroom in it except the start room.

 

 

 

 

Positive points of this architecture:

 

The rooms are linearly drawn thus, there is a high chance that the rooms can overlap. This results in an interesting maze because overlapping rooms are subtracted from each other which gives us a complex room instead of just a rectangular shape.

 

 

Negative Points of this architecture:

 

The overall look and feel of the dungeon/maze is a little bit dull. The rooms start as a rectangular shape and they don’t give us complex shape unless they overlap. Thus sometimes it feels boring to play even though the dungeons are generated differently each time.

 

 

Problems I faced and things I learned:

 

I had decided to go with Binary Space Partitioning algorithm. However, I wasn’t aware of the limitation of the pointers in C# scripting. I learned that C# is a managed language and the pointers are not a good way to implement a data structures like a Tree in C#. Tree data structure is the core of BSP algorithm. Thus, I decided to move on my own simple custom algorithm to generate dungeon linearly.

 

Project Name: Randomized Generation of 2D Dungeons

 

Technology: Unity Engine, C#

 

Type: Solo Project

 

 

Description:

Recently, our beloved Mario lost a bet against Bowser and he felt so bad that he started drinking. He started to spend his nights outside his castle and now his princess is worried about him. So, the princess gives us the task of bringing him back to castle from a bar. Beware, he can be easily disoriented if you are trying to cut corners and then he will lose his sense of direction. Hopefully, you might find some mushrooms in his pockets which can bring his senses back. Good Luck on your adventures!

bottom of page