So, you want to make your player walk around based on a grid, do you? Oh boy, that seems pretty hairy and scary, doesn’t it? It wouldn’t be so bad if you just had them jump from space to space with no walking animations. Just plop in the new positions. But that’s probably not the case. You probably want them to do something like *gasp* WALK into the next space. Gives a more fluid look to your game. But how do you move them just enough? And how do you prevent other, conflicting movements? If you aren’t careful, you may… BREAK THE GRID!
Dramatic speeches aside, I’m here to demystify this for you. With the right tools and know-how, it doesn’t have to be nearly as scary as you might think. Still a good deal of work, but it can be done. Now granted, this is the basic set-up, and you will probably have to expand upon it before its ready for your game. But of course, I can’t account for every possible scenario its going to be used in (not if this tutorial is going to stay on the shorter-ish side, anyway). The point is to get the basic foundation up and running for you. So without further ado, let’s slay this monster.
STEP 1 : Establish your grid and movement behavior
Well, we can’t move on a grid if we don’t have one. Use your tileset dimensions, for instance. For this tutorial, we’ll go with tiles that are 16×16 pixels.
So if you have a grid set-up, let’s make an actor behavior that will facilitate our movement scheme. For this, I am actually going to modify the behavior from another one of my tutorials: the Basic Four Way Movement tutorial from my Quest Pals section. Essentially, build the behavior as seen there, EXCEPT for the Always section where we did the actual movement. We’re going to re-vamp that to work with your grid.
So now we’ll need to add some more attributes to this four way scheme. We’ll get into details shortly, but for now understand you need these non-hidden attributes:
— Step Length (Number): How many pixels you want your actor to walk per step. For instance, you could say 2 pixels, in which case the actor would take 8 steps before stopping in the next grid space. Be certain that your step length can be divided into your dimensions and produce a whole number! 16 / 5 = 3.2 pixels = Not Good. This will break the grid.
— Step Interval (Number): How many seconds should your actor wait before taking another step. Probably will be something on the lower end, like a tenth of a second (.1) or perhaps even lower.
— Grid Space Dimensions (Number): How many pixels wide/high your grid spaces are. The behavior will assume that your grid is split into squares, thus making width and height equal to each other (most grids with this kind of movement are composed of squares anyway).
And some hidden attributes:
— Movement Countdown (Number): This helps regulate steps taken and the delay intervals between them. More on this later.
— Distance X (Number): This stores the Step Length attribute as either a postive or negative number when horizontal movement takes place. While steps are being processed, it remembers the direction we are going in. When vertical movement takes place, this is set to zero.
— Distance Y (Number): Like above, but flip horizontal and vertical.
Set those up alongside what you already have for our base Four Way Movement behavior.
STEP 2 : Entry Conditions For Movement
As you should have set-up, you have four controls for each of your directions (left, right, up, down). However, we can’t just start moving in any direction whenever we feel like it. We want to stay on the grid. That means we need some sort of gatekeeper condition that allows and disallows movement based on the current situation.
Our “gatekeeper” will have two conditions that need to be met:
Priority Line (the list that keeps track of pressed keys) must not be empty. We don’t want to move if no directional keys are down. As such, if Priority Line has something in it, at least one directional key is down.
- Movement Countdown must be equal to (or less than) zero. Movement Countdown, remember, keeps track of steps that need to be finished before a complete space-to-space movement is complete. If there are still steps to be made, we don’t want to start a new movement.
These are conditions we need to check every frame, so put an appropriate if-statement in the Always wrapper, like so:
STEP 3 : Preparing To Move
Take another look at the Basic Four Way Movement tutorial. See how we checked Priority Line for the key at the front of the list? We are going to do the same thing here.
This is where we assign Distance X and Distance Y their values for the upcoming move. When a move is started, they are kept at a particular value until the move is complete. As a quick referece, setting should go like this (where SL is our Step Length attribute):
Right : X = SL , Y = 0
Left : X = Negate SL , Y = 0
Down : X = 0 , Y = SL
Up : X = 0 , Y = Negate SL
(NOTE: Negate can be found under Numbers & Text >> Math)
(NOTE: If these values don’t make sense to you, I recommend reviewing this resource on positioning and movement)
You should have something that looks like what you see below. Its very similiar to the method employed by what you see in the Four-Way tutorial.
STEP 4 : Performing the Actual Movement
Haha… about time, right?
First, let’s set up Movement Countdown. Do this by setting it to Grid Space Dimensions divided by your Step Length. Remember the example above where we gave our attribute Step Length of 2 for a space 16 pixels wide? This is where we are putting that division result I was talking about (in this case, 8).
Second, we will perform our first step. For this, we set actor coordinate based on the X/Y Distance attributes. We do this by adding those attributes to our current position with some math (look below at the finished pic).
Now, we moved, but we haven’t put in the delay yet. We want to delay the next step for the time specified in our Step Interval attribute. For this, we will use a special “Do Every X Seconds” timer. And by special, I mean look at this timer tutorial. Last one I’m going to reference, OK? So inject ONLY the “Do Every X Seconds” part of the timer (we’ve already set up the outside elements we need for the “Do Every” loop to run correctly) from the timer tutorial into your code right after you commit the first step. Also, the X in “Do Every X Seconds” will be equal to your Step Interval attribute.
Now for a few modifications to our timer:
Once the timer has waited through a step’s delay, commit the next step. That is, set actor coordinates again using the X/Y Distance attributes. This happens in the same area where you decrement Movement Countdown.
- This one’s important! Instead of a “If Countdown <= 0, cancel”, change the 0 to a 1.
- Inside your new “If Countdown <= 1” conditional, add a “Do After Step Interval Seconds, Set Countdown to 0” event before you cancel.
View the finished “Always” wrapper code below (and don’t forget to make sure you set up your key press/release events as well). Quite a bit of it, but code gets that way sometimes when you want something done right. 🙂
So let me explain. Why did I change the 0 to a 1 in my cancel conditional? Remember how we made our first movement BEFORE the “Do Every X Seconds” loop? That’s because “Do Every X Seconds” acts as our delay. We executed the first movement before the loop’s first delay. Now, inside of the loop, we execute the decrementing of Countdown and the next step’s movement together. What this means is that, in essence, when the Countdown attribute has been decremented for the first time, two movements and one delay have occured. On the second decrement, three movements and two delays have occured. Make sense?
What this means is that if we let the countdown reach zero through the normal method, then we will have executed one extra movement. We don’t want that. So instead, we catch it at 1, cancel the “Do Every” loop, and manually throw in the last delay before Countdown officially reaches zero. This prevents extra movement, and furthermore prohibits the behavior from starting another space-to-space movement while the final delay is happening.
* * * * *
And now, you have a working grid movement behavior. Like I said, how you take and fit this into your game is up to you. Hopefully, though, this provides a sturdy foundation for you to work off. So fire it up, and happy Stencyling.
This is awesome Photon! I really appreciate it. The grid-based movement is broken on 3.0 and was attempting to rebuild from scratch and it totally makes sense (Way more than 2.0 version) and was exactly what I was looking for