| name | gameforge |
| description | Orchestrator skill that turns a one-line description into a runnable Phaser 3 game. Coordinates eight sub-skills (game-designer, world-architect, sprite-artist, tile-artist, bg-artist, codesmith, playtester, refiner) into a deterministic-where-possible, LLM-where-necessary pipeline. Image generation uses GPT Image 2 (gpt-image-2) at low quality by default. Use when the user wants to generate, refine, or test a 2D HTML5 game from natural language. |
Gameforge — Game Generation Orchestrator
Drives the full game-creation pipeline. The host agent (you) is the one calling LLM-bearing sub-skills; this skill describes the pipeline shape, the shared state file, validation gates, and halt conditions. All image generation goes through GPT Image 2 (gpt-image-2) at quality: low by default.
When to use
- "Make me a game where …"
- "Generate a Phaser game called …"
- "Refine the QA failures from the last run"
- Any request involving an 8-bit / pixel-art / 2D HTML5 game described in natural language
Pipeline
description
↓
game-designer → GDD + style.palette + levelHints
↓
world-architect → levels.json
↓
┌──────────────┬──────────────┬──────────────┬──────────────┐
sprite-artist tile-artist bg-artist audio-composer ← parallel
└──────────────┴──────────────┴──────────────┴──────────────┘
↓
palette-enforcer ← quantize all PNGs to chosen 8-bit palette
↓
codesmith → src/scenes/Game.js (imports AudioManager when state.audio is set)
↓
manifest-auditor → catches anim/texture key mismatches (fast, no browser)
mobile-compat-checker --fix → auto-patches roundPixels + image-rendering CSS
↓
parallel-qa-orchestra → 4 workers concurrently:
├── static (BFS reachability, border, jump arcs)
├── golden-path (boot, walk, jump, attack, win scenarios)
├── fuzzer (stuck, spawn-trap, no-progress, NaN)
└── physics-debug (hitbox alignment)
↓
VLM intent gate ← host agent reviews screenshot vs original description
↓ pass
Ship ←— refiner (loop, max 3) ←— fail
- game-designer turns prompt → GDD JSON (includes
style.palette auto-selection by genre).
- world-architect turns GDD →
levels.json (tile-based level layouts).
- sprite-artist turns GDD entities → sprite sheets + manifest. Uses GPT Image 2 (
gpt-image-2) by default at quality: low.
- tile-artist turns GDD tile palette →
tiles.png + tile metadata.
- bg-artist generates a parallax background image. Optional — skipped for top-down-adventure, abstract puzzle.
- audio-composer generates
sfx.json, music.json, and AudioManager.js from genre presets. Runs in parallel with art stages 3–5.
- palette-enforcer quantizes all generated PNGs to a named 8-bit palette (e.g. pico8, sweetie-16, endesga-32) for visual coherence.
- codesmith turns GDD + levels + manifest →
src/scenes/Game.js. Imports AudioManager and calls AudioManager.init(this) in create() when state.audio is set.
- manifest-auditor cross-references every animation/texture key in Game.js against manifest.json. Feeds mismatches to refiner before any browser is opened.
- mobile-compat-checker (with
--fix) auto-patches roundPixels: true and image-rendering: pixelated CSS; flags touch-input and audio-unlock gaps for refiner.
- parallel-qa-orchestra replaces the serial playtester→gap-checker chain. Runs 4 workers concurrently; merges into one failure list for the refiner.
- refiner consumes failures + current source → patched files. Loop back to parallel-qa-orchestra. Cap at 3 iterations.
Stages 3, 4, 5, 6 can run in parallel (independent inputs). Stage 7 is a fan-in (all art must be done first). Stages 9 and 10 are fast linting passes (no browser).
Shared state — game-state.json
Single source of truth at the project root. Every sub-skill reads/writes it. Schema:
{
"version": 1,
"name": "<project-name>",
"prompt": "<original user description>",
"genre": "top-down-adventure | platformer | shoot-em-up | puzzle | dungeon-crawler | top-down-rpg",
"createdAt": "<ISO timestamp>",
"gdd": <output from game-designer or null>,
"levels": [<output from world-architect>],
"assets": {
"sprites": [<manifest entries from sprite-artist>],
"tiles": <manifest from tile-artist or null>
},
"code": { "entryPoint": "src/main.js", "scenes": ["Boot","Preload","Game"] },
"qa": [<last 5 reports from playtester>]
}
Validate with scripts/validate_state.mjs <project-dir> after every mutation. Reject any change that breaks the schema.
Project layout (per generated game)
<project>/
├── game-state.json # shared state
├── package.json # phaser + vite
├── vite.config.mjs
├── index.html
├── public/
│ ├── assets/
│ │ ├── entities.png # from sprite-artist (one or more)
│ │ ├── tiles.png # from tile-artist
│ │ └── manifest.json # row/col labels per sheet
│ └── data/
│ └── levels.json # from world-architect
└── src/
├── main.js # Phaser bootstrap (template, never edit)
├── config.js # game config: pixelArt, FIT, RND seed
└── scenes/
├── Boot.js # template, never edit
├── Preload.js # builds anims from manifest, never edit
└── Game.js # codesmith-written
Boot.js and Preload.js are fixed across every game — they read manifest.json, build animations as <ENTITY_ID>-<state> (lowercased state), and stash levels + manifest on this.registry. Codesmith's Game.js consumes by name only.
Animation key convention
Every animation is <ENTITY_ID>-<state-lowercase>, e.g. KNIGHT-walk, SLIME-hurt, BULLET-idle. Frame index = row * cols + col, where row is the entity's index in the sheet's rows[] and col is the state's index in the sheet's cols[]. Codesmith MUST look these up via the manifest, never hard-code.
Workflow when invoked
Path A — fresh project from a description
- Ask user for project name (or accept arg). Run
scripts/init_project.mjs <name> to scaffold.
- Invoke game-designer with the user's description. Save GDD into
game-state.json. Validate.
- Invoke world-architect with the GDD. Save levels. Validate.
- In parallel:
- Invoke sprite-artist (default: GPT Image 2 at
quality: low; --placeholder for free iteration).
- Invoke tile-artist (
generateTilesetGPT() via src/lib/sprites.js — one GPT Image 2 call per tile type, 512×512 → 32×32; auto-falls back to solid-color if no FAL_KEY).
- Invoke bg-artist (
generate_bg.mjs --theme <theme>). Skip when genre is top-down-adventure or abstract puzzle.
- Write
public/assets/manifest.json and public/data/levels.json from state (the asset skills merge into the manifest as they go).
- Invoke codesmith with GDD + levels + manifest. Writes
src/scenes/Game.js (and optional helpers under src/). Codesmith reads manifest.bg and adds the parallax-background pattern when present.
- Invoke playtester. If failures, invoke refiner. Loop max 3.
- Report final status: passed / failed / partial. If passed, tell user to
cd <project> && npm run dev.
Refine an existing project
- Read
game-state.json and the latest QA report (qa/qa-report.json).
- If
passed === true, stop.
- Invoke refiner with failures + current source files. Apply edits.
- Invoke playtester. Loop until passed or 3 iterations.
Halt conditions
- Schema validation failure at any stage → halt, surface to user with the validation error. Do not loop.
- 3 refiner iterations without pass → halt, surface failures. Do not silently mark complete.
FAL_KEY and OPENAI_API_KEY both missing when an asset skill wants GPT Image 2 → fall back to procedural sprites/tiles and skip bg-artist.
- User cancels (SIGINT) → exit 130.
Optional: multiplayer
Add multiplayer to any generated game via the multiplayer skill:
node skills/multiplayer/scripts/init_server.mjs <project-dir>
node skills/multiplayer/scripts/patch_game.mjs <project-dir>
node skills/multiplayer/scripts/init_server.mjs <project-dir> --voice
node skills/multiplayer/scripts/init_server.mjs <project-dir> --lobby
Supports up to 4 players, 20 Hz tick rate, TypeScript shared schemas. See skills/multiplayer/SKILL.md.
References
references/pipeline.md — detailed stage interfaces and data flow
references/state-schema.md — full JSON schema with examples
references/phaser-cookbook.md — Phaser 3 patterns the codesmith MUST follow
Scripts
scripts/init_project.mjs <name> [--dir path] — scaffold from templates/phaser-game/
scripts/validate_state.mjs <project-dir> — schema check + invariant verification
scripts/run_pipeline.mjs <project-dir> — invoke the full pipeline (host agent drives all LLM sub-skills; no separate API key needed)