Rogue Like Random Maze Tutorial Pt 1

Favourite 27 favourites
Tutorial written by UberdroidGamesOriginally published on 14th, September 2015 - 3 revisions

DUNGEON CRAWLER MAZE PT 1: MAKING THE MAZE

This tutorial assumes you know your way around Construct 2 fairly well. The first part will just get the maze generated and the second part will deal with how to obscure areas of the maze the player can't see.

I'm going to go over how I make the maze for this demo:Rogue Like Maze Demo

Push the Random Maze button and walk around using the arrow keys. I'm only going over maze generation here, I'll do the lights in the next demo.

This is one way to make a random dungeon looking maze. The method is great for "Rogue Like" crawlers, but can be used for many other game applications and takes very few events. It's really the simplest random maze generator I've ever seen.

For the maze, I'm not using the Rogue style room-and-hallways method, but a random maze algorythim similar to the one used to make the mazes in in the 1980 arcade game, Berzerk. It doesn't gaurantee you can get from any space to any other, but you can get from any edge of the maze to any other, so it will always create a playalbe maze.

Here's a complete explanation of how the Berzerk and Frenzy mazes are generated:

Berzerk Maze Generator secret

For more information about other Rogue-like maze generation methods, check out this site:Understanding Roguelike Dungeons

For Graphics, I'm using a couple of tiles and a player object from a public domain tileset available at OpenGameArt.com here:

http://opengameart.org/content/dungeon-crawl-32x32-tiles

STEP 1 SETUP

Adding the WALL Sprite

I just grabbed a brick tile from the Dungeon-Crawl-32x32 tileset linked above.

To add a wall and give the dungeon a pseudo 3D depth effect similar to RPG maker, do the following:

1. Add a new sprite to the layer "walls" using a 32x32 brick wall image. Name it "wall"
2. Duplicate the frame so your wall animation now has 2 identical frames
3. On frame 1 (the second frame) use the rectangle tool with a color black and an alpha value of 50-100 to darken the bottom half of the wall as shown:
Then make sure you set the animation speed to 0.


Add 3 global variables:
DungeonWidth=19
DungeonHeight=13
SuppressWalls=0

STEP 2 MAKING THE OUTER WALLS

DungeonWidth and DungeonHeight are in 32x32 blocks, and should be an odd number because of how the maze is generated.

Add a function called "MakeDungeon" with no parameters.

The first thing you need to do is destroy the existing dungeon, if there is one, so add a for each loop:
for each "wall" => wall.Destroy

Then add 2 For loops like this:


This will create a row of walls at the top and bottom of the dungeon and columns along the left and right sides making a box around the dungeon.

It uses the loopindex("x") and loopindex("y") to count off spaces multiplied by 32 to place the outside walls.

If you call the MakeDungeion function, you should get this:

STEP 3 MAKING THE INNER PILLAR WALLS

For the inner pillars (we call them "pillars" because they are the solid walls from which our "random" walls will be created)

To add these, we need to make nested for loops for "x" and "y"
Make sure the "y" loop is inside the "x" loop. Below the "y" loop, add a sub event with the following conditions:

System/ Compare two values:

    loopindex("x")%2  = Equal to 1

System/ Compare two values:

    loopindex("y")%2  = Equal to 1

This will ensure that the action only takes place every ODD number for x and y.

The Modulo or % operator gives us the remainder if the first number is divided by the second. So a%b is the remainder of a/b. If any positive integer % 2 is 1, then we know it's an odd number because it has a remainder if divided by 2. It's just a handy way of making sure something is odd or even.

You can also use % to make sure you land on every 5th or 3rd number (or whatever number) the same way... for example if a number % 5 = 0 then we know the number is a multiple of 5.

If we add the actions

System/ Create object "wall" on layer "walls" at
x= loopindex("x") * 32
y= loopindex("y") * 32

We'll get this when we call MakeDungeon:


Just what we want. A wall on every other square. The "maze" happens when we start making walls between them!

STEP 4 MAKING THE RANDOM WALLS

This is where the magic happens. To make a random maze, all we do is for each of those inner "pillar" walls, we make one other wall either one square left, down, right, or up from it randomly. Once we do, we'll have a random maze. That's all there is to it.

First, get a random integer from 0 to 3

Right click on the For "y" loop and ADD a local variable. Name it "r"

Right after the action to create the pillar walls, add the action:

System/ Set Value r = int(random(0,4))

Now we have a random integer from 0 to 3. What we want to do now is add a wall to each pillar wall in one of 4 directions determined by the value of r. Like this:
Now what we COULD do is make 4 sub events to check if r is 0, 1, 2, or 3, and create our new wall accordingly like so:
And that would certainly work. BUT...

Boolean math

What if I told you that through the magic of boolean math, we can do the whole thing with NO sub-events, and a single action?
They called me mad! They said it couldn't be done!

All you have to do is add the single action as follows:
Let me explain:

Construct 2... and computers in general apply numeric values to true or false results. In this case, true = 1, and false = 0.

If, say, (r=1) is true, and we know true = 1, then we know that (r=1) = 1.
You can use that to add or multiply things. For example true + true = 2, or true times 32 = 32. Conversely, false times 32 = 0.

So the expression:

    (loopindex("x")*32)+(32*(r=0))-(32*(r=2))

Means loopindex("x") -the x position of the pillar wall that we just created
plus 32 if r = 0, minus 32 if r=2. If r is neither zero nor two, the result will be 0 or false times 32 + false times -32.

    Because true and false is interchangeable with 1 and 0, and expressions like (r=0) evaulate to true (1) or false (0).  

Same thing with the Y coordinate:

    (loopindex("y")*32)+(32*(r=1))-(32*(r=3))

If r is 1, then it's not 0 or 2, so it won't move at all in the x direction, but will move down (+32) * (r=1)

This logic can be really handy for making numerical decisions based on a bunch of true or false comparisons. With it, you can do the work of a bunch of "if" type statements in a single line of code.

With this new action, you should get a maze that looks something like this:


Results may vary, but you'll always get a nice maze looking maze. The problem is, its a little too "mazey." More like a labyrinth than a dungeon. How do we fix this?

STEP 5 ADDING VARIETY

Remember that SuppressWalls variable we made in step 1?

In the same event where we make all the inner walls, we're going to add a condition:

System/ Compare two values: random(10) > SuppressWalls

So your whole event block should look like this:


Now if you set SuppressWalls to 1 or 2, it will once in a while skip making a wall where it otherwise would. Results may vary, but you'll get a maze that looks more like this:
Open full size image

...With some open room-like areas as well as hallways and corridors.

For large boss-battle type levels, you might want to set it to 8 or 9 for wide-open arena like areas. 10 would mean no walls at all, just the outer walls.

STEP 6 ADDING THE 3D EFFECT TO THE WALLS

We want it to look more like this:
The brick walls appear to stick out like those in RPG Maker.

To do this, first create a family called "walls" and include only the object "wall."
Then add a new Sprite object. Resize it to 8x8 and set its intital visibility to "invisible." Name the object "feeler." I filled it with red color, but it doesn't matter.
The "Feeler."

Then add another function called "fixframes" again with no parameters.


For every wall, the "feeler" checks to see if there's a wall one space below it. If not, then we change the animation frame to 1, which is the wall with a shaded bottom half giving it an illusion of depth.

In this capx file, I call fixframes right after I call MakeDungeon. Between MakeDungeon and fixframes, I added a WAIT action for 0.2 seconds. If I don't do this it doesn't work for some reason.

Anyhow enjoy! In the demo you'll notice as you move the player around the map, you can only see what the player object can "see." I'll get into this in the second part of the tutorial.

Feel free to use this or any part of ths in your own game!

Continued in Part 2: rogue-like-random-maze-tutorial-pt2-limiting-your-visible-area

Unlock your full gamedev potential

Upgrade to the Personal Edition of Construct 2, it has way more features and won't holding back from making money and using your full creativity like the free edition does. It's a one off payment and all Construct 2 editor updates are free for life!

View deals

Plus, it's got a lot of additional features that will help you save time and make more impressive games!

Congratulations on finishing this tutorial!

Did you learn a lot from it? Share it now with your friends!

Share and Copy this Tutorial

You are free to copy, distribute, transmit and adapt this work with correct attribution. Click for more info.

Comments

1
qwertyuiop888 874 rep

Nice tutorial. This will definitely help me on my project. :D

Monday, May 02, 2016 at 1:18:17 AM
2
honeben 1,755 rep

Both parts of this tutorial are great learning tools that a lot of people (even beginner's taking time to try to follow) can really learn a lot from.

ESPECIALLY about the boolean math aspect and the trick to avoid creating multiple events as opposed to using one action. That was very impressive!!!

Sinistar99----In case you still don't follow why the wait .02 seconds is needed in-between calling the function MakeDungeon and fixframes, then take a look at this link:

www.scirra.com/tutorials/510/advanced-tips-and-tricks-that-construct2-offers

P.S. You could achieve the same result (and faster with no lag) using "Wait 0 seconds" FYI

Monday, July 25, 2016 at 10:58:29 PM
0
UberdroidGames 8,329 rep

Thanks honoben!

It looks like wait 0 might not work because it doesn't wait until the next tick it just waits until the current bunch of events are processed. The game has to have a tick happen before it can acknowledge new objects in collision checks and whatnot.

What Construct needs IMHO is a "sync" type action that forces a tick when called. like tick now... NOW I SAY! heh...

Thursday, September 15, 2016 at 7:30:19 PM
1
KoolEcky 16.2k rep

Great tutorial sinistar99. Interesting take.

Friday, September 23, 2016 at 5:41:16 PM
1
UberdroidGames 8,329 rep

BTW if you want to absolutely guarantee complete coverage and no blocked off areas, make every other block on every other row of blocks NOT produce a wall.

As long as there are never 4 wall producing pillars together, there won't be any blocked off areas. The maze will be fully covered and dead ends are possible, but you can always get to every part.

My maze above DOES risk blocked off areas.

Wednesday, November 16, 2016 at 4:46:04 PM

Leave a comment

Everyone is welcome to leave their thoughts! Register a new account or login.