We’ve all run into locked doors in dungeons before. Sometimes we just need to defeat an enemy or find a key to open the door, but there’s another option that makes the player think a bit more: solving a puzzle. Puzzles can be a nice break from battles for our players, so let’s learn how to make two types of puzzles that could be used to unlock a dungeon door.
For this tutorial, let’s look at two puzzles that just require the player to interact with some events to solve it (so no complicated math problems this time). The first puzzle will need the player to flip three levers up and down until each one is in the right position, and the second puzzle requires the player to change five crystals into the same color. Once both puzzles have been solved, the door will open.
Since we already know the number of events we will definitely need (1 for the locked door, 3 for the lever puzzle, and 5 for the crystal puzzle), we can go to our puzzle map and add in empty events for them. Beyond those events, I’ve also added some stone tablet events that explain what the player will need to do, as well as a few extra events that will come in handy for the crystal puzzle when we start working on it.
With our puzzle events named and on the map, we can get to the meat of the puzzles: the eventing.
Levers can make for a good simple puzzle since there are only two positions for them to be in, up and down (or left and right), so even if the player doesn’t know the correct positions they can still succeed just by trying all the possibilities. But since we don’t want our players to be stuck too long during this puzzle, we can give them a very clear hint with the stone tablet guide.
To solve this puzzle the player needs to have the first lever up, the second lever down, and the third lever up. There are a few ways we could check to make sure each lever is in the right position, but in this example we’ll keep it simple and assign each event a switch.
First thing we’ll event is the movement. Each switch event needs a page for when the lever is up and a page for when the lever is down, and interacting with the event will move the lever and turn the switch on or off so the other page will activate. The only major difference between the three events will be which switch is being turned on/off, in this case our first event uses Switch 17, our second uses Switch 18, and our third Switch 19.
Once all three levers can be moved up and down, we can add in the part where we check if all of them are in the right positions. If they are in the right positions, then the puzzle is solved and we can turn on a switch so that we know the puzzle is done (in this case the aptly named ‘Switch Puzzle Done!’ switch).
One way we could check is with a few nested conditional branches, each one checking an event’s assigned switch. Since we set up each event in the same way, we know that both the first and third events’ switches need to be Off while the second event’s needs to be On for our levers to be in the right positions.
Another option would be to use a script call to check each switch at the same time. The script call $gameSwitches.value(N) == true/false will let us check if a certain switch is On (true) or Off (false), so we could use it to check if all three of our lever switches are correct by putting ($gameSwitches.value(17) == false) && ($gameSwitches.value(18) == true) && ($gameSwitches.value(19) == false) into the script section of a conditional branch.
Either option will work, so go with what you’re more comfortable working with.
If all three switches are in the correct position, then we can play a happy SE and message to let the player know they solved the puzzle, and turn on our ‘Switch Puzzle Done!’ switch so that we can easily check if the puzzle is done later.
Now, we could put the check on every page of our switches, but that would actually be overkill. Since we know that it’s impossible for the puzzle to be solved if our first event’s switch is On, we don’t need to add the check to the first page, and can carry that logic over to our other events.
So our first and third events would have the conditional branch at the end of the second page:
While our second event would have the branch at the end of the first page:
And finally, since we don’t want the player to mess around with the levers once they’ve solved the puzzle, we can add a third page to the events that’s activated by the ‘Switch Puzzle Done!’ switch that simply tells the player the switch can’t move anymore.
All that’s left is to test it out in-game. Since this puzzle is so reliant on switches, if it’s not working right the first thing to check would be that we didn’t accidentally turn on/off or check the wrong switch in the events.
For our next puzzle, we want our players to touch the crystal events until all the crystals turn from red to green. The crystal events will be pretty similar to our previous levers, with two pages set up to cover each position option (red and green crystals) and a final third page for when the puzzle is finished. But since just changing the events one-by-one isn’t exactly a puzzle, let’s make it a bit more challenging by adding in a Lights Out effect: when the player activates an event, the events next to it also change.
To get that effect, we’ll need to know which events are next to each event (which we already know because we added all the events to the map at the same time) and have a way to toggle the neighboring events’ pages. Toggling a normal switch is easy enough to do, we just need a conditional branch to check if the switch is On, and turn it Off if it’s currently On or turn it On if it was Off.
But what if we wanted to have a lot of these types of puzzles in our games? While we could just use a different switch for every event (which would add up quickly) or have a set of switches that are reused for each puzzle (which means that the game can’t have more than one puzzle going on at the same time), there is another option: self-switches. Since each event has its own set of self-switches, if we know how to check and change them we don’t need to worry about running out of switches.
The only issue with using self-switches is that by default, there isn’t an event command that lets us change a different event’s self-switch. So before we can start setting up self-switch toggles, we need to learn a few script calls.
The first one we’ll need is one that lets us set a self-switch On or Off, which is $gameSelfSwitches.setValue([mapId, eventID, 'A-D'], true/false); . The part in the brackets is what we need to focus on, since it’s what tells the engine which event and which self-switch should be affected. ‘mapId’ tells us which map the affected event is on, ‘eventId’ tells us the exact event we’re affecting, and 'A-D' is which self-switch is being changed. However, if we’re only affecting events on the map the player is currently on then we can put $gameMap._mapId into our ‘mapId’ spot because it tells the engine that we’re looking at an event on the current map.
So if we wanted to turn self-switch A On for event 5 on our current map, our script call becomes $gameSelfSwitches.setValue([$gameMap._mapId, 5, 'A'], true);
The other script call we need is one that checks if a self-switch is On or Off, which turns out to be $gameSelfSwitches.value([mapId, eventID, 'A-D']) == true/false . It follows the same rules as our previous script call, so if we take a conditional branch and add in those script calls we can toggle an event’s self-switch:
Now, adding this conditional branch to each crystal event and manually adjusting the ‘eventId’ in each would work fine, but that’s a lot of points where we could accidentally mistype something and cause a problem. Since only the ‘eventId’ is going to be changed in each, why don’t we set up a common event so that we only need to write it once?
By taking our ‘eventId’ and replacing it with $gameVariables.value(N), we can just set a variable to our affected event’s Id and call our common event to have it toggle like we want. If we set up our second crystal to do this, we end up with two pages that look like this:
Where we flip the second crystal’s self-switch with the event command and then set our chosen variable to the neighboring event’s Id number and call the common event. Since this event has an event on its left side and right side, we need to set the variable and call the common event twice, once for each event. For our first and fifth crystals, since they only have one neighboring event, we only need to call the common event once.
With all five of our crystal events set up and properly changing themselves and their neighbors, we can think about the puzzle itself and how we’ll know when it’s solved. Checking if the player has solved the puzzle is pretty straightforward, we just need to make sure that all of our crystal events’ self-switches are On, and if they are then we can celebrate their success and turn on a ‘Crystal Puzzle Done!’ switch much like we did with the switch puzzle.
There are a few ways we could check to make sure each event’s self-switch is on, but for this example we can set up a common event that the crystal events call, and we’ll be checking each self-switch to see if it is Off. If any of the self-switches are Off (which means a crystal is still red), then it will activate the exit event processing command so the common event ends there. So the only way the common event will fully run is if each events’ self-switch is On.
By default, our crystal events would all start out red, which doesn’t exactly make for a challenging puzzle. We can change that by including an autorun event on the map that will turn two of our crystal events’ self-switches On so that there will be two green crystals from the start, and then turns on its own self-switch so that it only runs once.
And last, but certainly not least, is giving the player a way to reset the puzzle if they get stuck. For small or simple puzzles it may not be necessary, but sometimes it’s just nice to be able to go back to the start of the puzzle and try something new. So let’s add in a button event that gives the player a way to reset the crystal events. In this example it’s a simple Yes/No choice, where ‘Yes’ will use a script call for each crystal event to change them to their starting page, keeping in mind that two of them will be green (we could probably simplify this, but I like being able to easily see how many events are being affected). A second page that’s activated by the ‘Crystal Puzzle Done!’ switch makes it so the player can’t reset the crystals once they’ve solved it.
Now that all that eventing is finished, we can test it in-game and see it in action.
But What About the Locked Door?
Puzzles are fun, but if we don’t connect them to something rewarding then there isn’t a real reason for them to be in the game. Since we have a locked door on this map, we can have it open only if both puzzles have been solved. And to make sure the player knows the door is now unlocked, we can have it announce that it’s now open.
The door’s event needs three pages to pull this off. The first page is simply the locked door telling the player that they can’t go through it yet.
The second page is an autorun that will let the player know they’ve unlocked the door, by having it swing open. The only way for this page to activate is if both ‘Puzzle Done!’ switches are on, which means both puzzles were solved. To keep it from repeating over and over, we’ll have it turn on a self-switch.
And the third page is where we would put the actual map transfer so the door can work as, well, a door.
And that’s it! Now you can add some new puzzles to your game to challenge your players. Where would you consider using these types of puzzles? And how could you modify them to better fit your game?
Cliffs are something that can make a huge difference on your maps. I don’t know where you live, but if I look out of my window the landscape is far from being flat and so there are probably parts of your game’s world that could benefit from some height differences for the ground - being it some hills or high mountains.