Phaser AE

Brick-collecting stair race

Pro packv3.0.0-32DArcade

A race where the way forward is built from what you carry: collect bricks of your colour, lay them on the steps of a staircase, and get to the top before your rivals. The course, the runners and the rules are options, and the pack hands you the state to draw however you like.

This is a Pro pack. Upgrade to Phaser Pro to use it in your games.See Phaser Pro →

Released October 14, 2026 · updated October 20, 2026

Brick-collecting stair race: 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

collectBuild

function collectBuild(): Pack<{ collectBuild: CollectBuildApi }>

The collect-build pack: game.collectBuild, Bridge Race's rules. No options.

Helpers

courseDefaults

const courseDefaults: Required<CourseOptions>

The value used for each course option left out of CourseOptions.

createBridgeAutopilot

function createBridgeAutopilot(game: BridgeRaceGame, id = 'you'): BridgeAutopilot

The player's autopilot.

createBridgeRace

function createBridgeRace(options: BridgeRaceOptions = {}): BridgeRaceGame

Start a race. Throws, with every fault, on options validateBridgeRace refuses.

planCourse

function planCourse(options: CourseOptions, colours: number, rng: Rng): Course

Lay out a course for colours players.

validateBridgeRace

function validateBridgeRace(options: BridgeRaceOptions = {}): string[]

Check a race's options. Empty when it can be played.

Types

BridgeAutopilot

interface BridgeAutopilot

A player that picks the way to go.

  • next(): { x: number; y: number } — The way to go now: x across, y up the course.

BridgeEvent

type BridgeEvent = | { kind: 'pick'; runner: string; loose: boolean } | { kind: 'lay'; runner: string; stair: number; step: number; over: number } | { kind: 'blocked'; runner: string; stair: number } | { kind: 'floor'; runner: string; floor: number } | { kind: 'knock'; runner: string; victim: string; dropped: number } | { kind: 'finish'; runner: string; place: number } | { kind: 'end'; winner: string }

Something that happened.

BridgeRaceGame

interface BridgeRaceGame

A race.

  • readonly state: BridgeRaceState — The live state, changed in place as the race advances; use view().state for a copy.
  • readonly course: Course — The course laid out from the seed and the course options.
  • readonly options: Readonly<{ speed: number; climb: number; carry: number; knock: boolean; players: number }> — The speed, climb, carry, knock and players actually in use, after defaults are filled in.
  • move(x: number, y: number): void — The player's way to go: x across, y up the course (towards the finish).
  • step(dt: number): void — Advance, in fixed steps of 1/60 s.
  • suggest(id: string): { x: number; y: number } — The way a rival would go now, for any runner: what the autopilot plays by.
  • view(): BridgeView — What is where now: a copy of the state and the bricks lying on floors.
  • drain(): BridgeEvent[] — Take the events since the last drain, oldest first (at most the latest 512), and clear them.
  • snapshot(): BridgeRaceSave — Save the race as plain JSON; the course is not included, as it follows from the seed and options.
  • restore(save: BridgeRaceSave): void — Return to a saved race and discard pending events; the save must come from a race with the same seed and options.

BridgeRaceOptions

interface BridgeRaceOptions

A race's options.

  • seed?: number — Default 1.
  • players?: number — Runners, the player's first. Default 4.
  • course?: CourseOptions — The course.
  • speed?: number — Units a second on a floor. Default 6.
  • climb?: number — Speed on a staircase, as a share of speed. Default 0.75.
  • respawn?: number — Seconds before a picked-up brick comes back. Default 3.
  • carry?: number — The most bricks a runner carries. Default 40.
  • knock?: boolean — Runners knock each other down. Default true.
  • stun?: number — Seconds a knocked runner lies down. Default 1.2.
  • skill?: number — How sharp the rivals are, 0 to 1. Default 0.7.
  • names?: string[] — Runners' names.

BridgeRaceSave

interface BridgeRaceSave

A race saved as plain JSON (the course follows from the seed).

  • state: BridgeRaceState — The race state: time, phase, winner, runners and the colour laid on each step.
  • spots: SpotState[] — Whether each brick spot has its brick and, if not, the seconds until it returns; in Course.spots order.
  • loose: Loose[] — The scattered bricks lying where runners fell, each with its floor and position.
  • serial: number — Count of scattered bricks made so far, used to give each a fresh id.
  • rng: RngState — State of the random generator that scatters bricks and varies the rivals' thinking time.
  • carry: number — Seconds of step time not yet spent, less than one 1/60 s tick.

BridgeRaceState

interface BridgeRaceState

Where the race stands.

  • time: number — Seconds of play so far; stops when the race is over.
  • phase: 'play' | 'over' — 'play' while the race runs, 'over' once the first runner reaches the finish.
  • winner: string | null — Id of the first runner to finish, or null while the race is on.
  • runners: Runner[] — Every runner, the player's first; the runner's index is its colour.
  • steps: number[][] — Each staircase's steps, by the colour laid on them (-1 for none).

BridgeView

interface BridgeView

What is where.

  • state: BridgeRaceState — A deep copy of the race state, safe to keep after the race moves on.
  • bricks: { id: number; floor: number; x: number; y: number; z: number; colour: number }[] — Bricks lying on floors: a colour's own, or loose (colour -1) after a fall.

CollectBuildApi

interface CollectBuildApi

What the collect-build pack adds to a game: game.collectBuild.

  • create: typeof createBridgeRace — Start a race.
  • validate: typeof validateBridgeRace — Check a race's options.
  • course: typeof courseDefaults — The built-in course's numbers.
  • autopilot: typeof createBridgeAutopilot — A player for an attract mode or a test.

Course

interface Course

A course.

  • floors: Floor[] — The floors from the ground up; the last is the finish platform, so there are options.floors + 1.
  • stairs: Stair[] — Every staircase, floor by floor; options.bridges leave each floor but the finish.
  • spots: Spot[] — Every brick spot on every floor but the finish: options.bricks of each colour per floor.
  • options: Required<CourseOptions> — The layout options after filling in courseDefaults.

CourseOptions

interface CourseOptions

How a course is laid out.

  • floors?: number — Floors to cross before the finish. Default 3.
  • bridges?: number — Staircases from each floor to the next. Default 3.
  • steps?: number — Steps on a staircase. Default 14.
  • width?: number — A floor's width, across. Default 26.
  • depth?: number — A floor's depth, from its bottom edge to the staircases. Default 20.
  • run?: number — A staircase's length on the ground. Default 14.
  • rise?: number — How high each floor is above the last. Default 6.
  • stairWidth?: number — A staircase's width. Default 2.6.
  • bricks?: number — Brick spots of each colour on a floor. Default 10.

Floor

interface Floor

A floor: a rectangle at a height. The last is the finish platform.

  • index: number — Position in Course.floors, 0 for the ground floor; the last is the finish platform.
  • x: number — Left edge across the course, in world units; 0 for every floor.
  • y: number — Near edge, in world units along the course (the y axis); the next floor starts depth + run further on.
  • w: number — Width across (the x axis), in world units.
  • h: number — Depth along the course (the y axis), in world units; the finish platform is 8.
  • z: number — Height of the floor's surface, in world units: index * rise.
  • finish: boolean — Whether this is the finish platform at the top, which has no staircases leading up from it.

Runner

interface Runner

A runner.

  • id: string — Stable identifier: 'you' for the player, 'rival1', 'rival2' and so on for the rest.
  • name: string — Display name from BridgeRaceOptions.names (cycled if there are fewer names than runners).
  • colour: number — Its colour: its place in the list of runners.
  • player: boolean — Whether the player steers this runner; true only for the first.
  • x: number — Position across the course, in world units.
  • y: number — Position along the course (towards the finish), in world units, measured from the course start.
  • z: number — Its height: a floor's, or partway up a staircase.
  • floor: number — The floor it is on, or last left; the highest it has reached.
  • reached: number — Index of the highest floor it has reached, 0 at the start; its colour's bricks show on floors up to this one.
  • stair: number | null — The staircase it is on, and the top step it stands on (-1 at the foot).
  • step: number — Index of the top step it stands on while climbing; -1 at the foot of a staircase or when on no staircase.
  • stack: number — Bricks it carries, up to the carry option.
  • stunned: number — Seconds it still lies down, and still cannot be knocked again.
  • immune: number — Seconds before it can be knocked down again; set to the stun time plus 1 s after a knock.
  • place: number — Its place at the finish, or 0.
  • dx: number — The way it is going.
  • dy: number — Its heading along the course, positive towards the finish; a heading longer than 1 is cut to 1 when it moves.
  • plan: { mode: 'collect' | 'climb'; want: number; stair: number | null; think: number } — A rival's plan.

Spot

interface Spot

A brick spot.

  • id: number — Unique within the course, counting from 1; a brick lying on the spot reports this id.
  • floor: number — Index of the floor the spot is on.
  • colour: number — Colour of the runner who may pick the brick up: that runner's place in the race, from 0.
  • x: number — Position across the course (the x axis), in world units.
  • y: number — Position along the course (the y axis), in world units, measured from the course start rather than the floor's edge.

Stair

interface Stair

A staircase from floor from to the next, up the y axis from y0 to y1.

  • index: number — Position in Course.stairs; also the staircase's row in the race's steps.
  • from: number — Index of the floor this staircase leaves; it arrives on the next one up.
  • x: number — Centre of the staircase across the course (the x axis), in world units.
  • y0: number — Where the staircase starts along the course (the y axis), in world units: the far edge of floor from.
  • y1: number — Where the staircase ends along the course (the y axis), in world units: the near edge of the next floor.
  • z0: number — Height at the foot, in world units: the surface of floor from.
  • z1: number — Height at the head, in world units: the surface of the next floor.
  • width: number — Width across the course (the x axis), in world units.
  • steps: number — Number of steps, each (y1 - y0) / steps long.