I recently spoke with someone about the original Legend of Zelda (my all-time fav game) and he mentioned how the developers kept Link's movement within a grid. I never thought about it before and I thought it was really cool. It's sort of subtle but you can see here how Link seems to snap into the grid when the player turns:
I wanted to know more so I googled a bit and came across a blog post called Movement Mechanics by Troy Gilbert in which he explains what's going on. To sum it up, the sprites that make up Link and the background tiles are 16x16 but Link moves along a half-tile grid that is 8x8. The player can move Link up, down, left, or right one pixel at a time and the game will always keep Link aligned to the 8x8 grid so he can walk between obstacles and through doorways without getting caught on the edges.
I also came across a YouTube video Making Zelda in Game Maker: E015 - Aligning Player to Grid by Code Workshop. I don't use Game Maker Studio but I followed what the instructor explained and adapted it for my needs so I could see how this technique works.
Code Workshop explains that when you move in a direction Link aligns to the grid on the other axis. So if you move left or right along the X-axis, Link aligns to the Y-axis and if you move up or down along the Y-Axis he aligns to the X-axis.
Since I created my demo in Pico-8 I'm going to show my re-creation of Code Workshop's
align_to_grid function using Lua.
function align(val, alignTo) local remainder = val % alignTo local halfway = alignTo/2 if (remainder > halfway) then return alignTo - remainder else return -remainder end end
align function takes 2 parameters:
val which is the player's current x or y location (I'll explain more in a bit), and
alignTo, which is the amount of pixels you want your player to align to. Since Link aligns to an 8x8 grid, 8 will get passed in for
remainder is what's left from the x or y location divided by the
If the remainder is larger than the halfway point of the pixels you want to align to, then return
alignTo - remainder, otherwise return
The value returned from this function will be added to either the player's
For example, if the player presses
left they want to move along the negative X-axis (
vx is multiplied by the player's
speed and added to the
x value further down in the function), which means they might need to be realigned along the Y-axis. In this instance, the value returned from
align() will be added to the player's
if (btn(⬅️)) then vx = -1 y+=align(y, 8) end
The way I did this differs a bit from how Code Workshop did it so if you are interested you should definitely check out his video.
Here is a gif of my version in Pico-8 to show the player's 16x16 sprite snapping along an 8x8 grid.
A few months ago I entered a game jam and made a game (featuring that robot buddy in the gif above) where the player moves by pixels within a 16x16 grid but the movement was...well, bad. My character stuck to the corners every time I turned because the size of the player was just about equal to the space the sprite had to move and I wasn't sure at the time how to fix it. I can't wait to go back and update the movement logic with this technique!
- Movement Mechanics by Troy Gilbert
- Making Zelda in Game Maker: E015 - Aligning Player to Grid
- Nerdy Teachers - an awesome resource I used to refresh my memory on some Pico-8 stuff since it's been a while!