Agent skill
develop-web-game
Use when building or iterating on an HTML5 Canvas web game and you need a reliable develop-test loop: implement a small change, run the bundled Playwright test script with action bursts and deterministic time stepping, inspect screenshots and render_game_to_text output, review console errors, and fix issues before the next iteration. Covers canvas layout, game state exposure, progress tracking, and automated visual verification.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/develop-web-game
Metadata
Additional technical details for this skill
- tags
-
guide web-game html5-canvas playwright testing game-development
- author
- platxa-skill-generator
- version
- 1.0.0
- provenance
-
{ "upstream_sha": "c0e08fdaa8ed6929110c97d1b867d101fd70218f", "regenerated_at": "2026-02-04T15:54:11Z", "upstream_source": "develop-web-game", "generator_version": "1.0.0", "intent_confidence": 0.58 }
SKILL.md
Develop Web Game
Build HTML5 Canvas games in small steps and validate every change through an automated Playwright test loop: implement, act, pause, observe, adjust.
Overview
This guide teaches an iterative development workflow for browser-based games rendered on an HTML5 Canvas element. Each cycle follows a tight feedback loop:
- Pick a single feature or behavior to implement
- Make the smallest code change that moves the game forward
- Run the Playwright test script to exercise the change
- Inspect screenshots and text state output for correctness
- Review console errors and fix any regressions
- Repeat until stable
The workflow relies on two integration points the game must expose: window.render_game_to_text() for machine-readable state and window.advanceTime(ms) for deterministic frame stepping. These let the Playwright script drive the game without flaky timing dependencies.
What you will learn:
- Setting up skill paths and verifying Playwright prerequisites
- The implement-test-inspect core development loop
- Canvas layout, visual guidelines, and state exposure patterns
- Deterministic time stepping for reliable automated testing
- Progress tracking across agent handoffs
- Multi-step interaction verification and regression testing
Prerequisites:
- Node.js >= 18 with npm/npx on
PATH - Playwright (local dependency or global install via
npm install -g @playwright/mcp@latest) - An HTML file serving a Canvas-based game on a local dev server
Learning Path
Level 1: Project Setup
Set skill paths once per session:
export SKILL_HOME="${SKILL_HOME:-$HOME/.claude/skills/develop-web-game}"
export WEB_GAME_CLIENT="$SKILL_HOME/scripts/web_game_playwright_client.js"
export WEB_GAME_ACTIONS="$SKILL_HOME/references/action_payloads.json"
Verify Playwright availability:
command -v npx >/dev/null 2>&1 && echo "npx ready" || echo "install Node.js first"
If npx is missing, install Node.js and npm. If the project already has a local playwright dependency, prefer that over a global install.
Initialize progress tracking:
If progress.md exists, read it first and confirm the original user prompt is recorded at the top (prefixed with Original prompt:). Note any TODOs and suggestions left by a previous agent. If the file is missing, create it:
Original prompt: <user's request here>
## Progress
- [ ] Initial setup complete
Update progress.md after each meaningful chunk of work so another agent can pick up seamlessly.
Level 2: Core Development Loop
The fundamental cycle is implement-run-inspect-fix:
Step 1 -- Implement a small change. Modify the game code to add or adjust a single feature. Keep changes minimal so failures are easy to diagnose.
Step 2 -- Run the Playwright test script:
node "$WEB_GAME_CLIENT" \
--url http://localhost:5173 \
--actions-file "$WEB_GAME_ACTIONS" \
--click-selector "#start-btn" \
--iterations 3 \
--pause-ms 250
Required flags: --url and one of --actions-file, --actions-json, or --click. The script launches Chromium, injects the virtual-time shim, runs action bursts, captures screenshots to output/web-game/shot-{i}.png, and writes state-{i}.json from render_game_to_text().
Step 3 -- Inspect screenshots. Open each shot-{i}.png and verify expected visuals. Do not skip this step; screenshots are the source of truth for what the player sees.
Step 4 -- Inspect text state. Read state-{i}.json and confirm it matches what the screenshot shows. If render_game_to_text disagrees with the visual, fix the state function.
Step 5 -- Check console errors. If errors-{i}.json exists, fix the first new error before continuing. The script halts on the first error iteration.
Step 6 -- Iterate. Change one variable at a time (frames, inputs, timing, positions), then repeat steps 2-5 until stable.
Level 3: Advanced Verification
Multi-step interaction testing:
For each important interaction, trace the full causal chain and verify every intermediate state:
- Shooting an enemy: projectile spawns, travels, hits target, target health decreases, at zero health target disappears, score updates
- Collecting a key: key disappears from map, inventory updates, locked door becomes passable, player can enter next area
- Menu navigation: start/pause/resume/restart transitions all function correctly
Exercise all control paths: move, jump, shoot/attack, interact/use, menu select/confirm/cancel, pause/resume, restart, and any special abilities.
Inline action bursts:
When --actions-file is not flexible enough, pass actions directly:
node "$WEB_GAME_CLIENT" \
--url http://localhost:5173 \
--actions-json '{"steps":[{"buttons":["left_mouse_button"],"frames":2,"mouse_x":120,"mouse_y":80},{"buttons":[],"frames":6},{"buttons":["right"],"frames":8},{"buttons":["space"],"frames":4}]}' \
--iterations 1
Headed mode for debugging:
When headless screenshots look wrong (e.g., blank canvas from WebGL capture issues), switch to headed mode:
node "$WEB_GAME_CLIENT" \
--url http://localhost:5173 \
--actions-file "$WEB_GAME_ACTIONS" \
--headless false
Reset between scenarios:
When testing distinct features, avoid cross-test state contamination. Reload the page or restart the dev server between unrelated test runs.
Best Practices
Do
- Expose
window.render_game_to_text()returning concise JSON with mode, player position/velocity, active entities, score, and state flags - Expose
window.advanceTime(ms)wired into the game update loop for deterministic frame stepping - Use a single Canvas element centered in the viewport
- Draw backgrounds on the canvas itself, not via CSS
- Keep on-screen text minimal; show controls on a start/menu screen
- Include coordinate system documentation in
render_game_to_textoutput (origin, axis directions) - Capture gameplay screenshots beyond the start screen covering all new features
- Update
progress.mdwith TODOs and findings after each work session
Avoid
- Inventing a new test client; always use
$WEB_GAME_CLIENTunless explicitly required - Relying on wall-clock timing in tests; always use the
advanceTimehook - Making large multi-feature changes between test runs
- Skipping screenshot inspection; treating generated screenshots as the source of truth
- Overlaying dense text on the game canvas during play
- Using overly dark scenes that obscure interactive elements
- Leaving
progress.mdwithout updating it at session end
Common Questions
Q: The canvas screenshot is blank or transparent?
A: This usually means the canvas content was not captured correctly in headless mode. The script tries three capture methods: canvas.toDataURL(), Playwright element screenshot, and viewport clip. If all fail, rerun with --headless false to rule out WebGL/SwiftShader issues. Ensure the canvas has rendered at least one frame before capture.
Q: Tests are flaky with inconsistent state between runs?
A: Make sure window.advanceTime(ms) is connected to your game loop. Without deterministic time stepping, requestAnimationFrame timing varies between runs. The virtual-time shim intercepts setTimeout, setInterval, and requestAnimationFrame but the game loop must use advanceTime when available.
Q: How do I test keyboard and mouse input combinations?
A: Define action steps with multiple buttons and frame counts. Each step presses the listed buttons, advances the specified number of frames via advanceTime, then releases:
{
"steps": [
{ "buttons": ["left", "space"], "frames": 4 },
{ "buttons": [], "frames": 10 },
{ "buttons": ["right"], "frames": 8 }
]
}
Mouse actions use left_mouse_button or right_mouse_button with mouse_x/mouse_y coordinates relative to the canvas.
Q: Can I run this without a local dev server?
A: You need an HTTP URL. Start a local server with npx serve . or python3 -m http.server 5173 and point --url to it.
Examples
Example 1: Add a Jump Mechanic
User: Add jumping to the player character
Assistant:
1. Adds velocity_y and gravity to player state
2. Wires Space key to set velocity_y = -12
3. Updates render_game_to_text to include velocity_y
4. Runs: node "$WEB_GAME_CLIENT" --url http://localhost:5173 \
--actions-json '{"steps":[{"buttons":["space"],"frames":4},{"buttons":[],"frames":20}]}' \
--iterations 1
5. Opens shot-0.png -- player is mid-air, ground visible below
6. Reads state-0.json -- velocity_y is negative (ascending)
7. No errors-0.json -- clean run
Result: Jump mechanic working, player returns to ground after 20 frames
Example 2: Debug a Collision Bug
User: Enemies pass through walls on the right side
Assistant:
1. Reads render_game_to_text output showing enemy x > wall_x
2. Finds boundary check uses < instead of <=
3. Fixes: if (enemy.x + enemy.r >= wall.x) enemy.vx *= -1
4. Runs test script with enemies moving right for 30 frames
5. Opens screenshots -- enemies now bounce off right wall
6. Verifies state JSON shows enemy.x stays within bounds
7. Tests left wall too (regression check) -- still works
Result: Collision fixed for both walls, no regressions
Guardrails
- Always run
$WEB_GAME_CLIENTafter each meaningful change; do not skip the test step - Always visually inspect screenshots; do not assume correctness from state JSON alone
- Fix the first console error before continuing to the next feature
- Keep
progress.mdupdated so handoffs between agents are seamless - Do not switch from the bundled Playwright client to
@playwright/testunless explicitly asked - Change one variable at a time when debugging; large changes make failures hard to isolate
- Prefer a single canvas with
render_game_to_textandadvanceTimeintegration points - Use
--screenshot-dirto organize output per test scenario when running multiple test suites
References
Load these on demand when deeper detail is needed:
- Game architecture patterns:
references/game-architecture.md-- Canvas setup, render_game_to_text implementation, advanceTime hook, fullscreen toggle - Playwright test patterns:
references/playwright-testing.md-- test script flags, action payload format, virtual-time shim internals, capture methods
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?