Phaser AE

Enemy capture

Pro packv3.0.0-32DArcade

The arcade structure of a capture-and-clear platformer: trap an enemy, then pop, kick or roll it for chained scores, fruit and items, before the hurry-up catches you. Bubbles, snow or both do the trapping; this pack runs the session around them.

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

Enemy capture: 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

enemyCapture

function enemyCapture(): Pack<{ enemyCapture: typeof api }>

Install the renderer-independent enemy capture API.

Helpers

CAPTURE_SCORING

const CAPTURE_SCORING: CaptureScoring

The default scoring: doubling pops from 1000, a fruit per kill, doubling snowball chains from 500.

CAPTURE_TIMING

const CAPTURE_TIMING: CaptureTiming

The default timings, seconds.

captureConfig

function captureConfig(o: CaptureConfigInput): CaptureConfig

A complete configuration from a game's own parts, with plain defaults for the rest.

captureDifficulty

function captureDifficulty(name: CaptureDifficultyName): CaptureDifficulty

Difficulty presets: Arcade is the original tables, Normal is the gallery default, Easy is gentler still.

createCaptureGame

function createCaptureGame(initial: CaptureConfig): CaptureGame

Create a capture game from a configuration (see bubbleBobblePreset and snowBrosPreset).

Types

CaptureAnger

interface CaptureAnger

Anger: enemies that escape, the hurry-up and the last enemy speed up.

  • speed: number — Speed multiplier when angry.
  • onEscape: boolean — An enemy that breaks out of a bubble or snow is angry.
  • onHurry: boolean — Every enemy turns angry at the hurry-up.
  • lastEnemy: boolean — The last enemy is angry.
  • calmOnDeath: boolean — A player's death calms every enemy.

CaptureConfig

interface CaptureConfig

A complete capture game configuration. Presets build these; every field is data.

  • name: string — Name.
  • mechanic: "bubble" | "snow" | "both" — The capture mechanic(s): bubbles, snow or both at once.
  • tile: number — Tile size of the round maps.
  • legend: Readonly<Record<string, LegendEntry>> — Legend for round rows.
  • wrapY: boolean — Maps wrap bottom to top.
  • rounds: readonly CaptureRound[] — The rounds, in order.
  • loop: boolean — After the last round: start again from loopTo (true) or finish (false).
  • loopTo: number — Round to loop back to (1-based).
  • startRound: number — Starting round (1-based).
  • players: number — Players, 1 to 4.
  • player: CapturePlayer — Player rules.
  • kinds: Record<string, CaptureEnemyKind> — Enemy kinds.
  • shots: Record<string, ShotSpec> — Enemy projectiles by name (behaviours fire them by name).
  • bubbles: Partial<BubbleSettings> — Bubble rules (mechanic 'bubble' or 'both').
  • snow: Partial<SnowSettings> — Snow rules (mechanic 'snow' or 'both').
  • elements: Partial<ElementSettings> — Elemental effects (special bubbles).
  • scoring: CaptureScoring — Scoring.
  • items: CaptureItems — Items.
  • powerups: Record<string, CapturePowerup> — Named power-ups.
  • letters: CaptureLetters | null — Bonus-word letters, or null.
  • anger: CaptureAnger — Anger.
  • hurry: CaptureHurry | null — Time pressure, or null.
  • timing: CaptureTiming — Timings.
  • difficulty: CaptureDifficulty — Difficulty scaling.
  • seed: number — Seed.
  • invulnerable: boolean — Players never die (tests, demos).

CaptureConfigInput

type CaptureConfigInput = Pick<CaptureConfig, "name" | "mechanic" | "rounds" | "kinds"> & Partial<Omit<CaptureConfig, "name" | "mechanic" | "rounds" | "kinds" | "player" | "scoring" | "items" | "timing" | "anger">> & { /** The player: a walker profile and start points; lives, fire rate, auto-fire and push speed are optional. */ player: Pick<CapturePlayer, "profile" | "start"> & Partial<CapturePlayer>; /** Scoring overrides. */ scoring?: Partial<CaptureScoring>; /** Item overrides. */ items?: Partial<CaptureItems>; /** Timing overrides. */ timing?: Partial<CaptureTiming>; /** Anger overrides. */ anger?: Partial<CaptureAnger>; }

What captureConfig needs: the game's own parts, and any section to override.

CaptureCounter

type CaptureCounter = "blown" | "empty-pops" | "jumps" | "distance" | "lightning-pops" | "fire-pops" | "water-pops" | "wraps" | "fruits" | "specials"

Counters the game keeps across rounds (Bubble Bobble's special item triggers).

CaptureDifficulty

interface CaptureDifficulty

Difficulty and population scaling applied on top of any preset.

  • name: string — Name.
  • speed: number — Enemy speed multiplier.
  • trap: number — Multiplier on how long trapped (bubbled) enemies and snowballs hold.
  • minTrap: number — Shortest trapped time, seconds (late Bubble Bobble rounds trap for 1 s in the arcade).
  • patience: number — Multiplier on the hurry-up and chaser timers.
  • chaser: number — Chaser speed multiplier.
  • population: number — Fraction of each round's authored enemies that appear (at least one).
  • lives: number — Extra starting lives.
  • shots: number — Multiplier on the gap between enemy shots (2 = half as many shots).
  • minLetters: number — Letters offered on letter rounds even without a big pop (0: the arcade rule only).
  • column: 0 | 1 | 2 | 3 — Which of the four threshold columns of a counter item applies (Bubble Bobble's AA BB CC DD: 0 hardest .. 3 normal, 2 easy).

CaptureDifficultyName

type CaptureDifficultyName = "easy" | "normal" | "arcade"

Difficulty preset names. Arcade is the original tables; Normal (the gallery default) and Easy are gentler.

CaptureEffect

type CaptureEffect = | { kind: "power"; power: string } | { kind: "smart-bomb"; value: number } | { kind: "skip"; rounds: number } | { kind: "stop-timer" } | { kind: "freeze"; seconds: number; value: number } | { kind: "shower"; count: number; value: number; bonus: number; seconds: number }

What a special item does.

CaptureEnemyKind

interface CaptureEnemyKind

An enemy kind in a capture game: a platform-enemies kind plus capture rules.

  • enemy: EnemyKind — The platform-enemies kind (walker profile, movement or custom behaviour, modifiers).
  • capturable?: boolean — Can be bubbled or snowed. Default true.
  • deadly?: boolean — Touching it kills a player. Default true.
  • boss?: { hp: number; bonus: number; hurtBy: "ball" | "lightning" | "both" } | null — A boss: hit points, what hurts it, the bonus for beating it.
  • letter?: boolean — Carries a letter of the bonus word when killed (Snow Bros' face creatures). Default false.
  • required?: boolean — Must be cleared for the round to end. Default true (Snow Bros' Doskoi sentries are optional).

CaptureEnemyView

interface CaptureEnemyView

An enemy as read by renderers.

  • id: string — Id.
  • kind: string — Kind.
  • x: number — Centre x.
  • y: number — Centre y.
  • w: number — Size.
  • h: number — Size.
  • facing: -1 | 1 — Facing.
  • mode: WalkerMode — Movement mode.
  • vx: number — Velocity x.
  • state: "entering" | "active" | "covered" | "snowball" | "rolling" | "frozen" — 'entering' (dropping in), 'active', 'covered' (partly snowed), 'snowball', 'rolling', 'frozen'. Trapped enemies are drawn from their bubbles.
  • angry: boolean — Angry (faster, recoloured).
  • snow: number — Snow units (0 .. cover).
  • hp: number — Boss hit points left (0 for non-bosses).
  • hpMax: number — Boss hit points at the start.
  • hurt: number — Seconds since its last boss hit (flash).
  • snapped: boolean — Discontinuous move: snap the sprite.

CaptureEvent

type CaptureEvent = | { kind: "round-start"; round: number; name: string } | { kind: "round-clear"; round: number } | { kind: "score"; player: number; value: number; x: number; y: number; reason: string } | { kind: "blow"; player: number } | { kind: "throw"; player: number } | { kind: "kick"; player: number; enemy: string } | { kind: "capture"; enemy: string; enemyKind: string; x: number; y: number } | { kind: "escape"; enemy: string; enemyKind: string } | { kind: "pop"; player: number; enemies: number; bubbles: number; x: number; y: number } | { kind: "snowball"; enemy: string } | { kind: "kill"; enemy: string; enemyKind: string; cause: string; x: number; y: number } | { kind: "collect"; player: number; item: string; value: number; x: number; y: number } | { kind: "powerup"; player: number; power: string } | { kind: "letter"; player: number; letter: string; index: number } | { kind: "extend"; player: number } | { kind: "extra-life"; player: number; lives: number } | { kind: "hurry" } | { kind: "chaser"; id: string; chaser: string } | { kind: "death"; player: number; cause: string } | { kind: "respawn"; player: number } | { kind: "all-in-one"; player: number; reward: "items" | "face" } | { kind: "boss-hit"; enemy: string; hp: number } | { kind: "boss-defeated"; enemy: string; bonus: number } | { kind: "element"; element: "water" | "fire" | "lightning"; x: number; y: number } | { kind: "game-over" } | { kind: "complete" }

Events from drain().

CaptureGame

interface CaptureGame

A running capture game.

  • readonly config: CaptureConfig — The configuration (resolved).
  • readonly status: CaptureStatus — Current status.
  • readonly round: number — Current round (1-based).
  • readonly map: PlatformMap — The live map, world, director and fields of the current round (rebuilt each round).
  • readonly world: WalkerWorld — Walker world.
  • readonly enemies: EnemyDirector — Enemy director.
  • readonly bubbles: BubbleField | null — Bubble field (bubble mechanic) or null.
  • readonly snow: SnowField | null — Snow field (snow mechanic) or null.
  • readonly elements: Elements — Elemental effects.
  • control(player: number, input: Partial<CaptureInput>): void — Set a player's input.
  • tick(seconds: number): number — Advance by elapsed seconds (whole fixed steps of 1/60 s); returns the steps run.
  • step(): void — One fixed step.
  • readonly state: CaptureState — A fresh copy of the state for renderers.
  • drain(): CaptureEvent[] — Events since the last drain.
  • configure(patch: CapturePatch): void — Change rules while the game runs: bubble, snow, element and anger settings, scoring, timings, power-ups, letters, hurry, shots and the round list. The live fields of the current round are reconfigured at once (a round's trapped time and float speed are recomputed from the new rounds); everything applies to later rounds. Structural fields (mechanic, tile, legend, wrap, players, kinds, difficulty, seed) need a new game.
  • goToRound(n: number): void — Jump to a round (1-based), keeping scores and lives.
  • reset(): void — Start a new game from the configured start round.
  • snapshot(): CaptureSnapshot — Serialisable state.
  • restore(s: CaptureSnapshot): void — Restore a snapshot taken from a game with the same config.

CaptureHurry

interface CaptureHurry

Time pressure: a hurry-up, then an invincible chaser (and optional extra chasers later).

  • after: number — Seconds before the hurry-up (rounds may override).
  • chaserAfter: number — Seconds after the hurry-up before the chaser (rounds may override).
  • chaser: ChaserSpec — The chaser.
  • perPlayer: boolean — One chaser per live player (Bubble Bobble) or one in all.
  • extra: { spec: ChaserSpec; after: number; every: number; max: number } | null — Extra chasers released later (Snow Bros' slime ghosts).

CaptureInput

interface CaptureInput

Player input for one step.

  • x: number — -1 left .. 1 right.
  • y: number — -1 up .. 1 down.
  • jump: boolean — Jump held.
  • fire: boolean — Fire (blow, throw, kick) held.

CaptureItems

interface CaptureItems

Item timing and tables.

  • pointsAfter: number — Seconds into a round when the points item appears (0: never).
  • specialAfter: number — Seconds into a round when the special item appears.
  • pointsTable: { item: string; value: number }[] — Points items (value by index). Empty: no points items.
  • pick?: (ctx: PointsPickContext) => number — Which entry of pointsTable a round's points item is (Bubble Bobble's ROM rule is bubbleBobblePointsPick). Default a random entry.
  • specials: CaptureSpecialItem[] — Counter-driven special items.

CaptureItemView

interface CaptureItemView

A pickup or a flying corpse.

  • id: string — Id.
  • item: string — Item name.
  • kind: "corpse" | "fruit" | "points" | "special" | "diamond" | "drop" | "potion" | "money" | "letter" | "face" — 'corpse' (a popped enemy flying), 'fruit', 'points', 'special', 'diamond', 'drop', 'potion', 'money', 'letter', 'face'.
  • enemyKind: string — Enemy kind for corpses.
  • letter: string — Letter for letters.
  • value: number — Points.
  • x: number — Centre x.
  • y: number — Centre y.
  • age: number — Seconds alive.
  • landed: boolean — On the ground.
  • snapped: boolean — Discontinuous move: snap.

CaptureLetters

interface CaptureLetters

Bonus-word letters (EXTEND, SNOW).

  • word: string[] — The word, one entry per letter position.
  • source: "bubbles" | "creatures" — 'bubbles': letter bubbles float in on rounds with gaps (Bubble Bobble); 'creatures': a face item brings letter creatures (Snow Bros).
  • every: number — Seconds after the previous letter bubble has gone (collected or expired) before the next one floats in.
  • max?: number — Most letter bubbles on screen at once. Default 1.
  • creature?: string — Creature kind for 'creatures'.
  • complete: "extend" | "life" — Completing the word: an extra life and the round ends ('extend'), or just the life ('life').

CapturePatch

type CapturePatch = Partial<Pick<CaptureConfig, "bubbles" | "snow" | "elements" | "scoring" | "items" | "powerups" | "letters" | "anger" | "hurry" | "timing" | "shots" | "rounds" | "loop" | "loopTo" | "invulnerable">> & { player?: Partial<CaptureConfig["player"]> }

The rules configure can change on a running game.

CapturePlayer

interface CapturePlayer

Player rules.

  • profile: WalkerProfile — Movement profile.
  • lives: number — Starting lives.
  • start: { x: number; feet: number }[] — Default start points (rounds may override).
  • fireEvery: number — Seconds between shots.
  • autoFire: boolean — Holding fire repeats.
  • push: number — Walk speed multiplier while pushing a snowball.

CapturePlayerView

interface CapturePlayerView

A player as read by renderers.

  • id: string — Body id.
  • index: number — Index (0, 1).
  • score: number — Score.
  • lives: number — Lives left (including the one in play).
  • inGame: boolean — Still in the game.
  • dead: boolean — Dead (death animation).
  • x: number — Centre x.
  • y: number — Centre y.
  • facing: -1 | 1 — Facing.
  • mode: WalkerMode — Movement mode.
  • vx: number — Velocity x.
  • vy: number — Velocity y.
  • w: number — Size.
  • h: number — Size.
  • invulnerable: number — Seconds of invulnerability left (blink).
  • carried: boolean — Carried inside a snowball or riding water.
  • balloon: number — Seconds as a balloon left.
  • sinceFire: number — Seconds since the last shot (blow animation).
  • powers: string[] — Power-ups held.
  • letters: boolean[] — Letters collected.
  • pushing: boolean — Pushing a snowball.
  • stunned: boolean — Stunned (burnt).
  • snapped: boolean — Discontinuous move this step: snap the sprite.

CapturePowerup

interface CapturePowerup

Named power-up effects (sweets, shoes, potions). Multipliers apply until the player dies.

  • range?: number — Bubble or snow range multiplier.
  • shotSpeed?: number — Shot speed multiplier.
  • rapid?: number — Fire interval multiplier (0.5: twice as fast).
  • run?: number — Walk speed multiplier.
  • power?: number — Snow units per hit multiplier.
  • balloon?: number — Seconds as an invincible balloon that flies and kills what it touches (Snow Bros' green potion).

CaptureRound

interface CaptureRound

One round (screen, floor) of a capture game.

  • name?: string — Display name (e.g. 'ROUND 1', 'FLOOR 1').
  • rows: readonly string[] — Map rows through the legend.
  • legend?: Readonly<Record<string, LegendEntry>> — Legend override for this round.
  • currents?: readonly string[] — Air currents ('^' '>' 'v' '<' '.') for bubbles; default everything up.
  • holes?: { top: number[]; bottom: number[] } — Columns of the gaps in the ceiling and floor (where special and letter bubbles float in).
  • enemies: CaptureSpawn[] — Enemies.
  • start?: { x: number; feet: number }[] — Player start points (feet). Default: the config's.
  • hurry?: number — Seconds before the hurry-up. Default: the config's.
  • chaser?: number — Seconds after the hurry-up before the chaser appears. Default: the config's.
  • noHurry?: boolean — No hurry-up and no chaser on this round, however long it lasts. Default false.
  • chaserSpeed?: number — Chaser speed multiplier. Default 1.
  • enemySpeed?: number — Enemy speed multiplier for this round. Default 1.
  • trapTime?: number — Seconds a trapped enemy holds (bubbles) before the warning. Default: the bubble settings'.
  • floatSpeed?: number — Bubble float speed. Default: the bubble settings'.
  • specials?: { water?: number; fire?: number; lightning?: number } — Special bubbles that float in: rate per element (one every 60 / rate seconds).
  • items?: { points?: { x: number; feet: number }; special?: { x: number; feet: number } } — Where the points item and the special item appear.
  • fruitOnClear?: boolean — Turn leftover bubbles into fruit when the last enemy dies. Default false.
  • breath?: "lightning" | null — Players blow lightning instead of bubbles this round (Bubble Bobble's final round).

CaptureScoring

interface CaptureScoring

Scoring tables.

  • popChain: number[] — Points for each enemy of a simultaneous pop, in order (Bubble Bobble 1000, 2000, 4000 ...).
  • corpseItems: { item: string; value: number }[] — The fruit the k-th enemy of a pop turns into.
  • emptyPop: number — An empty bubble popped (also a bubble blown into a wall).
  • specialPop: number — A letter or special bubble popped.
  • snowHit: number — A snow shot landing on an enemy.
  • rollChain: number[] — Points for each enemy killed by one kicked snowball chain, in order.
  • diamonds: { water: number; fire: number; lightning: number; trapped: number | null } — Diamond values for enemies killed by water, fire, lightning, and trapped enemies hit by lightning (null: a bolt passes trapped enemies by).
  • drops: { item: string; value: number; weight: number; powerup?: string }[] — Items dropped by enemies killed by snowballs (weighted); an entry with powerup is a potion.
  • dropChance: number — Chance that a snowball kill drops an item.
  • allInOne: { item: string; value: number; count: number; faceEvery: number } | null — Clearing every enemy with one kick: items rain down (faceEvery-th time a face appears instead).
  • clearFruit: { digits: boolean; value: number } | null — Leftover bubbles become fruit when the last enemy dies (on fruitOnClear rounds, or matching tens and hundreds digits).
  • touchKill: number — Enemy touched by a balloon or a frozen enemy touched.
  • extraLives: number[] — Score thresholds for extra lives, then one every extraEvery (0 none).
  • extraEvery: number — Points between extra lives after the table.

CaptureSnapshot

interface CaptureSnapshot

Serialisable session state.

  • core: string — Session scalars, players, items and timers.
  • map: PlatformMapSnapshot — Map.
  • world: WalkerWorldSnapshot — Walker world.
  • enemies: EnemiesSnapshot — Enemy director.
  • bubbles: BubblesSnapshot | null — Bubbles.
  • snow: SnowSnapshot | null — Snow.
  • elements: ElementsSnapshot — Elements.
  • shots: { items: Projectile[]; seq: number } — Projectiles.
  • chasers: { items: Chaser[]; seq: number } — Chasers.

CaptureSpawn

interface CaptureSpawn

An enemy placed in a round.

  • kind: string — Kind name.
  • x: number — Centre x.
  • feet: number — Feet y.
  • delay?: number — Seconds after the round starts before it drops in. Default 0.
  • facing?: -1 | 1 — Facing. Default: toward the screen centre.

CaptureSpecialItem

interface CaptureSpecialItem

A special item earned by a counter reaching a threshold (per difficulty column).

  • item: string — Item name (renderers draw it).
  • counter: CaptureCounter — The counter.
  • at: [number, number, number, number] — Thresholds for columns AA BB CC DD.
  • effect: CaptureEffect — Effect when collected.
  • value: number — Points when collected.

CaptureState

interface CaptureState

The whole session state for renderers (a fresh copy per read).

  • status: CaptureStatus — Status.
  • statusTime: number — Seconds in the status.
  • round: number — Round number (1-based).
  • roundName: string — Round display name.
  • roundTime: number — Seconds of play in this round (resets on a death).
  • hurry: boolean — The hurry-up has sounded.
  • hurryTime: number — Seconds since the hurry-up (banner).
  • players: CapturePlayerView[] — Players.
  • enemies: CaptureEnemyView[] — Enemies (not trapped in bubbles).
  • bubbles: Bubble[] — Bubbles.
  • snow: SnowShot[] — Snow shots.
  • shots: Projectile[] — Enemy projectiles.
  • chasers: Chaser[] — Chasers.
  • items: CaptureItemView[] — Items and corpses.
  • water: WaterFlow[] — Water flows.
  • fire: FireDrop[] — Fires.
  • bolts: Bolt[] — Lightning bolts.
  • freeze: number — Seconds left of a freeze (heart).
  • shower: number — Seconds left of a shower bonus (potion).
  • letterAllowance: number — Letters offered this round (bubbles rule).
  • clearing: number — Seconds until the round ends after the last enemy (-1: not clearing).
  • hiScore: number — High score seen this session.
  • mapRevision: number — Map revision (renderers redraw cells when it changes).

CaptureStatus

type CaptureStatus = "ready" | "playing" | "dying" | "clear" | "extend" | "over" | "complete"

Session status.

CaptureTiming

interface CaptureTiming

Timings in seconds.

  • ready: number — Round intro before play.
  • dying: number — Death freeze.
  • clear: number — After the last enemy before the round ends (collecting fruit).
  • transition: number — Round-to-round transition.
  • extend: number — EXTEND celebration before the next round.
  • respawn: number — Invulnerability after a respawn.
  • entry: number — Seconds an enemy takes to drop into place.
  • corpseGhost: number — Seconds a popped enemy flies through everything before it can land.

PointsPickContext

interface PointsPickContext

What a points-item rule can see: the round, the players, how the previous round went, and the seeded stream.

  • round: number — Round number, from 1.
  • players: number — Players in the game.
  • previous: { time: number; hurry: boolean; chaser: boolean; umbrella: boolean } — The previous round: seconds it took, whether the hurry-up came, whether a chaser came, whether it was skipped by an umbrella.
  • rng: Rng — The session's seeded stream.