设为首页收藏本站同能贴吧 切换语言 繁体中文
开启辅助访问 切换到窄版
扫描二维码关注官方公众号
返回列表
+ 发新帖
查看: 96|回复: 0

[制作教程] Push/Pull Puzzle Tutorial

[复制链接]
累计送礼:
0 个
累计收礼:
1 个
  • TA的每日心情
    开心
    3 天前
  • 签到天数: 209 天

    连续签到: 2 天

    [LV.7]常住居民III

    4548

    主题

    864

    回帖

    2万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    VIP
    7
    卡币
    23103
    OK点
    16
    推广点
    0
    同能卷
    50
    积分
    28545

    灌水之王

    发表于 3 天前 | 显示全部楼层 |阅读模式
    Push/Pull Puzzle Tutorial
    By A-Moonless-Night
    Difficulty:Medium (this tutorial uses script calls)





    The purpose of this tutorial is to make a boulder that we can push and pull. There are far easier methods, but the mechanics of those are a little clunky, I feel, and I wanted to make a version that was similar to other games:

    1.       Press the action key to grab onto the boulder
    2.       Press the directional keys to push or pull the boulder
    3.       To release the boulder, press the action key again or turn away from the boulder

    As an added bonus, this tutorial also includes:

    1.       How to create a region that you can’t push the objects onto
    2.       An external event to check the placement of your objects
    3.       Methods for resetting the puzzle

    This tutorial includes some script calls in lieu of a multitude of variables and conditional branches, just to make things tidier. Copy the text as is and change the things I say to change and you should be fine.


    COMPATIBILITY:
    I’m not sure if this tutorial will work with pixel movement or 8-directional movement scripts.

    This tutorial would only work with MV if you were to alter the script snippets so they speak Javascript, OR use a bunch of variables and conditional branches instead.

    DEMO:
    If you don't feel like reading big ol' wall o' text, download the demo here: https://www.dropbox.com/s/y8suj0g4bi7fgnc/Push Pull tutorial.exe?dl=0
    I've tried to add comments in the events to show my workings.

    CREDITS:
    Feel free to credit me as A-Moonless-Night if you use this in your project, but it's not necessary.

    You must credit Shaz if you use her Remember Event Position script.

    TOOLS:

    Spoiler: You will need
    SCRIPTS:

    • Remember Event Position by Shaz
    Otherwise your events will all move back to their original places when you leave the map.
    Get it here: https://forums.rpgmakerweb.com/index.php?threads/remember-event-position.1853/


    GRAPHICS: (Optional)





    • A character set of your character pushing/pulling
    This is totally optional, but I think it looks better. You could set the Player to Stepping Animation instead (or do nothing, but I think it’s beneficial for the player to have a visual reminder of whether they’re pushing/pulling or not).


    VARIABLES:

    • Variable 0003:   Puzzle X (optional)
    • Variable 0004:   Puzzle Y (optional)
    • Variable 0005:   Region ID (optional)
    • Variable 0006:   Player Direction

    REGIONS: (optional)


    • Region ID 54:     Our ‘no-go’ Region
    • Region ID 20:     Region for Event 1 to go onto to complete puzzle
    • Region ID 21:     Region for Event 2 to go onto to complete puzzle

    AUDIO / SE:

    • Buzzer sound     (I use “Push”, 90 vol, 130 pitch)
    • Pushing sound   (I use “Push”, 80 vol, 100 pitch)
    • Pulling sound     (I use “Earth4”, 75 vol, 100 pitch)
    • Switch sound     (I use “Switch3”, 80 vol, 100 pitch) (optional)

    Setting up the Puzzle Area (optional)

    Spoiler




    For this tutorial, I’m going to be using a Region ID to designate an area that the pushable object cannot be moved onto. This is completely optional, but is useful for keeping the pushable objects to one part of the map, such as a designated ‘puzzle’ area.

    Create your map, and then your puzzle area. I like to use a different ground tile to show the areas where the objects can move, but that’s up to you. I also like to use one of the ‘symbol’ tiles to show the places where special objects should move onto to complete the puzzle.

    Once you’ve done that, use the Region Editor tool to paint the outside of the puzzle area with your no-go Region. In this tutorial, this will be Region 54, which I chose just because it’s less likely to be used for scripts and things, from what I’ve seen.

    If you’ve got an area that special objects should move onto to complete the puzzle, go ahead and paint those with differing Region IDs. I’ve used 20 for one and 21 for the other.







    Pushable Object/Boulder

    SpoilerFor the sake of this tutorial, I’m going to describe the pushable object as a boulder, but you can use any object/graphic that you like—whatever is relevant to you and your game. I will also include instructions for pushable objects that shouldn’t have a walking animation or should have a fixed direction, such as statues or braziers, and I’ll refer to those as fixed direction objects.

    First, we’re going to create an event, choose a graphic and give it a name. If it’s a moveable boulder, I’d name it Boulder and find a nice boulder graphic (there are boulders in the ‘!Other1’ character set).



    SpoilerPage 1:
    SpoilerThis page doesn’t need any conditions, so leave those. Tick the ‘Walking Anim.’ and ‘Direction Fix’ boxes. This is so that the boulder doesn’t turn to face us when we click on it.





    Set the trigger to Action Button and set the Speed to 2 and the Frequency to 3. This is because we want the boulder to move slowly, like we’re dragging it. Priority should be Same as Characters.

    For this page, we want to simply set Self Switch A to be on and then change the Actor’s graphic to a pushing graphic (optional)—alternatively, you can do Set Move Route> Player> Stepping Anim On. This is so the player has a visual cue that the pushing/pulling mechanic is ready.

                    Code:        
    1. Page 1:
    2. CONDITION: nil
    3. OPTIONS: Walking Anim ON, Direction Fix ON
    4. TRIGGER: Action Button
    5. SPEED: 2: 4x slower
    6. FREQ: 3: Normal
    7. @> Control Self Switch: A =ON
    8. @> Change Actor Graphic [pushing graphic] |OR| Set Move Route: Player (Wait) Stepping Anim ON
    复制代码






    Page 2:
    SpoilerCopy Event Page and then Paste Event Page (for convenience’s sake).

    First, we need to change the Trigger to Autorun and set the Condition to Self Switch A is ON. Delete the contents of the page.

    We’re going to make a Conditional Branch to check whether the player is pressing the action key/C button (which is space/enter/Z on your keyboard). Now, we could just go Conditional Branch > Button > C is Being Pressed, but I prefer to use this little script instead:
                    Code:        
    1. Input.trigger?(:C)
    复制代码






    This checks if the button has been tapped, rather than pushed and held. So, on tab 4 of the Conditional Branch window, select Script and type that in. Tick ‘Set handling when conditions do not apply’.

    Inside our Conditional Branch, we want to make a short wait of 5 frames, and then turn Self Switch A, B and C OFF. We also want to change our Actor Graphic back to its usual graphic (or set the Player Stepping Anim OFF).

    Now, inside our Else branch for that Conditional Branch, we want to make a set of Conditional Branches that check the direction the Player is facing, and then check which buttons are being pressed.

    We will need one Conditional Branch per direction, with Else off, and then some Conditional Branches nested inside each other that check the matching, opposite and other directions.

    For example, if the Player was facing Down, we would check if the Down Button was being pressed, and then in the Else branch check if the Up Button was being pressed, and then in that Else branch we would check whether the Left OR Right Buttons were being pressed.

    The easiest way to check multiple directions at once is to use the following script call in a Conditional Branch:
                    Code:        
    1. Input.press?(:LEFT) || Input.press?(:RIGHT)
    复制代码


    The || means OR in Ruby. To check Up or Down, you would replace the words inside the parentheses with  :UP  and  
    OWN
    . You could also use two more Conditional Branches nested inside each other, but this seemed tidier and kills two birds with one stone.

    Inside our matching direction Conditional Branch, we want to set the Self Switch B to ON. This is going to be our ‘pushing’ page (but more on that later).

    Inside our opposite direction Conditional Branch, we want to set Self Switch C to ON—this will be our ‘pulling’ page.

    In the other directions Conditional Branch, we want to do the same as the first Conditional Branch for pressing the action key (wait 5 frames, turn Self Switch A, B and C OFF, and change our Actor Graphic to its usual graphic/set the Player Stepping Anim OFF).

    Do this for each direction. I also put a comment at the top of each Conditional Branch saying what direction it’s for, just to remind myself.





    Spoiler                 Code:        
    1. Page 2:
    2. CONDITION: Self Switch A =ON
    3. OPTIONS: Walking Anim ON, Direction Fix ON
    4. TRIGGER: Autorun
    5. SPEED: 2: 4x slower
    6. FREQ: 3: Normal
    7. @> Conditional Branch: Script: Input.trigger?(:C)
    8.     @> Wait: 5 frames
    9.     @> Control Self Switch: A =OFF
    10.     @> Control Self Switch: B =OFF
    11.     @> Control Self Switch: C =OFF
    12.     @> Change Actor Graphic: [normal] |OR| Set Move Route: Player (Wait) Stepping Anim OFF
    13.     @>
    14. : Else
    15.     @> Conditional Branch: Player is Facing Down
    16.         @> Conditional Branch: The Down Button is Being Pressed
    17.             @> Control Self Switch: B =ON
    18.         : Else
    19. @> Conditional Branch: The Up Button is Being Pressed
    20.                 @> Control Self Switch: C =ON
    21.             : Else
    22.                 @> Conditional Branch: Script: Input.press?(:LEFT) ||
    23. Input.press?(:RIGHT)
    24.                     @> Wait: 5 frames
    25.                     @> Control Self Switch: A =OFF
    26.                     @> Control Self Switch: B =OFF
    27.                     @> Control Self Switch: C =OFF
    28.                     @> Change Actor Graphic: [normal] |OR| Set Move Route: Player (Wait) Stepping Anim OFF
    29.                     @>
    30.                     Branch End
    31.                 @>
    32.                 Branch End
    33.             @>
    34.             Branch End
    35.         @>
    36.         Branch End
    37. @> Conditional Branch: Player is Facing Left
    38.         @> Conditional Branch: The Left Button is Being Pressed
    39.             @> Control Self Switch: B =ON
    40.         : Else
    41. @> Conditional Branch: The Right Button is Being Pressed
    42.                 @> Control Self Switch: C =ON
    43.             : Else
    44.                 @> Conditional Branch: Script: Input.press?(:UP) || Input.press?(:DOWN)
    45.                     @> Wait: 5 frames
    46.                     @> Control Self Switch: A =OFF
    47.                     @> Control Self Switch: B =OFF
    48.                     @> Control Self Switch: C =OFF
    49.                     @> Change Actor Graphic: [normal] |OR| Set Move Route: Player (Wait) Stepping Anim OFF
    50.                     @>
    51.                     Branch End
    52.                 @>
    53.                 Branch End
    54.             @>
    55.             Branch End
    56.         @>
    57.         Branch End
    58. @> Conditional Branch: Player is Facing Right
    59.         @> Conditional Branch: The Right Button is Being Pressed
    60.             @> Control Self Switch: B =ON
    61.         : Else
    62. @> Conditional Branch: The Left Button is Being Pressed
    63.                 @> Control Self Switch: C =ON
    64.             : Else
    65.                 @> Conditional Branch: Script: Input.press?(:UP) || Input.press?(:DOWN)
    66.                     @> Wait: 5 frames
    67.                     @> Control Self Switch: A =OFF
    68.                     @> Control Self Switch: B =OFF
    69.                     @> Control Self Switch: C =OFF
    70.                     @> Change Actor Graphic: [normal] |OR| Set Move Route: Player (Wait) Stepping Anim OFF
    71.                     @>
    72.                     Branch End
    73.                 @>
    74.                 Branch End
    75.             @>
    76.             Branch End
    77.         @>
    78.         Branch End
    79. @> Conditional Branch: Player is Facing Up
    80.         @> Conditional Branch: The Up Button is Being Pressed
    81.             @> Control Self Switch: B =ON
    82.         : Else
    83. @> Conditional Branch: The Down Button is Being Pressed
    84.                 @> Control Self Switch: C =ON
    85.             : Else
    86.                 @> Conditional Branch: Script: Input.press?(:LEFT) || Input.press?(:RIGHT)
    87.                     @> Wait: 5 frames
    88.                     @> Control Self Switch: A =OFF
    89.                     @> Control Self Switch: B =OFF
    90.                     @> Control Self Switch: C =OFF
    91.                     @> Change Actor Graphic: [normal] |OR| Set Move Route: Player (Wait) Stepping Anim OFF
    92.                     @>
    93.                     Branch End
    94.                 @>
    95.                 Branch End
    96.             @>
    97.             Branch End
    98.         @>
    99.         Branch End
    复制代码










    Page 3: The ‘Pushing’ Page
    SpoilerHopefully you all are still with me! Now, let’s Copy Page 2 and then Paste Event Page. We want the Condition to be Self Switch B =ON and we want to turn Direction Fix off (unless you have a fixed object that shouldn’t turn, such as a statue). This will be our ‘pushing’ page.

    For this page, we also want a Conditional Branch that checks if the action key is being pressed and turns off those same self switches, so you can just leave the one there from the previous page (provided that you copied and pasted that page). Delete the other branches.



    SpoilerThis next part is if you want to have a region that the boulder cannot go onto, so just ignore this if you don’t want it.

    Inside the Else branch, control Variable 3 (Puzzle X) so that it’s equal to this event’s Map X. Set the operation to Set and then select Game Data > Character > This event’s Map X. OR go to Script and enter in the following code:
                    Code:        
    1. $game_map.events[event_id].x
    复制代码


    You can do either; they do the same thing. Next, control Variable 4 (Puzzle Y) and set it to this event’s Map Y by either going Game Data > Character > This event’s Map Y, OR use the code above, but replace the x with y.

    Now, since we’re going to be pushing the boulder, we want to check what the Region ID is for the tile behind the boulder. There’s not really any elegant way to do this, so we’re going to use a script call to check the player’s direction and then alter either the X or Y coordinates accordingly. We’ve stored those in the variables above to make it easier. Select Script Call and enter the following code:
                    Code:        
    1. if $game_player.direction == 2         #down
    2. $game_variables[4] += 1              #Y
    3. elsif $game_player.direction == 4    #left
    4. $game_variables[3] -= 1              #X
    5. elsif $game_player.direction == 6    #right
    6. $game_variables[3] += 1             #X
    7. else                                                        #up
    8. $game_variables[4] -= 1             #Y
    9. end
    复制代码


    I’ve used little comments in the script call (since I had space) to remind me which number equals which direction:


    • Down is 2
    • Left is 4
    • Right is 6
    • Up is 8.
    I’ll try not to spend the rest of this tutorial explaining what X and Y coordinates are, but here’s a quick exercise:

    Spoiler: Checking X and Y coordinates
    If you click the top left-hand corner of your map, you’ll see the coordinates in the bottom right-hand corner are 000,000. Now, click each tile down along the left margin. As you click each tile, you’ll see the coordinates change to 000,001, and then 000,002, etc. This is the Y coordinate.

    Go back to the top-left corner and this time, click along to the right along the top margin. Like before, you’ll see the numbers change, but this time it’ll be the X coordinate: 001,000, then 002,000, 003,000, etc.

    Basically, we’re either adding or subtracting from the relevant coordinate to locate the tile directly behind the event.

    Of course, we could use a bunch of Conditional Branches for this, but since they’re pretty simple checks (in my opinion), it’s a lot easier to just do a script call. The IF and ELSIF and ELSE statements function the same as a bunch of nested Conditional Branches.
    Next, we want to use Get Location Info (which is on the third tab of Event Commands underneath ‘Map’—I struggled to find it because I hadn’t used it before!) and we’re going to use this to get the Region ID from those Variables we set earlier.





    Under ‘Variable for Info’, choose Variable 5 (Region ID), and under ‘Info Type’, select Region ID. Select ‘Designation with variables’ and then put Variable 3 by Map X and Variable 4 by Map Y.

    Create a Conditional Branch that checks if Variable 5 (Region ID) is equal to 54, which is the region I’ve chosen to be impassable for boulder events. Inside this Conditional Branch, we want to play our buzzer sound effect to show that the boulder can’t move, and then we want to wait 5 frames, turn Self Switch A, B and C OFF, and change our Actor Graphic to its usual graphic/set the Player Stepping Anim OFF.

    Inside the Else branch of that Conditional Branch (or inside the Else branch of C Button Conditional Branch, if you didn’t want to use the Region ID gimmick), we’re going to make yet ANOTHER Conditional Branch (this tutorial involves a lot of checks, believe me), this time with a script call:
                    Code:        
    1. !$game_map.events[@event_id].passable?($game_map.events[@event_id].x, $game_map.events[@event_id].y, $game_player.direction)
    复制代码


    To break it down, the script call looks like this:
                    Code:        
    1. $game_map.events[EVID].passable?(X, Y, D)
    复制代码


    and asks if a tile is passable for EVID (event ID) at X and Y coordinates from Direction. You replace the EVID, X, Y and D with the relevant info. We put ! at the start of the script call so that it now asks whether a tile is NOT passable.

    Now, inside this branch, much like the previous branch, we want to play our buzzer sound, wait 5 frames, turn Self Switch A, B and C OFF, and change our Actor Graphic to its usual graphic/set the Player Stepping Anim OFF.

    In the Else branch, we want to play our pushing sound effect, and then we want to make the event move away from the player and the player step toward the event. This will make it seem like the player is pushing the boulder.

    Spoiler: Fixed Direction Objects
    If you have a fixed direction object, such as a statue, then make four separate Conditional Branches for each direction the player is facing, and then set a different move route inside each one. For example, if the player was facing down, you would make the statue move down, and if the player was facing left, you make the statue move left, etc. After those Conditional Branches, then do the move route for the player.




    Then we need to use the following script call to make it so that the boulder will remember this position next time we load the map:
                    Code:        
    1. $game_map.events[@event_id].save_pos()
    复制代码

    Make sure you have Shaz’s Remember Event Position script in your project, otherwise this will throw an error.





    Then, at the end of all of those branches, bar the one for the C button, we want to turn Self Switches B and C off.
    Spoiler                 Code:        
    1. Page 3:
    2. CONDITION: Self Switch B =ON
    3. OPTIONS: Walking Anim ON
    4. TRIGGER: Autorun
    5. @> Conditional Branch: Script: Input.trigger?(:C)
    6.     @> Wait: 5 frames
    7.     @> Control Self Switch: A =OFF
    8.     @> Control Self Switch: B =OFF
    9.     @> Control Self Switch: C =OFF
    10.     @> Change Actor Graphic: [normal] |OR| Set Move Route: Player (Wait) Stepping Anim OFF    @>
    11. : Else
    12.     @> Control Variables: [0003: Puzzle X] = $game_map.events[event_id].x
    13. @> Control Variables: [0004: Puzzle Y] = $game_map.events[event_id].y
    14. @> Script: if $game_player.direction == 2 #down
    15. $game_variables[4] += 1
    16. elsif $game_player.direction == 4 #left
    17. $game_variables[3] -= 1
    18. elsif $game_player.direction == 6 #right
    19. $game_variables[3] += 1
    20. else #up
    21. $game_variables[4] -= 1
    22. end
    23. @> Get Location Info: (VAR)[0005], Region ID, Variable [0003][0004]
    24. @> Conditional Branch: Variable [0005: Puzzle Region ID] == 54
    25. @> Play SE: [buzzer sound]
    26.         @> Wait: 5 frames
    27.         @> Control Self Switch: A =OFF
    28.         @> Control Self Switch: B =OFF
    29.         @> Control Self Switch: C =OFF
    30.         @> Change Actor Graphic: [normal] |OR| Set Move Route: Player (Wait) Stepping Anim OFF
    31.         @>
    32.     : Else
    33. @> Conditional Branch: Script: !$game_map.events[@event_id].passable?($game_map.events[@event_id].x, $game_map.events[@event_id].y, $game_player.direction)
    34.         @> Play SE: [buzzer sound]
    35.             @> Wait: 5 frames
    36.             @> Control Self Switch: A =OFF
    37.             @> Control Self Switch: B =OFF
    38.             @> Control Self Switch: C =OFF
    39.             @> Change Actor Graphic: [normal] |OR| Set Move Route: Player (Wait) Stepping Anim OFF            @>
    40.         : Else
    41.             @> Play SE: [pushing sound]
    42.             @> Set Move Route: This event (skip)
    43.                 $> Turn toward Player
    44.                 $> 1 Step Backward
    45.             @> Set Move Route: Player
    46.                 $> Change Speed: 2
    47.                 $> 1 Step Forward
    48.                 $> Change Speed: 4
    49.             @> Wait: 60 frames
    50. @> Script: $game_map.events[@event_id].save_pos()
    51.             @>
    52.             Branch End
    53.         @>
    54.         Branch End
    55.     @> Control Self Switch: B =OFF
    56.     @> Control Self Switch: C =OFF
    57. @>
    复制代码











    Page 4: The ‘Pulling’ Page
    SpoilerNow it’s time for our ‘pulling’ page. Copy Page 3 and then Paste Event Page. We want the Condition to be Self Switch C =ON.

    Keep the Conditional Branch that checks for the action button being pressed, as well as the processes there (turning the self switches off and changing the actor graphic/stepping animation). Delete everything in the Else branch.



    SpoilerOnce again, this next part is for the region ID check, so skip it if you don’t want it.

    We want to make a Conditional Branch and use the following script call:
                    Code:        
    1. $game_player.region_id != 54
    复制代码


    This checks if the player’s region ID is NOT equal to 54, our impassable region. We use this check because the tile the boulder will end up on is the one underneath the player, since we’re pulling the boulder toward us.

    Skip the above if you don’t want to use the Regions.

    Now we need to check if the player can actually move onto the tile behind them, and we will do this by figuring out which direction the player is facing and setting a variable to the opposite of that. To do this, we want to use a script call:
                    Code:        
    1. if $game_player.direction == 2          #down
    2. $game_variables[6] = 8
    3. elsif $game_player.direction == 4      #left
    4. $game_variables[6] = 6
    5. elsif $game_player.direction == 6      #right
    6. $game_variables[6] = 4
    7. else                                                         #up
    8. $game_variables[6] = 2
    9. end
    复制代码


    Basically, if we’re facing Down (aka direction 2), we want to set the variable (Variable 6, Player Direction) to the opposite, which is Up (aka Direction 8), and then we do this check for each direction. Once again, this can be achieved with conditional branches, but I think this is easier.

    Next, we want to do another Conditional Branch with a script call, this time to check if the tile the player will move onto is NOT passable. This is kind of like the check we did for the event in the pushing page, except using the player instead:
                    Code:        
    1. !$game_player.passable?($game_player.x, $game_player.y, $game_variables[6])
    复制代码


    Let’s break it down: the script call is
                    Code:        
    1. $game_player.passable?(X, Y, D)
    复制代码


    and checks if the tile at X and Y coordinates is passable for the player from Direction. We put ! at the start to check if it is NOT passable, and then use the player’s current coordinates for X and Y, and then we use Variable 6 for the Direction—this variable is the one that we just loaded the opposite of the player’s current direction into.

    Still with me? Inside this Conditional Branch, we want to play our buzzer sound, wait 5 frames, turn Self Switch A, B and C OFF, and change our Actor Graphic to its usual graphic/set the Player Stepping Anim OFF.

    In the Else branch, we want to play our pulling sound effect, and then make the player take one step backward (with direction fix on). We make a wait of 5 frames, and then we make the boulder turn toward the player and take one step forward (with through on and direction fix on). Then wait 65 frames.

    Spoiler: Fixed Direction Objects
    If you have a fixed direction object, such as a statue, do the move route for the player and then make four separate Conditional Branches for each direction the player is facing, and then set a different move route inside each one. For example, if the player was facing down, you would make the statue move up, and if the player was facing left, you make the statue move right, etc.




    Then, like with our pushing page, we need to use this script call to make it so that the boulder will remember this position next time we load the map:
                    Code:        
    1. $game_map.events[@event_id].save_pos()
    复制代码






    Now, we should have reached the Else branch of our previous Conditional Branch. In this one, play our buzzer sound, wait 5 frames, turn Self Switch A, B and C OFF, and change our Actor Graphic to its usual graphic/set the Player Stepping Anim OFF.

    Then, at the end of all of those branches, bar the one for the C button, we want to turn Self Switches B and C off.

    Spoiler                 Code:        
    1. Page 4:
    2. CONDITION: Self Switch C =ON
    3. OPTIONS: Walking Anim ON
    4. TRIGGER: Autorun
    5. SPEED: 2: 4x slower
    6. FREQ: 3: Normal
    7. @> Conditional Branch: Script: Input.trigger?(:C)
    8.     @> Wait: 5 frames
    9.     @> Control Self Switch: A =OFF
    10.     @> Control Self Switch: B =OFF
    11.     @> Control Self Switch: C =OFF
    12.     @> Change Actor Graphic: [normal] |OR| Set Move Route: Player (Wait) Stepping Anim OFF    @>
    13. : Else
    14.     @> Conditional Branch: Script: $game_player.region_id != 54
    15.         @> Script: if $game_player.direction == 2 #down
    16. $game_variables[6] = 8
    17. elsif $game_player.direction == 4 #left
    18. $game_variables[6] = 6
    19. elsif $game_player.direction == 6 #right
    20. $game_variables[6] = 4
    21. else #up
    22. $game_variables[6] = 2
    23. end
    24. @> Conditional Branch: Script: !$game_player.passable?($game_player.x, $game_player.y, $game_variables[6])
    25.         @> Play SE: [buzzer sound]
    26.             @> Wait: 5 frames
    27.             @> Control Self Switch: A =OFF
    28.             @> Control Self Switch: B =OFF
    29.             @> Control Self Switch: C =OFF
    30.             @> Change Actor Graphic: [normal] |OR| Set Move Route: Player (Wait) Stepping Anim OFF    @>
    31. : Else
    32.     @> Play SE: [pulling sound]
    33.     @> Set Move Route: Player
    34.         $> Direction Fix ON
    35.         $> Change Speed: 2
    36.         $> 1 Step Backward
    37.         $> Direction Fix OFF
    38.         $> Change Speed: 4
    39.     @> Wait: 5 frames
    40.     @> Set Move Route: This event (skip)
    41.         $> Through ON
    42.         $> Direction Fix OFF
    43.         $> Turn toward Player
    44.         $> 1 Step Forward
    45.         $> Direction Fix ON
    46.         $> Through OFF
    47.     @> Wait: 65 frames
    48.     @> Script: $game_map.events[@event_id].save_pos()
    49.     @>
    50.     Branch End
    51. : Else
    52. @> Play SE: [buzzer sound]
    53.             @> Wait: 5 frames
    54.             @> Control Self Switch: A =OFF
    55.             @> Control Self Switch: B =OFF
    56.             @> Control Self Switch: C =OFF
    57.             @> Change Actor Graphic: [normal] |OR| Set Move Route: Player (Wait) Stepping Anim OFF    @>
    58.     Branch End
    59. @> Control Self Switch: B =OFF
    60. @> Control Self Switch: C =OFF
    61. @>
    62. Branch End
    63. @>
    64. Branch End
    复制代码












    Page 5:(Optional)
    SpoilerIf you want to make it so that the boulder can’t move once the puzzle is finished, there are a few ways you can do this, depending on your puzzle.





    Copy Event Page 4 and delete everything, and set the Condition to be Self Switch D =ON, or a Switch that turns on when the puzzle is complete (whatever is easier). Set the Trigger to Action Button and leave the page blank.

    If your graphic is a statue, you can change it to be one with glowing eyes or flames or something that makes it visually obvious to the player that they can’t move it anymore.

                    Code:        
    1. Page 5: (optional)
    2. CONDITION: Self Switch D =ON
    3. OPTIONS: Walking Anim OFF, Direction Fix ON (Stepping Anim ON if the graphic allows)
    4. TRIGGER: Action Button
    5. SPEED: 2: 4x slower
    6. FREQ: 3: Normal
    复制代码











    Using an external event to control your puzzle

    SpoilerWe can also make a separate event that checks the position of our special objects. There are a couple of ways we can do this, but this is what I prefer to do:

    First, decide whether you want to use region IDs to track the position of your puzzle pieces, or whether you want to use map coordinates (X and Y).

    If you are going to use region IDs, I’d suggest using a separate ID for each square or area you want to push the object onto.

    If you’re going to use map coordinates, you can find these by selecting the tile you want in the editor and then checking the bottom right-hand corner for the coordinates (e.g. 005,006, which is X,Y).



    Spoiler




    For this tutorial, we’ll use Region IDs.

    Page 1 (external event):
    SpoilerCreate an event and leave the graphic blank. We want to set the Trigger to Parallel Process.

    Basically, the purpose of this event is to check whether our special object is on the spot where we want it to be, and if it is, then we want to turn said object’s self switch to D (which is the Page 5 we made earlier) to make it immovable.

    So, in the contents, if we’re using Region ID, we want to create a Conditional Branch with the script call:
                    Code:        
    1. $game_map.events[EVID].region_id == REGID
    复制代码


    Change EVID to the ID of the event you want to go there and REGID to the ID of the Region you’re using.

    For this tutorial, we’ll use Regions 20 and 21 for two separate objects. Event 1 will need to be pushed onto Region 20 and Event 2 will need to be pushed onto Region 21.




    SpoilerSpoiler: Coordinates option
    If you are using coordinates, then the script call will be the following:
                    Code:        
    1. $game_map.events[EVID].x == XCOORD && $game_map.events[EVID].y == XCOORD
    复制代码


    This checks if EVID’s coordinates are equal to both XCOORD and YCOORD. && means and. Just change EVID to the ID of the event you want to go there and XCOORD and YCOORD to their respective coordinates.

    Inside the conditional branch, we want to make a script call:
                    Code:        
    1. $game_self_switches[[@map_id, EVID, “D”]] == true
    复制代码


    Replace EVID with the ID of your event. Play your switch sound effect, and then copy and paste the above script call, but make it so that EVID’s self switch A is equal to false. Copy and paste it again and again and do that for self switches B and C.

    Now we want to change the actor’s graphic back to normal or set the stepping animation off, and we also want to set their speed to normal and turn direction fix off. This is important, otherwise they’ll keep looking like they’re pushing something or keep staring in one direction.

    Finally, turn this event’s Self Switch A ON.

    Copy and paste the above Conditional Branch and change the EVIDs, Region IDs, etc., so that they are relevant for our other event, Event 2. Rather than turning on Self Switch A, we want to turn Self Switch B ON.

    Spoiler                 Code:        
    1. Page 1 (external event):
    2. TRIGGER: Parallel Process
    3. @> Conditional Branch: Scripts: $game_map.events[1].region_id == 20
    4.     @> Script: $game_self_switches[[@map_id, 1, “D”]] == true
    5.     @> Play SE: [switch sound]
    6.     @> Script: $game_self_switches[[@map_id, 1, “A”]] == false
    7. @> Script: $game_self_switches[[@map_id, 1, “B”]] == false
    8. @> Script: $game_self_switches[[@map_id, 1, “C”]] == false
    9. @> Change Actor Graphic: [normal] |OR| Set Move Route: Player (Wait) Stepping Anim OFF
    10. @> Set Move Route: Player (Wait)
    11. $>Direction Fix OFF
    12. $>Change Speed: 4
    13. @> Control Self Switch: A =ON
    14. @>
    15. : Branch End
    16. @> Conditional Branch: Scripts: $game_map.events[2].region_id == 21
    17.     @> Script: $game_self_switches[[@map_id, 2, “D”]] == true
    18.     @> Play SE: [switch sound]
    19.     @> Script: $game_self_switches[[@map_id, 2, “A”]] == false
    20. @> Script: $game_self_switches[[@map_id, 2, “B”]] == false
    21. @> Script: $game_self_switches[[@map_id, 2, “C”]] == false
    22. @> Change Actor Graphic: [normal] |OR| Set Move Route: Player (Wait) Stepping Anim OFF
    23. @> Set Move Route: Player (Wait)
    24. $>Direction Fix OFF
    25. $>Change Speed: 4
    26. @> Control Self Switch: B =ON
    27. @>
    28. : Branch End
    复制代码











    Page 2 (external event):
    SpoilerThe easiest thing is to copy the first event page and then paste event page. Set the condition to Self Switch A =ON. Delete the first Conditional Branch and change the event so that it turns its Self Switch C ON.

    Spoiler                 Code:        
    1. Page 2 (external event):
    2. CONDITION: Self Switch A =ON
    3. TRIGGER: Parallel Process
    4. @> Conditional Branch: Scripts: $game_map.events[2].region_id == 21
    5.     @> Script: $game_self_switches[[@map_id, 2, “D”]] == true
    6.     @> Play SE: [switch sound]
    7.     @> Script: $game_self_switches[[@map_id, 2, “A”]] == false
    8. @> Script: $game_self_switches[[@map_id, 2, “B”]] == false
    9. @> Script: $game_self_switches[[@map_id, 2, “C”]] == false
    10. @> Change Actor Graphic: [normal] |OR| Set Move Route: Player (Wait) Stepping Anim OFF
    11. @> Set Move Route: Player (Wait)
    12. $>Direction Fix OFF
    13. $>Change Speed: 4
    14. @> Control Self Switch: C =ON
    15. @>
    16. : Branch End
    复制代码










    Page 3 (external event):
    SpoilerOnce again, copy the first event page, select page 2 and then paste event page—this is so it appears at the end. Set the condition to Self Switch B =ON. Delete the second Conditional Branch and change the event so that it turns its Self Switch C ON.

    Alternatively, rather than having a Self Switch, you can create a switch just for this puzzle. I prefer to use self switches, purely because I’m super stingy when it comes to my switches, but it’s up to you. A regular switch is probably easier.

    Spoiler                 Code:        
    1. Page 3 (external event):
    2. CONDITION: Self Switch B =ON
    3. TRIGGER: Parallel Process
    4. @> Conditional Branch: Scripts: $game_map.events[1].region_id == 20
    5.     @> Script: $game_self_switches[[@map_id, 1, “D”]] == true
    6.     @> Play SE: [switch sound]
    7.     @> Script: $game_self_switches[[@map_id, 1, “A”]] == false
    8. @> Script: $game_self_switches[[@map_id, 1, “B”]] == false
    9. @> Script: $game_self_switches[[@map_id, 1, “C”]] == false
    10. @> Change Actor Graphic: [normal] |OR| Set Move Route: Player (Wait) Stepping Anim OFF
    11. @> Set Move Route: Player (Wait)
    12. $>Direction Fix OFF
    13. $>Change Speed: 4
    14. @> Control Self Switch: C =ON OR Control Switches: [##: Puzzle Complete] =ON
    15. @>
    16. : Branch End
    复制代码










    Page 4 (external event):
    SpoilerFinally, create a new event page and set the condition to Self Switch C =ON. The trigger should be Action Button.

    If you would prefer to have a regular switch turn on when the puzzle is complete, set that as the trigger instead.

    Spoiler                 Code:        
    1. Page 4 (external event):
    2. CONDITION: Self Switch C =ON  OR Switch ##: Puzzle Complete =ON
    3. TRIGGER: Action Button
    复制代码















    Resetting your puzzle

    SpoilerBut let’s say we’re playing our game and we get halfway through our puzzle and realise that we’ve stuffed it up, or we should have done it a different way. Since we’re using Shaz’s Remember Event Position script, we can’t just leave the room and come back in—everything will still be the same.

    There are a few ways we can do this, and I’ll explain a couple of options below.

    Option 1: I want the pieces to reset if I leave the room
    SpoilerFor this option, you simply need to add the following to any exits you have in your puzzle room.





    We need to check to see whether the puzzle is complete or not. Make a Conditional Branch before your Transfer Player command, and have it check to see if our puzzle switch is OFF. This is either checking if our checker event’s Self Switch C (or whatever is the self switch is for the final, empty page) is on, or checking to see if our Puzzle Complete switch is off—it depends on what you prefer.

    If you’re using the self switch option, then you’ll need to use this script call in your Conditional Branch:
                    Code:        
    1. $game_self_switches[[@map_id, EVID, "C"]] == false
    复制代码


    EVID should be the ID of the external checker event.

    We don’t need to have Set Handling checked. Inside this Conditional Branch, use the following script call for each of your pushable objects:
                    Code:        
    1. $game_map.events[EVID].forget_pos()
    复制代码


    This makes it so that the event forgets its previously remembered position and moves back to its default position.

    Then we need to turn the self switches for our special objects off:
                    Code:        
    1. $game_self_switches[[@map_id, EVID, "D"]] = false
    复制代码


    And finally, we need to turn the self switches for our external checker event off, using the same script call above. Set Self Switches B and A off.

    This will only happen if the puzzle isn’t complete yet—otherwise, you’ll transfer to the next map as usual and everything will stay put.

    Spoiler                 Code:        
    1. Option 1:
    2. @> Play SE: [transfer sound]
    3. @> Fadeout Screen
    4. @> Wait: 15 frames
    5. @> Conditional Branch: Script: $game_self_switches[[@map_id, 7, “C”]] == false
    6.     @> Script: $game_map.events[1].forget_pos()
    7.     @> Script: $game_map.events[2].forget_pos()
    8.     @> Script: $game_map.events[3].forget_pos()
    9. @> Script: $game_map.events[4].forget_pos()
    10.     @> Script: $game_self_switches[[@map_id, 1, "D"]] = false
    11.     @> Script: $game_self_switches[[@map_id, 2, "D"]] = false
    12.     @> Script: $game_self_switches[[@map_id, 7, "A"]] = false
    13. @> Script: $game_self_switches[[@map_id, 7, "B"]] = false
    14. @>
    15. : Branch End
    16. @> Transfer Player: [## Your Map]
    17. @> Wait: 15 frames
    18. @> Fadein Screen
    19. @>
    复制代码










    Option 2: I want to use a button/lever to reset the puzzle
    SpoilerFirst, we need to make our event. This could be a lever on the floor or a button on the wall, or even a person standing in the corner. Just make sure it’s away from the actual puzzle. Give it an appropriate graphic. For this tutorial, I’m using a lever.

    For the lever, set Walking Anim and Direction Fix on. The trigger should be Action Button.

    Make a Conditional Branch and use the following script call (or check if your Puzzle Switch is ON):
                    Code:        
    1. $game_self_switches[[@map_id, EVID, "C"]] == true
    复制代码


    EVID should be the ID of your checker event.

    Make sure Set Handling is checked.





    Inside this Conditional Branch, put anything you want to happen once the puzzle is COMPLETE, such as the lever clicking but not moving, a message saying “the lever is stuck”, etc.

    In the Else branch, set Move Route for the lever and have it turn. It depends on what graphic you are using, but if you’re just using one of the default levers, then turn Direction Fix OFF, have it turn left, wait, and then right. You can also play a ‘switch’ sound.

    Fadeout screen, and then set each Event’s location back to its original spot. This might be a little time-consuming, because you have to select each event on the map, remember its ID and where it is, and then enter that under Direct Designation.

    After that, we use that script call for Shaz’s Remember Event Position script to set these events back to their default position:
                    Code:        
    1. $game_map.events[EVID].forget_pos()
    复制代码


    Then we need to turn the self switches for our special objects off:
                    Code:        
    1. $game_self_switches[[@map_id, EVID, "D"]] = false
    复制代码


    And finally, we need to turn the self switches for our external checker event off, using the same script call above. Set Self Switches B and A off.

    Set Move Route for the lever again and have it turn down, and then set Direction Fix ON.

    Wait 15 frames, and then fadein screen.

    Spoiler                 Code:        
    1. Option 2:
    2. @> Conditional Branch: Script: $game_self_switches[[@map_id, 7, “C”]] == true
    3.     @> Set Move Route: This event (Wait)
    4.         $> Direction Fix OFF
    5.         $> Turn Left
    6.         $> SE: [switch sound]
    7.         $> Wait: 10 frames
    8.         $> Turn Right
    9.         $> Wait: 10 frames
    10.         $> Turn Left
    11.         $> Wait: 10 frames
    12.         $> Turn Down
    13.         $> Direction Fix ON
    14. @>
    15. : Else
    16. @> Fadeout Screen
    17. @> Wait: 15 frames
    18. @> Set Event Location: [Event Name], (X, Y)
    19. @> Set Event Location: [Event Name], (X, Y)
    20. @> Set Event Location: [Event Name], (X, Y)
    21. @> Set Event Location: [Event Name], (X, Y)
    22. @> Script: $game_map.events[1].forget_pos()
    23.     @> Script: $game_map.events[2].forget_pos()
    24.     @> Script: $game_map.events[3].forget_pos()
    25. @> Script: $game_map.events[4].forget_pos()
    26.     @> Script: $game_self_switches[[@map_id, 1, "D"]] = false
    27.     @> Script: $game_self_switches[[@map_id, 2, "D"]] = false
    28.     @> Script: $game_self_switches[[@map_id, 7, "A"]] = false
    29. @> Script: $game_self_switches[[@map_id, 7, "B"]] = false
    30. @> Set Move Route: This event (Wait)
    31.         $> Turn Down
    32.         $> Direction Fix ON
    33. @> Wait: 15 frames
    34. @> Fadein Screen
    35. @>
    36. : Branch End
    复制代码










    Option 3: I want the player to press a button to reset the puzzle
    Spoiler



    Yessir. Now, there are a couple of ways that you can do this, but having a parallel process event on the puzzle map is probably the easiest. It’s much like the lever event, except with a few changes.

    Make an event and set the trigger to Parallel Process. You don’t need to fiddle with anything else.

    Make a Conditional Branch that checks to see if a button is being pressed. For the sake of this tutorial, we’re going to use the A button, which is the SHIFT key.

    Inside the Conditional Branch, make another Conditional Branch and use the following script call (or check if your Puzzle Switch is ON):
                    Code:        
    1. $game_self_switches[[@map_id, EVID, "C"]] == true
    复制代码


    Here inside this Conditional Branch is where you want to put anything that should happen once the puzzle is COMPLETE, such as a message popping up saying, “this puzzle is complete; you can’t reset it”, or similar. You could play a buzzer sound as well.

    In the Else branch, fadeout screen, set each Event’s location back to its original spot, and then use the script call from Shaz’s Remember Event Position script to set them back to their default position:
                    Code:        
    1. $game_map.events[EVID].forget_pos()
    复制代码


    Then we need to turn the self switches for our special objects off:
                    Code:        
    1. $game_self_switches[[@map_id, EVID, "D"]] = false
    复制代码


    Then we need to turn the self switches for our external checker event off, using the same script call above. Set Self Switches B and A off.

    Finally, teleport the player back to the entrance or somewhere relevant outside of the puzzle map—otherwise, they could have pressed the button while they were in the middle of the puzzle and they might end up with a boulder on their head.

    Wait 15 frames, and then fadein screen.

    Spoiler                 Code:        
    1. Option 3:
    2. @> Conditional Branch: The A Button is Being Pressed
    3. @> Conditional Branch: Script: $game_self_switches[[@map_id, 7, “C”]] == true
    4.         @> Play SE: [buzzer sound]
    5.         @> Text:
    6.             : This puzzle is complete
    7.         @> Wait 30 frames
    8. @>
    9. : Else
    10. @> Fadeout Screen
    11. @> Wait: 15 frames
    12. @> Set Event Location: [Event Name], (X, Y)
    13. @> Set Event Location: [Event Name], (X, Y)
    14. @> Set Event Location: [Event Name], (X, Y)
    15. @> Set Event Location: [Event Name], (X, Y)
    16. @> Script: $game_map.events[1].forget_pos()
    17.         @> Script: $game_map.events[2].forget_pos()
    18.         @> Script: $game_map.events[3].forget_pos()
    19. @> Script: $game_map.events[4].forget_pos()
    20.         @> Script: $game_self_switches[[@map_id, 1, "D"]] = false
    21.         @> Script: $game_self_switches[[@map_id, 2, "D"]] = false
    22.         @> Script: $game_self_switches[[@map_id, 7, "A"]] = false
    23. @> Script: $game_self_switches[[@map_id, 7, "B"]] = false
    24. @> Transfer Player: [## Your Map]
    25. @> Wait: 15 frames
    26. @> Fadein Screen
    27. @>
    28. : Branch End
    复制代码











    That's all, folks—I hope you found this tutorial helpful!

    For more info, check the demo.​








    本贴来自国际rpgmaker官方论坛作者:A-Moonless-Night处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:https://forums.rpgmakerweb.com/threads/push-pull-puzzle-tutorial.89479/

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    x
    天天去同能,天天有童年!
    回复 送礼论坛版权

    使用道具 举报

    文明发言,和谐互动
    文明发言,和谐互动
    高级模式
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    简体中文
    繁體中文
    English(英语)
    日本語(日语)
    Deutsch(德语)
    Русский язык(俄语)
    بالعربية(阿拉伯语)
    Türkçe(土耳其语)
    Português(葡萄牙语)
    ภาษาไทย(泰国语)
    한어(朝鲜语/韩语)
    Français(法语)
    关闭

    幸运抽奖

    社区每日抽奖来袭,快来试试你是欧皇还是非酋~

    立即查看

    聊天机器人
    Loading...

    QQ|Archiver|手机版|小黑屋|同能RPG制作大师 ( 沪ICP备12027754号-3 )

    GMT+8, 2026-7-15 18:04 , Processed in 0.159284 second(s), 52 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表