概述 本技能用于指导 AI 智能体使用 crisp-game-lib 创建或修复浏览器迷你游戏。仅在用户明确要求使用 crisp-game-lib,或现有项目已采用该库时使用。
工作流程
- 选择方案前先检查现有项目,保留其固定的库版本、入口风格、辅助函数与测试脚手架。
- 对于新项目,需先阅读 project-setup-and-modes.md,再在 CDN/经典脚本与 npm/打包器两种设置中做选择,然后创建入口文件或选择版本。
- 编码前先声明每个命名动作及其物理绑定。对于单按钮游戏,需说明按下、长按或释放各自的作用,以及哪些阶段有意不使用。
- 实现一个清晰的帧顺序:输入 → 状态/物理 → 生成 → 绘制/碰撞 → 计分 → 游戏结束。
- 应用下述运行时约定,并只验证本次改动能够触达的行为。新游戏或涉及入口、输入、音频、循环的改动需要在真实浏览器中做运行时检查;局部修复则需要针对受影响的检查加启动冒烟测试。
- 第一个可工作循环之后,先记录任何有趣的涌现行为,再判断某个碰撞伪影、绘制顺序效果或物理交互是缺陷还是更好的机制。
- 在经典脚本项目中,使用 if (!ticks) { ... } 进行首帧初始化。在打包器项目中,遵循现有的 init({ update, title, description, characters, options }) 入口风格。
运行时约定
- 仅使用文档化的 API。测试 mock 可能暴露浏览器 bundle 中不存在的全局变量。查阅 api.md 获取确切的签名、颜色、声音、碰撞属性与选项;使用标准 JavaScript,或自行定义缺失的辅助函数。
- 绘制顺序即碰撞顺序。一个形状只能检测同一帧中更早绘制的形状。先绘制目标,再绘制检测器。
- 将 input.isJustPressed 视为统一输入,它合并了键盘按键与指针输入。使用 keyboard.code[...] 表示具名键盘动作,使用 pointer.isJustPressed 表示仅指针输入。统一输入适用于“任意输入即开始”的场景。
- 每个命名动作只定义一次绑定。每个阶段必须读取同一组同义输入。多个物理按键绑定到同一个命名动作并不会产生额外的游戏动作。
- 保持库自带与游戏自有的街机循环相互独立。正常循环使用 title、description、库的计分渲染以及 end()。自定义的吸引/仪式/名字输入循环则拥有上述全部内容。实现或修改自定义循环前,先阅读 project-setup-and-modes.md。
- 可听地验证音频。对于 crisp-game-lib 1.5.0+ 的内置音频,需在 bundle 之前加载两个 algo-chip 全局变量,并在首次输入后确认 algoChipSession != null。缺少全局变量会静默禁用 play() 与 BGM。
- 使用当前粒子语法:调用 particle(pos, { count, speed, angle, angleWidth }); 不要引入旧版的位置参数形式。
- 避免用白色绘制可见艺术图形,因为在各内置主题中它与背景颜色一致。请使用其他颜色或 light_* 变体。
最小碰撞模式
color("red"); enemies.forEach((enemy) => box(enemy.pos, 10));
color("blue"); if (box(player.pos, 8).isColliding.rect.red) { end(); }
条件性参考
- 当确切的库行为很重要时,阅读 api.md。其 API 枚举是权威来源,不要凭记忆重建。
- 仅当存在一个与所请求的控制或游戏模式匹配的完整循环能降低实现风险时,才阅读 examples.md。
- 在涉及 CDN/npm 骨架、版本固定、默认输入绑定、自定义街机所有权,或本仓库的模拟器/测试器约束时,阅读 project-setup-and-modes.md。
验证 在真实浏览器中检查适用项:
- 启动时没有控制台错误或未捕获异常;
- 控制在每个可达阶段只映射到其命名动作;
- 碰撞方向与绘制顺序符合预期规则;
- 计分与游戏结束行为符合所选的所有权模式;
- 当音频发生改动时,用户激活后能产生声音;
- 当游戏声明支持移动端时,指针/触摸输入可用。
对于本仓库的自动化测试套件,还需遵守 project-setup-and-modes.md 中的测试者约定。不要将该约定强加给不相关的用户项目。