Introducing Diagonal Movement into RPG Maker

This article explains how to introduce diagonal movement into RPG Maker. By default, RPG Maker assumes characters can only face four directions. Although there is support for eight directions, it is not implemented.

We start by seeing how we can turn our four-directional movement into eight-directional movement.

Direction Numbers

RPG Maker uses numbers to represent each direction.

1 - down-left
2 - down
3 - down-right
4 - left
6 - right
7 - up left
8 - up
9 - up right

If you have a keyboard with a numpad, you might notice the directions correspond to the layout, with 5 in the center.

Handling Direction Input

RPG Maker provides two ways to check your direction.

Input.dir4. This returns the number corresponding to 4-directional movement.

Input.dir8. This returns the number corresponding to 8-directional movement.

When you press one key, it will be a 4-dir move. When you hold down two keys, the game will automatically find which two keys you’re pressing and calculate the appropriate direction value.

Note that if you hold two keys and use dir4, the game will simply round it off to one of the 4-dir directions.

Performing Diagonal Movement

RPG Maker already supports diagonal movement. They come with the move route editor. This means that most of the work is done for you: all we need to do is call it.

Here is the signature for diagonal movement, defined in Game_Character

Because the default engine uses 4-dir movement, all directions are stored in four directions. You can see that it simply picks one of the orthogonal directions. If we are changing to 8-dir movement, we can now store our actual diagonal value in the direction. For compatibility purposes, I decide to take the long way around:

Recall that in Ace, you can have 8 blocks of character sprites per sheet. This is what the index is for. The math is used to take all of those values and figure out which region on the spritesheet should the sprite be copied from.

Spritesheet Format

We need to decide on a format to use for our spritesheets. Once we have chosen a format, every movement spritesheet must follow that format. For simplicity, let’s just place them side-by-side, since that’s what the sheet I found comes with.

We have something like this

So basically, we have our orthogonal movement as index 0, and our diagonal movement as index 1. Now the question is how all of the calculations from above can be used to figure out whether we want to use orthogonal or diagonal, and which is direction to use.

Math Tricks

We notice a relationship between the orthogonal movement and diagonal movement.

For directions 1 and 2, we use the top row.
For directions 4 and 7, we use the second row.
For directions 6 and 3, we use the third row.
For directions 8 and 9, we use the fourth row.

Now, there is an easy way to calculate this. We use the follow formula

for even dir, use dir
for odd dir, use dir * 2 % 10

So when we are moving in direction 7, the row to use is equal to 7 * 2 % 10 = 4, and so when the engine sees 4, it will know to pick the second row.

This math isn’t really necessary. You could just as easily use a set of conditional branches.

Updating the Sprite or the Character?

At this point, you as the scripter have to make some more decisions. We know that we need to update the index and the direction, but there are two places where this can be done.

`Game_Character` – these objects stores all of the properties

`Sprite_Character` – these objects take the characters and draw them

In Game_Character, the direction is set whenever you move. This value should accurately reflect the character’s direction, in case you need to use the direction for other purposes (and there are quite a few cases where we actually need a character’s direction)

I would prefer to modify the sprite method. As mentioned above, we need to handle the orthogonal and diagonal cases separately, so I simply overwrote the method completely:

Now that we have updated the character’s direction to reflect 8-dir, and the sprite knows how to render the character, we should have a pretty good 8-dir movement behavior.

Other Character Objects

The player is only one type of character. We also have events, followers and vehicles. However, because they all use the same methods that we have customized, they will automatically support proper 8-dir movement as well!

Triggering Events

One thing you will immediately notice is that you can’t trigger events diagonally. I will cover this topic in a later tutorial, where we look at how a simple direction affects whether an event is triggered or not.

Recap

The purpose of this tutorial was to demonstrate how you can implement 8-dir movement in your game. Basically

Modify the player input to support 8 directional input

Store the player’s direction

Update the sprite to use the new format

This can be done in any number of ways. I have shown one way, but it may not be the most optimal or compatible way. A copy of the script can be found here.

Moving Forward

While we have successfully introduced diagonal sprites, we have revealed issues with other aspects of the engine. Because the engine assumed everything was 4-dir, all of the logic involving character direction is based on this assumption. There are still several other things to cover before we have a fully functioning 8-dir movement script.

Credits

All of the sprites shown in the screenshots are taken from this website: http://usui.moo.jp/rpg_chadot.html

Spread the Word

If you liked the post and feel that others could benefit from it, consider tweeting it or sharing it on whichever social media channels that you use. You can also follow @HimeWorks on Twitter or like my Facebook page to get the latest updates or suggest topics that you would like to read about.

You may also like...

23 Responses

Yesterday, I got this working up until the part where you insert the custom sprites, and I messed my game up pretty badly. I fixed it and tried to give it another go today. I got up until the “def move_by_input” part (so, basically, I got nothing done) where I replaced what was there with what you made, and it gave me an error. Something about “expecting keyword end, got $end” or something like that. What did I do wrong?

Okay, I got past that part, you were correct, but got stuck on the next part. Got error “undefined method ‘th_8dir_movement_move_diagonal’ for #” Guessing it has to do with “alias :th_8dir_movement_move_diagonal :move_diagonal” but when I kept that in I got error “undefined method ‘move_diagonal’ for class Game_characterbase”. I also tried to move the “alias” part UNDER “def_movediagonal” but I got an error saying “stack level too deep”.

The alias defined a new method called th_8dir_movement_move_diagonal which is defined to be whatever move_diagonal does at the time of aliasing. The class name is Game_CharacterBase, so if you defined your own class called Game_characterbase, you are basically creating a new class instead of working with the existing one.

Alright, that makes sense. So the alias basically made it so th_8dir_movement_move_diagonal does the same thing as move_diagonal. So where do I put the alias? Also, could I potentially replace all instances of th_8dir_movement_move_diagonal with move_diagonal or would that not work at all?

You can define them anywhere. Aliasing is just like any other line of code.

The reason why aliasing is done is so when you make modifications to existing methods, you can still call upon the old logic so you don’t completely replace them.
It would be more useful to experiment with aliasing in a separate script to understand what it’s doing.

Thanks for providing such comprehensive explanations for your many scripts.

I can’t seem to get diagonal movement to work in VX Ace. For starters, the diagonal movement signature (“def move_diagonal(horz, vert)”) is in Game_CharacterBase for me, not Game_Character. Is this a versioning issue? Regardless, I’ve tried to include your scripts in Game_Character and Game_Player but I’m still stuck with four directions of movement. I don’t see a core script requirement for this one, but did I not look close enough?

I took a look at your scripts again and found that it was an input error on my end. Simple mistake, so sorry to post about it!

I’m interested in eight-direction movement with isometric maps, so I’m going to try your script with MGC ISO Engine. Also, I know that Victor has a script for pixel (non-grid) movement that I’d also like to include. Any thoughts on these?

The reason I take interest in diagonal movement is because I take an interest in the idea of isometric parallaxing and what it has to offer in reward for hard work, as there isn’t much you can show using the regular default 2D rpgmaker view. Something however is a concern is the way that the maps come out when you make them match the axis of diagonal movement, yet when you try less harsh of angles, the character ends up running into the wall, all in like this diagram: https://drive.google.com/file/d/0B9oxIE0LXB7cS2ppbTBjdkVidXM/view?usp=sharing
Do you have any suggestions? I’m basically just trying to see what’s best in order to accomplish something that’s visually revealing.

When the player attempts to make an impossible diagonal movement, the character stops, instead of say, you’ve got trees on either side left and right of you and you’re trying to move diagonally left-down so the character instead moves down only.
Do you think it would be better that way? Or do you prefer the movement process this script uses?

To create code blocks or other preformatted text, indent by four spaces:

This will be displayed in a monospaced font. The first four
spaces will be stripped off, but all other whitespace
will be preserved.
Markdown is turned off in code blocks:
[This is not a link](http://example.com)