Hello! Welcome back to your JRPG development journey.
In our last lesson, we focused on the high-level design principles for creating compelling maps: overworlds, towns, and dungeons. We discussed how to guide the player, create atmosphere, and build a cohesive world. Now, it's time to zoom in on a critical component of dungeon design and bring it to life in our engine.
This lesson directly addresses the learning outcome: Design and implement a simple environmental puzzle (e.g., switch and door). Puzzles are a hallmark of the classic JRPGs you admire, serving as a welcome break from combat and rewarding player observation. We will explore the architectural patterns behind these puzzles and then implement the necessary logic in our event system to make them a reality.
1. The Architecture of an Environmental Puzzle
At its core, an environmental puzzle is a state management problem. The player performs an action (pulls a lever), which changes the state of the game world (a flag is set to true), and another part of the world reacts to this state change (a door opens). Given your background in front-end development, you can think of this as being very similar to component state in a web application: user interaction updates a state variable, and other components re-render or change behavior based on that new state.
Let's begin by exploring some common puzzle patterns using the familiar context of RPG Maker.
Eventing Two Switch Puzzles | The Official RPG Maker Blog
The article "Eventing Two Switch Puzzles" from the official RPG Maker Blog provides an excellent breakdown of how to think about puzzles in terms of events, switches (our game flags), and conditional pages. It's a perfect visual guide to the logic we're about to build.
Read the following sections: Flipping Levers into the Right Positions: Focus on how each lever is an event with two pages (up/down) controlled by a switch. Pay close attention to how a conditional branch checks the state of multiple switches to determine if the puzzle is solved. But What About the Locked Door?: This section shows the final pieceāan event (the door) that has different pages based on whether the puzzle-solving switches are active.
The key takeaways from that reading are:
- Puzzle elements are events: Levers, buttons, and doors are all just events on the map.
- State is stored in flags/switches: A global "Switch" (which we call a game flag) is used to track the state of each puzzle piece.
- Events have multiple pages: An event's appearance and behavior change based on which of its pages is active.
- Conditions determine the active page: The state of game flags determines which page of an event is currently shown and executed. For example, the door's "open" page is only active if
Switch_Puzzle_DoneisON.
2. Evolving the Puzzle: From Switches to Variables
Simple on/off switches are great, but many JRPG puzzles require more complex state, such as pushing multiple blocks onto pressure plates. In these cases, using a single boolean flag isn't enough. We need a variable to count how many conditions have been met.
This next video demonstrates a "rocks and switches" puzzle. It's a bit more advanced, but it perfectly illustrates the use of variables and the concept of a "parallel process" for continuous state checking.
RPG Maker MZ Tutorial #33 - Rocks & Switches Puzzle!
Watch this tutorial from RPGGameMaker to see a more dynamic puzzle in action. Don't worry about memorizing every step in RPG Maker; focus on the underlying logic.
Please watch these key segments: Setting up Rocks and Switches (00:55 - 02:31): Notice how rocks are events that can be pushed by the player. Implementing the Bridge Logic (03:00 - 04:39): The key here is that the bridge appears only when a variable called bridge_puzzle reaches a value of 3. This is more flexible than a simple on/off switch. Puzzle Manager Setup (04:39 - 08:15): The video introduces a 'puzzle manager' event that runs in parallel. In our engine, this logic would live in our main GameManager or Scene_Map update loop. It constantly checks the coordinates of the rocks and switches. Switch Activation Logic (08:35 - 12:37): This is the core logic. See how it checks if a rock's coordinates match a switch's coordinates, and if so, increments the bridge_puzzle variable.
This video introduces two powerful concepts:
- Using Variables for Complex State: Instead of a boolean
isPuzzleSolved, we have a numberactivatedSwitches. This allows for puzzles like "press 3 of the 5 buttons" or "light the 4 torches." - Continuous State Checking: The "parallel process" in RPG Maker is an event that runs its code on every frame. In our custom engine, this translates to logic inside our main game loop (
updatemethod) that constantly checks puzzle conditions, such as "is rock X on top of switch Y?"
3. Implementation in Our Engine
Now, let's translate these design patterns into concrete code for our engine. This will involve enhancing the event system we designed in Module 3.
Step 1: Enhancing Event Data with Conditions
Our events need to support multiple pages, where only one page is active at a time. To do this, we'll add a conditions block to each page in our event's JSON data.
An event page will only be active if all of its conditions are met. The engine will check pages in reverse order (from highest page number to lowest), activating the first one whose conditions are satisfied. Page 1 (index 0) usually has no conditions and serves as the default state.
Here is an example structure for an event's page:
{
"image": "door_closed.png",
"commands": [ /* ... */ ],
"trigger": "onAction",
"conditions": {
"flags": [
{ "id": "dungeon_lever_1", "status": "OFF" }
],
"variables": [
{ "id": "activated_statues", "value": 0, "operator": "equals" }
]
}
}
The game's Scene_Map will be responsible for iterating through each event's pages on load and during updates to determine which page should be active.
Step 2: Implementing Commands to Change State
To make puzzles work, our EventInterpreter needs commands to manipulate the game's state (the flags and variables we introduced in Module 3).
controlFlag command:
This command will set a boolean flag to true (ON) or false (OFF).
{
"command": "controlFlag",
"flagId": "dungeon_lever_1",
"value": true
}
controlVariable command:
This command can perform mathematical operations on a numerical variable.
{
"command": "controlVariable",
"variableId": "activated_statues",
"operation": "add",
"value": 1
}
Your EventInterpreter will process these commands and update the central GameState object accordingly.
Step 3: Building a Switch and Door Puzzle
Let's put it all together to create a classic lever-and-door puzzle.
The Lever Event:
This event has two pages. Interacting with it toggles a flag and changes its own appearance.
-
Page 1 (Default State - Lever is Down):
- Condition: None (it's the default).
- Image:
lever_down.png. - Trigger:
onAction(player interaction). - Commands:
{ "command": "controlFlag", "flagId": "lever1_is_up", "value": true }{ "command": "playSound", "sfx": "switch_click" }
-
Page 2 (Active State - Lever is Up):
- Condition: Flag
lever1_is_upmust beON. - Image:
lever_up.png. - Trigger:
onAction. - Commands:
{ "command": "controlFlag", "flagId": "lever1_is_up", "value": false }{ "command": "playSound", "sfx": "switch_click" }
- Condition: Flag
When the player interacts with the lever, it sets the flag lever1_is_up to true. The engine immediately re-evaluates the event's pages, sees that the condition for Page 2 is now met, and switches the event's appearance to lever_up.png. The next interaction will run the commands on Page 2, setting the flag back to false and reverting to Page 1.
The Door Event:
This event has three pages that control its behavior.
A typical spritesheet for a door animation, showing closed, opening, and fully open states. The opening frames would be played by an autorun event.
-
Page 1 (Locked Door):
- Condition: Flag
lever1_is_upmust beOFF. - Image:
door_closed.png. - Trigger:
onAction. - Collision: Blocks player movement.
- Commands:
{ "command": "showText", "text": "The door is sealed shut." }
- Condition: Flag
-
Page 2 (Door Opening Animation):
- Condition: Flag
lever1_is_upmust beONAND Self-FlagAmust beOFF. - Image:
door_closed.png. - Trigger:
autoRun(runs once automatically as soon as its conditions are met). - Collision: Blocks player movement (initially).
- Commands:
{ "command": "playSound", "sfx": "heavy_door" }{ "command": "animate", "target": "this_event", "animation": ["door_opening_1.png", "door_opening_2.png", "door_open.png"], "speed": 4 }{ "command": "setCollision", "passable": true }{ "command": "controlSelfFlag", "flag": "A", "value": true }
- Condition: Flag
-
Page 3 (Door is Open):
- Condition: Self-Flag
Amust beON. - Image:
door_open.png. - Trigger: None.
- Collision: Does not block player movement.
- Commands: None.
- Condition: Self-Flag
When the lever is pulled, lever1_is_up becomes true. The door event's Page 2 conditions are met, and its autoRun trigger fires. It plays an animation and sound, sets itself to be passable, and critically, turns on its own Self-Flag A. This ensures the animation only plays once. Now, the condition for Page 3 is met, and the door remains permanently open.
Test your understanding!
Using the logic we just discussed, how would you design the conditions for a door that only opens when two different levers (lever1 and lever2) are both in the "up" position? You would need two flags: lever1_is_up and lever2_is_up. What would the conditions block for the door's "Opening Animation" page look like?
Show answer
The conditions block for the door's second page would need to check that both flags are ON.
"conditions": {
"flags": [
{ "id": "lever1_is_up", "status": "ON" },
{ "id": "lever2_is_up", "status": "ON" }
],
"selfFlags": [
{ "id": "A", "status": "OFF" }
]
}
This demonstrates how you can create combination puzzles by simply adding more required conditions to an event page.
Conclusion
Today you've bridged the gap between abstract design and concrete implementation for a core JRPG feature. Environmental puzzles are a fantastic way to add depth and variety to your dungeons, and now you have the architectural foundation to build them.
Key Takeaways:
- Puzzles are State Machines: Environmental puzzles are fundamentally about managing game state. Player actions trigger state changes.
- Flags and Variables are Your Tools: Simple boolean flags (
switches) handle on/off states, while numerical variables are perfect for more complex counting or combination puzzles. - Conditional Event Pages are Key: The ability for an event to change its appearance and behavior based on the current game state is the mechanism that brings puzzles to life.
- Triggers Drive the Logic:
onActiontriggers react to direct player input, whileautoRunand parallel processes (onUpdate) react automatically to changes in the game world.
Preview of the next lesson:
Now that we have a way to make our dungeons more interactive and engaging with puzzles, the next step is to populate them with challenges. In our next lesson, we will design and implement a random encounter system with region-specific enemy groups and encounter rates, another essential pillar of classic JRPG gameplay.
Can't find a good explanation? Sign up and we'll make it for you
Sign up