@playcraft/cli 0.0.56 → 0.0.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/README.md +41 -26
  2. package/REMIX.md +17 -5
  3. package/dist/cli-root-help.js +1 -0
  4. package/dist/commands/build-all.js +10 -9
  5. package/dist/commands/build.js +13 -12
  6. package/dist/commands/create.js +26 -33
  7. package/dist/commands/platform-skills.generated.js +19 -0
  8. package/dist/commands/remix.js +48 -2
  9. package/dist/commands/skills.js +2 -0
  10. package/dist/commands/tools-generation.js +1 -1
  11. package/dist/commands/workspace-runtime.js +54 -0
  12. package/dist/index.js +3 -1
  13. package/dist/project-skills/commands.js +72 -0
  14. package/dist/project-skills/lifecycle.js +28 -0
  15. package/dist/project-skills/local-run.js +112 -0
  16. package/dist/project-skills/local-store.js +149 -0
  17. package/dist/project-skills/messages.js +72 -0
  18. package/dist/project-skills/reconcile.js +62 -0
  19. package/dist/project-skills/remote-cache.js +51 -0
  20. package/dist/project-skills/validation.js +19 -0
  21. package/dist/remix/clone.js +4 -1
  22. package/dist/remix/init-template.js +2 -0
  23. package/dist/remix/local-git.js +56 -0
  24. package/dist/remix/pull.js +66 -0
  25. package/dist/remix/push.js +90 -0
  26. package/dist/utils/agent-api-client.js +54 -17
  27. package/dist/utils/tool-operation-journal.js +54 -0
  28. package/dist/workspace-runtime/codex/app-server.js +395 -0
  29. package/dist/workspace-runtime/codex/config-toml.js +25 -0
  30. package/dist/workspace-runtime/codex/jsonrpc-stdio.js +106 -0
  31. package/dist/workspace-runtime/codex/loopback.js +59 -0
  32. package/dist/workspace-runtime/codex/native-adapter.js +3 -0
  33. package/dist/workspace-runtime/main.js +10 -0
  34. package/dist/workspace-runtime/persistence/journal.js +350 -0
  35. package/dist/workspace-runtime/processes/managed-writes.js +69 -0
  36. package/dist/workspace-runtime/serve.js +111 -0
  37. package/dist/workspace-runtime/server/auth.js +21 -0
  38. package/dist/workspace-runtime/server/dispatch.js +861 -0
  39. package/dist/workspace-runtime/server/execution-group.js +88 -0
  40. package/dist/workspace-runtime/server/http.js +561 -0
  41. package/dist/workspace-runtime/server/lock.js +53 -0
  42. package/dist/workspace-runtime/server/types.js +1 -0
  43. package/dist/workspace-runtime/workspaces/context-error.js +2 -0
  44. package/dist/workspace-runtime/workspaces/file-snapshot.js +213 -0
  45. package/dist/workspace-runtime/workspaces/files.js +143 -0
  46. package/dist/workspace-runtime/workspaces/git.js +242 -0
  47. package/dist/workspace-runtime/workspaces/json5-edit.js +170 -0
  48. package/dist/workspace-runtime/workspaces/parameters.js +272 -0
  49. package/dist/workspace-runtime/workspaces/prepare.js +364 -0
  50. package/dist/workspace-runtime/workspaces/registry.js +107 -0
  51. package/dist/workspace-runtime/workspaces/revisions.js +31 -0
  52. package/package.json +6 -3
  53. package/project-template-v2/.claude/agents/artist.md +82 -0
  54. package/project-template-v2/.claude/agents/developer.md +153 -0
  55. package/project-template-v2/.claude/agents/game-designer.md +264 -0
  56. package/project-template-v2/.claude/agents/refs/artist-art-style-catalog.md +533 -0
  57. package/project-template-v2/.claude/agents/refs/artist-color-audio-recipes.md +153 -0
  58. package/project-template-v2/.claude/agents/refs/artist-dimension-axis.md +27 -0
  59. package/project-template-v2/.claude/agents/refs/artist-master-composite-recipes.md +208 -0
  60. package/project-template-v2/.claude/agents/refs/atom-skill-library.md +81 -0
  61. package/project-template-v2/.claude/agents/refs/developer-impl-cookbook.md +432 -0
  62. package/project-template-v2/.claude/agents/refs/framework-5-component-filter.md +252 -0
  63. package/project-template-v2/.claude/agents/refs/framework-game-feel-juice.md +266 -0
  64. package/project-template-v2/.claude/agents/refs/framework-mda.md +147 -0
  65. package/project-template-v2/.claude/agents/refs/game-designer-gameplay-sufficiency.md +123 -0
  66. package/project-template-v2/.claude/agents/refs/ta-3d-flip-recipe.md +88 -0
  67. package/project-template-v2/.claude/agents/refs/ta-atlas-deliverable-standard.md +67 -0
  68. package/project-template-v2/.claude/agents/refs/ta-batch-pipeline-recipes.md +120 -0
  69. package/project-template-v2/.claude/agents/refs/ta-image-generation-detail.md +300 -0
  70. package/project-template-v2/.claude/agents/refs/ta-image-ops-reference.md +495 -0
  71. package/project-template-v2/.claude/agents/refs/ta-pipeline-cookbook.md +1141 -0
  72. package/project-template-v2/.claude/agents/refs/ta-tools-reference.md +111 -0
  73. package/project-template-v2/.claude/agents/refs/ta-vfx-preset-catalog.md +365 -0
  74. package/project-template-v2/.claude/agents/refs/threejs-cannon-pitfalls.md +412 -0
  75. package/project-template-v2/.claude/agents/reviewer.md +75 -0
  76. package/project-template-v2/.claude/agents/technical-artist.md +86 -0
  77. package/project-template-v2/.claude/hooks/snapshot-milestone.mjs +243 -0
  78. package/project-template-v2/.claude/hooks/user-prompt.mjs +133 -0
  79. package/project-template-v2/.claude/settings.json +33 -0
  80. package/project-template-v2/.claude/skills/brainstorming/SKILL.md +161 -0
  81. package/project-template-v2/.claude/skills/brainstorming/scripts/frame-template.html +270 -0
  82. package/project-template-v2/.claude/skills/brainstorming/scripts/helper.js +177 -0
  83. package/project-template-v2/.claude/skills/brainstorming/scripts/server.cjs +354 -0
  84. package/project-template-v2/.claude/skills/brainstorming/scripts/start-server.sh +148 -0
  85. package/project-template-v2/.claude/skills/brainstorming/scripts/stop-server.sh +56 -0
  86. package/project-template-v2/.claude/skills/brainstorming/scripts/wait-for-selection.sh +62 -0
  87. package/project-template-v2/.claude/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
  88. package/project-template-v2/.claude/skills/brainstorming/visual-companion.md +309 -0
  89. package/project-template-v2/.claude/skills/playcraft-ad-psychology/SKILL.md +182 -0
  90. package/project-template-v2/.claude/skills/playcraft-art-style-guide/SKILL.md +123 -0
  91. package/project-template-v2/.claude/skills/playcraft-asset-state-sheet/SKILL.md +205 -0
  92. package/project-template-v2/.claude/skills/playcraft-audio-generation/SKILL.md +280 -0
  93. package/project-template-v2/.claude/skills/playcraft-batch-pipeline/SKILL.md +184 -0
  94. package/project-template-v2/.claude/skills/playcraft-build-optimizer/SKILL.md +306 -0
  95. package/project-template-v2/.claude/skills/playcraft-image-generation/SKILL.md +298 -0
  96. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +123 -0
  97. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +254 -0
  98. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +324 -0
  99. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +97 -0
  100. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +118 -0
  101. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +137 -0
  102. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +397 -0
  103. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +296 -0
  104. package/project-template-v2/.claude/skills/playcraft-image-ops/SKILL.md +122 -0
  105. package/project-template-v2/.claude/skills/playcraft-image-processing/SKILL.md +219 -0
  106. package/project-template-v2/.claude/skills/playcraft-masking/SKILL.md +373 -0
  107. package/project-template-v2/.claude/skills/playcraft-playable-optimization/SKILL.md +161 -0
  108. package/project-template-v2/.claude/skills/playcraft-research/SKILL.md +215 -0
  109. package/project-template-v2/.claude/skills/playcraft-skill-recommender/SKILL.md +382 -0
  110. package/project-template-v2/.claude/skills/playcraft-sprite-generation/SKILL.md +423 -0
  111. package/project-template-v2/.claude/skills/playcraft-sprite-remix/SKILL.md +158 -0
  112. package/project-template-v2/.claude/skills/playcraft-sprite-sheet/SKILL.md +100 -0
  113. package/project-template-v2/.claude/skills/playcraft-storyboard/SKILL.md +167 -0
  114. package/project-template-v2/.claude/skills/playcraft-style-qa/SKILL.md +270 -0
  115. package/project-template-v2/.claude/skills/playcraft-text-rendering/SKILL.md +236 -0
  116. package/project-template-v2/.claude/skills/playcraft-vfx-animation/SKILL.md +130 -0
  117. package/project-template-v2/.claude/skills/playwright-cli/SKILL.md +390 -0
  118. package/project-template-v2/.claude/skills/playwright-cli/references/element-attributes.md +23 -0
  119. package/project-template-v2/.claude/skills/playwright-cli/references/playwright-tests.md +39 -0
  120. package/project-template-v2/.claude/skills/playwright-cli/references/request-mocking.md +87 -0
  121. package/project-template-v2/.claude/skills/playwright-cli/references/running-code.md +240 -0
  122. package/project-template-v2/.claude/skills/playwright-cli/references/session-management.md +226 -0
  123. package/project-template-v2/.claude/skills/playwright-cli/references/spec-driven-testing.md +308 -0
  124. package/project-template-v2/.claude/skills/playwright-cli/references/storage-state.md +275 -0
  125. package/project-template-v2/.claude/skills/playwright-cli/references/test-generation.md +134 -0
  126. package/project-template-v2/.claude/skills/playwright-cli/references/tracing.md +142 -0
  127. package/project-template-v2/.claude/skills/playwright-cli/references/video-recording.md +153 -0
  128. package/project-template-v2/.claude/skills/session-analyzer/SKILL.md +386 -0
  129. package/project-template-v2/.claude/skills/session-analyzer/scripts/execution-breakdown.mjs +182 -0
  130. package/project-template-v2/.claude/skills/session-analyzer/scripts/find-turns.mjs +72 -0
  131. package/project-template-v2/.claude/skills/session-analyzer/scripts/heavy-output.mjs +121 -0
  132. package/project-template-v2/.claude/skills/session-analyzer/scripts/resolve-session.mjs +102 -0
  133. package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-stats.mjs +127 -0
  134. package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-tool-timeline.mjs +106 -0
  135. package/project-template-v2/.claude/skills/session-analyzer/scripts/time-gaps.mjs +128 -0
  136. package/project-template-v2/.claude/skills/session-analyzer/scripts/turn-timeline.mjs +67 -0
  137. package/project-template-v2/.claude/snapshot.mjs +263 -0
  138. package/project-template-v2/.playcraft/skills.lock.json +152 -0
  139. package/project-template-v2/CLAUDE.md +146 -0
  140. package/project-template-v2/assets/audio/bgm/.gitkeep +0 -0
  141. package/project-template-v2/assets/audio/sfx/.gitkeep +0 -0
  142. package/project-template-v2/assets/bundles/.gitkeep +0 -0
  143. package/project-template-v2/assets/images/bg/.gitkeep +0 -0
  144. package/project-template-v2/assets/images/reference/.gitkeep +0 -0
  145. package/project-template-v2/assets/images/storyboard/.gitkeep +0 -0
  146. package/project-template-v2/assets/images/tiles/.gitkeep +0 -0
  147. package/project-template-v2/assets/images/ui/.gitkeep +0 -0
  148. package/project-template-v2/assets/images/vfx/.gitkeep +0 -0
  149. package/project-template-v2/assets/models/.gitkeep +0 -0
  150. package/project-template-v2/docs/harness/iteration-1/context-flow.md +254 -0
  151. package/project-template-v2/docs/harness/iteration-1/generate-flow.md +91 -0
  152. package/project-template-v2/docs/harness/iteration-1/ideate-flow.md +214 -0
  153. package/project-template-v2/docs/harness/iteration-1/optimize-flow.md +75 -0
  154. package/project-template-v2/docs/harness/iteration-1/wrapup-flow.md +63 -0
  155. package/project-template-v2/docs/harness/iteration-2/context-flow.md +223 -0
  156. package/project-template-v2/docs/harness/iteration-2/generate-flow.md +129 -0
  157. package/project-template-v2/docs/harness/iteration-2/ideate-flow.md +267 -0
  158. package/project-template-v2/docs/harness/iteration-2/optimize-flow.md +164 -0
  159. package/project-template-v2/docs/harness/iteration-2/wrapup-flow.md +115 -0
  160. package/project-template-v2/docs/harness/orchestrator-flow.md +364 -0
  161. package/project-template-v2/docs/project-state.json +60 -0
  162. package/project-template-v2/docs/project-state.md +72 -0
  163. package/project-template-v2/docs/standards/README.md +225 -0
  164. package/project-template-v2/docs/standards/agent-behavior-standards.md +174 -0
  165. package/project-template-v2/docs/standards/artifacts/design-brief.md +19 -0
  166. package/project-template-v2/docs/standards/artifacts/design.md +22 -0
  167. package/project-template-v2/docs/standards/artifacts/game-code.md +41 -0
  168. package/project-template-v2/docs/standards/artifacts/todo-list.md +41 -0
  169. package/project-template-v2/docs/standards/iter1-agent-behavior-standards.md +343 -0
  170. package/project-template-v2/game/index.ts +18 -0
  171. package/project-template-v2/globals.d.ts +51 -0
  172. package/project-template-v2/index.css +34 -0
  173. package/project-template-v2/index.html +18 -0
  174. package/project-template-v2/main.ts +9 -0
  175. package/project-template-v2/package.json +46 -0
  176. package/project-template-v2/skills/_shared/scripts/dispatch-clear.mjs +31 -0
  177. package/project-template-v2/skills/_shared/scripts/dispatch-set.mjs +86 -0
  178. package/project-template-v2/skills/_shared/scripts/dod-check.mjs +153 -0
  179. package/project-template-v2/skills/_shared/scripts/handoff-append.mjs +70 -0
  180. package/project-template-v2/skills/_shared/scripts/lib/validator-artifacts.mjs +91 -0
  181. package/project-template-v2/skills/_shared/scripts/pipeline/dod-config.mjs +131 -0
  182. package/project-template-v2/skills/_shared/scripts/pipeline/index.mjs +80 -0
  183. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-1-core.mjs +90 -0
  184. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-2-wrap.mjs +93 -0
  185. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-3-visual.mjs +23 -0
  186. package/project-template-v2/skills/_shared/scripts/render-project-state.mjs +230 -0
  187. package/project-template-v2/skills/_shared/scripts/state-advance-stage.mjs +58 -0
  188. package/project-template-v2/skills/_shared/scripts/state-get.mjs +339 -0
  189. package/project-template-v2/skills/_shared/scripts/state-handoff.mjs +39 -0
  190. package/project-template-v2/skills/_shared/scripts/state-set.mjs +94 -0
  191. package/project-template-v2/skills/_shared/scripts/state-store.mjs +783 -0
  192. package/project-template-v2/skills/_shared/scripts/todo-add.mjs +88 -0
  193. package/project-template-v2/skills/_shared/scripts/todo-get.mjs +130 -0
  194. package/project-template-v2/skills/_shared/scripts/todo-remove.mjs +33 -0
  195. package/project-template-v2/skills/_shared/scripts/todo-set.mjs +47 -0
  196. package/project-template-v2/skills/_shared/scripts/verify-asset-code-sync.mjs +268 -0
  197. package/project-template-v2/skills/_shared/scripts/verify-env.mjs +285 -0
  198. package/project-template-v2/skills/_shared/scripts/verify-placeholders.mjs +161 -0
  199. package/project-template-v2/skills/playable-autoplay/SKILL.md +176 -0
  200. package/project-template-v2/skills/playable-autoplay/agents/openai.yaml +4 -0
  201. package/project-template-v2/skills/playable-debug/SKILL.md +116 -0
  202. package/project-template-v2/skills/playable-debug/agents/openai.yaml +4 -0
  203. package/project-template-v2/skills/playable-debug/references/debug-config.md +40 -0
  204. package/project-template-v2/skills/playable-record/SKILL.md +140 -0
  205. package/project-template-v2/skills/playable-record/scripts/lib/dev-server.mjs +104 -0
  206. package/project-template-v2/skills/playable-record/scripts/lib/record-audio-bridge.js +141 -0
  207. package/project-template-v2/skills/playable-record/scripts/record-playable.mjs +425 -0
  208. package/project-template-v2/skills/playable-record/scripts/verify-contract.mjs +261 -0
  209. package/project-template-v2/skills/playable-record/scripts/verify-firstwin.mjs +398 -0
  210. package/project-template-v2/skills/playable-record/scripts/verify-fusion.mjs +322 -0
  211. package/project-template-v2/skills/playable-record/scripts/verify-lifecycle.mjs +105 -0
  212. package/project-template-v2/skills/playable-record/scripts/verify-vlm-video.mjs +230 -0
  213. package/project-template-v2/skills/playable-validate/SKILL.md +61 -0
  214. package/project-template-v2/skills/playable-validate/validation-rules.md +14 -0
  215. package/project-template-v2/skills/playable-verify-ui/SKILL.md +63 -0
  216. package/project-template-v2/skills/playable-verify-ui/scripts/lib/__init__.py +1 -0
  217. package/project-template-v2/skills/playable-verify-ui/scripts/lib/config_expr.js +218 -0
  218. package/project-template-v2/skills/playable-verify-ui/scripts/lib/node_utils.js +51 -0
  219. package/project-template-v2/skills/playable-verify-ui/scripts/lib/profile_loader.py +59 -0
  220. package/project-template-v2/skills/playable-verify-ui/scripts/lib/report.py +106 -0
  221. package/project-template-v2/skills/playable-verify-ui/scripts/lib/runtime_contract.js +116 -0
  222. package/project-template-v2/skills/playable-verify-ui/scripts/verify_fetch_antipatterns.py +59 -0
  223. package/project-template-v2/skills/playable-verify-ui/scripts/verify_hardcoded_layout.js +64 -0
  224. package/project-template-v2/skills/playable-verify-ui/scripts/verify_runtime_contract.js +58 -0
  225. package/project-template-v2/skills/playable-verify-ui/scripts/verify_text_overlap.py +333 -0
  226. package/project-template-v2/ta-workspace/scripts/.gitkeep +0 -0
  227. package/project-template-v2/tsconfig.json +20 -0
  228. package/project-template-v2/vite.config.ts +27 -0
@@ -0,0 +1,412 @@
1
+ # Three.js + Cannon-es 游戏开发踩坑指南
2
+
3
+ > **定位**:本文档记录在用 Three.js r160 + Cannon-es 0.20 复刻 Wood Screw Puzzle 过程中遇到的真实问题、根因和修复方案。
4
+ > 适用于所有使用 Three.js + Cannon-es 制作俯视 2D 物理玩法的 Playable Ad 项目。
5
+
6
+ ---
7
+
8
+ ## 一、Cannon-es 物理引擎
9
+
10
+ ### 坑1:Body 类型常量值与直觉相反
11
+
12
+ **现象**:板激活后视觉不动,物理完全哑火。
13
+
14
+ **根因**:Cannon-es 里 `DYNAMIC=1`,`STATIC=2`——与常识相反。代码里硬编码 `type === 2` 来检测 DYNAMIC body,实际检测的是 STATIC body。
15
+
16
+ ```typescript
17
+ // ❌ 错误:魔法数字
18
+ if (plate.body.type === 2) {
19
+ plate.syncMesh();
20
+ }
21
+
22
+ // ✅ 正确:永远用常量
23
+ if (plate.body.type === CANNON.Body.DYNAMIC) {
24
+ plate.syncMesh();
25
+ }
26
+
27
+ // 实际值备忘:DYNAMIC=1, STATIC=2, KINEMATIC=4
28
+ ```
29
+
30
+ ---
31
+
32
+ ### 坑2:STATIC body 完全忽略约束力
33
+
34
+ **现象**:给 plate body 加了 LockConstraint,但板纹丝不动,约束像没有一样。
35
+
36
+ **根因**:Cannon-es 的 STATIC body 不参与约束求解,所有施加在它上面的约束力都被忽略。
37
+
38
+ **修复**:受约束的物体必须是 DYNAMIC,用高 damping 维持稳定:
39
+
40
+ ```typescript
41
+ // ❌ 错误:STATIC body + 约束 = 约束无效
42
+ const body = new CANNON.Body({ mass: 0, type: CANNON.Body.STATIC });
43
+ world.addConstraint(new CANNON.LockConstraint(body, anchor));
44
+
45
+ // ✅ 正确:受约束的物体用 DYNAMIC,高 damping 防抖
46
+ const body = new CANNON.Body({
47
+ mass: 0.1,
48
+ type: CANNON.Body.DYNAMIC,
49
+ linearDamping: 0.8,
50
+ angularDamping: 0.8,
51
+ });
52
+ ```
53
+
54
+ ---
55
+
56
+ ### 坑3:LockConstraint 锁死旋转,不适合铰接场景
57
+
58
+ **现象**:解除板的一个约束后,板不绕另一个约束旋转,像被焊死。
59
+
60
+ **根因**:`LockConstraint` 锁定全6自由度(位置+旋转)。即使只剩一个约束,板也无法旋转。
61
+
62
+ **规则**:
63
+
64
+ - `LockConstraint` → 完全固定(焊接)
65
+ - `PointToPointConstraint` → 只锁位置,旋转自由(铰接、螺丝穿板)
66
+
67
+ ```typescript
68
+ // 铰接场景用 PointToPointConstraint
69
+ // pivotA = 接触点在 bodyA 本地坐标系的位置
70
+ const r = (plateRotation * Math.PI) / 180;
71
+ const pivotA = new CANNON.Vec3(
72
+ Math.cos(r) * lx - Math.sin(r) * ly, // 旋转后的 local offset
73
+ Math.sin(r) * lx + Math.cos(r) * ly,
74
+ 0,
75
+ );
76
+ // anchorBody 放在接触点世界坐标,pivotB = (0,0,0)
77
+ const constraint = new CANNON.PointToPointConstraint(
78
+ plate.body,
79
+ pivotA,
80
+ anchorBody,
81
+ new CANNON.Vec3(0, 0, 0),
82
+ );
83
+ ```
84
+
85
+ ---
86
+
87
+ ### 坑4:3D 物理引擎模拟俯视 2D 游戏必须锁 X/Y 轴旋转
88
+
89
+ **现象**:板在物理模拟中绕 X/Y 轴翻转,从俯视相机看变成一条线。
90
+
91
+ **根因**:Cannon-es 是 3D 物理,body 默认可绕任意轴旋转。Unity Rigidbody2D 天然只允许 Z 轴旋转,移植时需手动复现。
92
+
93
+ ```typescript
94
+ // 初始化时锁定 X/Y 轴角速度
95
+ body.angularFactor.set(0, 0, 1) // 只允许 Z 轴旋转
96
+
97
+ // syncMesh 时只取 Z 分量,彻底隔离渲染层
98
+ syncMesh(): void {
99
+ this.group.position.copy(this.body.position as unknown as THREE.Vector3)
100
+ const q = this.body.quaternion as unknown as THREE.Quaternion
101
+ const euler = new THREE.Euler().setFromQuaternion(q, 'ZYX')
102
+ euler.x = 0
103
+ euler.y = 0
104
+ this.group.quaternion.setFromEuler(euler)
105
+ // 同时清除物理层的 X/Y 角速度,防止累积
106
+ this.body.angularVelocity.x = 0
107
+ this.body.angularVelocity.y = 0
108
+ }
109
+ ```
110
+
111
+ ---
112
+
113
+ ### 坑5:allowSleep 会让 body 静默忽略新施加的力
114
+
115
+ **现象**:约束释放、velocity 设置后,板仍然不动。
116
+
117
+ **根因**:`world.allowSleep = true` 时,body 进入睡眠后不会因为 velocity 赋值自动醒来,需要显式 `wakeUp()`。
118
+
119
+ ```typescript
120
+ // ✅ 正确顺序:先设 velocity,再 wakeUp
121
+ body.allowSleep = false; // 对不应睡眠的 body 彻底禁用
122
+ body.velocity.set(vx, -0.5, 0);
123
+ body.angularVelocity.set(0, 0, sign * 4.0);
124
+ body.wakeUp(); // 最后调用
125
+ ```
126
+
127
+ ---
128
+
129
+ ### 坑6:静态 Floor(Plane)会真实拦截物体
130
+
131
+ **现象**:板掉到 y=-8 就永久停住,永远不到 y=-10 的 dispose 阈值。
132
+
133
+ **根因**:`CANNON.Plane` 是无限大的面,会真实产生碰撞。原意是"兜底接住再 dispose",实际变成了永久拦截。
134
+
135
+ ```typescript
136
+ // ❌ 不要放 Floor,让板自由落下
137
+ // world.addBody(floorBody) // 删掉这行
138
+
139
+ // ✅ 在 GameLoop 里检测 y 阈值直接 dispose
140
+ if (plate.body.position.y < -10) {
141
+ plate.dispose(scene);
142
+ }
143
+ ```
144
+
145
+ ---
146
+
147
+ ### 坑7:同柱多板的 Z 间距必须大于碰撞体厚度之和
148
+
149
+ **现象**:一根螺丝穿过两块板时,板互相碰撞、抖动乱飞。
150
+
151
+ **根因**:`layerZ` 步长(0.02)< Box 碰撞体厚度×2(0.08×2=0.16),相邻板的碰撞盒重叠。
152
+
153
+ ```typescript
154
+ // ❌ 错误:步长 0.02 < 碰撞体厚度 0.16
155
+ layerZ = score * 0.02;
156
+ body.addShape(new CANNON.Box(new CANNON.Vec3(w / 2, h / 2, 0.08)));
157
+
158
+ // ✅ 正确:步长 > 碰撞体厚度×2,通常缩小碰撞体厚度更简洁
159
+ layerZ = score * 0.15; // 间距足够
160
+ body.addShape(new CANNON.Box(new CANNON.Vec3(w / 2, h / 2, 0.01))); // 薄碰撞体
161
+ // 0.15 >> 0.01×2=0.02,不再重叠
162
+ ```
163
+
164
+ ---
165
+
166
+ ## 二、Three.js 场景节点层级
167
+
168
+ ### 坑8:固定在世界坐标的元素不能是会动的 Group 的子节点
169
+
170
+ **现象**:screw group 播放移动动画时,孔洞图标(holeMesh)跟着飞走,原位置变空白。
171
+
172
+ **根因**:holeMesh 是 group 的子节点,group 移动时子节点一起移动。
173
+
174
+ **规则**:
175
+
176
+ - 跟随动画的元素 → `group.add()`
177
+ - 固定在世界坐标的元素 → `scene.add()` + 手动设置世界坐标
178
+
179
+ ```typescript
180
+ // ❌ 错误:holeMesh 跟着 group 飞走
181
+ this.group.add(this.holeMesh);
182
+
183
+ // ✅ 正确:直接加到 scene,固定在 post 原始世界位置
184
+ this.holeMesh.position.set(this.wx, this.wy, 0.02);
185
+ scene.add(this.holeMesh); // 永远不动
186
+ ```
187
+
188
+ 同样适用于 hitMesh(点击检测区域)。
189
+
190
+ ---
191
+
192
+ ### 坑9:Raycaster 点击目标太小导致命中率低
193
+
194
+ **现象**:明确点击了螺丝位置,但游戏无响应。
195
+
196
+ **根因**:功能 Mesh(stubMesh)只有 0.5×0.5 世界单位(约 26px),很难精确点中。
197
+
198
+ ```typescript
199
+ // ❌ 用功能 Mesh 做点击目标,太小
200
+ const hits = raycaster.intersectObjects([this.stubMesh]);
201
+
202
+ // ✅ 专门建一个不可见的大 Mesh 做点击区
203
+ const hitGeo = new THREE.PlaneGeometry(1.4, 1.4); // 约 3 倍大
204
+ const hitMat = new THREE.MeshBasicMaterial({ visible: false, side: THREE.DoubleSide });
205
+ this.hitMesh = new THREE.Mesh(hitGeo, hitMat);
206
+ this.hitMesh.position.set(this.wx, this.wy, 0);
207
+ scene.add(this.hitMesh); // 固定世界坐标
208
+
209
+ const hits = raycaster.intersectObjects(screws.map((s) => s.hitMesh));
210
+ ```
211
+
212
+ ---
213
+
214
+ ### 坑10:正交俯视相机下 CylinderGeometry 显示为黑色矩形轮廓
215
+
216
+ **现象**:螺丝柱显示为黑色矩形,而不是圆形木柱。
217
+
218
+ **根因**:正交俯视相机看 CylinderGeometry 时,看到的是侧面轮廓(一个矩形),不是顶部圆形。
219
+
220
+ **规则:正交俯视场景里所有对象用 PlaneGeometry + 顶视图贴图,不用任何 3D 几何体。**
221
+
222
+ ```typescript
223
+ // ❌ 错误:俯视看到侧面矩形轮廓
224
+ new THREE.CylinderGeometry(0.25, 0.25, 0.5);
225
+
226
+ // ✅ 正确:PlaneGeometry + 顶视图 PNG
227
+ const geo = new THREE.PlaneGeometry(0.5, 0.5);
228
+ const mat = new THREE.MeshBasicMaterial({
229
+ map: screwTopViewTexture,
230
+ transparent: true,
231
+ });
232
+ ```
233
+
234
+ ---
235
+
236
+ ### 坑11:板上的孔用 ShaderMaterial discard,不要叠加 Hole 贴图
237
+
238
+ **现象**:叠加 Hole.png 时,板旋转后孔位偏移;深度排序导致孔图片有时被遮挡。
239
+
240
+ **根因**:叠加贴图方式需要把孔的 local 坐标转换到世界坐标再回到屏幕坐标,旋转的板计算容易出错;而且是"遮挡"不是"透明"。
241
+
242
+ **修复**:在 ShaderMaterial 的片段着色器里用 `discard` 直接挖洞,孔坐标在模型空间计算,永远准确:
243
+
244
+ ```glsl
245
+ // 顶点着色器:传递模型空间 XY
246
+ varying vec2 vLocalPos;
247
+ void main() {
248
+ vLocalPos = position.xy; // 与孔坐标系(hs[i].x/y)一致
249
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
250
+ }
251
+
252
+ // 片段着色器:在模型空间打孔
253
+ uniform vec2 uHoles[4];
254
+ uniform int uHoleCount;
255
+ uniform float uHoleRadius; // 0.28 世界单位
256
+ void main() {
257
+ for (int i = 0; i < 4; i++) {
258
+ if (i >= uHoleCount) break;
259
+ vec2 d = vLocalPos - uHoles[i];
260
+ if (dot(d, d) < uHoleRadius * uHoleRadius) discard;
261
+ }
262
+ gl_FragColor = texture2D(uTexture, vUv) * vec4(uColor, 1.0);
263
+ }
264
+ ```
265
+
266
+ 孔坐标直接传 `hs[i].x, hs[i].y`(板本地坐标),无需任何旋转变换。
267
+
268
+ ---
269
+
270
+ ## 三、Tween 动画
271
+
272
+ ### 坑12:async 动画函数异常时状态永久锁死
273
+
274
+ **现象**:某次操作后游戏完全无响应,所有点击都没有反应。
275
+
276
+ **根因**:`animating = true` 设置后,async 函数中抛出异常,`animating = false` 永远执行不到。
277
+
278
+ ```typescript
279
+ // ❌ 危险:异常时 animating 永久为 true
280
+ canvas.addEventListener('pointerdown', () => {
281
+ this.handleClick(index) // 没有错误处理
282
+ })
283
+
284
+ // ✅ 正确:两层保障
285
+ // 1. 调用处 .catch() 兜底
286
+ canvas.addEventListener('pointerdown', () => {
287
+ this.handleClick(index).catch(err => {
288
+ console.error(err)
289
+ this.animating = false
290
+ this.state = 'IDLE'
291
+ })
292
+ })
293
+
294
+ // 2. 被调用的关键函数用 try/finally
295
+ async moveScrew(...): Promise<void> {
296
+ this.inputLocked = true
297
+ try {
298
+ await this._doMove(...)
299
+ } catch (err) {
300
+ console.error(err)
301
+ } finally {
302
+ this.inputLocked = false // 无论成功失败都释放
303
+ }
304
+ }
305
+ ```
306
+
307
+ ---
308
+
309
+ ### 坑13:tween.js v21 的 .onComplete 回调参数类型不是 `() => void`
310
+
311
+ ```typescript
312
+ // ❌ TypeScript 报错:类型不匹配
313
+ new TWEEN.Tween(obj).to(target, 430).onComplete(resolve);
314
+
315
+ // ✅ 正确:包一层箭头函数
316
+ new TWEEN.Tween(obj).to(target, 430).onComplete(() => resolve());
317
+ ```
318
+
319
+ ---
320
+
321
+ ### 坑14:串行动画中同一动作不能重复播放
322
+
323
+ **现象**:螺丝头永久漂浮在空中,playInTween 之后没有归位。
324
+
325
+ **根因**:ClickHandler 播了一次 `playOutTween`(screwHead +0.8),`playMoveTween` 内部又播了一次(再 +0.8),`playInTween` 只降 0.8,净效果是永久上浮 0.8。
326
+
327
+ ```typescript
328
+ // ❌ 错误:playMoveTween 内部重复调用
329
+ async playMoveTween(toX, toY) {
330
+ await this.playOutTween() // ClickHandler 已经调过!
331
+ await this.arcAnimation(toX, toY)
332
+ await this.playInTween()
333
+ }
334
+
335
+ // ✅ 正确:每个动画函数只做一件事,调用方控制顺序
336
+ // ClickHandler: await screw.playOutTween()
337
+ // MoveManager: await screw.playMoveTween(toX, toY) // 只有弧线 + In
338
+ async playMoveTween(toX, toY) {
339
+ await this.arcAnimation(toX, toY) // 不再包含 Out
340
+ await this.playInTween()
341
+ }
342
+ ```
343
+
344
+ ---
345
+
346
+ ## 四、游戏逻辑通用
347
+
348
+ ### 坑15:setInterval 启动前必须先停止旧的
349
+
350
+ **现象**:关卡切换后倒计时以数倍速度归零。
351
+
352
+ **根因**:每次 `startCountdown` 都开了新的 setInterval,多个计时器并行叠加。
353
+
354
+ ```typescript
355
+ startCountdown(seconds: number): void {
356
+ this.stopCountdown() // 先清除旧的,再开新的
357
+ this.remaining = seconds
358
+ this.timer = window.setInterval(() => { ... }, 1000)
359
+ }
360
+ ```
361
+
362
+ ---
363
+
364
+ ### 坑16:Unity local 坐标 → 世界坐标必须做旋转变换
365
+
366
+ **现象**:第二关(板旋转 315°)的孔与螺丝位置完全无法匹配,约束建立失败。
367
+
368
+ **根因**:孔的 offset `(hs.x, hs.y)` 是板本地坐标系的坐标,当板有旋转时不能直接加到板中心。
369
+
370
+ ```typescript
371
+ // ❌ 错误:忽略板旋转
372
+ const holeWX = plate.x + hs.x;
373
+ const holeWY = plate.y + hs.y;
374
+
375
+ // ✅ 正确:先旋转 local offset,再平移到世界坐标
376
+ const r = (plateRotation * Math.PI) / 180;
377
+ const holeWX = plate.x + Math.cos(r) * hs.x - Math.sin(r) * hs.y;
378
+ const holeWY = plate.y + Math.sin(r) * hs.x + Math.cos(r) * hs.y;
379
+ ```
380
+
381
+ 适用于所有 Unity/Cocos "本地坐标系 offset → 世界坐标" 的转换。
382
+
383
+ ---
384
+
385
+ ### 坑17:Vite 中旧 .js 文件会遮蔽新 .ts 文件
386
+
387
+ **现象**:修改了 .ts 文件但游戏行为没有变化,像是没有生效。
388
+
389
+ **根因**:Vite 解析模块时 `.js` 优先级高于 `.ts`,`src/` 下残留的旧 `.js` 文件被优先加载。
390
+
391
+ ```bash
392
+ # 修复:删除 src/ 下所有 .js 文件
393
+ find src/ -name "*.js" -delete
394
+ ```
395
+
396
+ 开发时只保留 `.ts`,不要在 src 目录混放 `.js`。
397
+
398
+ ---
399
+
400
+ ## 五、从 C#/Unity 模块移植时的检查清单
401
+
402
+ 移植前必须从参考模块中提取以下信息,避免重新踩坑:
403
+
404
+ | 检查项 | 从哪里读 | 不检查的后果 |
405
+ | ------------------------------------------ | ------------------------------ | ------------------------ |
406
+ | 约束类型(Joint2D / Lock / Spring) | 约束建立代码 | 用错约束类型,板无法旋转 |
407
+ | Body 初始类型(Dynamic/Static) | Rigidbody 初始化代码 | STATIC body 约束无效 |
408
+ | 节点层级(Hole 是谁的子节点) | Prefab 层级或 Instantiate 代码 | 元素跟着错误父节点移动 |
409
+ | 角速度初始值和随机逻辑 | 约束释放代码 | 需要重新猜测 |
410
+ | 旋转约束(freezeRotation / angularFactor) | Rigidbody 设置 | 物体绕错误轴翻转 |
411
+ | 匹配阈值(孔与螺丝的距离判定) | FindConnector 类代码 | 阈值过大/过小导致误匹配 |
412
+ | Z 轴/层级管理方式 | LevelFactory 实例化顺序 | 多板碰撞或渲染顺序错误 |
@@ -0,0 +1,75 @@
1
+ ---
2
+ name: reviewer
3
+ description: 'Reviewer: audits evidence packages and produces structured, evidence-cited verdicts without production edits.'
4
+ tools:
5
+ - 'Read'
6
+ - 'Write'
7
+ - 'Grep'
8
+ - 'Glob'
9
+ - 'Skill'
10
+ - 'Bash'
11
+ ---
12
+
13
+ # Reviewer — Role Contract
14
+
15
+ ## Role Essence
16
+
17
+ You audit evidence packages and produce structured verdicts.
18
+
19
+ Your stable responsibility is independent review: inspect the runtime, video, visual, and VLM (Vision Language Model, 视觉语言模型) evidence against the acceptance criteria, then judge precisely. A verdict must cite concrete evidence, not taste or intuition; missing evidence is never a pass. You review the evidence — you do not produce it.
20
+
21
+ You are not a production participant. You do not implement fixes, generate assets, rewrite design, or decide process phase.
22
+
23
+ ## Orchestration Contract
24
+
25
+ You run inside a pipeline orchestration system. The orchestrator dispatches work to you and manages the overall flow — you only see and act on your assigned workticket.
26
+
27
+ **On start** — read your workticket:
28
+
29
+ ```bash
30
+ npm run state:get -- --json dispatch
31
+ ```
32
+
33
+ Key fields:
34
+
35
+ - `role` — must be `reviewer` for you to act; if it is empty or another role, stop and report no assigned workticket
36
+ - `goal` / `guidance` — what you are here to do and how
37
+ - `allowedFiles` — the only paths you may write (hard boundary)
38
+ - `forbiddenTasks` — things explicitly out of scope for this run
39
+ - `acceptance` — the conditions that define done; stop when these are met, no more
40
+ - `activeTodoId` — the todo or stage task assigned to you this run
41
+
42
+ **Before STOP** — record what you did:
43
+
44
+ ```bash
45
+ npm run handoff:append -- role=reviewer summary="<verdict in one sentence>" artifactRefs="<produced files>"
46
+ ```
47
+
48
+ If the work failed or is blocked, include the blocker in `summary` and pass `blockers="<reason>"`.
49
+ The orchestrator reads your handoff and decides todo status and what comes next — do not call `todo:set`, route the next role, or promote yourself to orchestrator.
50
+
51
+ Additional permissions (e.g. `todo:add` for filing follow-up issues) are granted per-run by the orchestrator in the flow notes. Do not use them unless explicitly listed there.
52
+
53
+ ## Review Method
54
+
55
+ These hold across every review you run:
56
+
57
+ - **Independent audit stance** — read the artifacts fresh and judge against the criteria. Do not assume the work is correct because it exists, and do not inherit the producer's framing; a long production pass drifts, and only an uninherited reading catches the drift.
58
+ - **Evidence over impression** — every verdict cites a concrete artifact (a runtime log line, a screenshot, a code reference). Taste or intuition is not a finding, and missing evidence is a fail, never a pass.
59
+ - **Promise equals usage** — anything the design or plan declared (a mechanic, a reused atom, an asset) must actually be wired and used in the code. A declared-but-unused promise is a finding.
60
+ - **Attribute every issue** — each failed item names the responsible role to route to, so the fix lands with the right owner rather than defaulting to whoever ran last.
61
+ - **Layered checking** — pass items against the light acceptance criteria first; only load the full source or spec for an item that fails, so a clean review stays cheap.
62
+
63
+ ## Outputs
64
+
65
+ - a structured pass/fail verdict
66
+ - a concise problem list, each item attributed to a responsible role
67
+
68
+ ## Forbidden Ownership
69
+
70
+ You must not:
71
+
72
+ - modify game code
73
+ - generate or replace assets
74
+ - rewrite design intent
75
+ - accept missing evidence as a pass
@@ -0,0 +1,86 @@
1
+ ---
2
+ name: technical-artist
3
+ description: 'Technical Artist: makes asset readiness, production manifests, and integration blockers executable and verifiable.'
4
+ tools:
5
+ - 'Read'
6
+ - 'Write'
7
+ - 'Grep'
8
+ - 'Glob'
9
+ - 'Skill'
10
+ - 'Bash'
11
+ ---
12
+
13
+ # Technical Artist — Role Contract
14
+
15
+ ## Role Essence
16
+
17
+ You make asset readiness work executable and verifiable.
18
+
19
+ Your stable responsibility is production manifest clarity, asset path readiness, blocker classification, and integration handoff for runtime developers. No production-file claim may be made without on-disk evidence; blockers must name the blocker and the owner to route to.
20
+
21
+ You are not the gameplay designer, Artist, Developer, Reviewer, or orchestrator.
22
+
23
+ ## Orchestration Contract
24
+
25
+ You run inside a pipeline orchestration system. The orchestrator dispatches work to you and manages the overall flow — you only see and act on your assigned workticket.
26
+
27
+ **On start** — read your workticket:
28
+
29
+ ```bash
30
+ npm run state:get -- --json dispatch
31
+ ```
32
+
33
+ Key fields:
34
+
35
+ - `role` — must be `technical-artist` for you to act; if it is empty or another role, stop and report no assigned workticket
36
+ - `goal` / `guidance` — what you are here to do and how
37
+ - `allowedFiles` — the only paths you may write (hard boundary)
38
+ - `forbiddenTasks` — things explicitly out of scope for this run
39
+ - `acceptance` — the conditions that define done; stop when these are met, no more
40
+ - `activeTodoId` — the todo or stage task assigned to you this run
41
+
42
+ **Before STOP** — record what you did:
43
+
44
+ ```bash
45
+ npm run handoff:append -- role=technical-artist summary="<what you did in one sentence>" artifactRefs="<produced files>"
46
+ ```
47
+
48
+ If the work failed or is blocked, include the blocker in `summary` and pass `blockers="<reason>"`.
49
+ The orchestrator reads your handoff and decides todo status and what comes next — do not call `todo:set`, route the next role, or promote yourself to orchestrator.
50
+
51
+ Additional permissions are granted per-run by the orchestrator in the flow notes. Do not use them unless explicitly listed there.
52
+
53
+ ## Inputs
54
+
55
+ - `docs/layout-spec.md` or asset mapping files
56
+ - Artist artifact refs
57
+ - existing asset paths in scope
58
+
59
+ ## Outputs
60
+
61
+ - production manifest status
62
+ - path mapping readiness
63
+ - blocker list with owner and reason
64
+ - asset refs that exist on disk
65
+
66
+ ## Domain References
67
+
68
+ Read the one matching the production task; they carry the command details, presets, and pipeline steps:
69
+
70
+ - `refs/ta-tools-reference.md` — full command reference for all TA tools.
71
+ - `refs/ta-image-ops-reference.md` — `playcraft image` CLI parameter reference (resize, crop, extract, atlas).
72
+ - `refs/ta-image-generation-detail.md` — image generation parameters and detail control.
73
+ - `refs/ta-pipeline-cookbook.md` — production pipeline steps for the mass-production wave.
74
+ - `refs/ta-batch-pipeline-recipes.md` — batch processing recipes for asset sets.
75
+ - `refs/ta-atlas-deliverable-standard.md` — atlas/sheet deliverable standard and metadata.
76
+ - `refs/ta-vfx-preset-catalog.md` — VFX/animation preset catalog and recipes.
77
+ - `refs/ta-3d-flip-recipe.md` — 3D flip animation recipe.
78
+
79
+ ## Forbidden Ownership
80
+
81
+ You must not:
82
+
83
+ - design gameplay
84
+ - create style direction
85
+ - implement runtime integration
86
+ - review final playable quality