Phaser AE

Game feel

Free packv3.0.0-42D and 3DLook

The screen-level juice every action game wants when something hits: a camera shake, a trauma meter, a full-screen flash, a hit-stop, a slow-motion beat and a zoom punch, each one call on `game.feel`. They touch only what is drawn, so the simulation never moves and a replay is unchanged.

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

Released October 14, 2026 · updated October 19, 2026

Game feel: 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

feel

function feel(options: FeelOptions = {}): Pack<{ feel: FeelApi }>

The feel pack: game.feel, a simulate step after physics-2d, all state reset on scene exit. No world requirement: it writes the KERNEL camera's shake and punch, which every world shares. A 2D world adds them to its rendered offset; a 3D world jitters the look and narrows the fov. flash alone needs a screen-space world, and says so. Throws on an option out of range.

Types

FeelApi

interface FeelApi

What game.feel presents. Defaults: shake 6 / 0.3 s, addTrauma 0.3, flash white / 0.25 s / alpha 1, hitstop 0.08 s, slowMotion 0.3 / 0.5 s / 0.25 s ramp, zoomPunch 0.1 / 0.25 s.

  • shake(power?: number, duration?: number, options?: ShakeOptions): void — A jitter of up to power world units (pixels in a 1:1 2D game) that falls away over duration seconds. A new shake replaces the running one unless the running one is still stronger now, after its decay.
  • addTrauma(amount?: number): void — Add amount (0 to 1) to the trauma, clamped to 1. Trauma drives its own shake, traumaPower × trauma^traumaExponent, and drains at traumaDecay per second, so knocks accumulate: three small hits shake harder than one, and a big one cannot be outdone by a small one. It adds to any shake running.
  • flash(color?: string, duration?: number, alpha?: number): void — A full-screen colour wash fading out over duration s. It is one screen-space object, so it needs world-screen composed; without one it is a no-op and says so once in dev, because a silent flash is indistinguishable from an explosion that did not fire.
  • hitstop(seconds?: number): void — Freeze the sim for seconds of wall time (timeScale 0), then restore the scale in force before. Overlapping calls take the longer remaining time.
  • slowMotion(scale?: number, seconds?: number, rampOut?: number): void — Run the sim at scale (0 to 1) for seconds of wall time, then ease back to the scale in force before over rampOut seconds: a dramatic kill, a near miss. A new call replaces a running one; a hit-stop freezes on top.
  • zoomPunch(amount?: number, duration?: number): void — Zoom in by amount (0.1 = 10 %) and ease back quadratically over duration s. A new punch replaces the current one.
  • readonly shaking: boolean — True while a shake is running or trauma is above zero.
  • readonly trauma: number — The current trauma, 0 to 1.

FeelOptions

interface FeelOptions

Manifest options for the feel pack; every one is optional.

  • shakeDecay?: ShakeDecay — Default decay curve for shake when its options name none; default linear.
  • traumaPower?: number — Camera offset in world units (pixels in a 1:1 2D game) at full trauma, 1; default 18.
  • traumaDecay?: number — Trauma lost per second, 0.05 to 20; default 2.5, so a full knock dies away in 0.4 s.
  • traumaExponent?: number — The offset follows trauma raised to this power, 1 to 4; default 2, so small knocks stay small and big ones jolt.
  • traumaFrequency?: number — New random trauma offsets per second, eased between, 0 to 120; default 0, a new offset every simulation step.
  • traumaRoll?: number — Degrees the view turns at full trauma, following trauma^traumaExponent as the offset does; 0 to 30, default 0 (none). Needs post, as ShakeOptions.roll does.

FeelTrauma

interface FeelTrauma

What feel registers for other packs (kind feel, name trauma), so a pack that requires feel can knock the camera without the game handing it game.feel: k.registry.get<FeelTrauma>('feel', 'trauma')?.add(0.4).

  • readonly name: 'trauma' — Always 'trauma'.
  • add(amount: number): void — Add trauma, as game.feel.addTrauma does.

ShakeDecay

type ShakeDecay = 'linear' | 'quadratic' | 'none'

How a shake's strength falls over its duration: linear, quadratic (eases out: strong, then a long tail), or none (full strength until it stops).

ShakeOptions

interface ShakeOptions

How one shake moves the camera; every field is optional.

  • axis?: 'both' | 'x' | 'y' — both (default) jitters x and y independently; x or y jitters along that axis only. Ignored when angle is set.
  • angle?: number — Shake along one direction only, in radians (0 is +x, π/2 is +y, down the screen in 2D): a knock from a hit, a recoil. Default none, which uses axis.
  • decay?: ShakeDecay — How the strength falls over the duration; default the pack's shakeDecay option, itself linear by default.
  • frequency?: number — New random offsets per second, eased between, for a slower rumble; 0 (the default) picks a new offset every simulation step, the classic buzz. Up to 120.
  • roll?: number — Also turn the view by up to this many degrees, jittered and decaying as the offset does: a rotational shake. It needs post composed, because it turns the finished world image about the screen centre (zoomed just enough to keep the corners covered) while the HUD stays still; without post it throws in development. Default 0.