@playcraft/skills 0.0.2

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 (479) hide show
  1. package/README.md +333 -0
  2. package/dist/src/index.d.ts +3 -0
  3. package/dist/src/index.d.ts.map +1 -0
  4. package/dist/src/index.js +2 -0
  5. package/dist/src/index.js.map +1 -0
  6. package/dist/src/skills.loader.d.ts +31 -0
  7. package/dist/src/skills.loader.d.ts.map +1 -0
  8. package/dist/src/skills.loader.js +200 -0
  9. package/dist/src/skills.loader.js.map +1 -0
  10. package/dist/src/skills.types.d.ts +44 -0
  11. package/dist/src/skills.types.d.ts.map +1 -0
  12. package/dist/src/skills.types.js +9 -0
  13. package/dist/src/skills.types.js.map +1 -0
  14. package/package.json +35 -0
  15. package/skills/2048_core.aigameplay/SKILL.md +123 -0
  16. package/skills/2048_core.aigameplay/manifest.json +159 -0
  17. package/skills/2048_core.aigameplay/ref/pgs-schema.json +194 -0
  18. package/skills/2048_core.aigameplay/ref/reducer.template.ts +189 -0
  19. package/skills/SKILL.md +46 -0
  20. package/skills/ad_compliance_rules.aiconfig/SKILL.md +85 -0
  21. package/skills/ad_compliance_rules.aiconfig/manifest.json +60 -0
  22. package/skills/agent_remix_orchestrator.aicomponent/SKILL.md +257 -0
  23. package/skills/agent_remix_orchestrator.aicomponent/manifest.json +12 -0
  24. package/skills/app_metadata.aiconfig/SKILL.md +53 -0
  25. package/skills/app_metadata.aiconfig/manifest.json +32 -0
  26. package/skills/appear_sfx.aiaudio/SKILL.md +59 -0
  27. package/skills/appear_sfx.aiaudio/manifest.json +45 -0
  28. package/skills/appear_sfx.aiaudio/ref/appear.mp3 +0 -0
  29. package/skills/arrow_move_error_sfx.aiaudio/SKILL.md +59 -0
  30. package/skills/arrow_move_error_sfx.aiaudio/manifest.json +45 -0
  31. package/skills/arrow_move_error_sfx.aiaudio/ref/arrow_move_error.mp3 +0 -0
  32. package/skills/arrow_path_data_format.aicomponent/SKILL.md +152 -0
  33. package/skills/arrow_path_data_format.aicomponent/manifest.json +57 -0
  34. package/skills/arrow_path_data_format.aicomponent/ref/LevelParser.ts +188 -0
  35. package/skills/arrow_path_data_format.aicomponent/ref/LevelTypes.ts +131 -0
  36. package/skills/arrow_pick_match_rules.aigameplay/SKILL.md +117 -0
  37. package/skills/arrow_pick_match_rules.aigameplay/manifest.json +105 -0
  38. package/skills/arrow_pick_match_rules.aigameplay/ref/pgs-schema.json +180 -0
  39. package/skills/asset_pipeline_scripts.aicomponent/SKILL.md +117 -0
  40. package/skills/asset_pipeline_scripts.aicomponent/manifest.json +17 -0
  41. package/skills/asset_pipeline_scripts.aicomponent/ref/gen-sprite.sh +105 -0
  42. package/skills/ball_sort.aigameplay/SKILL.md +109 -0
  43. package/skills/ball_sort.aigameplay/manifest.json +155 -0
  44. package/skills/ball_sort.aigameplay/ref/pgs-schema.json +192 -0
  45. package/skills/ball_sort.aigameplay/ref/reducer.template.ts +156 -0
  46. package/skills/basketball_shot.aigameplay/SKILL.md +94 -0
  47. package/skills/basketball_shot.aigameplay/manifest.json +150 -0
  48. package/skills/basketball_shot.aigameplay/ref/pgs-schema.json +229 -0
  49. package/skills/basketball_shot.aigameplay/ref/reducer.template.ts +189 -0
  50. package/skills/bg_music.aiaudio/SKILL.md +61 -0
  51. package/skills/bg_music.aiaudio/manifest.json +48 -0
  52. package/skills/bg_music.aiaudio/ref/bg.mp3 +0 -0
  53. package/skills/big_watermelon.aigameplay/SKILL.md +94 -0
  54. package/skills/big_watermelon.aigameplay/manifest.json +155 -0
  55. package/skills/big_watermelon.aigameplay/ref/pgs-schema.json +191 -0
  56. package/skills/big_watermelon.aigameplay/ref/reducer.template.ts +202 -0
  57. package/skills/block_puzzle.aigameplay/SKILL.md +121 -0
  58. package/skills/block_puzzle.aigameplay/manifest.json +154 -0
  59. package/skills/block_puzzle.aigameplay/ref/pgs-schema.json +170 -0
  60. package/skills/block_puzzle.aigameplay/ref/reducer.template.ts +182 -0
  61. package/skills/board_entity_sprite.aiimage/SKILL.md +255 -0
  62. package/skills/board_entity_sprite.aiimage/manifest.json +153 -0
  63. package/skills/board_entity_sprite.aiimage/ref/ProceduralCar.ts +357 -0
  64. package/skills/board_entity_sprite.aiimage/ref/car.png +0 -0
  65. package/skills/board_entity_sprite.aiimage/ref/car.webp +0 -0
  66. package/skills/bottom_ui_bar.aicomponent/SKILL.md +50 -0
  67. package/skills/bottom_ui_bar.aicomponent/manifest.json +31 -0
  68. package/skills/bottom_ui_bar.aicomponent/ref/GameBottomUI.ts +27 -0
  69. package/skills/bubble_shooter.aigameplay/SKILL.md +129 -0
  70. package/skills/bubble_shooter.aigameplay/manifest.json +181 -0
  71. package/skills/bubble_shooter.aigameplay/ref/pgs-schema.json +226 -0
  72. package/skills/bubble_shooter.aigameplay/ref/reducer.template.ts +228 -0
  73. package/skills/button_click_sfx.aiaudio/SKILL.md +59 -0
  74. package/skills/button_click_sfx.aiaudio/manifest.json +45 -0
  75. package/skills/button_click_sfx.aiaudio/ref/button_click.mp3 +0 -0
  76. package/skills/calm_piano.aiaudio/SKILL.md +68 -0
  77. package/skills/calm_piano.aiaudio/manifest.json +50 -0
  78. package/skills/camera_controller_3d.aicomponent/SKILL.md +100 -0
  79. package/skills/camera_controller_3d.aicomponent/manifest.json +52 -0
  80. package/skills/camera_controller_3d.aicomponent/ref/CameraController.ts +199 -0
  81. package/skills/camera_controller_3d.aicomponent/ref/OrbitControlsAdapter.ts +152 -0
  82. package/skills/candy_tile.aiimage/SKILL.md +62 -0
  83. package/skills/candy_tile.aiimage/manifest.json +49 -0
  84. package/skills/car_parking.aigameplay/SKILL.md +105 -0
  85. package/skills/car_parking.aigameplay/manifest.json +164 -0
  86. package/skills/car_parking.aigameplay/ref/pgs-schema.json +163 -0
  87. package/skills/car_parking.aigameplay/ref/reducer.template.ts +166 -0
  88. package/skills/castle.aiimage/SKILL.md +64 -0
  89. package/skills/castle.aiimage/manifest.json +48 -0
  90. package/skills/cheerful_ukulele.aiaudio/SKILL.md +72 -0
  91. package/skills/cheerful_ukulele.aiaudio/manifest.json +50 -0
  92. package/skills/click_sfx.aiaudio/SKILL.md +59 -0
  93. package/skills/click_sfx.aiaudio/manifest.json +45 -0
  94. package/skills/click_sfx.aiaudio/ref/click.mp3 +0 -0
  95. package/skills/combo_display.aicomponent/SKILL.md +45 -0
  96. package/skills/combo_display.aicomponent/manifest.json +31 -0
  97. package/skills/combo_display.aicomponent/ref/ComboManager.ts +362 -0
  98. package/skills/combo_display.aicomponent/ref/ComboSmallUI.ts +232 -0
  99. package/skills/combo_praise_text.aicomponent/SKILL.md +56 -0
  100. package/skills/combo_praise_text.aicomponent/manifest.json +34 -0
  101. package/skills/combo_praise_text.aicomponent/ref/ComboManager.ts +362 -0
  102. package/skills/countdown_timer.aicomponent/SKILL.md +44 -0
  103. package/skills/countdown_timer.aicomponent/manifest.json +35 -0
  104. package/skills/countdown_timer.aicomponent/ref/CountdownDisplay.ts +213 -0
  105. package/skills/cta_platform_config.aiconfig/SKILL.md +72 -0
  106. package/skills/cta_platform_config.aiconfig/manifest.json +56 -0
  107. package/skills/debug_overlay.aicomponent/SKILL.md +75 -0
  108. package/skills/debug_overlay.aicomponent/manifest.json +17 -0
  109. package/skills/debug_overlay.aicomponent/ref/DebugOverlay.ts +144 -0
  110. package/skills/desert.aiimage/SKILL.md +63 -0
  111. package/skills/desert.aiimage/manifest.json +49 -0
  112. package/skills/difficulty_curve_designer.aiconfig/SKILL.md +68 -0
  113. package/skills/difficulty_curve_designer.aiconfig/manifest.json +36 -0
  114. package/skills/digit_renderer.aicomponent/SKILL.md +43 -0
  115. package/skills/digit_renderer.aicomponent/manifest.json +25 -0
  116. package/skills/digit_renderer.aicomponent/ref/DigitRenderer.ts +237 -0
  117. package/skills/download_button.aicomponent/SKILL.md +44 -0
  118. package/skills/download_button.aicomponent/manifest.json +25 -0
  119. package/skills/download_button.aicomponent/ref/DownloadButton.ts +137 -0
  120. package/skills/draw_line_puzzle.aigameplay/SKILL.md +84 -0
  121. package/skills/draw_line_puzzle.aigameplay/manifest.json +152 -0
  122. package/skills/draw_line_puzzle.aigameplay/ref/pgs-schema.json +189 -0
  123. package/skills/draw_line_puzzle.aigameplay/ref/reducer.template.ts +194 -0
  124. package/skills/easy_to_hard.aiconfig/SKILL.md +52 -0
  125. package/skills/easy_to_hard.aiconfig/manifest.json +33 -0
  126. package/skills/eight_ball_pool.aigameplay/SKILL.md +104 -0
  127. package/skills/eight_ball_pool.aigameplay/manifest.json +152 -0
  128. package/skills/eight_ball_pool.aigameplay/ref/pgs-schema.json +205 -0
  129. package/skills/eight_ball_pool.aigameplay/ref/reducer.template.ts +198 -0
  130. package/skills/energetic_electronic.aiaudio/SKILL.md +69 -0
  131. package/skills/energetic_electronic.aiaudio/manifest.json +51 -0
  132. package/skills/fail_sfx.aiaudio/SKILL.md +59 -0
  133. package/skills/fail_sfx.aiaudio/manifest.json +44 -0
  134. package/skills/fail_sfx.aiaudio/ref/fail.mp3 +0 -0
  135. package/skills/figer_icon.aiimage/SKILL.md +58 -0
  136. package/skills/figer_icon.aiimage/manifest.json +48 -0
  137. package/skills/figer_icon.aiimage/ref/figer.png +0 -0
  138. package/skills/figer_icon.aiimage/ref/figer.webp +0 -0
  139. package/skills/forest.aiimage/SKILL.md +74 -0
  140. package/skills/forest.aiimage/manifest.json +48 -0
  141. package/skills/fruit_tile.aiimage/SKILL.md +68 -0
  142. package/skills/fruit_tile.aiimage/manifest.json +48 -0
  143. package/skills/game_over_panel.aicomponent/SKILL.md +47 -0
  144. package/skills/game_over_panel.aicomponent/manifest.json +61 -0
  145. package/skills/game_over_panel.aicomponent/ref/GameOverPanel.ts +74 -0
  146. package/skills/game_scene.aicomponent/SKILL.md +57 -0
  147. package/skills/game_scene.aicomponent/manifest.json +36 -0
  148. package/skills/game_scene.aicomponent/ref/Game.ts +748 -0
  149. package/skills/gameplay_balance_check.aivalidator/SKILL.md +69 -0
  150. package/skills/gameplay_balance_check.aivalidator/manifest.json +21 -0
  151. package/skills/gameplay_unit_test.aivalidator/SKILL.md +89 -0
  152. package/skills/gameplay_unit_test.aivalidator/manifest.json +17 -0
  153. package/skills/gameplay_unit_test.aivalidator/ref/gameplay.test.ts +202 -0
  154. package/skills/gameplay_unit_test.aivalidator/ref/vitest.config.ts +13 -0
  155. package/skills/grid_board_layout.aicomponent/SKILL.md +85 -0
  156. package/skills/grid_board_layout.aicomponent/manifest.json +69 -0
  157. package/skills/grid_board_layout.aicomponent/ref/BoardLayout.ts +416 -0
  158. package/skills/grid_board_layout.aicomponent/ref/BoardLayout3D.ts +125 -0
  159. package/skills/grid_board_layout.aicomponent/ref/BoardLayoutMath.ts +85 -0
  160. package/skills/grid_board_layout.aicomponent/ref/BoardRenderer3D.ts +298 -0
  161. package/skills/heart_lives.aicomponent/SKILL.md +42 -0
  162. package/skills/heart_lives.aicomponent/manifest.json +25 -0
  163. package/skills/heart_lives.aicomponent/ref/HeartDisplay.ts +96 -0
  164. package/skills/idle-breathe.aicomponent/SKILL.md +27 -0
  165. package/skills/idle-breathe.aicomponent/manifest.json +20 -0
  166. package/skills/idle-breathe.aicomponent/ref/phaser.js +25 -0
  167. package/skills/idle-breathe.aicomponent/ref/playcanvas.js +29 -0
  168. package/skills/jewel_tile.aiimage/SKILL.md +63 -0
  169. package/skills/jewel_tile.aiimage/manifest.json +49 -0
  170. package/skills/knife_hit.aigameplay/SKILL.md +103 -0
  171. package/skills/knife_hit.aigameplay/manifest.json +151 -0
  172. package/skills/knife_hit.aigameplay/ref/pgs-schema.json +202 -0
  173. package/skills/knife_hit.aigameplay/ref/reducer.template.ts +196 -0
  174. package/skills/left_right_parkour.aigameplay/SKILL.md +120 -0
  175. package/skills/left_right_parkour.aigameplay/manifest.json +165 -0
  176. package/skills/left_right_parkour.aigameplay/ref/pgs-schema.json +200 -0
  177. package/skills/left_right_parkour.aigameplay/ref/reducer.template.ts +194 -0
  178. package/skills/level_data_pack.aiconfig/SKILL.md +64 -0
  179. package/skills/level_data_pack.aiconfig/manifest.json +37 -0
  180. package/skills/level_data_validator.aivalidator/SKILL.md +85 -0
  181. package/skills/level_data_validator.aivalidator/manifest.json +17 -0
  182. package/skills/level_data_validator.aivalidator/ref/LevelValidator.ts +113 -0
  183. package/skills/level_lifecycle.aicomponent/SKILL.md +81 -0
  184. package/skills/level_lifecycle.aicomponent/manifest.json +87 -0
  185. package/skills/level_lifecycle.aicomponent/ref/LevelLifecycle.ts +235 -0
  186. package/skills/level_solvability_validator.aivalidator/SKILL.md +74 -0
  187. package/skills/level_solvability_validator.aivalidator/manifest.json +23 -0
  188. package/skills/level_solvability_validator.aivalidator/ref/LevelValidator.ts +186 -0
  189. package/skills/level_state.aicomponent/SKILL.md +55 -0
  190. package/skills/level_state.aicomponent/manifest.json +34 -0
  191. package/skills/level_state.aicomponent/ref/LevelDataManager.ts +26 -0
  192. package/skills/level_state.aicomponent/ref/LevelManager.ts +26 -0
  193. package/skills/loading_screen.aicomponent/SKILL.md +57 -0
  194. package/skills/loading_screen.aicomponent/manifest.json +43 -0
  195. package/skills/loading_screen.aicomponent/ref/LoadingUI.ts +339 -0
  196. package/skills/lose_result_panel.aiimage/SKILL.md +58 -0
  197. package/skills/lose_result_panel.aiimage/manifest.json +47 -0
  198. package/skills/lose_result_panel.aiimage/ref/lose.png +0 -0
  199. package/skills/lose_result_panel.aiimage/ref/lose.webp +0 -0
  200. package/skills/lose_sfx.aiaudio/SKILL.md +59 -0
  201. package/skills/lose_sfx.aiaudio/manifest.json +45 -0
  202. package/skills/lose_sfx.aiaudio/ref/lose.mp3 +0 -0
  203. package/skills/match-pop.aicomponent/SKILL.md +29 -0
  204. package/skills/match-pop.aicomponent/manifest.json +19 -0
  205. package/skills/match-pop.aicomponent/ref/phaser.js +30 -0
  206. package/skills/match-pop.aicomponent/ref/playcanvas.js +22 -0
  207. package/skills/match3_core.aigameplay/SKILL.md +125 -0
  208. package/skills/match3_core.aigameplay/manifest.json +107 -0
  209. package/skills/match3_core.aigameplay/ref/pgs-schema.json +154 -0
  210. package/skills/match3_core.aigameplay/ref/reducer.template.ts +191 -0
  211. package/skills/match_engine.aicomponent/SKILL.md +84 -0
  212. package/skills/match_engine.aicomponent/manifest.json +23 -0
  213. package/skills/match_engine.aicomponent/ref/MatchEngine.ts +75 -0
  214. package/skills/memory_match.aigameplay/SKILL.md +111 -0
  215. package/skills/memory_match.aigameplay/manifest.json +164 -0
  216. package/skills/memory_match.aigameplay/ref/pgs-schema.json +190 -0
  217. package/skills/memory_match.aigameplay/ref/reducer.template.ts +162 -0
  218. package/skills/merge_core.aigameplay/SKILL.md +112 -0
  219. package/skills/merge_core.aigameplay/manifest.json +154 -0
  220. package/skills/merge_core.aigameplay/ref/pgs-schema.json +202 -0
  221. package/skills/merge_core.aigameplay/ref/reducer.template.ts +179 -0
  222. package/skills/mistake_sfx.aiaudio/SKILL.md +59 -0
  223. package/skills/mistake_sfx.aiaudio/manifest.json +45 -0
  224. package/skills/mistake_sfx.aiaudio/ref/mistake.mp3 +0 -0
  225. package/skills/nomove_hint_overlay.aiimage/SKILL.md +58 -0
  226. package/skills/nomove_hint_overlay.aiimage/manifest.json +48 -0
  227. package/skills/nomove_hint_overlay.aiimage/ref/nomove_hint.png +0 -0
  228. package/skills/nomove_hint_overlay.aiimage/ref/nomove_hint.webp +0 -0
  229. package/skills/normal_dot.aiimage/SKILL.md +58 -0
  230. package/skills/normal_dot.aiimage/manifest.json +46 -0
  231. package/skills/normal_dot.aiimage/ref/normal_dot.png +0 -0
  232. package/skills/normal_dot.aiimage/ref/normal_dot.webp +0 -0
  233. package/skills/ocean.aiimage/SKILL.md +71 -0
  234. package/skills/ocean.aiimage/manifest.json +49 -0
  235. package/skills/particle-confetti.aicomponent/SKILL.md +32 -0
  236. package/skills/particle-confetti.aicomponent/manifest.json +21 -0
  237. package/skills/particle-confetti.aicomponent/ref/html5-spritesheet.js +17 -0
  238. package/skills/particle-confetti.aicomponent/ref/phaser.js +38 -0
  239. package/skills/particle-explosion.aicomponent/SKILL.md +37 -0
  240. package/skills/particle-explosion.aicomponent/manifest.json +24 -0
  241. package/skills/particle-explosion.aicomponent/ref/html5-spritesheet.js +40 -0
  242. package/skills/particle-explosion.aicomponent/ref/phaser.js +46 -0
  243. package/skills/particle-explosion.aicomponent/ref/playcanvas.js +33 -0
  244. package/skills/particle-trail.aicomponent/SKILL.md +25 -0
  245. package/skills/particle-trail.aicomponent/manifest.json +22 -0
  246. package/skills/particle-trail.aicomponent/ref/phaser.js +31 -0
  247. package/skills/path_animation.aicomponent/SKILL.md +82 -0
  248. package/skills/path_animation.aicomponent/manifest.json +77 -0
  249. package/skills/path_animation.aicomponent/ref/AnimationManager.ts +694 -0
  250. package/skills/path_animation.aicomponent/ref/AnimationManager3D.ts +317 -0
  251. package/skills/path_elimination_rules.aigameplay/SKILL.md +88 -0
  252. package/skills/path_elimination_rules.aigameplay/manifest.json +119 -0
  253. package/skills/path_elimination_rules.aigameplay/ref/pgs-schema.json +227 -0
  254. package/skills/path_input_handler.aicomponent/SKILL.md +87 -0
  255. package/skills/path_input_handler.aicomponent/manifest.json +97 -0
  256. package/skills/path_input_handler.aicomponent/ref/InputHandler.ts +714 -0
  257. package/skills/path_input_handler.aicomponent/ref/InputHandler3D.ts +204 -0
  258. package/skills/path_renderer.aicomponent/SKILL.md +101 -0
  259. package/skills/path_renderer.aicomponent/manifest.json +69 -0
  260. package/skills/path_renderer.aicomponent/ref/PathRenderer.ts +509 -0
  261. package/skills/path_renderer.aicomponent/ref/PathRenderer3D.ts +176 -0
  262. package/skills/path_renderer.aicomponent/ref/PathRenderers.ts +640 -0
  263. package/skills/phaser.aicomponent/SKILL.md +315 -0
  264. package/skills/phaser.aicomponent/manifest.json +156 -0
  265. package/skills/phaser.aicomponent/ref/BootScene.ts +29 -0
  266. package/skills/phaser.aicomponent/ref/GameConfig.ts +29 -0
  267. package/skills/phaser.aicomponent/ref/GameScene.ts +88 -0
  268. package/skills/phaser.aicomponent/ref/PreloaderScene.ts +78 -0
  269. package/skills/phaser.aicomponent/ref/SceneKeys.ts +7 -0
  270. package/skills/phaser.aicomponent/ref/SoundUtils.ts +21 -0
  271. package/skills/phaser.aicomponent/ref/UiLayout.ts +74 -0
  272. package/skills/phaser.aicomponent/ref/globals.d.ts +52 -0
  273. package/skills/phaser.aicomponent/ref/index.css +40 -0
  274. package/skills/phaser.aicomponent/ref/index.html +14 -0
  275. package/skills/phaser.aicomponent/ref/index.ts +48 -0
  276. package/skills/phaser.aicomponent/ref/main.ts +16 -0
  277. package/skills/phaser.aicomponent/ref/package.json +22 -0
  278. package/skills/phaser.aicomponent/ref/tsconfig.json +25 -0
  279. package/skills/phaser.aicomponent/ref/webpack.config.js +57 -0
  280. package/skills/phaser_scene_lifecycle.aicomponent/SKILL.md +63 -0
  281. package/skills/phaser_scene_lifecycle.aicomponent/manifest.json +33 -0
  282. package/skills/pick_and_match_rules.aigameplay/SKILL.md +113 -0
  283. package/skills/pick_and_match_rules.aigameplay/manifest.json +121 -0
  284. package/skills/pick_and_match_rules.aigameplay/ref/pgs-schema.json +354 -0
  285. package/skills/pin_pull.aigameplay/SKILL.md +110 -0
  286. package/skills/pin_pull.aigameplay/manifest.json +164 -0
  287. package/skills/pin_pull.aigameplay/ref/pgs-schema.json +201 -0
  288. package/skills/pin_pull.aigameplay/ref/reducer.template.ts +216 -0
  289. package/skills/playable_app_logo.aiimage/SKILL.md +58 -0
  290. package/skills/playable_app_logo.aiimage/manifest.json +47 -0
  291. package/skills/playable_app_logo.aiimage/ref/logo.png +0 -0
  292. package/skills/playable_app_logo.aiimage/ref/logo.webp +0 -0
  293. package/skills/playable_end_screen_layout.aicomponent/SKILL.md +75 -0
  294. package/skills/playable_end_screen_layout.aicomponent/manifest.json +24 -0
  295. package/skills/playable_guidance_layer.aicomponent/SKILL.md +89 -0
  296. package/skills/playable_guidance_layer.aicomponent/manifest.json +24 -0
  297. package/skills/playable_hud_layout.aicomponent/SKILL.md +96 -0
  298. package/skills/playable_hud_layout.aicomponent/manifest.json +24 -0
  299. package/skills/playable_scripts_build.aicomponent/SKILL.md +69 -0
  300. package/skills/playable_scripts_build.aicomponent/manifest.json +53 -0
  301. package/skills/playable_scripts_build.aicomponent/ref/builds.config.js +257 -0
  302. package/skills/playcraft-3d-flip-sprite/SKILL.md +336 -0
  303. package/skills/playcraft-3d-flip-sprite/renderer/flatten_glb.mjs +62 -0
  304. package/skills/playcraft-3d-flip-sprite/renderer/render.mjs +325 -0
  305. package/skills/playcraft-3d-flip-sprite/renderer/render_single.mjs +138 -0
  306. package/skills/playcraft-asset-management/SKILL.md +73 -0
  307. package/skills/playcraft-audio-generation/SKILL.md +126 -0
  308. package/skills/playcraft-build/SKILL.md +44 -0
  309. package/skills/playcraft-code-editor/SKILL.md +71 -0
  310. package/skills/playcraft-create-remix/SKILL.md +62 -0
  311. package/skills/playcraft-deploy/SKILL.md +59 -0
  312. package/skills/playcraft-image-generation/SKILL.md +148 -0
  313. package/skills/playcraft-image-processing/SKILL.md +216 -0
  314. package/skills/playcraft-platform-intro/SKILL.md +41 -0
  315. package/skills/playcraft-prefab/SKILL.md +98 -0
  316. package/skills/playcraft-project-management/SKILL.md +57 -0
  317. package/skills/playcraft-remix-workflow/SKILL.md +119 -0
  318. package/skills/playcraft-remix-workflow/references/xplatform.schema.json5 +31 -0
  319. package/skills/playcraft-save/SKILL.md +46 -0
  320. package/skills/playcraft-skill-recommender/SKILL.md +152 -0
  321. package/skills/playcraft-sprite-generation/SKILL.md +534 -0
  322. package/skills/playcraft-sprite-remix/SKILL.md +155 -0
  323. package/skills/playcraft-sprite-sheet/SKILL.md +97 -0
  324. package/skills/playtest_report.aivalidator/SKILL.md +103 -0
  325. package/skills/playtest_report.aivalidator/manifest.json +21 -0
  326. package/skills/preloader_scene.aicomponent/SKILL.md +58 -0
  327. package/skills/preloader_scene.aicomponent/manifest.json +43 -0
  328. package/skills/preloader_scene.aicomponent/ref/Preloader.ts +339 -0
  329. package/skills/progress_bar.aicomponent/SKILL.md +38 -0
  330. package/skills/progress_bar.aicomponent/manifest.json +25 -0
  331. package/skills/progress_bar.aicomponent/ref/ProgressDisplay.ts +140 -0
  332. package/skills/references/xplatform.schema.json5 +31 -0
  333. package/skills/responsive_2d_layout.aicomponent/SKILL.md +161 -0
  334. package/skills/responsive_2d_layout.aicomponent/manifest.json +43 -0
  335. package/skills/responsive_2d_layout.aicomponent/ref/UiLayout.ts +56 -0
  336. package/skills/run_context_state.aicomponent/SKILL.md +54 -0
  337. package/skills/run_context_state.aicomponent/manifest.json +40 -0
  338. package/skills/run_context_state.aicomponent/ref/RunContextRuntime.ts +30 -0
  339. package/skills/score-fly.aicomponent/SKILL.md +31 -0
  340. package/skills/score-fly.aicomponent/manifest.json +21 -0
  341. package/skills/score-fly.aicomponent/ref/phaser.js +26 -0
  342. package/skills/score-fly.aicomponent/ref/playcanvas.js +28 -0
  343. package/skills/score_goal.aiconfig/SKILL.md +46 -0
  344. package/skills/score_goal.aiconfig/manifest.json +33 -0
  345. package/skills/screen-flash.aicomponent/SKILL.md +30 -0
  346. package/skills/screen-flash.aicomponent/manifest.json +20 -0
  347. package/skills/screen-flash.aicomponent/ref/phaser.js +48 -0
  348. package/skills/screen-shake.aicomponent/SKILL.md +30 -0
  349. package/skills/screen-shake.aicomponent/manifest.json +19 -0
  350. package/skills/screen-shake.aicomponent/ref/phaser.js +23 -0
  351. package/skills/screen-shake.aicomponent/ref/playcanvas.js +44 -0
  352. package/skills/screw_puzzle.aigameplay/SKILL.md +116 -0
  353. package/skills/screw_puzzle.aigameplay/manifest.json +164 -0
  354. package/skills/screw_puzzle.aigameplay/ref/pgs-schema.json +235 -0
  355. package/skills/screw_puzzle.aigameplay/ref/reducer.template.ts +213 -0
  356. package/skills/settings_state.aicomponent/SKILL.md +61 -0
  357. package/skills/settings_state.aicomponent/manifest.json +33 -0
  358. package/skills/settings_state.aicomponent/ref/SettingsManager.ts +130 -0
  359. package/skills/slide_out_to_tray_animation.aicomponent/SKILL.md +64 -0
  360. package/skills/slide_out_to_tray_animation.aicomponent/manifest.json +58 -0
  361. package/skills/slide_out_to_tray_animation.aicomponent/ref/AnimationManager.ts +164 -0
  362. package/skills/slide_out_to_tray_animation.aicomponent/ref/AnimationManager3D.ts +198 -0
  363. package/skills/slide_out_to_tray_animation.aicomponent/ref/BezierUtils.ts +59 -0
  364. package/skills/slot_machine.aigameplay/SKILL.md +119 -0
  365. package/skills/slot_machine.aigameplay/manifest.json +166 -0
  366. package/skills/slot_machine.aigameplay/ref/pgs-schema.json +212 -0
  367. package/skills/slot_machine.aigameplay/ref/reducer.template.ts +212 -0
  368. package/skills/sniper_shot.aigameplay/SKILL.md +84 -0
  369. package/skills/sniper_shot.aigameplay/manifest.json +153 -0
  370. package/skills/sniper_shot.aigameplay/ref/pgs-schema.json +211 -0
  371. package/skills/sniper_shot.aigameplay/ref/reducer.template.ts +211 -0
  372. package/skills/solitaire.aigameplay/SKILL.md +101 -0
  373. package/skills/solitaire.aigameplay/manifest.json +151 -0
  374. package/skills/solitaire.aigameplay/ref/pgs-schema.json +200 -0
  375. package/skills/solitaire.aigameplay/ref/reducer.template.ts +176 -0
  376. package/skills/sound-effects/SKILL.md +46 -0
  377. package/skills/sound_utils.aicomponent/SKILL.md +52 -0
  378. package/skills/sound_utils.aicomponent/manifest.json +30 -0
  379. package/skills/sound_utils.aicomponent/ref/SoundUtils.ts +29 -0
  380. package/skills/sprite-animation-2d.aicomponent/SKILL.md +45 -0
  381. package/skills/sprite-animation-2d.aicomponent/manifest.json +28 -0
  382. package/skills/sprite-animation-2d.aicomponent/ref/html5.js +83 -0
  383. package/skills/sprite-animation-2d.aicomponent/ref/phaser.js +38 -0
  384. package/skills/sprite-animation-2d.aicomponent/ref/playcanvas.js +67 -0
  385. package/skills/sprite_entity_renderer.aicomponent/SKILL.md +148 -0
  386. package/skills/sprite_entity_renderer.aicomponent/manifest.json +17 -0
  387. package/skills/sprite_entity_renderer.aicomponent/ref/SpriteEntityRenderer.ts +126 -0
  388. package/skills/success_sfx.aiaudio/SKILL.md +59 -0
  389. package/skills/success_sfx.aiaudio/manifest.json +45 -0
  390. package/skills/success_sfx.aiaudio/ref/success.mp3 +0 -0
  391. package/skills/tap_blast.aigameplay/SKILL.md +116 -0
  392. package/skills/tap_blast.aigameplay/manifest.json +153 -0
  393. package/skills/tap_blast.aigameplay/ref/pgs-schema.json +208 -0
  394. package/skills/tap_blast.aigameplay/ref/reducer.template.ts +202 -0
  395. package/skills/theme_state.aicomponent/SKILL.md +53 -0
  396. package/skills/theme_state.aicomponent/manifest.json +33 -0
  397. package/skills/theme_state.aicomponent/ref/ThemeManager.ts +174 -0
  398. package/skills/theme_switcher_build.aicomponent/SKILL.md +62 -0
  399. package/skills/theme_switcher_build.aicomponent/manifest.json +38 -0
  400. package/skills/theme_switcher_build.aicomponent/ref/theme-index.ts +8 -0
  401. package/skills/theme_variant.aiconfig/SKILL.md +78 -0
  402. package/skills/theme_variant.aiconfig/manifest.json +39 -0
  403. package/skills/theme_variant.aiconfig/ref/ExampleTheme/index.ts +16 -0
  404. package/skills/theme_variant.aiconfig/ref/ExampleTheme/levelEasy.json +141 -0
  405. package/skills/threejs.aicomponent/SKILL.md +422 -0
  406. package/skills/threejs.aicomponent/manifest.json +166 -0
  407. package/skills/threejs.aicomponent/ref/AssetLoader.ts +158 -0
  408. package/skills/threejs.aicomponent/ref/BaseScene.ts +88 -0
  409. package/skills/threejs.aicomponent/ref/GameConfig.ts +47 -0
  410. package/skills/threejs.aicomponent/ref/MainScene.ts +170 -0
  411. package/skills/threejs.aicomponent/ref/PreloaderScene.ts +93 -0
  412. package/skills/threejs.aicomponent/ref/SceneKeys.ts +6 -0
  413. package/skills/threejs.aicomponent/ref/SceneManager.ts +69 -0
  414. package/skills/threejs.aicomponent/ref/ViewportManager.ts +62 -0
  415. package/skills/threejs.aicomponent/ref/globals.d.ts +74 -0
  416. package/skills/threejs.aicomponent/ref/index.css +80 -0
  417. package/skills/threejs.aicomponent/ref/index.html +20 -0
  418. package/skills/threejs.aicomponent/ref/index.ts +117 -0
  419. package/skills/threejs.aicomponent/ref/main.ts +10 -0
  420. package/skills/threejs.aicomponent/ref/package.json +23 -0
  421. package/skills/threejs.aicomponent/ref/tsconfig.json +24 -0
  422. package/skills/threejs.aicomponent/ref/webpack.config.js +61 -0
  423. package/skills/time_clear_goal.aiconfig/SKILL.md +46 -0
  424. package/skills/time_clear_goal.aiconfig/manifest.json +32 -0
  425. package/skills/time_icon.aiimage/SKILL.md +58 -0
  426. package/skills/time_icon.aiimage/manifest.json +47 -0
  427. package/skills/time_icon.aiimage/ref/time.png +0 -0
  428. package/skills/time_icon.aiimage/ref/time.webp +0 -0
  429. package/skills/top_ui_bar.aicomponent/SKILL.md +45 -0
  430. package/skills/top_ui_bar.aicomponent/manifest.json +27 -0
  431. package/skills/top_ui_bar.aicomponent/ref/GameTopUI.ts +229 -0
  432. package/skills/tower_defence.aigameplay/SKILL.md +117 -0
  433. package/skills/tower_defence.aigameplay/manifest.json +175 -0
  434. package/skills/tower_defence.aigameplay/ref/pgs-schema.json +247 -0
  435. package/skills/tower_defence.aigameplay/ref/reducer.template.ts +239 -0
  436. package/skills/tray_container.aicomponent/SKILL.md +143 -0
  437. package/skills/tray_container.aicomponent/manifest.json +58 -0
  438. package/skills/tray_container.aicomponent/ref/TrayRenderer.ts +155 -0
  439. package/skills/tray_container.aicomponent/ref/TrayRenderer3D.ts +281 -0
  440. package/skills/tray_container.aicomponent/ref/TrayRendererHtmlOverlay.ts +228 -0
  441. package/skills/tutorial_overlay.aicomponent/SKILL.md +46 -0
  442. package/skills/tutorial_overlay.aicomponent/manifest.json +34 -0
  443. package/skills/tutorial_overlay.aicomponent/ref/TutorialManager.ts +367 -0
  444. package/skills/tween-animation-2d.aicomponent/SKILL.md +35 -0
  445. package/skills/tween-animation-2d.aicomponent/manifest.json +28 -0
  446. package/skills/tween-animation-2d.aicomponent/ref/phaser.js +49 -0
  447. package/skills/tween-animation-2d.aicomponent/ref/playcanvas.js +36 -0
  448. package/skills/typescript_module_patterns.aicomponent/SKILL.md +209 -0
  449. package/skills/typescript_module_patterns.aicomponent/manifest.json +28 -0
  450. package/skills/typescript_module_patterns.aicomponent/ref/globals.d.ts +31 -0
  451. package/skills/ui-transition.aicomponent/SKILL.md +33 -0
  452. package/skills/ui-transition.aicomponent/manifest.json +19 -0
  453. package/skills/ui-transition.aicomponent/ref/phaser.js +45 -0
  454. package/skills/ux_flow_spec.aiconfig/SKILL.md +82 -0
  455. package/skills/ux_flow_spec.aiconfig/manifest.json +39 -0
  456. package/skills/wave_difficulty.aiconfig/SKILL.md +46 -0
  457. package/skills/wave_difficulty.aiconfig/manifest.json +33 -0
  458. package/skills/webpack_build.aicomponent/SKILL.md +204 -0
  459. package/skills/webpack_build.aicomponent/manifest.json +29 -0
  460. package/skills/webpack_build.aicomponent/ref/package.json +16 -0
  461. package/skills/webpack_build.aicomponent/ref/webpack.config.js +53 -0
  462. package/skills/win_anim_sfx.aiaudio/SKILL.md +59 -0
  463. package/skills/win_anim_sfx.aiaudio/manifest.json +46 -0
  464. package/skills/win_anim_sfx.aiaudio/ref/win_anim.mp3 +0 -0
  465. package/skills/win_dot.aiimage/SKILL.md +58 -0
  466. package/skills/win_dot.aiimage/manifest.json +47 -0
  467. package/skills/win_dot.aiimage/ref/win_dot.png +0 -0
  468. package/skills/win_dot.aiimage/ref/win_dot.webp +0 -0
  469. package/skills/win_result_panel.aiimage/SKILL.md +58 -0
  470. package/skills/win_result_panel.aiimage/manifest.json +47 -0
  471. package/skills/win_result_panel.aiimage/ref/win.png +0 -0
  472. package/skills/win_result_panel.aiimage/ref/win.webp +0 -0
  473. package/skills/word_connect.aigameplay/SKILL.md +86 -0
  474. package/skills/word_connect.aigameplay/manifest.json +154 -0
  475. package/skills/word_connect.aigameplay/ref/pgs-schema.json +212 -0
  476. package/skills/word_connect.aigameplay/ref/reducer.template.ts +186 -0
  477. package/src/index.ts +10 -0
  478. package/src/skills.loader.ts +225 -0
  479. package/src/skills.types.ts +42 -0
@@ -0,0 +1,69 @@
1
+ ---
2
+ name: gameplay_balance_check.aivalidator
3
+ description: 玩法平衡性校验器 - 分析关卡配置和玩法参数,检查难度合理性、可完成性、首关保胜、CTA 时机
4
+ triggers: 平衡性,balance check,校验,validate,难度检查,difficulty check,关卡校验,level check,可完成性
5
+ ---
6
+
7
+ # 玩法平衡性校验器(Gameplay Balance Checker)
8
+
9
+ ## 说明
10
+
11
+ 分析关卡配置和玩法参数,检查试玩广告的平衡性问题。输出结构化校验报告,涵盖:
12
+
13
+ - **可完成性**:是否存在不可能完成的关卡
14
+ - **难度曲线**:曲线是否平滑递进,有无突然跳变
15
+ - **首关保胜**:第一关是否保证玩家成功
16
+ - **CTA 时机**:CTA 触发是否在峰值体验之后
17
+ - **时长预算**:总时长是否在 30-60 秒的试玩广告最佳区间
18
+
19
+ ## Imports
20
+
21
+ (无外部依赖,独立运行)
22
+
23
+ ## 校验维度
24
+
25
+ | 维度 | 检查内容 | 严重级别 |
26
+ |------|---------|---------|
27
+ | 首关保胜 | `firstLevelGuaranteeWin` 是否为 `true`,首关 `difficultyScale` 是否 ≤ 0.3 | ERROR |
28
+ | 不可能关卡 | 是否存在 `difficultyScale` = 1.0 的关卡 | ERROR |
29
+ | 曲线平滑性 | 相邻关卡难度差是否 > 0.5 | WARNING |
30
+ | CTA 时机 | `ctaTriggerAfterLevel` 是否 ≥ `peakDifficultyLevel` | WARNING |
31
+ | 时长预算 | 所有关卡预估总时长是否在 30-60 秒内 | WARNING |
32
+ | 峰值位置 | 峰值是否在总关卡数的 50%-75% 位置 | INFO |
33
+
34
+ ## 报告格式
35
+
36
+ ```markdown
37
+ # 玩法平衡性校验报告
38
+
39
+ ## 总体评级:✅ PASS / ⚠️ WARNING / ❌ FAIL
40
+
41
+ ### 详细结果
42
+ | # | 维度 | 状态 | 说明 |
43
+ |---|------|------|------|
44
+ | 1 | 首关保胜 | ✅ | difficultyScale[0] = 0.2, firstLevelGuaranteeWin = true |
45
+ | 2 | ... | ... | ... |
46
+
47
+ ### 建议
48
+ - ...
49
+ ```
50
+
51
+ ## Skill Definition
52
+
53
+ tools:
54
+ - read
55
+ - write
56
+ - bash
57
+ prompt_extension: |
58
+ You are a gameplay balance validator for playable ads (试玩广告).
59
+ Read game/config.json and all level data files, then check these dimensions:
60
+ 1. First level guarantee: firstLevelGuaranteeWin must be true AND
61
+ difficultyScale[0] must be ≤ 0.3 (trivially easy)
62
+ 2. Smooth difficulty curve: adjacent levels' difficulty difference must not exceed 0.5
63
+ 3. No impossible levels: no level should have difficultyScale = 1.0
64
+ 4. CTA timing: ctaTriggerAfterLevel should be ≥ peakDifficultyLevel
65
+ (CTA fires after peak engagement, not before)
66
+ 5. Duration budget: estimated total playtime across all levels should be 30-60 seconds
67
+ (the sweet spot for playable ad retention)
68
+ Output a structured markdown report with pass/warn/fail status for each dimension.
69
+ Write the report to stdout or a designated output path.
@@ -0,0 +1,21 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "atomId": "gameplay_balance_check.aivalidator",
4
+ "bundleType": "aivalidator",
5
+ "category": "validator",
6
+ "mode": "fixed",
7
+ "label": {
8
+ "zh": "玩法平衡性校验器",
9
+ "en": "Gameplay balance checker"
10
+ },
11
+ "tags": ["validator", "balance", "gameplay", "difficulty", "level", "quality", "playable-ads"],
12
+ "bindingRoles": ["levelValidator"],
13
+ "imports": [],
14
+ "validation": {
15
+ "target": "gameplay",
16
+ "outputFormat": "report"
17
+ },
18
+ "files": {
19
+ "skill": "SKILL.md"
20
+ }
21
+ }
@@ -0,0 +1,89 @@
1
+ ---
2
+ name: gameplay_unit_test.aivalidator
3
+ description: 路径消除玩法的纯逻辑单元测试框架。使用 vitest 测试 LevelParser、碰撞检测、消除规则、胜负条件,不依赖 Phaser 或浏览器。
4
+ triggers: 单元测试,unit test,vitest,测试玩法,测试逻辑,验证消除规则,test gameplay
5
+ ---
6
+
7
+ # 玩法逻辑单元测试(Gameplay Unit Tests)
8
+
9
+ ## 说明
10
+
11
+ 为路径消除玩法的核心逻辑提供**纯函数单元测试**:
12
+
13
+ - 不依赖 Phaser(不需要浏览器或 Canvas)
14
+ - 不依赖 DOM(纯 Node.js 环境运行)
15
+ - 测试覆盖:坐标解析、碰撞检测、消除规则、胜负判定
16
+
17
+ ## Scaffold
18
+
19
+ | 目标路径 | 来源 | 说明 |
20
+ |---------|-----|------|
21
+ | `tests/gameplay.test.ts` | `ref/gameplay.test.ts` | 完整测试用例 |
22
+ | `vitest.config.ts` | `ref/vitest.config.ts` | Vitest 配置 |
23
+
24
+ `package.json` 新增:
25
+ ```json
26
+ {
27
+ "scripts": {
28
+ "test": "vitest run",
29
+ "test:watch": "vitest"
30
+ },
31
+ "devDependencies": {
32
+ "vitest": "^3.0.0"
33
+ }
34
+ }
35
+ ```
36
+
37
+ ## 使用方式
38
+
39
+ ```bash
40
+ pnpm test # 运行所有测试
41
+ pnpm test:watch # 监听模式(修改代码自动重跑)
42
+ ```
43
+
44
+ ## 测试覆盖
45
+
46
+ | 模块 | 测试点 |
47
+ |------|--------|
48
+ | `LevelParser` | Cocos→Phaser 坐标翻转 / 路径离散化 / 方向推导 |
49
+ | 碰撞检测 | `isCellOccupied` 正确性 / `ignorePathIndex` 排除自身 |
50
+ | 消除规则 | 方向无阻挡→成功 / 方向有阻挡→失败 / 已消除不参与碰撞 |
51
+ | 胜负条件 | 全部消除→胜利 / 生命归零→失败 |
52
+ | 数据校验 | 坐标越界检测 / 空路径检测 |
53
+
54
+ ## Recipe
55
+
56
+ | 决策 | 原因 |
57
+ |------|------|
58
+ | **与 Phaser 完全解耦** | 玩法规则(坐标解析、碰撞检测、消除判断)是纯函数,不需要 Canvas 或 DOM;在 Node.js 中运行测试速度快 10 倍以上 |
59
+ | **Vitest 而非 Jest** | 项目使用 ESM 模块,Vitest 原生支持 ESM + TypeScript,无需额外 Babel 配置 |
60
+ | **测试纯函数,不测场景生命周期** | Phaser Scene 的 `create/update` 测试成本高且价值低;核心算法的正确性才是单元测试的目标 |
61
+
62
+ ## Adapter
63
+
64
+ - **Role**: `gameplayTest` — 玩法逻辑纯函数单元测试框架
65
+ - **Provides**: `tests/gameplay.test.ts` 测试套件、`vitest.config.ts` 测试配置、`pnpm test` / `pnpm test:watch` 命令
66
+ - **Requires**: `arrow_path_data_format.aicomponent`(LevelParser、LevelTypes 被测对象)
67
+ - **Consumed by**: Agent 在修改游戏逻辑后执行 `pnpm test` 验证正确性;无上游 skill 依赖
68
+ - **Integration point**: 根目录 `vitest.config.ts` —— `pnpm test` 运行 `tests/` 目录下所有测试文件
69
+
70
+ ## Imports
71
+
72
+ - `arrow_path_data_format.aicomponent`(硬依赖:LevelParser + LevelTypes)
73
+ - `path_elimination_rules.aigameplay`(参考:PGS 测试用例)
74
+ - `level_data_validator.aivalidator`(可选:集成校验测试)
75
+
76
+ ## Skill Definition
77
+
78
+ ```yaml
79
+ tools:
80
+ - read_file
81
+ - write_file
82
+ inputs:
83
+ - source: ref/gameplay.test.ts
84
+ - source: ref/vitest.config.ts
85
+ outputs:
86
+ - testSuite: tests/gameplay.test.ts
87
+ - testConfig: vitest.config.ts
88
+ - testScripts: test / test:watch npm scripts
89
+ ```
@@ -0,0 +1,17 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "atomId": "gameplay_unit_test.aivalidator",
4
+ "bundleType": "aivalidator",
5
+ "category": "validator",
6
+ "mode": "fixed",
7
+ "label": {
8
+ "zh": "玩法逻辑单元测试",
9
+ "en": "Gameplay logic unit tests"
10
+ },
11
+ "tags": ["test", "unit-test", "vitest", "gameplay", "quality", "validation"],
12
+ "bindingRoles": ["testFramework"],
13
+ "files": {
14
+ "skill": "SKILL.md",
15
+ "ref": ["ref/gameplay.test.ts", "ref/vitest.config.ts"]
16
+ }
17
+ }
@@ -0,0 +1,202 @@
1
+ import { describe, test, expect } from "vitest";
2
+ import { parseLevelJson } from "../src/game/levels/LevelParser";
3
+ import { ArrowDirection } from "../src/game/levels/LevelTypes";
4
+ import type { RawLevelJson, ParsedLevel } from "../src/game/levels/LevelTypes";
5
+
6
+ // ─── 测试数据 ────────────────────────────────────
7
+
8
+ const simpleLevelRaw: RawLevelJson = {
9
+ name: 1,
10
+ row: 4,
11
+ col: 4,
12
+ arrows: [
13
+ [[0, 2], [1, 2], [2, 2]], // 水平路径,箭头朝右
14
+ [[3, 1], [2, 1], [1, 1]], // 水平路径,箭头朝左
15
+ ],
16
+ levelTime: 0,
17
+ };
18
+
19
+ const blockedLevelRaw: RawLevelJson = {
20
+ name: 2,
21
+ row: 5,
22
+ col: 5,
23
+ arrows: [
24
+ [[0, 2], [1, 2], [2, 2]], // 朝右
25
+ [[3, 2], [3, 3], [3, 4]], // 在右边挡住第一条路径
26
+ ],
27
+ levelTime: 60,
28
+ };
29
+
30
+ // ─── LevelParser 测试 ────────────────────────────
31
+
32
+ describe("LevelParser", () => {
33
+ test("解析基础关卡结构", () => {
34
+ const level = parseLevelJson(simpleLevelRaw);
35
+ expect(level.index).toBe(1);
36
+ expect(level.rows).toBe(4);
37
+ expect(level.cols).toBe(4);
38
+ expect(level.paths.length).toBe(2);
39
+ expect(level.timeSeconds).toBe(0);
40
+ });
41
+
42
+ test("Cocos → Phaser 坐标翻转 (y 轴反转)", () => {
43
+ const level = parseLevelJson(simpleLevelRaw);
44
+ // Cocos y=2 在 4 行棋盘中 → Phaser y = 4-1-2 = 1
45
+ const firstPath = level.paths[0];
46
+ expect(firstPath.points[0].y).toBe(1); // rows-1-cocosY = 4-1-2 = 1
47
+ });
48
+
49
+ test("路径方向由最后两点推导", () => {
50
+ const level = parseLevelJson(simpleLevelRaw);
51
+ // 第一条路径:[0,2] → [1,2] → [2,2],最后两点 x 递增 → right
52
+ expect(level.paths[0].direction).toBe(ArrowDirection.Right);
53
+ // 第二条路径:[3,1] → [2,1] → [1,1],最后两点 x 递减 → left
54
+ expect(level.paths[1].direction).toBe(ArrowDirection.Left);
55
+ });
56
+
57
+ test("head 为路径最后一个点", () => {
58
+ const level = parseLevelJson(simpleLevelRaw);
59
+ expect(level.paths[0].head).toEqual({ x: 2, y: 1 }); // Phaser 坐标
60
+ });
61
+
62
+ test("indices 包含路径覆盖的所有格子", () => {
63
+ const level = parseLevelJson(simpleLevelRaw);
64
+ const path0 = level.paths[0];
65
+ // 水平路径 x: 0→1→2, y: 1 (Phaser), cols=4
66
+ // indices: 1*4+0=4, 1*4+1=5, 1*4+2=6
67
+ expect(path0.indices).toContain(4);
68
+ expect(path0.indices).toContain(5);
69
+ expect(path0.indices).toContain(6);
70
+ expect(path0.indices.length).toBe(3);
71
+ });
72
+
73
+ test("带时间限制的关卡", () => {
74
+ const level = parseLevelJson(blockedLevelRaw);
75
+ expect(level.timeSeconds).toBe(60);
76
+ });
77
+ });
78
+
79
+ // ─── 碰撞检测测试 ──────────────────────────────────
80
+
81
+ describe("碰撞检测", () => {
82
+ function isCellOccupied(
83
+ level: ParsedLevel,
84
+ col: number,
85
+ row: number,
86
+ removedPaths: Set<number>,
87
+ ignorePathIndex?: number,
88
+ ): boolean {
89
+ const idx = row * level.cols + col;
90
+ return level.paths.some((p, i) => {
91
+ if (removedPaths.has(i)) return false;
92
+ if (ignorePathIndex !== undefined && i === ignorePathIndex) return false;
93
+ return p.indices.includes(idx);
94
+ });
95
+ }
96
+
97
+ test("路径覆盖的格子返回 occupied", () => {
98
+ const level = parseLevelJson(simpleLevelRaw);
99
+ const removed = new Set<number>();
100
+ // 第一条路径覆盖 (0,1), (1,1), (2,1)
101
+ expect(isCellOccupied(level, 0, 1, removed)).toBe(true);
102
+ expect(isCellOccupied(level, 1, 1, removed)).toBe(true);
103
+ });
104
+
105
+ test("空格子返回 not occupied", () => {
106
+ const level = parseLevelJson(simpleLevelRaw);
107
+ const removed = new Set<number>();
108
+ expect(isCellOccupied(level, 3, 3, removed)).toBe(false);
109
+ });
110
+
111
+ test("已消除路径不参与碰撞", () => {
112
+ const level = parseLevelJson(simpleLevelRaw);
113
+ const removed = new Set<number>([0]); // 第一条路径已消除
114
+ expect(isCellOccupied(level, 0, 1, removed)).toBe(false);
115
+ });
116
+
117
+ test("ignorePathIndex 排除自身", () => {
118
+ const level = parseLevelJson(simpleLevelRaw);
119
+ const removed = new Set<number>();
120
+ // 格子 (0,1) 被路径0占据,但 ignore 路径0 → 返回 false
121
+ expect(isCellOccupied(level, 0, 1, removed, 0)).toBe(false);
122
+ });
123
+ });
124
+
125
+ // ─── 消除规则测试 ──────────────────────────────────
126
+
127
+ describe("消除规则", () => {
128
+ function canEliminate(
129
+ level: ParsedLevel,
130
+ pathIndex: number,
131
+ removedPaths: Set<number>,
132
+ ): boolean {
133
+ const path = level.paths[pathIndex];
134
+ const dx = path.direction === "right" ? 1 : path.direction === "left" ? -1 : 0;
135
+ const dy = path.direction === "down" ? 1 : path.direction === "up" ? -1 : 0;
136
+
137
+ let x = path.head.x;
138
+ let y = path.head.y;
139
+ const maxSteps = Math.max(level.cols, level.rows) + 1;
140
+
141
+ for (let step = 0; step < maxSteps; step++) {
142
+ x += dx;
143
+ y += dy;
144
+ if (x < 0 || y < 0 || x >= level.cols || y >= level.rows) {
145
+ return true; // 到达边界,可消除
146
+ }
147
+ const idx = y * level.cols + x;
148
+ const blocked = level.paths.some((p, i) => {
149
+ if (removedPaths.has(i) || i === pathIndex) return false;
150
+ return p.indices.includes(idx);
151
+ });
152
+ if (blocked) return false;
153
+ }
154
+ return false;
155
+ }
156
+
157
+ test("方向无阻挡 → 可消除", () => {
158
+ const level = parseLevelJson(simpleLevelRaw);
159
+ const removed = new Set<number>();
160
+ // 第一条路径朝右 head=(2,1),右边 (3,1) 无路径 → 可消除
161
+ expect(canEliminate(level, 0, removed)).toBe(true);
162
+ });
163
+
164
+ test("方向有阻挡 → 不可消除", () => {
165
+ const level = parseLevelJson(blockedLevelRaw);
166
+ const removed = new Set<number>();
167
+ // 第一条路径朝右,但 col=3 有第二条路径占据 → 不可消除
168
+ expect(canEliminate(level, 0, removed)).toBe(false);
169
+ });
170
+
171
+ test("消除阻挡路径后 → 原路径可消除", () => {
172
+ const level = parseLevelJson(blockedLevelRaw);
173
+ const removed = new Set<number>([1]); // 移除阻挡的第二条路径
174
+ expect(canEliminate(level, 0, removed)).toBe(true);
175
+ });
176
+ });
177
+
178
+ // ─── 胜负条件测试 ──────────────────────────────────
179
+
180
+ describe("胜负条件", () => {
181
+ test("所有路径消除 → 胜利", () => {
182
+ const level = parseLevelJson(simpleLevelRaw);
183
+ const removed = new Set<number>([0, 1]);
184
+ const isWin = removed.size >= level.paths.length;
185
+ expect(isWin).toBe(true);
186
+ });
187
+
188
+ test("部分路径消除 → 未胜利", () => {
189
+ const level = parseLevelJson(simpleLevelRaw);
190
+ const removed = new Set<number>([0]);
191
+ const isWin = removed.size >= level.paths.length;
192
+ expect(isWin).toBe(false);
193
+ });
194
+
195
+ test("生命归零 → 失败", () => {
196
+ let lives = 3;
197
+ lives--; // 第一次扣命
198
+ lives--; // 第二次扣命
199
+ lives--; // 第三次扣命
200
+ expect(lives <= 0).toBe(true);
201
+ });
202
+ });
@@ -0,0 +1,13 @@
1
+ import { defineConfig } from "vitest/config";
2
+ import path from "path";
3
+
4
+ export default defineConfig({
5
+ test: {
6
+ globals: true,
7
+ },
8
+ resolve: {
9
+ alias: {
10
+ assets: path.resolve(__dirname, "assets"),
11
+ },
12
+ },
13
+ });
@@ -0,0 +1,85 @@
1
+ ---
2
+ name: grid_board_layout.aicomponent
3
+ description: 格子棋盘布局计算器。根据关卡的行列数和屏幕尺寸计算最优格子大小、棋盘位置和缩放/拖拽边界约束。
4
+ triggers: 需要在屏幕上布局可变尺寸的格子棋盘、计算格子坐标或实现棋盘缩放/拖拽时触发。
5
+ ---
6
+
7
+ # 格子棋盘布局(Grid Board Layout)
8
+
9
+ ## 说明
10
+
11
+ **布局系数**:棋盘可用区域、cell 尺寸与边距须与 **`responsive_2d_layout.aicomponent` 第一节(Layout Canon)** 一致——使用同一套 \(W_r, H_r\)、**uiScale / vScale**,不得在棋盘模块内单独发明一套缩放比。
12
+
13
+ **纵向扣减**:顶栏 / 底栏预留高度与 **`playable_hud_layout.aicomponent`** 合同一致(`H_mid = H_r - H_top - H_bottom`)。
14
+
15
+ **职责边界**:本 skill 只做「在已给定可用矩形内的格子几何」;顶栏/底栏预留高度若来自设计稿 dp,通过 **vScale**(或 Canon 规定的等价方式)换算,与全局 UI 对齐。
16
+
17
+ `BoardLayout` 负责将 `rows × cols` 的棋盘正确布局在屏幕内:
18
+
19
+ - 根据屏幕可用高度(减去 UI 条)和 `rows × cols` 计算最优 `cellSize`
20
+ - 应用 `CELL_SPACING_MULTIPLIER`(默认 1.15)放大格子间距,提升点击体验
21
+ - 计算 `boardOffsetX / boardOffsetY`(棋盘左上角坐标)
22
+ - 计算缩放/拖拽的边界约束(`minZoom / maxZoom / panBounds`)
23
+
24
+ ## Scaffold
25
+
26
+ | 目标路径 | 来源 | 说明 |
27
+ |---------|-----|-----|
28
+ | `src/game/scenes/GameUI/BoardLayout.ts` | `ref/BoardLayout.ts` | 棋盘布局计算 |
29
+
30
+ ## Imports
31
+
32
+ - `phaser.aicomponent`(硬依赖)
33
+ - `responsive_2d_layout.aicomponent`(硬依赖:屏幕尺寸参数)
34
+
35
+ ## Skill Definition
36
+
37
+ ```yaml
38
+ tools:
39
+ - read_file
40
+ - write_file
41
+ inputs:
42
+ - source: src/game/scenes/GameUI/BoardLayout.ts
43
+ outputs:
44
+ - boardLayout: computeBoardLayout() + BoardLayout module
45
+ ```
46
+
47
+ ## Recipe
48
+
49
+ | 决策 | 原因 |
50
+ |------|------|
51
+ | **纯计算,无渲染** | `computeBoardLayout()` 是纯函数,输入为行列数+屏幕尺寸,输出为几何参数;渲染器(PathRenderer/InputHandler)依赖此数据,反向依赖会造成循环 |
52
+ | **遵从 Layout Canon** | cellSize 和偏移量必须使用 `uiScale/vScale` 换算,不得另起一套缩放;保证棋盘与 UI 坐标系一致 |
53
+ | **CELL_SPACING_MULTIPLIER 放大格子间距** | 实际格子稍小于 cellSize,留出视觉间距和点击余量;1.15 是试玩广告实践中手感较好的值 |
54
+
55
+ ## Adapter
56
+
57
+ - **Role**: `gridBoardLayout` — 可变尺寸格子棋盘的几何布局计算器
58
+ - **Provides**: `computeBoardLayout()` 函数、`BoardLayout` 类型(cellSize、boardOffsetX/Y、minZoom、maxZoom、panBounds)
59
+ - **Requires**: `phaser.aicomponent`、`responsive_2d_layout.aicomponent`(屏幕尺寸参数,确保坐标系一致)
60
+ - **Consumed by**: `game_scene.aicomponent`(初始化棋盘几何)、`path_renderer.aicomponent`(格子像素坐标)、`path_input_handler.aicomponent`(命中检测)、`debug_overlay.aicomponent`(格子坐标可视化)
61
+ - **Integration point**: `src/game/scenes/GameUI/BoardLayout.ts` → `Game.ts` 在 `create()` 中调用 `computeBoardLayout()` 并缓存结果
62
+
63
+ ## 使用示例
64
+
65
+ ```typescript
66
+ const layout = computeBoardLayout({
67
+ rows: level.rows,
68
+ cols: level.cols,
69
+ screenWidth: width,
70
+ screenHeight: height,
71
+ topUIHeight: GAME_TOP_UI_BAR_HEIGHT,
72
+ });
73
+
74
+ this.cellSize = layout.cellSize;
75
+ this.boardOffsetX = layout.boardOffsetX;
76
+ this.boardOffsetY = layout.boardOffsetY;
77
+
78
+ // 格子中心坐标
79
+ cellCenter(col: number, row: number) {
80
+ return {
81
+ x: this.boardOffsetX + col * this.cellWidth + this.cellWidth / 2,
82
+ y: this.boardOffsetY + row * this.cellHeight + this.cellHeight / 2,
83
+ };
84
+ }
85
+ ```
@@ -0,0 +1,69 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "atomId": "grid_board_layout.aicomponent",
4
+ "bundleType": "aicomponent",
5
+ "category": "layout",
6
+ "mode": "fixed",
7
+ "label": { "zh": "格子棋盘布局", "en": "Grid board layout" },
8
+ "tags": ["layout", "grid", "board", "cell-size", "zoom", "pan", "drag-bounds", "threejs", "3d", "xz-plane"],
9
+ "bindingRoles": ["gridBoardLayout"],
10
+ "renderBackend": ["phaser", "threejs"],
11
+ "engineVariants": {
12
+ "phaser": {
13
+ "imports": ["phaser.aicomponent", "responsive_2d_layout.aicomponent"],
14
+ "scaffoldFiles": {
15
+ "src/game/scenes/GameUI/BoardLayout.ts": { "source": "ref/BoardLayout.ts", "mode": "full", "weight": 10 }
16
+ }
17
+ },
18
+ "threejs": {
19
+ "imports": ["threejs.aicomponent"],
20
+ "scaffoldFiles": {
21
+ "src/game/utils/BoardLayout3D.ts": { "source": "ref/BoardLayout3D.ts", "mode": "full", "weight": 10 },
22
+ "src/game/rendering/BoardRenderer3D.ts": { "source": "ref/BoardRenderer3D.ts", "mode": "full", "weight": 10 }
23
+ }
24
+ }
25
+ },
26
+ "sharedFiles": {
27
+ "src/game/utils/BoardLayoutMath.ts": { "source": "ref/BoardLayoutMath.ts", "mode": "full", "weight": 10 }
28
+ },
29
+ "scaffold": {
30
+ "files": {
31
+ "src/game/scenes/GameUI/BoardLayout.ts": {
32
+ "source": "ref/BoardLayout.ts",
33
+ "mode": "full",
34
+ "weight": 10
35
+ }
36
+ }
37
+ },
38
+ "imports": [
39
+ { "slot": "engine", "pinAtomId": "phaser.aicomponent", "edgeKind": "requires", "bindAs": "engine" },
40
+ { "slot": "responsiveLayout","pinAtomId": "responsive_2d_layout.aicomponent", "edgeKind": "requires", "bindAs": "layout" }
41
+ ],
42
+ "exports": [
43
+ { "name": "BoardLayout", "kind": "module", "location": "src/game/scenes/GameUI/BoardLayout.ts" },
44
+ { "name": "computeBoardLayout", "kind": "function", "location": "src/game/scenes/GameUI/BoardLayout.ts" },
45
+ { "name": "BoardLayout3D", "kind": "class", "location": "src/game/utils/BoardLayout3D.ts" },
46
+ { "name": "BoardRenderer3D", "kind": "class", "location": "src/game/rendering/BoardRenderer3D.ts" },
47
+ { "name": "BoardLayoutMath", "kind": "module", "location": "src/game/utils/BoardLayoutMath.ts" }
48
+ ],
49
+ "neutralDescriptor": {
50
+ "geometry": "dynamic cell-size calculator for a variable-size grid that fits within screen bounds or 3D camera frustum, with configurable margins and spacing",
51
+ "layers": ["grid-math", "zoom-constraint", "pan-constraint", "3d-xz-layout"],
52
+ "replaceable": ["margin ratio", "scale factor", "cell spacing multiplier", "zoom range", "coordinate system"]
53
+ },
54
+ "usageHints": [
55
+ "computeBoardLayout() 根据 rows×cols 和可用空间计算最优格子大小和棋盘偏移(纯数学,引擎无关)",
56
+ "BoardLayout3D 在 Three.js XZ 平面布局棋盘,getCellWorldPos(col, row) 返回世界坐标",
57
+ "3D 模式以原点为棋盘中心,cellSize 默认 1.0 世界单位",
58
+ "BOARD_MARGIN_RATIO 控制棋盘与屏幕边缘的留白比例(默认 0.07)",
59
+ "CELL_SPACING_MULTIPLIER 放大格子尺寸但保持路径线宽不变,提升点击体验",
60
+ "返回 cellSize / cellWidth / cellHeight / boardOffsetX / boardOffsetY"
61
+ ],
62
+ "files": {
63
+ "skill": "SKILL.md",
64
+ "boardLayout": "ref/BoardLayout.ts",
65
+ "boardLayout3D": "ref/BoardLayout3D.ts",
66
+ "boardRenderer3D": "ref/BoardRenderer3D.ts",
67
+ "boardLayoutMath": "ref/BoardLayoutMath.ts"
68
+ }
69
+ }