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:
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:
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...
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:
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:
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:
...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.
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: