Phaser AE

Scaled depth

Free packv3.0.0-42DArcade

A pseudo-3D world of scaled sprites over a patterned ground, as plain data: a camera that pitches, rolls and tilts, ground and ceiling patterns cut into scanline bands, and a field of objects that arrive from the horizon, pass behind the camera and collide on the way. It draws nothing itself, so any 2D sprite renderer can present it.

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

Released October 14, 2026 · updated October 20, 2026

Scaled depth: 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.

What it does

The camera turns world points into a screen position, a scale and a rotation. Its horizon can pitch with the player's height, the whole view can roll about a pivot for a banking jet, and a tilt turns it to look down on the world, up to straight overhead, so the roofs of towers grow towards the camera. The inverses answer the questions a game asks back: the ground point under the pointer, a point at a depth, and the rectangle that covers a rolled screen.

The ground is a surface: a plane of coloured cells, as a checkerboard, row or column stripes, or bands whose colour pair alternates with every depth row. bands() slices it into scanline strips with a stable contract, telling a sprite renderer what colours to draw where, and surfaceTransform() gives the same thing as numbers for a shader. A surface above the camera is a ceiling.

A depth field holds the objects. Each lives in the world frame (scenery, ground targets, traffic) or the camera frame (shots, formations holding station, enemies arriving from behind), and moves by velocity, along an authored depth path or by homing. The field runs each object's life through spawned, entered, behind, receded and expired, streams seeded scenery by distance, sweeps collisions over each step's relative motion so a fast object cannot jump past the player's plane, picks objects under a screen point for lock-on, and lists them projected and sorted far to near, with shadows. Everything snapshots and restores as plain data.

Features

  • A projecting camera — position, scale, roll and fog per point, with a horizon that pitches and a view that rolls about a pivot.
  • Look-down tilt — a true rotation about the x axis, from level to straight overhead, with a painter's order for upright things seen from above.
  • Inverses — the ground point under a screen pixel for pointer aiming and shadows, unprojection at a depth, and roll helpers.
  • Scanline surfaces — checkerboards, row and column stripes and alternating band patterns for grounds and ceilings, with haze towards the horizon.
  • Two frames of objects — world-frame scenery and camera-frame formations and shots in one field.
  • Motion — velocity, Catmull-Rom or linear depth paths that hold, end or continue, aiming and homing steering.
  • A lifecycle — events as objects spawn, enter view, pass behind, recede and expire.
  • Seeded scenery streams — sections of rows of weighted kinds laid by distance, the same in any window and any order.
  • Swept collision — boxes swept over relative motion, earliest contact first, filtered by kind, group and frame.
  • Screen picks — objects under a point with a radius and a depth window, for crosshairs and lock-on.
  • A sorted draw list — sprites far to near with scale, rotation, fog and shadows, ready for any renderer.
  • A road projector — hands world-frame projection to a pseudo-3D road so traffic follows its curves and hills.

Good for

  • Third-person into-the-screen shooters over a checkerboard ground, in the style of Space Harrier.
  • Jet combat with a rolling view, enemies from behind and lock-on missiles, in the style of After Burner.
  • Helicopter shooters that switch between a view behind the craft and one straight down on a city, in the style of Thunder Blade.
  • The objects of sprite-scaling racers: traffic, palms and signs riding a pseudo-3D road.
  • Your own scaling games: a jet-ski ride over a striped sea, or a flight down a tunnel with a ceiling and bats.

Make it yours

There are no pack options; everything is configured through its factories. The camera takes the screen size, a focal length or field of view, the horizon row, the tilt, near and far planes, the roll pivot, fog distances and an optional projector. Surfaces take tile sizes, a grid of cell colours, a height, an origin and a haze. The field takes its far and behind distances, a live-object cap (default 2048, at most 16384) and named paths. Scenery streams take a seed and sections of rows, each with kinds, spacing, jitter, lateral ranges, a chance and mirroring.

Two different games on the same pack: a low third-person runner whose camera pitches with the hero's height over a column-striped ground, with formations on camera-frame paths and trees streamed by distance; and a helicopter game whose camera tilts to look straight down on streamed towers and tanks, sorted with the ground order, then swings level behind the craft for the next section.

A quick look

A camera, a field with a path, a ground and a scenery stream, stepped and drawn:

const SD = game.scaledDepth;
const cam = SD.createDepthCamera({ width: 320, height: 224, focal: 160, horizon: 169, far: 160 });
const field = SD.createDepthField({ far: 160 });
const ground = SD.surface({ tileWidth: 2, tileDepth: 3, cells: [["#a4f7a4", "#73c573"], ["#94e694", "#84d684"]] });
const trees = SD.createSceneryStream({ seed: 1, sections: [{ from: 0, to: 3000, spacing: 20, rows: [{ kinds: [{ kind: "tree", w: 2, h: 6 }], x: [-15, 15] }] }] });
const me = field.spawn({ kind: "player", frame: "camera", z: 6, w: 1.2, h: 2, anchor: "base", keep: true });
field.feed(trees, camZ + 160); field.step(dt, camZ);
for (const c of field.collide(me, { kinds: ["tree"] })) die(c.other);
for (const b of cam.bands(ground)) drawBand(b);
for (const s of field.view(cam, { shadows: true })) drawSprite(s.kind, s.x, s.y, s.w, s.h, s.rot);

Works with

  • scaler-runner — third-person runner rules built on this world.
  • jet-combat — banking jet combat that uses its roll, pitch, picks and steering.
  • heli-assault — helicopter rules that use its tilted overhead camera.
  • pseudo-road — the segmented road of sprite-scaling racers, joined through its road projector.
  • rail-route — for true 3D on a camera path, when free camera rotation is needed.

Good to know

  • There is no true yaw: heading is lateral camera movement and pitch moves the horizon. Tilt about the x axis is the one true rotation; free rotation belongs on rail-route and a 3D renderer.
  • Surfaces are flat planes; hills and curves come from pseudo-road.
  • Collision is between axis-aligned boxes, exact for straight motion within a step and conservative for curved paths.
  • A field holds at most 16384 live objects, and bands are capped by maxBands (default 4096).

More Arcade packs

Show all →