Phaser AE

Slingshot siege

Pro packv3.0.0-13DArcade

A slingshot demolition puzzle on real rigid bodies: structures of wood, glass and stone that crack and topple under each shot, goals to destroy within a limited number of shots, and a generator that proves every level it makes can be won.

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

Released October 19, 2026

Slingshot siege: 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

slingshotSiege

function slingshotSiege(): Pack<{ slingshotSiege: SlingshotSiegeApi }>

The slingshot-siege pack: Angry Birds' rules on real rigid bodies, independent of rendering.

Helpers

createSlingshotSiege

const createSlingshotSiege = (config: SiegeConfig): Promise<SlingshotSiege>=> …

Create a round, the same as SlingshotSiege.create.

generateSiege

async function generateSiege(o: SiegeOptions = {}): Promise<SiegeLevel>

Generate a level and prove it winnable by playing it through the physics. Throws on an option outside its bounds, and when no certified arrangement is found in 30 attempts.

SIEGE_FAMILIES

const SIEGE_FAMILIES: readonly SiegeFamily[]

Every structure family.

Classes

SlingshotSiege

class SlingshotSiege

A siege round on its own rigid world.

  • readonly config: SiegeConfig — The configuration it was created with (an owned copy).
  • static async create(c: SiegeConfig): Promise<SlingshotSiege> — Create a round with its own physics world; resolves when the rigid-body runtime is ready. Throws on an unknown material, duplicate piece ids, or a number outside its bounds.
  • get state(): SiegeState — A fresh copy of the state, with every body's pose.
  • get solved(): boolean — Whether the round is won.
  • get lost(): boolean — Whether the round is lost.
  • get busy(): boolean — Whether a shot is still settling.
  • get origin(): Point — Where shots leave from.
  • trajectory(velocity: Point, seconds = 2): Point[] — The free flight of a shot at velocity for seconds (0.1 to 5, default 2), as 41 points.
  • aimAt(point: Point, flight = 0.8): Point | null — The launch velocity that lands on point after flight seconds (default 0.8), or null when that would need more than shotSpeed.
  • aimFromDrag(dx: number, dy: number): Point | null — The velocity of a slingshot drag of (dx, dy): opposite the drag at 4.5 a unit, capped at shotSpeed, with z 0; null for a drag too short to launch. Throws when dx or dy is outside -30 to 30.
  • fire(velocity: Point): { valid: boolean; reason: string } — Fire at velocity. Invalid, firing nothing, when the round is over, the shots are spent, a shot was fired in the last 0.2 s or one is still settling. Throws when the velocity is out of bounds.
  • step(dt: number): void — Advance by dt seconds (0 to 0.1) in fixed 1/120 s ticks; the remainder carries to the next call.
  • hint(): { target: string; velocity: Point } | null — A shot at a standing goal, leftmost first: its id and a velocity that reaches it, or null.
  • reset(): void — Rebuild the round: every piece whole, the shots restored, the history cleared.
  • undo(): boolean — Take back the last shot by rebuilding the world and replaying the earlier ones; false if there is none.
  • redo(): boolean — Replay a shot undo took back; false if there is none.
  • dispose(): void — Release the physics world; the round cannot be used afterwards.

Types

SiegeConfig

interface SiegeConfig

A siege round: the structure, the launcher and the limits.

  • pieces: LaunchPiece[] — Every piece, from 1 to 160, with distinct ids.
  • origin: Point — Where shots leave from, world units.
  • gravity: number — Gravity along y in world units a second squared, from -30 to 0 (negative pulls down).
  • ammo: number — Shots at the start of the round, a whole number from 1 to 80.
  • shotSpeed: number — The fastest a shot may leave, world units a second, from 5 to 40.
  • materials?: Record<string, MaterialDef> — Materials by name, merged over DEFAULT_MATERIALS.
  • goals?: string[] — The materials whose pieces must all be destroyed to win. Default ['goal'].
  • floor?: { x: number; y: number; z: number; sx: number; sy: number; sz: number } | null — The ground the structure stands on: a static box (centre and full size). Default 70 by 1 by 12 at (3, -0.5, 0); null for none.
  • settle?: number — Seconds a shot may take to settle before the next may be fired. Default 6.

SiegeFamily

type SiegeFamily = 'towers' | 'bridges' | 'pyramid' | 'staircase' | 'fortress' | 'cantilever'

The structure families: posts and roofs in towers, spans on piers, brick pyramids, stone stairs with a goal on each step, stone fortresses with glass roofs, and a weighted cantilever.

SiegeLevel

interface SiegeLevel

A generated level and the proof that it can be won.

  • seed: number — The seed it was generated from.
  • difficulty: Difficulty — The difficulty it was generated at.
  • config: SiegeConfig — The round to play: pass it to createSlingshotSiege.
  • parameters: Required<SiegeOptions> — The options with every default filled in; pass them back to get the same level.
  • solution: { time: number; velocity: Point }[] — A winning sequence the generator played through the physics: each shot's velocity and when it was fired.
  • metrics: { family: string; encounters: string[]; groups: number; pieces: number; targets: number; certificateShots: number; duration: number; structure: string } — The level's structure family and encounters, counts, the verified shot count and its duration.

SiegeOptions

interface SiegeOptions

Options for generateSiege; each is optional and checked against its bounds.

  • seed?: number — Unsigned 32-bit seed. Default 1.
  • difficulty?: Difficulty — easy, medium, hard or very-hard. Default medium.
  • groups?: number — Assemblies, from 1 to 8. Default 2, 3, 4 or 5 by difficulty, plus 1 on an odd seed.
  • pattern?: 'auto' | SiegeFamily — The structure family the level opens with (the seed picks one for auto); others are mixed in after it.
  • ammo?: number — Shots at the start, from 1 to 60. Default 3 a group plus 3, 2, 1 or 0 by difficulty.

SiegeState

interface SiegeState

The round's state, an owned copy.

  • time: number — Seconds simulated since the round started or was reset.
  • ammo: number — Shots left.
  • shots: number — Shots fired.
  • score: number — Points: each destroyed piece's material score.
  • destroyed: string[] — Ids of the pieces destroyed, in order (pieces knocked out of the play area count).
  • busy: boolean — Whether a shot is still settling; no shot can be fired meanwhile.
  • lost: boolean — Out of shots with a goal standing.
  • solved: boolean — Every goal destroyed, once settled.
  • stars: number — Rating from 1 to 3 once solved, 0 before: three for using at most six tenths of the shots, two for fewer than all, one otherwise.
  • poses: LaunchPose[] — Every body's pose, for the renderer.

SlingshotSiegeApi

type SlingshotSiegeApi = typeof kit & { DEFAULT_MATERIALS: typeof DEFAULT_MATERIALS }

game.slingshotSiege: the round, its generator and the built-in materials.