skillZs
★ LIVE SKILL TAGS ★
>>> LIVE SKILLS INDEX <<<
* OPEN SOURCE *
NO LOGIN, NO TRACKING
※ REAL INSTALL DATA ※
← back to all skills
yakoub-ai/phaser4-gamedev99 installs

phaser-playtest

This skill should be used when the user asks to "playtest my game", "test my Phaser game", "does my game actually run", "check the game in a browser", "verify the game works", "smoke test the game", "automate game testing", "catch black screens", "check for asset 404s", "measure FPS", "screenshot the game", "write a playtest scenario", or whenever Phaser 4 code has been written or changed and needs runtime verification before being handed back to the user.

How do I install this agent skill?

npx skills add https://github.com/yakoub-ai/phaser4-gamedev --skill phaser-playtest
view source ↗

Is this agent skill safe to install?

  • Gen Agent Trust Hubpass

    The skill is a specialized testing harness for Phaser 4 games that uses Playwright to perform runtime verification such as asset loading, canvas rendering, and frame rate monitoring. It follows security best practices by recommending that testing hooks only be exposed in development environments. No malicious patterns, exfiltration attempts, or unauthorized access vectors were detected.

  • Socketwarn

    1 alert: gptAnomaly

  • Snykpass

    Risk: LOW · No issues

What does this agent skill do?

Phaser 4 Playtesting (Runtime Verification)

npx tsc --noEmit proves the code compiles. It says nothing about whether the game runs. Every failure below type-checks perfectly and still ships a broken game:

FailureWhat the player seesWhat TypeScript says
Asset path typoInvisible spritesNothing — it's a string
Scene missing from scene: []Black screenNothing
create() throws after first lineHalf-built sceneNothing
Depth/alpha/camera-scroll mistakeBlank canvasNothing
Physics body never addedPlayer falls through floorNothing
Uncapped emitter12 fpsNothing

Runtime verification is not optional. Run the harness after any change that touches scene lifecycle, asset loading, physics, or rendering — before telling the user it works.

Run It

node "${CLAUDE_PLUGIN_ROOT}/skills/phaser-playtest/scripts/playtest.mjs" --project .

The harness starts the dev server itself, drives headless Chromium, and shuts the server down again. No config, no test files required.

Requires Playwright in the project (once):

npm install -D playwright && npx playwright install chromium

What it checks

  1. Page loads — HTTP status of the document
  2. Canvas created — a sized <canvas> exists (fails ⇒ Phaser never booted)
  3. Phaser instance reachable — finds the Phaser.Game on window
  4. Game booted — isBooted === true
  5. Active scenes — which scenes run, and how many display objects each holds
  6. Scenes render content — warns on a scene with an empty display list
  7. Frame rate — median and 5th-percentile FPS sampled over real frames
  8. Canvas renders content — pixel analysis; catches the black screen
  9. No uncaught exceptions — pageerror with stack
  10. No console errors
  11. All assets load — including files the dev server masks as 200 text/html

Exit code 0 = pass, 1 = check failures, 2 = harness error. Writes .playtest/report.json plus PNG screenshots.

Options

FlagPurpose
--project DIRProject root (default: cwd)
--url URLTest an already-running server instead of starting one
--mode dev|buildbuild runs npm run build + preview — catches base-path and bundling bugs
--scenario FILEDrive a scripted play session (see below)
--device iphone|androidMobile viewport, DPR, touch, and UA
--settle MSWait before probing (default 3000; raise for slow preloads)
--fail-on-warnTreat console warnings as failures (CI)
--jsonEmit only JSON — use when parsing results
--headedShow the browser

Make the Game Testable (one line)

The deep checks need the game instance. Bundled games keep it in module scope, so expose it in dev builds only:

const game = new Phaser.Game(config);
if (import.meta.env.DEV) (window as any).__PHASER_GAME__ = game;
export default game;

Without it the harness still catches black screens, exceptions, and 404s, but skips scene, FPS, and state assertions — and says so. Add the line; it costs nothing in production. See references/instrumenting-games.md for deterministic-testing hooks (seeded RNG, time control, state injection).

Scenario Scripts

A scenario drives input and asserts on live game state. game is bound to the running instance inside every expression.

// playtest/combat.mjs
export default [
  { name: 'reaches gameplay', action: 'expect',
    expect: { expression: `game.scene.isActive('GameScene')`, equals: true } },

  { name: 'walk right', action: 'key', key: 'ArrowRight', duration: 600 },

  { name: 'player advanced', action: 'expect',
    expect: { expression: `game.scene.getScene('GameScene').player.x > 400`, equals: true } },

  { name: 'attack lands', action: 'press', key: 'Space',
    expect: { expression: `game.registry.get('enemyHp')`, atMost: 90 } },

  { name: 'after-combat', action: 'screenshot' },

  { name: 'holds frame rate', action: 'expect',
    expect: { expression: `game.loop.actualFps`, atLeast: 55 } },
];

Actions: wait (ms), key (key, duration), press (key), click (x, y canvas-relative), screenshot (name), expect. Assertions: equals (deep), atLeast, atMost, or bare expression for truthy.

Full reference: references/playtest-harness.md. Worked example: examples/scenario.example.mjs.

Turning a Plan into Tests

Acceptance criteria from /phaser-gdd or the phaser-architect agent translate directly into scenario steps. Write the scenario when the feature is specified, not after it breaks:

Acceptance criterionScenario assertion
"Player jumps 3 tiles high"game.scene.getScene('GameScene').player.y, atMost: spawnY - 96
"Enemy dies in 3 hits"press attack ×3, then enemy.active, equals: false
"Score persists across scenes"start GameOver, then game.registry.get('score'), atLeast: 10
"Runs at 60fps with 50 enemies"spawn via eval, then game.loop.actualFps, atLeast: 55

Reading a Failure

Harness outputRoot cause to check first
canvas created failsScene threw in constructor/init, or the bundle 500s. Read console errors.
active scenes: no scene is runningScene missing from scene: [], or create() threw before completing
canvas renders content blank, scenes activeObjects off-camera, alpha: 0, wrong depth, or camera not following
scenes render content warns emptycreate() returned early — usually an exception swallowed by a try
all assets load fails with text/htmlPath typo, or the asset is in src/ instead of public/
frame rate lowUncapped particles, no object pooling, per-frame allocation. Use /phaser-analyze.
Phaser game instance found warnsAdd the __PHASER_GAME__ line above

CI

- run: npm ci
- run: npx playwright install --with-deps chromium
- run: npx tsc --noEmit
- run: node scripts/playtest.mjs --project . --mode build --fail-on-warn

Copy playtest.mjs into the project's own scripts/ so CI does not depend on the plugin being installed.

Discipline

  • Run the harness before reporting a feature complete — not after the user reports a bug.
  • A passing tsc plus a failing playtest means the work is not done.
  • When it fails, read .playtest/report.json and the screenshots before editing code. Investigation-first applies here exactly as in phaser-debugger.
  • Keep a scenario per major feature under playtest/; they are regression tests.

When the failure came from a player

If you are here because someone reported a bug rather than because you just changed code, use skills/phaser-feedback/ instead of writing a scenario straight away. It covers triaging the report first (a "too hard" complaint is not a defect and has no repro), and maps each claim shape to the right construct — --repeat for "sometimes", sample for "gets stuck", waitFor for "takes too long", --heap for "slows down over time".

Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.

<a href="https://skillzs.dev/skills/yakoub-ai/phaser4-gamedev/phaser-playtest">View phaser-playtest on skillZs</a>