Like the boot a legendary hero used to kill Fenrir, The Iron Shoe is an amalgamation of many disparate pieces. To date, the blog has focused on RPG Maker tutorials, scripts written by others, and an intermediate level of probing under RPG Maker VX Ace’s hood. Today we add another category, dev blog posts, focusing on the making of Vidar, a story-driven puzzler and dungeon explorer.
For these dev blog posts, it’s my intention to be much more informal. So strap yourself in while I talk a little about what I’m doing with Vidar.
By way of background, Vidar involves exploration of a multi-level dungeon. Don’t fret – you won’t be fighting any monsters, but instead be racing against a timer to solve complex puzzles using all of your favorite mechanics (frictionless ice, pushing boxes, reflecting mirros) and some new ones (well it wouldn’t be fun if I spoiled that, would it?). Vidar’s story is driven by the characters you meet in town, but the story evolves dynamically over the course of the game. Indeed, there are hundreds of twists and turns that the story can take, such that you may end up with a completely different understanding of Vidar and its problems than your friend did in her game.
I want to encourage players to explore those twist and turns in multiple plays of the game, but repeatedly playing the same puzzles gets boring quickly. So I’ve designed a random dungeon generator for Vidar.
The puzzles aren’t procedurally generated – I wanted to have more fine-tuned control over the level of difficulty, the particular puzzle elements at play, etc. Moreover, the outline of a map is the same. Within a map, I designate a space for spawning a puzzle, and tell the generator “ok, here is a bucket of options, choose one and place it in that space.”
So already we need a few components to do this:
- The map outline
- A puzzle, which represents the area in the correct map, along with a list of all of the options
- The options
The map part of this is simple. It might look something like this:
As described above, the puzzle needs a few different pieces. It needs to know where to spawn, and what its options are. So I built a class:
class Puzzle attr_accessor :x attr_accessor :y attr_accessor :map_func attr_accessor :option_list def initialize(coord, array_of_options, map_func) @x = coord @y = coord @option_list = array_of_options @map_func = map_func end def map map_func.call end end
All of this is pretty straight forward, except the map_func. Indeed, when I create the puzzle I pass in a block instead of an integer for the map id. Nine times out of ten, this block just resolves to an integer. But every so often in Vidar, there is a chance you end up with a different map.
When you start a new game, I choose which of the three maps above will serve as the third room in the Dark Cave biome, and store the map id of the chosen map as a variable. But since I don’t know the map id ahead of time, I need to instead provide a function that resolves to the correct variable. From there it’s simple.
The options are the meat of what the player actually sees. An option contains a bunch of lists of all the components or mechanics. So for example, the option will have a list of torches, a list of switches, a list of doors, etc. Other than that, all it needs to know is which puzzle it belongs to.
The generator will run only once – when you create a new game (we don’t want it to overwrite puzzles in a save file!). When it does, it:
- Looks at the first puzzle’s list of possible options and chooses one at random
- Goes through that option’s lists and spawns all of the necessary events accordingly
- Chooses the next puzzle and repeats
That’s all for now! I’ll definitely go more into detail about the options, and how we get from an option to events on the screen to interact with, later!