Phaser AE

Screw colour-sorting puzzles

Free packv3.0.0-12DPhysics

The rules of a screw-sorting physics puzzle. Tap the screws nothing covers and each goes into a box of its colour or a small waiting buffer; full boxes leave and new ones open, plates swing and fall as their screws go, and the board must be cleared before the buffer overflows.

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

Released October 19, 2026

Screw colour-sorting puzzles: 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

screwSort

function screwSort(): Pack<{ screwSort: ScrewSortApi }>

The screw-sort pack: game.screwSort, Screw Jam's rules on plates and screws of plate-stack's.

Functions

createScrewSort

function createScrewSort(level: ScrewSortLevel): ScrewSortGame

Make a game of a level. Throws, listing every problem, on a level validateScrewSortLevel refuses.

generateScrewSort

function generateScrewSort(options: ScrewSortGenerateOptions = {}): ScrewSortLevel

Make a level: plates in layers over the board, screws through their holes in colours that fill whole boxes, and a box queue the search can clear. Throws when no clearable level comes of the options.

solveScrewSort

function solveScrewSort(level: ScrewSortLevel, options: { maxStates?: number } = {}): string[] | null

Search for an order to take the screws in that clears the board without overflowing the buffer. Coverage is taken from the plates where they start (a plate covers while it still has a screw), so the search is exact and quick; the real plates swing as they lose screws, which can only uncover more, or now and then less, than this. Returns the screw ids in order, or null when none is found within maxStates (default 50,000).

validateScrewSortLevel

function validateScrewSortLevel(level: ScrewSortLevel): string[]

Check a level and say what is wrong with it, as plain sentences; empty when it can be played.

Types

ScrewBox

interface ScrewBox

An open box.

  • colour: string — Its colour.
  • count: number — Screws in it.

ScrewSortApi

interface ScrewSortApi

What the screw-sort pack adds to a game: game.screwSort.

  • create: typeof createScrewSort — Make a game of a level.
  • generate: typeof generateScrewSort — Make a clearable level.
  • solve: typeof solveScrewSort — Search for an order that clears a level.
  • validate: typeof validateScrewSortLevel — Check a level; empty when it can be played.

ScrewSortEvent

type ScrewSortEvent = | { kind: 'take'; screw: string; colour: string; to: 'box' | 'buffer'; slot: number } | { kind: 'board'; colour: string; from: number; box: number } | { kind: 'full'; box: number; colour: string } | { kind: 'open'; box: number; colour: string } | { kind: 'fall'; plate: string } | { kind: 'won' } | { kind: 'lost'; cause: 'overflow' }

What happened, for the presenter.

ScrewSortGame

interface ScrewSortGame

A game of one level.

  • readonly level: Readonly<ScrewSortLevel> — The level, as played (a copy).
  • readonly state: Readonly<ScrewSortState> — The state, live.
  • readonly stack: PlateStack — The plates and screws. Replaced by a restart or a restore.
  • tap(screw: string): 'box' | 'buffer' | null — Tap a screw: where it went, or null when it is covered, gone, or the game is over.
  • step(dt: number): void — Advance by dt seconds: plates pivot and fall.
  • drain(): ScrewSortEvent[] — What happened since the last drain, oldest first.
  • view(): ScrewSortView — Everything to draw.
  • restart(): void — Start the level again.
  • snapshot(): ScrewSortSave — The game as plain JSON: its moves, replayed on restore.
  • restore(save: ScrewSortSave): void — Resume a snapshot of this level. Throws on another level's, and leaves the game as it was.

ScrewSortGenerateOptions

interface ScrewSortGenerateOptions

How to make a level.

  • seed?: number — The seed. The same options and seed give the same level. Default 0.
  • id?: string — An id for the level. Default screw-sort-<seed>.
  • width?: number — The board's width. Default 600.
  • height?: number — The board's height. Default 820.
  • plates?: number — How many plates. Default 8.
  • layers?: number — How many layers they lie in. Default 4.
  • shapes?: 'bars' | 'squares' | 'discs' | 'mix' — The plates' shapes: bars, squares, rounded discs or a mix. Default the mix.
  • colours?: ReadonlyArray<string> — The screw colours to use. Default five.
  • capacity?: number — Screws per box. Default 3.
  • open?: number — Boxes open at once. Default 2.
  • buffer?: number — The buffer's size. Default 5.
  • plateColours?: ReadonlyArray<string> — The plates' colours.

ScrewSortLevel

interface ScrewSortLevel

A level.

  • id?: string — Its id, which saves carry.
  • name?: string — A name to show.
  • stack: PlateStackSpec — The board, plates and screws (each screw with a colour).
  • boxes: string[] — The colour of every box, in the order they open. Each colour needs capacity screws per box.
  • capacity?: number — Screws per box. Default 3.
  • open?: number — How many boxes are open at once. Default 2.
  • buffer?: number — How many screws the waiting buffer holds. Default 5.
  • solution?: string[] — A known solution: screw ids in the order to take them.

ScrewSortMove

type ScrewSortMove = { kind: 'advance'; seconds: number } | { kind: 'tap'; screw: string }

A move: time passing, or a screw tapped.

ScrewSortSave

interface ScrewSortSave

A saved game.

  • format: 'phaser-ae-screw-sort' — Always 'phaser-ae-screw-sort'.
  • version: 1 — The save format's version, 1.
  • level: string — The level's id ('' for a level without one).
  • history: ReturnType<History<unknown, ScrewSortMove>['snapshot']> — The moves, as the kernel's history saves them.

ScrewSortState

interface ScrewSortState

The game's state, to read.

  • phase: 'playing' | 'won' | 'lost' — 'playing', 'won' or 'lost'.
  • cause: 'overflow' | null — Why a lost game was lost.
  • boxes: (ScrewBox | null)[] — The open boxes, by slot; null where the queue has run out.
  • opened: number — How many boxes of the queue have opened.
  • buffer: (string | null)[] — The waiting buffer, by slot: a screw's colour, or null.
  • taken: string[] — The screws taken, in order.
  • time: number — Seconds played.

ScrewSortView

interface ScrewSortView

Everything a presenter draws.

  • plates: PlateView[] — The plates as they are now (the plate-stack's view).
  • screws: ScrewView[] — The screws still in the board, and whether each is covered.
  • boxes: (ScrewBox | null)[] — The open boxes.
  • queue: string[] — The boxes still to open, in order.
  • buffer: (string | null)[] — The waiting buffer.
  • capacity: number — Screws per box.