Phaser AE

Marble-chain shooter

Pro packv3.0.0-32DGrid

The chain marble shooter: coloured balls roll along a track towards a hole, and the player shoots balls into the chain to make runs of three that pop. Pop every ball before the front one reaches the hole.

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

Released October 14, 2026 · updated October 19, 2026

Marble-chain shooter: 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

rail

function rail(): Pack<{ rail: RailApi }>

The rail pack: game.rail, Zuma's rules. No options.

Helpers

createZuma

function createZuma(options: ZumaOptions = {}): ZumaGame

Start a game. Throws, with every fault, on options validateZuma refuses.

createZumaAutopilot

function createZumaAutopilot(game: ZumaGame, options: { pause?: number } = {}): ZumaAutopilot

The game's autopilot, shooting at most every pause seconds (default 0.45).

makeTrack

function makeTrack(def: TrackDef): Track

A track from its definition.

validateZuma

function validateZuma(options: ZumaOptions = {}): string[]

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

zumaLevels

const zumaLevels: ZumaLevel[]

The built-in levels: a spiral in to the frog, a serpent across the board and a long spiral of three turns.

Types

Ball

interface Ball

A ball in the chain: its colour, and how far along the track it is (below 0 it has not come out yet).

  • id: number — A number unique among the balls and shots of the game, given when the ball enters play and kept for good.
  • colour: number — Its colour, a whole number from 0 to the level's colours less 1.
  • s: number — Distance along the track in track units, 0 at the start; below 0 until it has come out.

ChainSegment

interface ChainSegment

A run of touching balls in the chain, as a save holds it.

  • balls: Ball[] — Its balls, tail first.
  • v: number — The speed it rolls at, track units a second; negative while it rolls back.

RailApi

interface RailApi

What the rail pack adds to a game: game.rail.

  • create: typeof createZuma — Start a game.
  • validate: typeof validateZuma — Check a game's options.
  • levels: typeof zumaLevels — The built-in levels.
  • track: typeof makeTrack — A track from its definition.
  • autopilot: typeof createZumaAutopilot — A player for an attract mode or a test.

Track

interface Track

A track: its length, and where a distance along it is and which way it runs there.

  • readonly length: number — Total length of the track in track units, measured along the polyline.
  • readonly points: readonly Vec[] — The polyline's points in order from the start to the hole.
  • at(s: number): Vec & { angle: number } — The place at distance s along the track, and angle, the direction it runs there in radians; s is held between 0 and length.

TrackDef

type TrackDef = { points: [number, number][] } | { spiral: { cx: number; cy: number; outer: number; inner: number; turns: number; start?: number; steps?: number } }

How a track is given: points, or a spiral (from outer radius in to inner, turns times round a centre).

Vec

interface Vec

A point.

  • x: number — Horizontal coordinate, in track units.
  • y: number — Vertical coordinate, in track units.

ZumaAutopilot

interface ZumaAutopilot

A player that aims, swaps and shoots.

  • act(dt: number): boolean — Advance its clock; when it is ready, aim (and swap) and say whether to shoot.

ZumaEvent

type ZumaEvent = | { kind: 'shoot'; colour: number } | { kind: 'insert'; colour: number } | { kind: 'pop'; count: number; combo: number; score: number } | { kind: 'retract' } | { kind: 'join' } | { kind: 'miss' } | { kind: 'swap' } | { kind: 'danger'; left: number } | { kind: 'won' } | { kind: 'lost' }

Something that happened.

ZumaGame

interface ZumaGame

A game.

  • readonly state: ZumaState — Where the game stands; it changes as the game runs.
  • readonly track: Track — The level's track, built from its definition.
  • readonly level: ZumaLevel — The level being played.
  • readonly options: Readonly<{ ball: number; shot: number; retract: number; range: number }> — The options with defaults filled in: a ball's width, and in units a second a shot's speed and a split chain's roll back, and how far a shot flies.
  • aimAt(angle: number): void — Aim, in radians.
  • shoot(): boolean — Shoot the current ball.
  • swap(): void — Swap the current ball and the next.
  • colours(): number[] — The colours still in the chain.
  • step(dt: number): void — Advance dt seconds in fixed steps of 1/120 s, taking at most 0.25 s at a call. Throws if dt is negative or not a number.
  • view(): ZumaView — What is where, copied.
  • drain(): ZumaEvent[] — Events since the last call; the latest 512 are kept.
  • snapshot(): ZumaSave — The game as plain JSON.
  • restore(save: ZumaSave): void — Pick up a saved game made with the same level and options; pending events are dropped.

ZumaLevel

interface ZumaLevel

A level.

  • name: string — The level's display name.
  • track: TrackDef — The track the chain rolls along: a polyline or a spiral.
  • frog: [number, number] — Where the frog sits.
  • balls: number — Balls in the chain, and colours among them.
  • colours: number — Colours among the balls, a whole number from 1 to 8.
  • speed: number — Units a second the chain is pushed; and while rushing in, until its front is until of the way along.
  • rush?: { speed: number; until: number } — Faster entry at the start: the chain rolls at speed units a second until its front is until (0 to 1) of the way along.

ZumaOptions

interface ZumaOptions

A game's options.

  • seed?: number — Default 1: the chain's colours and the frog's.
  • level?: ZumaLevel — The level. Default zumaLevels[0].
  • ball?: number — A ball's width. Default 32.
  • shot?: number — Units a second a shot flies, and the chain rolls back to close a gap. Default 900 and 220.
  • retract?: number — Units a second a split chain rolls back to close a gap; default 220.
  • range?: number — The furthest a shot flies before it is gone. Default 2000.

ZumaSave

interface ZumaSave

A game saved as plain JSON.

  • state: ZumaState — The game state.
  • segments: Segment[] — The runs of balls in the chain, back to front: each holds its balls tail first and the speed it rolls at in units a second (negative while rolling back).
  • shots: { id: number; x: number; y: number; vx: number; vy: number; colour: number; flown: number }[] — Shots in flight: place, direction of travel as a unit vector (vx, vy), colour, and the distance flown so far.
  • serial: number — The count of ids handed out to balls and shots so far.
  • carry: number — Seconds of step time not yet spent, less than one fixed step of 1/120 s.
  • rng: RngState — The state of the game's random stream.

ZumaState

interface ZumaState

Where the game stands.

  • phase: 'play' | 'won' | 'lost' — 'play' while it runs, 'won' once every ball has popped, 'lost' once the front ball reaches the hole.
  • time: number — Seconds played.
  • score: number — Points: ten a ball, times one more for each step of the combo, and 50 times the streak for each shot that pops from the third in a row.
  • popped: number — Balls popped, the longest combo, and shots in a row that popped something.
  • combo: number — The longest combo so far: the most pops in one chain reaction, a single pop counting 1.
  • streak: number — Shots in a row that popped something; a shot that pops nothing or misses resets it to 0.
  • aim: number — The frog: where it aims, the ball it will shoot and the one after.
  • current: number — Colour of the ball the frog shoots next.
  • next: number — Colour of the ball that comes up after it.

ZumaView

interface ZumaView

What is where.

  • state: ZumaState — A copy of the game state.
  • balls: (Ball & { x: number; y: number; angle: number })[] — Balls on the track, with their place and the way the track runs there.
  • shots: { id: number; x: number; y: number; colour: number }[] — Shots in flight: their id, place and colour.
  • frog: Vec — Where the frog sits: the level's frog.
  • front: number — How far along the front ball is, 0 to 1.