Phaser AE

Grid lane movement

Free packv3.0.0-42DPhysics

Four-way movement along the lanes of a tile grid: from tile centre to tile centre, turning only at junctions, the way maze chases and bomb-laying games move. Put a sprite on the lanes, say what is a wall, and the steering, cornering and stopping are done for you.

This is a Free pack. Every phaser.io account can use it in their games.

Released October 14, 2026 · updated October 19, 2026

Grid lane movement: a screenshot of its demo
A note about these graphics

Expansion packs don't come with graphics. This screenshot is one way of drawing what the pack does, made for its demo: none of the sprites, tiles or backgrounds in it are in the pack.

That's by design. A pack is a game's logic, mechanics and effects, and it works with whatever art you give it. Some packs draw effects, backdrops or 3D scenes of their own, but none carries a game's sprites.

So the look is yours. Make the art on phaser.io, bring your own, or let your agent draw it in code: the same pack can look like anything.

What it does

The pack comes in two parts that share no state. The lane component, game.grid.lane(h, spec), puts a 2D object on the lanes in world pixels. You give it a walls(c, r) function and a speed; it reads the arrows and WASD itself, or takes want() calls from an enemy's brain, a swipe or a replay. With a physics body on the object it sets the body's velocity, so walls stay solid to the physics and contacts still fire; without one it moves the position directly.

Grid movement looks simple and is easy to get subtly wrong, so the lane component keeps five rules. The most recent key wins, so holding left and tapping up at a junction turns up. A turn is taken when the object is within a tolerance of the lane, and reversing needs no alignment. If the turn is open but the object stopped a few pixels short, it slides onto the lane and then turns. A lane centre still ahead is always reachable, even when the tile beyond it is a wall. And blocked ahead, it stops exactly on the centre, never a fraction past, so the next turn is aligned.

The second part is the grid walker, createGridWalker, re-exported from the grid-walker pack. It works in tiles and tiles per second on a state of its own, with no world or renderer, and has buffered turns, arcade early and late cornering, wrap portals, timed travel pieces and snapshots. The maze-chase, bomb and excavation rules packs move their actors with it.

Features

  • A lane component — lane, want, halt, cell, centre, free, canGo, laneX and laneY on game.grid.
  • Keyboard or manual steering — arrows and WASD by default, keys of your own per direction, or input: 'manual' for enemies, swipes and replays.
  • Two movement modes — 'remember', where a press keeps the object going until a wall, and 'held', where it moves only while a key is down.
  • Cornering assist — an object that stopped short of a turn slides onto the lane, within a reach you set.
  • Exact stops — blocked ahead, it stops on the tile centre, so later turns line up.
  • Physics or not — drives a body's velocity when there is one, and moves the position when there is not.
  • Direction columns — h.grid.dx and dy say which way it is moving and wx and wy which way it wants to go, for choosing sprite frames.
  • The grid walker — a pure walker in tile units, with arcade cornering windows, wrap portals and snapshots.

Good for

  • Maze chases in the style of Pac-Man, with the player in remember mode and each enemy steered by want().
  • Bomb-laying grid games in the style of Bomberman, moving on lanes between blocks.
  • Ice-block and digging games in the style of Pengo or Dig Dug.
  • Block-pushing puzzles in the style of Sokoban, and snakes, with smooth motion between tiles.
  • Top-down or side-on grid levels where a tilemap's solid tiles are the walls.
  • New grid rules packs that need movement in tiles with no renderer, through the walker.

Make it yours

The pack options set the grid: tile size (16 by default), originX and originY for where tile (0, 0) sits, turnTolerance (3 pixels) and assist (half a tile; 0 turns it off). Every one can be overridden per lane, so objects on grids of different sizes can share a game. Each lane also chooses its walls function, speed, mode, input and keys.

Two different uses: a maze chase on 16-pixel tiles where the player is in remember mode and keeps moving until a wall, while each enemy is on input: 'manual' and picks among the directions free() allows at every junction; and a held-mode puzzle on 32-pixel tiles where the character moves only while a key is down, steered by keys of the game's choosing, with a tilemap's map.solid as the walls.

A quick look

A hero on the lanes, steered by the keyboard, and an enemy steered by its own choices:

const hero = game.spawn({ id: 'hero', x, y, width: 16, height: 16, body: { shape: 'box', friction: 0, fixedRotation: true } });
game.grid.lane(hero, { walls: (c, r) => MAZE[r]?.[c] === '#', speed: 88, mode: 'remember' });

game.grid.lane(ghost, { walls: map.solid, speed: 70, input: 'manual' });
const options = [[1, 0], [-1, 0], [0, 1], [0, -1]].filter(([dx, dy]) => game.grid.free(ghost, dx, dy));
game.grid.want(ghost, ...pick(options));
if (caught) game.grid.halt(ghost);

Works with

  • tiles-2d — map.solid is a ready-made walls function.
  • physics-2d — when the object has a body, the lane component sets its velocity so walls stay solid.
  • grid-walker — the pure walker in tile units, for rules code with no world.
  • maze-chase, grid-bombs, grid-kick and excavation — rules packs whose actors move on the walker.
  • controls-2d — for free movement instead, such as a twin-stick hero.

Good to know

  • Four directions only, with no diagonals and no speed ramps, in both parts.
  • The lane component has no wrap or portals: a tunnel needs the world's own wrapping. The walker has portals.
  • The two parts use different units, pixels on an object and tiles on the walker's own state; map the walker's tiles to the world yourself.
  • With a body, the wall it stops at must also be solid to the physics; give the body friction: 0 and fixedRotation: true, or corners catch.
  • Lanes have no snapshot of their own: the h.grid columns and the object's position are the state.

More Physics packs

Show all →