Phaser AE

Grid lane walker

Free packv3.0.0-0Logic

Lane movement for maze and grid games: a walker that moves from tile centre to tile centre and turns only at junctions, the way the classic maze chases and bomb-laying games move. It gets the feel of arcade cornering right and keeps everything in tiles, so the rules can own it.

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

Released October 19, 2026

Grid lane walker: 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.

The pack

gridWalker

function gridWalker(): Pack<{ gridWalker: GridWalkerApi }>

The grid-walker pack: game.gridWalker, the pure grid walker. It needs no world; a rules pack imports createGridWalker instead. No options.

Helpers

createGridWalker

function createGridWalker(config: GridWalkerConfig)

Create a headless continuous walker in tile units; wall and portal policies belong to the caller. Throws on an invalid config (see GridWalkerConfig).

Classes

GridWalker

class GridWalker

Continuous buffered tile movement with exact centre handling and immediate reversals.

  • readonly config: GridWalkerConfig — The configuration the walker was created with.
  • constructor(cfg: GridWalkerConfig)
  • get state() — A copy of the current pose; changing the copy does nothing to the walker.
  • want(d: GridDirection) — Buffers the heading to take at the next junction where that turn is open; a full reversal happens at once. Throws if the direction is not up, left, down or right.
  • place(at: GridPoint, direction = this.s.direction) — Moves the walker to at (finite tile coordinates) facing direction, default the current heading, and clears any buffered turn and corner alignment. Throws on non-finite coordinates or an invalid direction.
  • tick( dt: number, speed = this.config.speed, onCentre?: (p: GridPoint, d: GridDirection) => GridDirection, onEnter?: (p: GridPoint, d: GridDirection) => void, onTravel?: (part: GridTravel) => void, ) — Advances dt seconds at speed tiles/s (default config.speed) and returns the new state. Movement is split into pieces of at most 1/64 tile and stops exactly at tile centres, so a large frame never skips a decision: - onCentre(cell, heading) runs each time the walker sits exactly on a tile centre (not while sliding onto a lane), including every tick it waits there against a wall, and returns the heading to want next, as want() would; a ghost's brain picks its turn here. - onEnter(cell, heading) runs when the walker's rounded tile changes, or it arrives through a portal: one tile ahead of its next centre, which is when the arcade ghosts look ahead. - onTravel(part) reports every piece of the trajectory with its time window in the tick, including the stationary remainder after a wall stop; a portal is a zero-length portal piece, never a sweep. Throws when dt is outside 0..10 s, speed outside 0..10000 tiles/s, or a tick would take over a million pieces.
  • snapshot() — A copy of the current state, to save; the same as state.
  • restore(state: GridWalkerState) — Replaces the state with a saved one from snapshot(). Throws if a direction is invalid, x, y or line is not finite, or align is not "x", "y" or null.

Types

GridDirection

type GridDirection = "up" | "left" | "down" | "right"

Renderer-independent lane movement. Coordinates are tile centres: integers, one tile = 1 unit.

GridPoint

interface GridPoint

Tile-centre coordinates; one tile is one model unit.

  • x: number — Column position in tiles; tile centres are integers and x grows to the right.
  • y: number — Row position in tiles; tile centres are integers and y grows downwards, so "up" is -1.

GridTravel

interface GridTravel

One part of a tick's trajectory. Times are fractions of the tick in [0, 1]. Portal segments have equal start/end times and represent discontinuities, never travel through intervening space.

  • from: GridPoint — Where this part of the trajectory starts, in tiles.
  • to: GridPoint — Where this part of the trajectory ends, in tiles; for a portal it is the arrival point.
  • start: number — When the part starts, as a fraction of the tick from 0 to 1.
  • end: number — When the part ends, as a fraction of the tick from 0 to 1; equal to start for a portal.
  • kind: "move" | "portal" — move for travel through space, portal for a jump that crosses no intervening tiles.

GridWalkerApi

interface GridWalkerApi

What the grid-walker pack adds to a game: game.gridWalker.

  • create: typeof createGridWalker — Make a walker (see createGridWalker).

GridWalkerConfig

interface GridWalkerConfig

Movement speed, blocking predicate, corner windows and optional directed portals.

  • at: GridPoint — Starting position in tiles; both coordinates must be finite. Tile centres are integers.
  • direction?: GridDirection — Starting heading; default left. Throws if it is not up, left, down or right.
  • speed: number — Tiles per second; finite and not negative. Throws otherwise.
  • walls: (x: number, y: number) => boolean — Whether tile (x, y), in integer tile coordinates, blocks movement. Asked for tiles outside any board too, so it must answer for them.
  • turnBefore?: number — How far before a tile centre, in tiles, a wanted turn may still be taken; 0 to under 0.5, default 0. Throws outside that range.
  • turnAfter?: number — How far past a tile centre, in tiles, a wanted turn may still be taken; 0 to under 0.5, default 0. Throws outside that range.
  • arcadeAsymmetry?: boolean — When true, the before and after windows swap for headings that move up or left, reproducing the arcade original's lopsided cornering; default false.
  • portal?: (at: GridPoint, direction: GridDirection) => GridPoint | null — Directed portal lookup: the tile an actor leaving at in direction arrives at, or null.
  • portalAt?: "centre" | "edge" — Where a portal fires. centre (default) jumps from the source tile's centre to the destination's centre. edge walks on to the source tile's outer edge, jumps to the matching edge of the destination tile and carries the remaining distance on, so a wrap tunnel slides off one side and in from the other without skipping a tile or needing walkable cells beyond the board. The cell beyond the source edge is never tested.

GridWalkerState

interface GridWalkerState extends GridPoint

Current continuous pose, buffered heading and residual diagonal corner alignment.

  • direction: GridDirection — The heading it is travelling in now.
  • wanted: GridDirection — The buffered heading it takes at the next junction where that turn is open; equal to direction when no turn is waiting.
  • align: "x" | "y" | null — The axis it is still sliding onto a lane along after a corner turned off-centre, or null when it is on a lane.
  • line: number — The lane coordinate in tiles that align slides to; 0 while align is null.