How I Created a Roguelike Map With Procedural Generation

Tulio Allan Marks
9 min readOct 25, 2020

First things first, let’s take a look into Wikipedia definitions:

“Procedural generation is a method of creating data algorithmically as opposed to manually, typically through a combination of human-generated assets and algorithms coupled with computer-generated randomness and processing power.”

In simple words, it’s a way to generate rule-based random content for our productions. Those rules could be of any kind, a mix with fractals, Perlin noise, Voronoi diagram, step by step “fixed rules”, or our own rules. The important here, at least I think that, is to be creative. In productions, I like to include video games, board games, novels, videos, music, images, art, and experiences at all.

To illustrate better what Procedural Generation is, I want to show you some examples.

A little bit about the past…

This subject isn’t new, we can see that in the old school games like Simcity 2000, Diablo, and XCOM: UFO Defense (one of my favorite ever). In those games, it’s easy to see how every new play has a different map generation, or a set of missions, or attributes for your weapons, for example.

In the case of Simcity 2000, we can define some parameters before the generation of the map occurs, click in the “Generate” button, and see the many different results each time. To be more specific, some of those parameters could be the level of water, with rivers, with ocean, mountains or not. With this kind of approach, an infinite count of new gameplays could be generated, any of them with different aspects, challenges, and game features to explore during the play.

Another very exciting example is Spore because this game uses procedural generation in a vast scope of content like creatures, creature animations, and entire planets. We can save a lot of time and hundreds of megabytes in the game build if we compare the number of models that can be reached with procedurally generated content, to the number of pre-made models. On the other side, more time to define and develop those algorithms will be needed.

I can’t finish this example section without quoting No Man’s Sky, in this game the expression “vast scope” is too small to express how far the developers go, generating random trees, creatures, biomes, civilizations, planets, and the cosmos. YES, the game universe with quintillions of planets (I don’t even know how much zeros that number have). But, the interesting here is, those planets weren’t generated in-game, at runtime. They were generated before, but yet procedural generated, then the players can discover all of them (sure kkk) during the same gameplay experience. Think, how nice could be to name a planet and another player finds your named planet! When you have quintillions of planets! Now, the game in terms of exploration is very engaging, because the developers added the multiplayer option. So, let’s explore the quintillions of planets together.

With those samples, we can note the procedural generation is vastly used in game development. From my experience as a gamer, I think this kind of approach can extend the gameplay and bring some kind of uncertainty about what will happen in the game. Then I can play the game several times and each time the experience will be unique, or almost unique, for me UFO: XCOM Defense represents greatly one of those cases. I played several times, then I stopped to play another game. Sometime after I came back because I knew that I could find new uniquely fun times again, and I was right. Then a lot of years after, the new version, XCOM: Enemy Unknown, arrived, and again I was happily playing and playing, and always trying different strategies in the battles.

The game: HoaderLike

Months ago, I found myself thinking about procedural generation, for some reason this subject comes and goes from my mind. At that time, I was playing Enter the Gungeon and was always looking at how that could be improved, then I decided to give it a try and one more time go on an adventure: “Let’s create my own roguelike WITH PROCEDURAL GENERATION”.

After some internal brainstormings and dream-ideas, I started a Game Design Document, talked with my brother-in-law, added more ideas, got some references from movies and art concepts from Pinterest. The HoaderLike roguelike started to gain form.

HoaderLike is a 2D roguelike game based in an apocalyptic future, where the raw resources aren’t easy to find. As a player, you are a scientist-crazy-inventor and need to defeat a company that controls everything. That call came when you saw the cabinet empty, without toilet paper to do your stuff, and decided something needed to be done, like a divine call (if you are imagining this scene add the holy lights kkkk).

The gameplay is basically a loop between an action scene, where you need to fight with robots, collect material to upgrade your exosuit weapons, and a garage scene where you can improve yourself to the next run.

… from scratches to first idea …

The first part of the procedural generation that I’m developing for my game is the map generation. To do that I took some references and ideas from the XCOM game and imagined some kind of grid structure.

A Plot is a component like a grid, where each cell is named Area. I called Plot and not grid because in my idea, each plot will be a “scene” of the storyline. Basically, will happen some boss encounters, a challenge to get an important item, maybe some puzzle, it isn’t clear for me yet.

The objective behind the areas is to create the variations of the Plot using pre-made tilemaps, and put those into every area. So, a plot have a random size, not less than 3 areas, and not more than 5 areas. After the first implementation and tests, I decided those numbers were exactly what I had in mind in terms of space for the gameplay, it’s a similar concept to a room in the roguelike game-style.

To choose how each plot will look, thinking like what kind of biome the plot will be, I put a property with the “Type” of the plot. The context of my game is a city, so to feel more trustable, the plot’s type could be cross-roads, or avenue, residential, or industrial. I applied this same concept to the areas, where each area could be a road, construction site, building, park, or just an open space.

Now, we know almost everything to start to see how I implemented that stuff, just one thing left, Prefabs! This component allows us to configure a group of other components that define an area. For example, for an area of type “building”, I planned to create 3 or 4 different prefabs. In that way, we will have an interesting mix of plots to be done, giving some kind of randomness. The interesting thing about Prefabs is that I can extend those to create more and more different content.

… How I implemented it …

Let’s work! But before I start telling you about the implementation I want to say this isn’t a tutorial, it’s more of an experience report.

Said that I used Unity with C# language to develop everything, but certainly you can create it in any other framework and language that you want to use.

I started writing the classes for Area and Plot like described. Here you can see that I added a property Position, it will be used to store the X and Y position in the plot.

In the Plot class, I added a list of Area and Position, but I didn’t use it at first. Also added AreaSize to help me to render correctly the tiles. At this point it is important to say I used a component from Unity called Tilemap, this provides an easy way to control what will be rendered using tiles in a grid. To start I defined the size of 8x8 tiles per Area.

Let’s jump to the process, it occurs in 3 steps and I created the classes PlotFactory and PlotRoadVerticalFactory to help with this, see below:

  • First, create the Plot class: define a random size between 3 and 5 of width and height. And receive in a parameter the Plot type (I didn’t define a way to randomize that). To help I create the PlotConstraints class.

MinMaxI(int min, int max) just stores the min and max values to be used in the future.

  • Generate the Areas for the plot: the PlotRoadVerticalFactory.Generate() is where part of the magic happens. In the concept of PlotRoadVerticalFactory, it is responsible to generate a Plot with a vertical road, during the development I had an idea to add an entrance and an exit so I had put 2 other areas outside the original size, something like what shows in the image below.
  • Add the plot’s definition to the World tilemap: this step takes every prefab defined in each area and copies it to the World Tilemap, in this line:
TileMapUtil.CopyTo(area.Prefab, WorldMap, areaOffset);

The correct position of each area is calculated using the offset variable, which is defined by the area position multiplied by the number of the tiles (AreaSize). To finish it, I put the player into the entrance (not important in the procedural generation context).

For your life … new inputs = exclusively outputs …

In the implementation, it’s possible to see some parameters that can be changed to get different results. Like the size of the plot which inflicts directly to the numbers of areas generated, and looking from a bigger picture, it inflicts directly how can be the gameplay, long or short, a lot of to explore or not, more or less difficult to find an important item, more or less space to fight with the bosses, and several others.

To the infinity and beyond …

After this code, I added some controllers like player movement, gun control, and enemies, then you can see the results in this video or in this PLAYABLE VERSION in Itch.io.

For further reading, I already planned a second article with the next iteration of improvement on this code. The plan is to generate multiple plots with multiple exits e more generation parameters.

Before you go…

Hope you enjoyed this reading and that have given insights to you to go further with your development.

Feel free to comment, add suggestions and questions.

You can follow me on Itch.io or Youtube and connect on LinkedIn.

--

--

Tulio Allan Marks

Engaging others, through digital experiences, to collaborate to improve organizations, cultures, and the environment.