@Luke
How is the overall dungeon layout generated randomly?
the overall dungeon layout isn’t actually randomly generated, i made four by hand and just randomly choose from this list (spoilers):
the layout might not be random, but the rooms that make up the dungeon are randomly connected to make each dungeon unique.
now if i wanted to make a random layout for a dungeon, i’d use an algorithm to create a maze that i’d use as a template.
how do you generate consistent dungeons but with the right amount of variation?
by cheating (see above)
How do you find the right dungeon tilemaps to connect to each one?
the dungeon layout is authored as an image, like this:

the green pixel marks the entrance and the red pixel marks the exit, and every pink pixel is a room in the dungeon. each pink room in the dungeon can have between one and four doors, depending on how many other rooms are bordering it. since there are four directions a door can be in (north, east, south, and west), that means there are 15 different combinations of doors that a room can have! here is a table that lists them all (an X means there is a door in that direction):
id |
north |
east |
south |
west |
1 |
X |
|
|
|
2 |
|
X |
|
|
3 |
|
|
X |
|
4 |
|
|
|
X |
5 |
X |
X |
|
|
6 |
X |
|
X |
|
7 |
X |
|
|
X |
8 |
|
X |
X |
|
9 |
|
X |
|
X |
10 |
|
|
X |
X |
11 |
X |
X |
X |
|
12 |
X |
X |
|
X |
13 |
X |
|
X |
X |
14 |
|
X |
X |
X |
15 |
X |
X |
X |
X |
so, for each pixel in the image I figure out the correct room type based on how many pixels border it. you can see the code for this in the getRoomType
function.
for each of these room types, I hand wrote six possible tilemaps that can be loaded for that combination of doors. you can see all of these tilemaps inside of the setTilemap
function, which takes two arguments: the room type (a number between 1-15 from the above table) and the room index (a number between 0-5 which represents the version of the room to load).
when this game generates a dungeon it loops over the layout image and for each pixel figures out the correct room type and a random room index and stores them in a double array of numbers. all of this logic is inside the loadDungeon
function.
you might also see a variable called roomIndices
in that function, that’s an array that keeps track of the last index used for each possible room type. whenever a new room is generated, we increment that number for the room type so that we aren’t just loading the same room over and over again.
Would something like this be possible without using multiple tilemaps?
sure! i would keep the logic pretty much the same and just “draw” each tilemap onto one giant tilemap as the world is generated. that’s pretty easy to do (see the tile util extension for blocks that let you set/get the tiles from a tilemap in a variable).
however, that strategy would only work because each of the tilemaps in this game are the same size and always place doors in the same place. if you wanted to do more varied rooms, you’d have to figure out how to draw “hallways” between the rooms which would probably be really annoying. I know we did this on stream at some point…
How did you store and read player changes to a dungeon room after they have left?
I keep a double array that marks each of the rooms that they player has visited. then you can just check it by doing visited[col][row]
. there isn’t much state to this game, either a room has been cleared or it hasn’t. it’s impossible to leave a room that isn’t cleared (the doors are locked), so keeping track of visits was all i had to do.
for more complicated state, you can simply modify the tilemap when you enter and leave a room. as long as you keep a reference to that tilemap (e.g. in a variable, an array, or using the connections blocks in the tile-util extension), when you reload that tilemap using the same reference then the changes will persist.