develop-web-game

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Develop Web Game

开发Web游戏

Build games in small steps and validate every change. Treat each iteration as: implement → act → pause → observe → adjust.
逐步构建游戏并验证每一处改动。将每次迭代视为:实现→操作→停顿→观察→调整。

Skill paths (set once)

技能路径(仅需设置一次)

bash
export CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
export WEB_GAME_CLIENT="$CODEX_HOME/skills/develop-web-game/scripts/web_game_playwright_client.js"
export WEB_GAME_ACTIONS="$CODEX_HOME/skills/develop-web-game/references/action_payloads.json"
User-scoped skills install under
$CODEX_HOME/skills
(default:
~/.codex/skills
).
bash
export CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
export WEB_GAME_CLIENT="$CODEX_HOME/skills/develop-web-game/scripts/web_game_playwright_client.js"
export WEB_GAME_ACTIONS="$CODEX_HOME/skills/develop-web-game/references/action_payloads.json"
用户级技能安装在
$CODEX_HOME/skills
目录下(默认路径:
~/.codex/skills
)。

Workflow

工作流程

  1. Pick a goal. Define a single feature or behavior to implement.
  2. Implement small. Make the smallest change that moves the game forward.
  3. Ensure integration points. Provide a single canvas and
    window.render_game_to_text
    so the test loop can read state.
  4. Add
    window.advanceTime(ms)
    .
    Strongly prefer a deterministic step hook so the Playwright script can advance frames reliably; without it, automated tests can be flaky.
  5. Initialize progress.md. If
    progress.md
    exists, read it first and confirm the original user prompt is recorded at the top (prefix with
    Original prompt:
    ). Also note any TODOs and suggestions left by the previous agent. If missing, create it and write
    Original prompt: <prompt>
    at the top before appending updates.
  6. Verify Playwright availability. Ensure
    playwright
    is available (local dependency or global install). If unsure, check
    npx
    first.
  7. Run the Playwright test script. You must run
    $WEB_GAME_CLIENT
    after each meaningful change; do not invent a new client unless required.
  8. Use the payload reference. Base actions on
    $WEB_GAME_ACTIONS
    to avoid guessing keys.
  9. Inspect state. Capture screenshots and text state after each burst.
  10. Inspect screenshots. Open the latest screenshot, verify expected visuals, fix any issues, and rerun the script. Repeat until correct.
  11. Verify controls and state (multi-step focus). Exhaustively exercise all important interactions. For each, think through the full multi-step sequence it implies (cause → intermediate states → outcome) and verify the entire chain works end-to-end. Confirm
    render_game_to_text
    reflects the same state shown on screen. If anything is off, fix and rerun. Examples of important interactions: move, jump, shoot/attack, interact/use, select/confirm/cancel in menus, pause/resume, restart, and any special abilities or puzzle actions defined by the request. Multi-step examples: shooting an enemy should reduce its health; when health reaches 0 it should disappear and update the score; collecting a key should unlock a door and allow level progression.
  12. Check errors. Review console errors and fix the first new issue before continuing.
  13. Reset between scenarios. Avoid cross-test state when validating distinct features.
  14. Iterate with small deltas. Change one variable at a time (frames, inputs, timing, positions), then repeat steps 7–13 until stable.
Example command (actions required):
node "$WEB_GAME_CLIENT" --url http://localhost:5173 --actions-file "$WEB_GAME_ACTIONS" --click-selector "#start-btn" --iterations 3 --pause-ms 250
Example actions (inline JSON):
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 }
  ]
}
  1. 确定目标。定义一个需要实现的单一功能或行为。
  2. 小步实现。做出最微小的改动来推进游戏开发。
  3. 确保集成点。提供单个画布和
    window.render_game_to_text
    方法,以便测试循环能够读取状态。
  4. 添加
    window.advanceTime(ms)
    。强烈建议使用确定性的步骤钩子,让Playwright脚本能够可靠地推进帧;如果没有这个钩子,自动化测试可能会不稳定。
  5. 初始化progress.md。如果
    progress.md
    已存在,先读取它,并确认顶部记录了原始用户提示(以
    Original prompt:
    为前缀)。同时注意之前Agent留下的待办事项和建议。如果文件不存在,创建它并在顶部写入
    Original prompt: <prompt>
    ,再追加更新内容。
  6. 验证Playwright可用性。确保
    playwright
    可用(本地依赖或全局安装)。不确定的话,先检查
    npx
  7. 运行Playwright测试脚本。每次完成有意义的改动后,必须运行
    $WEB_GAME_CLIENT
    ;除非必要,不要创建新的客户端。
  8. 使用负载参考。基于
    $WEB_GAME_ACTIONS
    来编写操作,避免猜测键名。
  9. 检查状态。在每次输入序列后捕获截图和文本状态。
  10. 检查截图。打开最新的截图,验证预期的视觉效果,修复任何问题,然后重新运行脚本。重复此过程直到正确。
  11. 验证控件与状态(多步骤聚焦)。全面测试所有重要交互。对于每个交互,思考它涉及的完整多步骤序列(原因→中间状态→结果),并验证整个链条端到端正常工作。确认
    render_game_to_text
    返回的状态与屏幕显示一致。如果有任何异常,修复后重新运行。 重要交互示例:移动、跳跃、射击/攻击、互动/使用、菜单中的选择/确认/取消、暂停/继续、重启,以及请求中定义的任何特殊能力或解谜操作。多步骤示例:射击敌人应减少其生命值;当生命值归零时,敌人应消失并更新分数;收集钥匙应解锁门并允许关卡推进。
  12. 检查错误。查看控制台错误,在继续之前修复第一个新出现的问题。
  13. 场景间重置状态。在验证不同功能时,避免测试间的状态交叉影响。
  14. 小增量迭代。每次只更改一个变量(帧、输入、时间、位置),然后重复步骤7-13直到稳定。
示例命令(需传入操作参数):
node "$WEB_GAME_CLIENT" --url http://localhost:5173 --actions-file "$WEB_GAME_ACTIONS" --click-selector "#start-btn" --iterations 3 --pause-ms 250
示例操作(内联JSON):
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 }
  ]
}

Test Checklist

测试检查清单

Test any new features added for the request and any areas your logic changes could affect. Identify issues, fix them, and re-run the tests to confirm they’re resolved.
Examples of things to test:
  • Primary movement/interaction inputs (e.g., move, jump, shoot, confirm/select).
  • Win/lose or success/fail transitions.
  • Score/health/resource changes.
  • Boundary conditions (collisions, walls, screen edges).
  • Menu/pause/start flow if present.
  • Any special actions tied to the request (powerups, combos, abilities, puzzles, timers).
测试请求中添加的所有新功能,以及你的逻辑改动可能影响的任何区域。识别问题、修复问题,然后重新运行测试以确认问题已解决。
测试内容示例:
  • 主要移动/交互输入(如移动、跳跃、射击、确认/选择)。
  • 胜利/失败或成功/失败的过渡。
  • 分数/生命值/资源变化。
  • 边界条件(碰撞、墙壁、屏幕边缘)。
  • 菜单/暂停/启动流程(如果存在)。
  • 与请求相关的任何特殊操作(道具、连招、技能、解谜、计时器)。

Test Artifacts to Review

需检查的测试产物

  • Latest screenshots from the Playwright run.
  • Latest
    render_game_to_text
    JSON output.
  • Console error logs (fix the first new error before continuing). You must actually open and visually inspect the latest screenshots after running the Playwright script, not just generate them. Ensure everything that should be visible on screen is actually visible. Go beyond the start screen and capture gameplay screenshots that cover all newly added features. Treat the screenshots as the source of truth; if something is missing, it is missing in the build. If you suspect a headless/WebGL capture issue, rerun the Playwright script in headed mode and re-check. Fix and rerun in a tight loop until the screenshots and text state look correct. Once fixes are verified, re-test all important interactions and controls, confirm they work, and ensure your changes did not introduce regressions. If they did, fix them and rerun everything in a loop until interactions, text state, and controls all work as expected. Be exhaustive in testing controls; broken games are not acceptable.
  • Playwright运行生成的最新截图。
  • 最新的
    render_game_to_text
    JSON输出。
  • 控制台错误日志(在继续之前修复第一个新错误)。 运行Playwright脚本后,你必须实际打开并可视化检查最新截图,而不仅仅是生成它们。确保所有应在屏幕上显示的内容都实际可见。不要只停留在启动屏幕,要捕获涵盖所有新增功能的游戏截图。将截图视为事实来源;如果某内容缺失,说明构建版本中存在问题。如果怀疑是无头模式/WebGL捕获问题,在有头模式下重新运行Playwright脚本并再次检查。在一个紧凑的循环中修复并重新运行,直到截图和文本状态看起来正确。验证修复后,重新测试所有重要交互和控件,确认它们正常工作,并确保你的改动没有引入回归问题。如果出现回归,修复后重新运行所有测试,直到交互、文本状态和控件都符合预期。要全面测试控件;游戏不能存在功能损坏的情况。

Core Game Guidelines

核心游戏开发准则

Canvas + Layout

画布与布局

  • Prefer a single canvas centered in the window.
  • 优先使用在窗口中居中的单个画布。

Visuals

视觉效果

  • Keep on-screen text minimal; show controls on a start/menu screen rather than overlaying them during play.
  • Avoid overly dark scenes unless the design calls for it. Make key elements easy to see.
  • Draw the background on the canvas itself instead of relying on CSS backgrounds.
  • 尽量减少屏幕上的文本;在启动/菜单屏幕上显示控件说明,而非在游戏过程中叠加显示。
  • 除非设计需要,否则避免过于昏暗的场景。确保关键元素易于查看。
  • 在画布本身绘制背景,而不是依赖CSS背景。

Text State Output (render_game_to_text)

文本状态输出(render_game_to_text)

Expose a
window.render_game_to_text
function that returns a concise JSON string representing the current game state. The text should include enough information to play the game without visuals.
Minimal pattern:
js
function renderGameToText() {
  const payload = {
    mode: state.mode,
    player: { x: state.player.x, y: state.player.y, r: state.player.r },
    entities: state.entities.map((e) => ({ x: e.x, y: e.y, r: e.r })),
    score: state.score,
  };
  return JSON.stringify(payload);
}
window.render_game_to_text = renderGameToText;
Keep the payload succinct and biased toward on-screen/interactive elements. Prefer current, visible entities over full history. Include a clear coordinate system note (origin and axis directions), and encode all player-relevant state: player position/velocity, active obstacles/enemies, collectibles, timers/cooldowns, score, and any mode/state flags needed to make correct decisions. Avoid large histories; only include what's currently relevant and visible.
暴露一个
window.render_game_to_text
函数,返回代表当前游戏状态的简洁JSON字符串。文本应包含足够信息,以便无需视觉即可了解游戏状态。
最简实现模式:
js
function renderGameToText() {
  const payload = {
    mode: state.mode,
    player: { x: state.player.x, y: state.player.y, r: state.player.r },
    entities: state.entities.map((e) => ({ x: e.x, y: e.y, r: e.r })),
    score: state.score,
  };
  return JSON.stringify(payload);
}
window.render_game_to_text = renderGameToText;
保持负载简洁,优先包含屏幕上的交互元素。优先使用当前可见的实体,而非完整历史。 包含清晰的坐标系说明(原点和轴方向),并编码所有与玩家相关的状态:玩家位置/速度、活跃障碍物/敌人、可收集物品、计时器/冷却时间、分数,以及做出正确决策所需的任何模式/状态标志。避免庞大的历史记录;只包含当前相关且可见的内容。

Time Stepping Hook

时间步进钩子

Provide a deterministic time-stepping hook so the Playwright client can advance the game in controlled increments. Expose
window.advanceTime(ms)
(or a thin wrapper that forwards to your game update loop) and have the game loop use it when present. The Playwright test script uses this hook to step frames deterministically during automated testing.
Minimal pattern:
js
window.advanceTime = (ms) => {
  const steps = Math.max(1, Math.round(ms / (1000 / 60)));
  for (let i = 0; i < steps; i++) update(1 / 60);
  render();
};
提供确定性的时间步进钩子,以便Playwright客户端能够以可控的增量推进游戏。暴露
window.advanceTime(ms)
(或一个转发到游戏更新循环的轻量包装器),并让游戏循环在该钩子存在时使用它。 Playwright测试脚本使用此钩子在自动化测试中确定性地推进帧。
最简实现模式:
js
window.advanceTime = (ms) => {
  const steps = Math.max(1, Math.round(ms / (1000 / 60)));
  for (let i = 0; i < steps; i++) update(1 / 60);
  render();
};

Fullscreen Toggle

全屏切换

  • Use a single key (prefer
    f
    ) to toggle fullscreen on/off.
  • Allow
    Esc
    to exit fullscreen.
  • When fullscreen toggles, resize the canvas/rendering so visuals and input mapping stay correct.
  • 使用单个按键(优先选择
    f
    键)来切换全屏模式。
  • 允许使用
    Esc
    键退出全屏。
  • 切换全屏时,调整画布/渲染尺寸,确保视觉效果和输入映射保持正确。

Progress Tracking

进度跟踪

Create a
progress.md
file if it doesn't exist, and append TODOs, notes, gotchas, and loose ends as you go so another agent can pick up seamlessly. If a
progress.md
file already exists, read it first, including the original user prompt at the top (you may be continuing another agent's work). Do not overwrite the original prompt; preserve it. Update
progress.md
after each meaningful chunk of work (feature added, bug found, test run, or decision made). At the end of your work, leave TODOs and suggestions for the next agent in
progress.md
.
如果
progress.md
不存在则创建它,并在开发过程中追加待办事项、笔记、注意事项和未完成的工作,以便其他Agent可以无缝接手。 如果
progress.md
已存在,先读取它,包括顶部的原始用户提示(你可能在继续其他Agent的工作)。不要覆盖原始提示;保留它。 在完成每一个有意义的工作块(添加功能、发现bug、运行测试或做出决策)后,更新
progress.md
。 在工作结束时,在
progress.md
中为下一个Agent留下待办事项和建议。

Playwright Prerequisites

Playwright前置条件

  • Prefer a local
    playwright
    dependency if the project already has it.
  • If unsure whether Playwright is available, check for
    npx
    :
    command -v npx >/dev/null 2>&1
  • If
    npx
    is missing, install Node/npm and then install Playwright globally:
    npm install -g @playwright/mcp@latest
  • Do not switch to
    @playwright/test
    unless explicitly asked; stick to the client script.
  • 如果项目已包含
    playwright
    依赖,优先使用本地依赖。
  • 如果不确定Playwright是否可用,检查
    npx
    是否存在:
    command -v npx >/dev/null 2>&1
  • 如果缺少
    npx
    ,安装Node/npm,然后全局安装Playwright:
    npm install -g @playwright/mcp@latest
  • 除非明确要求,不要切换到
    @playwright/test
    ;坚持使用客户端脚本。

Scripts

脚本

  • $WEB_GAME_CLIENT
    (installed default:
    $CODEX_HOME/skills/develop-web-game/scripts/web_game_playwright_client.js
    ) — Playwright-based action loop with virtual-time stepping, screenshot capture, and console error buffering. You must pass an action burst via
    --actions-file
    ,
    --actions-json
    , or
    --click
    .
  • $WEB_GAME_CLIENT
    (默认安装路径:
    $CODEX_HOME/skills/develop-web-game/scripts/web_game_playwright_client.js
    )——基于Playwright的操作循环,包含虚拟时间步进、截图捕获和控制台错误缓冲。你必须通过
    --actions-file
    --actions-json
    --click
    传入输入序列。

References

参考

  • $WEB_GAME_ACTIONS
    (installed default:
    $CODEX_HOME/skills/develop-web-game/references/action_payloads.json
    ) — example action payloads (keyboard + mouse, per-frame capture). Use these to build your burst.
  • $WEB_GAME_ACTIONS
    (默认安装路径:
    $CODEX_HOME/skills/develop-web-game/references/action_payloads.json
    )——示例操作负载(键盘+鼠标,逐帧捕获)。使用这些来编写你的输入序列。