CHAPTER 11

image

Puzzles

A common mainstay of most role-playing games (RPGs), both new and old, is the puzzle. Defeating monsters and other assorted baddies to get through dungeons can be fun for quite a while, but puzzles break the monotony and make it so that the players have to flex their mental muscles as well as their alter egos’ physical muscles. During the course of this chapter, I will be covering three puzzles that I have devised in my time working with RPG Maker VX Ace (RMVXA). Without further ado, let us begin with the first one.

Slippery Floors!

Perhaps the bane of any gamer who has played RPGs for even a short amount of time, slippery floors prevent you from controlling your character until it slams face-first into an obstacle. Making slippery floors is actually a very nuanced process in RMVXA eventing, as there are many things you have to take in consideration. For example:

  • You have to prevent the player from inputting actions as he or she is slipping.
  • You have to define what constitutes a slippery floor, unless you have an entire floor full of such tiles.
  • You want the game to auto-input movement commands in the same direction, until the player gets stuck against an obstacle.
  • You have to determine when the player has been stopped by an obstacle, so that he or she can move manually again.

The good news is that, once you understand what you need to do, you only require a single Parallel Process event to handle everything.

Creating Our Staging Area

First, however, I’m going to unveil the tweaked version of Abandoned Mine FB1, which is where I’ll have the icy area that the player can slide on. Take a look at Figure 11-1 to see the area map. I segmented the large central area and separated the westernmost part of the floor into its own little section. Besides that, I added secret passages that connect the eastern sections. I placed a new staircase at the northern end of the western corridor. So, how does the top floor connect with this lower floor of the mines?

  • The staircase at (23,15) on F1F leads to the ice section staircase located at (24,44).
  • The stairs at (48,5) on F1F lead to (49,34) on FB1.

9781484207857_Fig11-01.jpg

Figure 11-1. A screenshot of the first basement floor of the mines

That leaves the two staircases at the western corridor and a third near the northeastern corner of FB1 (at 49,10). We’ll set up those transfer events, once we work with the last level of this dungeon. For now, let’s work on our sliding puzzle!

Eventing Our Sliding Puzzle

We’ll begin by defining the icy floor as slippery, through the use of terrain tags. You could use Regions as well. The particular tile I’m using is Ground (Crystal), located within the A tab of the Dungeon tileset. Once that is done, we create a Parallel Process event to hold our slippery floor logic. I’ll break this down into parts.

@>Control Variables: [0002:X] = Player's Map X
@>Control Variables: [0003:Y] = Player's Map Y
@>Get Location Info: [0017], Terrain Tag, Variable [0002][0003]
@>Conditional Branch: Variable [0017:TerrainTag] == 1
@>Loop
      @>Set Move Route: Player (Skip, Wait)
       :              : $>Walking Animation OFF
       :              : $>Change Speed: 5
       :              : $>Change Freq: 5
      @>Label: Repeat

As is standard with most of our Parallel Process events, we have it write the player’s current location to a pair of variables and then fetch the location info for the tile that the player character is standing on at that precise moment. Next, we have a conditional branch that only triggers if the Terrain Tag is equal to 1. If it is, we use the Loop event command. As per its name, event commands within a Loop will repeat endlessly until you use a Jump To Label to escape the loop. In essence, an Autorun event is a loop (which is the reason why it is so easy to accidentally hang your game using one, if you forget to use a self-switch or some other method to break out of the event page).

The first order of action when the event enters its loop is to make it so that the player appears as if he/she is sliding on air. As mentioned near the start of the book, turning off a character’s walking animation will accomplish precisely that. We can increase the speed at which the player slips on ice by using Change Speed and increasing its value. I set it to 5. Change Frequency does nothing in this particular exercise, but I kept it there for testing purposes. You’ll see why it does nothing, as I reveal more of the event. The last thing I placed in that sample code was Label: Repeat. That was not a coincidence. Everything after that label will be repeated until a certain condition is met (more on that later). Here’s the second part of the event:

@>Control Switches: [0026:WalkMovement] = OFF
@>Set Move Route: Player (Skip, Wait)
:               : $>1 Step Forward
@>Control Variables: [0019:X'] = Player's Map X
@>Control Variables: [0020:Y'] = Player's Map Y
@>Conditional Branch: Variable [0019:X'] == Variable [0002:X]
   @>Conditional Branch: Variable [0020:Y'] == Variable [0003:Y]
      @>Jump to Label: GoToNext
      @>
   : Else
      @>Control Variables: [0002:X] = Player's Map X
      @>Control Variables: [0003:Y] = Player's Map Y
      @>Jump to Label: Repeat
      @>
   : Branch End
   @>
: Else
   @>Control Variables: [0002:X] = Player's Map X
   @>Control Variables: [0003:Y] = Player's Map Y
   @>Jump to Label: Repeat
   @>
: Branch End

As of this time, the player character has no walking animation. We want to have a dedicated switch that is off when the player cannot move and is flipped on when he/she can. (You could invert the states so that the switch is on when the player cannot move. Just make sure you keep track of the fact.) WalkMovement will be that switch. We’ll have a conditional branch after this loop that checks to see if WalkMovement is off. If it is, we restore the player’s walking animation and normalize his/her speed. But, I’m getting ahead of myself.

When the player is found to be on slippery ground, he/she will slip uncontrollably in his/her current direction. It is extremely important that you make sure that you toggle both the “Skip if cannot move” and “Wait for completion” check boxes. If the former is untoggled, the game will hang as soon as the player reaches an obstacle. If the latter is untoggled, the event will not work. (Give it a try and note how the character moves on the icy terrain.) Next, I assign a new pair of variables to store the player’s current x and y coordinates after moving one space. Why? Well, recall the last bullet point in the summary list at the start of the chapter. We need to check to see if the player has been stopped by an obstacle.

We can figure that out by comparing the values of X’ and Y’ with the values of X and Y. The only time X’ and X (and Y’ and Y) will be identical is when the player is stationary. How can I guarantee this? It all comes down to the event flow. At the very top of the event, we write the player’s location to X and Y. After moving a single space (or failing to, if the character is already adjacent to an obstacle), we write his/her location to X’ and Y’.

We escape the loop if the values of X’ and Y’ are equal to the values of X and Y; otherwise, we loop back to the top of the sequence.

A Note About Redundant Code

As it turns out, you may have already noticed that we don’t actually require that Loop command. That’s something really important to learn in programming in general and RMVXA specifically: Don’t do in ten lines what you can do in nine or fewer. In other words, make your events as efficient as possible. As you gain proficiency with RMVXA, you’ll probably find cases in which you created an event that has some fat that can be trimmed with no negative effects. In this case, the Loop command doesn’t take anything away from the slippery floor event, but you can use labels to achieve the same effect.

Eventing Our Sliding Puzzle (continued)

Here’s the last part of the slippery floor event:

   @>
: Branch End
@>Label: GoToNext
@>Conditional Branch: Switch [0026:WalkMovement] == OFF
   @>Set Move Route: Player (Skip, Wait)
   :               : $>Walking Animation ON
   :               : $>Change Speed: 4
   :               : $>Change Freq: 3
   @>Control Switches: [0026:WalkMovement] = ON
   @>
: Branch End
@>

This is where we go if the player is stationary from having bumped into an obstacle. We check to make sure that WalkMovement is off and restore the player character’s walking animation and set its speed back to 4. We set WalkMovement to ON and we’re all set. Of course, the event still isn’t as clean as it could be. Think hard on what the event is doing, and see if you can trim it down some more.

Creating the Icy Area

Of course, we’ve gone through all the trouble of creating this event. It wouldn’t be proper to just have it there doing nothing. Hence, let’s make a little ice maze. You can already see it in a zoomed-out state in the full-map screenshot, but Figure 11-2 shows a zoomed-in picture of the relevant area.

9781484207857_Fig11-02.jpg

Figure 11-2. The ice area in the first basement floor

Note the secret passage on the right-hand side of the ice maze. We have a small section at the northwest corner of the room with three chests to reward exploration. You can add or remove obstacles, as wanted, to make it easier or harder to reach the chests or the entrance to the passage.

A Treasured Intermission

Speaking of chests, I scattered Mithril gear throughout the dungeon, to serve as the party’s possible upgrades. The first floor contains the Mithril Rod, which is actually a downgrade for Noah, but as good as any item to sell for gold. It also contains a Mithril Axe that will work wonderfully as an upgrade for Eric. The second floor has a Mithril Bow and a Mithril Shield. Finally, the third floor that I’m going to add in a few moments will contain Mithril Armour (RMVXA uses British English for item names, for some odd reason, considering that most of the rest of the engine uses American English) and a Mithril Circlet. Now then, let’s add the third and final floor to our dungeon, so I can talk about the second puzzle of this chapter. (See Figure 11-3.)

9781484207857_Fig11-03.jpg

Figure 11-3. The bottom floor of the abandoned mines

For the final floor, I added a staircase in the left room, covered the hallway linking the two other rooms with debris, used a secret passage to connect them via an alternate route, and sealed off the entrance with a door.

  • The staircase at (3,41) of this level connects with the stairs at (49,10) on FB1.
  • The newly added staircase at (6,15) of this level connects with the other new staircase at (3,5) of FB1.

The door is the protagonist of our next puzzle.

Riddles!

Riddles are one of my favorite ways of flexing my gray matter. Quite a few RPGs have one quest or another that involves having to solve a riddle. For this exercise, we’ll have that locked door pose a riddle to the player when he/she interacts with it. If the player can answer the riddle correctly, the door will open; otherwise, it will remain shut, patiently waiting.

Overview

How do we begin? We have two ways of handling a riddle.

  • We could use Show Choices to display three possible answers and a Cancel option. Alternatively, we could have Show Choices display four answers and set the “When Cancel” option to Disallow (forcing the player to choose an answer) or Branch (and then have a Continue/Cancel branch pop up if the player would rather not try to answer).
  • We can use Name Input Processing to have the player write his/her answer to the riddle in question and then have a conditional branch that triggers if the answer is correct.

I’ll be showing off the second method, as it is a little more involved eventing-wise.

Our Riddle of Choice

The first order of business is to figure out what riddle we want the player to solve. I’ll be using a classic riddle solved by Oedipus. Here it is (well, one translation of it, anyway): “What is that which has one voice and yet becomes four-footed and two-footed and three-footed?” (The traditional answer for that, by the way, is man. For the purposes of this exercise, we’ll make human the answer.) As the correct answer has five letters, we want the input box generated by the Name Input Processing command to have a limit of five characters. As you may have already noticed, we are using this event command in quite an unconventional way. It is intended as the means of changing a character’s name. For example, you could have a Name Input Processing event that allows the player to change Eric’s name to something else. Here, we want to use the command, to allow the player to answer a riddle.

Creating Our Riddle Event

To begin, you’ll want to make your way to the Actors tab of the Database and increase the maximum number of actors from ten to eleven. Once you do that, you’ll get a blank actor on the new slot. That’s exactly what we want. You could have a portrait for the riddle giver in this way, if you so desire. Because the player is talking to a door, we’ll skip that. Next, we have to write the player’s input into a variable. This is where we call upon scripting once again to come to our aid. Thankfully, the scripting required is not nearly as elaborate as that for the Smoke Bombs in Chapter 9. We need scripting for four small things.

  1. Placing the blank actor’s name into a variable. We need to find out where RMVXA stores actor names.
  2. Using a Ruby method to make the player’s answer case insensitive.
  3. Using the Script option in the Conditional Branch command to write out the conditional we need.
  4. For subsequent attempts, we want to clear out the blank actor’s name before the player tries again.

You might wonder why at all we have to do this. After all, Conditional Branch also has an option on page 2 to check for a particular actor’s name. Well, let’s follow that thought process and work out a simple riddle event. In theory, your riddle event could look as simple as this.

@>Text: -, -, Normal, Bottom
:     : What is that which has one voice and yet becomes
:     : four-footed and two-footed and three-footed?
@>Name Input Processing:  , 5 characters
@>Conditional Branch: [] is Name 'human' Applied
   @>Text: -, -, Normal, Bottom
   :     : Correct.
   @>
: Else
   @>Text: -, -, Normal, Bottom
   :     : Wrong.
   @>
: Branch End
@>

We have a single text box giving the riddle to be solved, and then a screen comes up, so that the player can write in his/her answer. The screen in question is displayed in Figure 11-4.

9781484207857_Fig11-04.jpg

Figure 11-4. The Name Input Processing event command in action

However, as you’ll quickly find, if you do not write human exactly as I did in the relevant sentence, you will receive an error message. After all, the conditional branch is looking for “human,” not “hUmAn” or “HUMAN.” It also doesn’t solve the minor problem that the blank actor’s name will not be cleared if the player writes an incorrect answer. So, let us begin with our small snippets of Ruby script.

Finding How RMVXA Handles Actor Names Within Its Code

First, we have to find out how RMVXA handles actor names within the code. A good place to start our search is the code that governs the Conditional Branch command. After all, one of the possible conditionals involves inputted names. Running a search in the Script Editor for “conditional branch” returns a single result. Click it and scroll down until you find this part of the code.

when 4  # Actor
    actor = $game_actors[@params[1]]
    if actor
       case @params[2]
       when 0  # in party
          result = ($game_party.members.include?(actor))
       when 1  # name
          result = (actor.name == @params[3])

From here, we learn that, whatever our end result looks like, it has to involve $game_actors in some capacity. As it turns out, that is correct. There is a Game_Actors class within the Script Editor, but checking it out is largely fruitless, save for one single tidbit: This is a wrapper for an actor array. An array in programming is a list of items. In this case, Game_Actors combines all of the relevant actor information into a single array. What we want is a specific actor’s name, so let’s head on over to Game_Actor, where we’re almost immediately greeted by the information following:

attr_accessor :name                     # Name
attr_accessor :nickname                 # Nickname
attr_reader   :character_name           # character graphic filename
attr_reader   :character_index          # character graphic index
attr_reader   :face_name                # face graphic filename
attr_reader   :face_index               # face graphic index
attr_reader   :class_id                 # class ID
attr_reader   :level                    # level
attr_reader   :action_input_index       # action number being input
attr_reader   :last_skill               # For cursor memorization:  Skill

attr_accessor, attr_reader, and attr_writer (not present in Game_Actor) are a trio of Ruby modules that allows for instance variables to be used outside of the classes in which they normally exist. For the purposes of this exercise, all you have to know is that the listed attributes are contained within the array created by $game_actors. This is what you would need to write in the Script box of Control Variables to fetch an actor’s name: $game_actors[n].name (where n is equal to the actor’s ID in the Database).

Image Note  You can also grab the other attributes in the same way. Just replace name with the attribute in question. Level, in particular, could be pretty useful in creating areas that can only be accessed if a player is of a certain level or higher.

How to Use the Script Option to Store and Modify Text in a Variable

To be precise, we’ll be storing an actor name within the Riddle1 variable, but this can be applied to any other type of text you can think of. While the most common use of variables in RMVXA is to store numbers, text can fit in there just fine. In any case, now that we know how to call for a specific actor’s name, we can write that value into a variable by using the Script option.

@>Control Variables: [0016:Riddle1] = $game_actors[11].name

That’s what the event command should look like, once you’re done (11 being the database ID of the new blank actor for this specific exercise). Next, we have to make sure that the player receives a positive response for a correct answer, no matter how it is written. There is a class within Ruby called String that contains various methods we can use to modify text. You can check the appropriate help page within RMVXA for additional details, but the two we’re interested in are upcase and downcase. Suppose the player writes “Human” in the name input screen. If we modified it with upcase, it would become “HUMAN.” On the other hand, downcase would turn it into “human.” For this exercise, I’ll be using downcase. What we want to do is modify the contents of the Riddle1 variable after the previously pictured event command has been processed. It’s as simple as doing the following:

  • Finding Script on page 3 of the event command list
  • Writing in $game_variables[16] = $game_variables[16].downcase (or whichever variable ID you are using for your riddle)

Image Note  Make sure that you don’t split a single expression in twain while scripting. In the following lines of script, the first example is correct; the second is incorrect.

@>Script: $game_variables[16] =
:       : $game_variables[16].downcase

@>Script: $game_variables[16] = $game_variables
:       : [16].downcase

It’s easier if you think of the preceding as three separate expressions. $game_variables[16] is the first one, the equal sign is the second, and applying the downcase method to $game_variables is the third. RMVXA reads the second example as four expressions, as you’re cutting the third into two halves.

Finishing Up Our Riddle Event

Next, we need a conditional branch, to check if the value of our riddle variable is equal to human (if you used upcase instead of downcase, you’ll want to check for HUMAN instead). We use the script option and write out $game_variables[16] = "human" (make sure you include the quotation marks). In this particular case, you can either check “Set handling when conditions do not apply” or have another conditional branch for $game_variables[16] != "human" (!= is “not equal” in Ruby). In either case, the last thing that requires scripting is emptying out the actor name. To do this, we have another line of script: $game_actors[11].name = ""

The quotation marks are important here as well. If you leave the method assignment completely empty, the game will crash with an error. Here’s what the skeleton of the completed event looks like:

@>Text: -, -, Normal, Bottom
:     : What is that which has one voice and yet becomes
:     : four-footed and two-footed and three-footed?
@>Name Input Processing:  , 5 characters
@>Control Variables: [0016:Riddle1] = $game_actors[11].name
@>Script: $game_variables[16] =
:       : $game_variables[16].downcase
@>Conditional Branch: Script: $game_variables[16] == "human"
   @>Text: -, -, Normal, Bottom
   :     : Correct.
   @>
: Else
   @>Text: -, -, Normal, Bottom
   :     : Wrong.
   @>
: Branch End
@>Script: $game_actors[11].name = ""
@>

Because we want the door to open on a correct answer, you’ll want to flip a self-switch after the door announces “Correct.” Next, you display a message stating that the door opens and then switch to a second event page that is completely blank. There are areas of opportunity to tweak this event as well. Here are some tips if you choose to do so:

  • You can directly modify an actor’s name, as already noted in the last line of the completed event. Turns out you don’t even have to have a variable to store the name given the fact. You could just apply downcase to $game_actors[11].name instead.
  • You could use the Name Applied conditional in the Conditional Branch command.

One of the beauties of programming (and working with RMVXA events) is that there can be multiple correct solutions to a problem. Some may even be equally efficient! I have one more puzzle to discuss in this chapter, so let’s get to it!

Remote Statue Manipulation!

I left the most nuanced of the three puzzles for last. Manipulating objects from a distance has been a mechanic used in many video game genres throughout the years. For this exercise, the player will be sent to a distant snowy mountain to move two statues to their respective pedestals. Figure 11-5 is a screenshot of the area in question. The map is 27×23 and uses the Exterior tileset.

9781484207857_Fig11-05.jpg

Figure 11-5. The map where the statue manipulation puzzle takes place

We have a pair of dragons that will be our statues for this exercise. The rock crosses on either side of the area are actually events that will disappear once the puzzle has been completed. The same goes for the three rocks blocking the staircase at the northern end of the area.

Overview

Here are the things that we need, in no particular order:

  • Have an event that allows the player to start the puzzle (we’ll place it on the gravestone).
  • Once the puzzle has started, we freeze the player character in place and scroll the map up a few squares, so that the statues are at the center of the player’s vision.
  • Set up an event that translates the player’s arrow keys presses into statue movement. This event could also allow the player to press a button to cancel out of the puzzle (if the player would rather go do something else, for example) without completing it.
  • Make the extra rocks disappear once the puzzle has been solved.
  • After each move, check to see if the statues are on their pedestals. If they are, we flip a switch confirming that the puzzle has been solved. Otherwise, we allow the player to move the statues again.
  • The two events that will represent the statues
  • An invisible event that blocks the player from moving while the puzzle is in progress

First, place the assorted rocks that will prevent the player from passing to the other side of the area until he/she completes the puzzle. Next, place a green dragon event at (12,10) and a red dragon event at (14,8). I specified color to differentiate the two statues. This will be important, as we want the green dragon to go on the left pedestal and the red dragon to go on the right pedestal. The pedestals are at (11,8) and (15,8) and are the golden cobblestone tiles present in tab A of the Exterior tileset.

Creating the Puzzle Trigger (Interaction) Event

The first event we’re going to fill out is the first one that the player will interact with, namely, the gravestone event. When the player interacts with the gravestone, we want a message to be displayed, then the game will ask if the player wants to touch the gravestone. If he/she does, we scroll the map up to center the player’s vision on the statues. We need to differentiate between when the puzzle is active and when it is not. For that, we can have a switch called StatuePuzzleStart. When it is off, the puzzle is inactive. When it is on, the puzzle is active. Check the following code to see the gravestone event in its entirety and note the extra things that it has. Some of it may not make sense currently, but it should by the end of this exercise.

@>Conditional Branch: Switch [0029:StatuePuzzleDone] == OFF
   @>Conditional Branch: Switch [0030:StatuePuzzleStart] == OFF
      @>Text: -, -, Normal, Bottom
      :     : The gravestone says: Place the statues
      :     : on their pedestals to open the way forward.
      @>Text: -, -, Normal, Bottom
      :     : Will you touch the gravestone?
      @>Show Choices: Yes, No
      : When [Yes]
         @>Scroll Map: Up, 5, 4
         @>Set Move Route: Player (Wait)
         :               : $>Direction Fix ON
         @>Text: -, -, Normal, Bottom
         :     : Press A to reset the statues.
         :     : Press a directional key to move the statues.
         @>Control Switches: [0031:ButtonPressOFF] = ON
         @>Jump to Label: PuzzleStart
         @>
      : When [No]
         @>
      : Branch End
     @>
: Branch End
@>Label: PuzzleStart
@>Control Switches: [0030:StatuePuzzleStart] = ON
@>
: Branch End
@>Conditional Branch: Switch [0029:StatuePuzzleDone] == ON
   @>Text: -, -, Normal, Bottom
   :     : This gravestone no longer serves any purpose.
   @>
: Branch End
@>

So, the player has touched the gravestone and is now looking at the statues. We have to make it so that he/she can actually move them. That’s a job worthy of a Parallel Process event. First, however, two squares south of the gravestone, you’ll want to place a blank event that requires StatuePuzzleStart to be flipped on and has a Same As Characters priority. This ensures that the player is locked into one location for the duration of the puzzle. Given that we’re going to be using arrow key conditionals, we don’t want the player’s character to suddenly run off mid-puzzle.

Creating the Puzzle Logic Event

The Parallel Process event will have two pages. The first page will cover button presses, while the second page will check to see if the statues are at their desired destinations. Here’s the first part of page 1 of the Parallel Process event:

@>Conditional Branch: The Down Button is Being Pressed
   @>Set Move Route: [LeftStatue] (Skip)
   :               : $>Move Down
   @>Set Move Route: [RightStatue] (Skip, Wait)
   :               : $>Move Down
   @>Jump to Label: SpotCheck
   @>
: Branch End
@>Conditional Branch: The Left Button is Being Pressed
   @>Set Move Route: [LeftStatue] (Skip)
   :               : $>Move Left
   @>Set Move Route: [RightStatue] (Skip, Wait)
   :               : $>Move Right
   @>Jump to Label: SpotCheck
   @>
: Branch End
@>Conditional Branch: The Right Button is Being Pressed
   @>Set Move Route: [LeftStatue] (Skip)
   :               : $>Move Right
   @>Set Move Route: [RightStatue] (Skip, Wait)
   :               : $>Move Left
   @>Jump to Label: SpotCheck
   @>
: Branch End
@>Conditional Branch: The Up Button is Being Pressed
   @>Set Move Route: [LeftStatue] (Skip)
   :               : $>Move Up
   @>Set Move Route: [RightStatue] (Skip, Wait)
   :               : $>Move Up
   @>Jump to Label: SpotCheck
   @>
: Branch End

We have a conditional branch for each separate direction. Of course, it wouldn’t be much of a puzzle if both statues moved identically, so we make it so that the right statue (that would be the red one) moves on an inverted horizontal axis. In simpler terms, the red statue will move left when the player presses right and right when the player presses left. Notice how I only use the wait command once per branch. There’s nothing wrong with having a wait command on the left statue’s movement as well, but it just makes the puzzle take longer. When you set it up as I have, both of the statues will move in response to the key press, and the puzzle flows faster. Here’s the second half of page 1:

@>Conditional Branch: The X Button is Being Pressed
   @>Text: -, -, Normal, Bottom
   :     : Reset the statues?
   @>Show Choices: Yes, No
   : When [Yes]
      @>Set Event Location: [LeftStatue], (012,010)
      @>Set Move Route: [LeftStatue]
      :               : $>Turn toward Player
      @>Set Event Location: [RightStatue], (014,008)
      @>Set Move Route: [RightStatue] (Wait)
      :               : $>Turn toward Player
      @>Scroll Map: Down, 5, 4
      @>Set Move Route: Player (Wait)
      :               : $>Direction Fix OFF
      @>Control Switches: [0030:StatuePuzzleStart] = OFF
      @>
   : When [No]
      @>
   : Branch End
   @>
: Branch End
@>Label: SpotCheck
@>Control Switches: [0031:ButtonPressOFF] = OFF
@>Control Switches: [0032:ButtonPress] = ON
@>

As mentioned before, we want the player to have a way to stop the puzzle if he or she would rather do something else. RMVXA has three otherwise functionless buttons named X, Y, and Z that tie into the A, S, and D keys of a keyboard, respectively. So, when the player presses A during the puzzle, the game will ask if he or she wishes to reset the statues. Saying no does nothing, but saying yes returns both statues to their initial positions. We scroll the map down the number of squares that we had moved it up previously and turn off the Direction Fix that we had imposed on the character.

At the very bottom of page 1, we have the SpotCheck label referenced in the quartet of directional conditional branches. The pair of button press switches is used for flow control. In essence, we want the following sequence:

  • The player presses one of the arrow keys. The relevant actions are processed and switches are flipped, causing the Parallel Process page to execute page 2.
  • Page 2 of the event checks to see if both statues reached their respective pedestals in that particular button press.
  • If they didn’t, we toggle switches such that page 1 is now ready to be executed once again.

It is functionally a two-page loop that can be broken by puzzle completion or the player pressing A and selecting Yes. With that said, page 1 requires that StatuePuzzleStart and ButtonPressOFF be on. Page 2, on the other hand, requires that StatuePuzzleStart and ButtonPress be on. Don’t let the minor switch name differences trip you up! If they do, feel free to differentiate them a little more. Check the following code for the first part of page 2 of the Parallel Process event.

@>Control Variables: [0023:LeftStatueX] = [LeftStatue]'s Map X
@>Control Variables: [0024:LeftStatueY] = [LeftStatue]'s Map Y
@>Control Variables: [0025:RightStatueX] = [RightStatue]'s Map X
@>Control Variables: [0026:RightStatueY] = [RightStatue]'s Map Y
@>Conditional Branch: Variable [0023:LeftStatueX] == 11
   @>Conditional Branch: Variable [0024:LeftStatueY] == 8
      @>Conditional Branch: Variable [0025:RightStatueX] == 15
         @>Conditional Branch: Variable [0026:RightStatueY] == 8
            @>Text: -, -, Normal, Bottom
             :           : About time!
            @>Fadeout Screen
            @>Play SE: 'Push', 80, 100
            @>Set Event Location: [LeftStatue], (011,008)
            @>Set Event Location: [RightStatue], (015,008)
            @>Control Switches: [0029:StatuePuzzleDone] = ON
            @>Scroll Map: Down, 5, 4
            @>Fadein Screen
            @>Control Switches: [0030:StatuePuzzleStart] = OFF
            @>Set Move Route: Player (Wait)
            :                               : $>Direction Fix OFF
            @>
         : Else
            @>Jump to Label: DirectionCheck
            @>
         : Branch End
         @>
      : Else
         @>Jump to Label: DirectionCheck
         @>
      : Branch End
   @>
: Else
   @>Jump to Label: DirectionCheck

Dissecting the Statue Manipulation Puzzle Logic

Now, don’t run off just yet. This might seem a bit overwhelming, but it’s actually very simple. Here’s a play-by-play of what the preceding event does:

  • We create a whopping four new variables to store the values of X and Y for both of the statues.
  • Once adequately stored, we check said values against the pedestal positions, as defined earlier in this section.
  • If all four of the variables check out, it means that both statues are in their rightful places. We have Eric say a short remark and then fade out the screen.
  • A sound effect is played, and the event locations of both statues are moved to the pedestal location. If you do not do this, the statues will move back to their original locations after the player leaves the map. For our game’s purposes, this is actually unimportant (this will be a location visited only once), but it can be, if you want to make puzzles of this type in locations that the player would want to visit multiple times.
  • We set StatuePuzzleDone to on, scroll the map back down the same number of steps we scrolled it up before, and fade in.
  • The rest of the event has the same logic used when the player presses A to cancel out of the puzzle.
  • On the other hand, if any of the four variables are off, we jump to the DirectionCheck label near the bottom of the page.
   @>
: Branch End
@>Label: DirectionCheck
@>Control Switches: [0032:ButtonPress] = OFF
@>Control Switches: [0031:ButtonPressOFF] = ON
@>

By swapping which of the button press switches is toggled, we can switch between the two pages of the Parallel Process event as needed. On that note, we have concluded our third and final puzzle for the chapter!

Creating the Second Town

All that remains is adding a relevant location that will lead us to the snowy statue puzzle mountain area. Use Load Sample Map to add Mountain Village to your project’s map list. We’re going to be tweaking the bottom part of the village to serve our needs. Take a peek at Figure 11-6, to see the changes.

9781484207857_Fig11-06.jpg

Figure 11-6. The tweaked part of the Mountain Village. The rest of the terrain remains the same as normal

That cavern entrance connects with the one staircase in the Abandoned Mines we have not touched until now. For the sake of clarity, I’m talking about the stairs at (4,34) of FB1. The block impeding entry into the village is actually an event (the graphic is from !Door2) that transfers the player to our statue puzzle area. This block disappears once StatuePuzzleDone is turned on by completing the statue puzzle.

Additional Exercises

As is tradition, I’ll close out the chapter by giving you some exercises to work on.

  1. Create a crate-pushing puzzle that involves three buttons that need weight to stay pushed down. When all three buttons are pressed, open a door.
    • If you want to have a crate that can be both pushed and pulled, you could have a Show Choices command that disallows being canceled. Then, the player could choose whether to push or pull the crate.
    • Be mindful of the order of your movement events. You want the crate to move first when pushed, but you want the player to move first when it is pulled. Doing it backward is self-defeating at best and can hang your game at worst (if you don’t set the relevant move commands to skip, if they cannot be executed).
  2. Make some ice blocks that slide in one direction until they collide with an obstacle.
    • This is as simple as applying the same sliding logic to the blocks that we assign to the player.
    • The blocks can have an Action Button trigger. Given that they can be pushed from all directions, you’ll need to have a conditional branch for each of the player’s facings, to handle the block’s movement.

Summary

This chapter covered three puzzles that I have devised in the time that I’ve used RMVXA. We made a door that could only be opened by correctly answering a riddle, a movement puzzle involving slippery ice, and a manipulation puzzle involving a pair of dragon statues. In the next chapter, we’ll be populating our newly added town.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset