@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,357 @@
1
+ import * as THREE from "three";
2
+
3
+ /**
4
+ * 程序化 3D 卡通赛车工厂
5
+ *
6
+ * 使用多个基础几何体组装出精致的 Low-Poly 风格赛车模型:
7
+ * - 车身:圆润 BoxGeometry(边缘 round 处理)+ 车漆材质
8
+ * - 引擎盖:前部凸起
9
+ * - 座舱:深色框架 + 半透明蓝色挡风玻璃
10
+ * - 4 轮子:黑色轮胎 Cylinder + 银色金属轮毂
11
+ * - 前大灯:白色球体 emissive
12
+ * - 尾灯:红色方块 emissive
13
+ * - 后扰流板:赛车尾翼 + 支撑柱
14
+ * - 地面软阴影
15
+ *
16
+ * 多色变体策略:传入不同 color hex,共享几何体缓存,独立材质实例。
17
+ *
18
+ * 朝向约定:模型默认车头朝 -Z(即 "up" 方向对应 rotationY = 0)。
19
+ */
20
+
21
+ export interface CarStyle {
22
+ /** 车身比例 (相对于 cellSize * scale) */
23
+ bodyRatio?: { w: number; h: number; l: number };
24
+ /** 轮子半径倍率 */
25
+ wheelRadius?: number;
26
+ /** 是否有尾翼 */
27
+ hasSpoiler?: boolean;
28
+ /** 是否有车灯 */
29
+ hasLights?: boolean;
30
+ }
31
+
32
+ const DEFAULT_STYLE: Required<CarStyle> = {
33
+ bodyRatio: { w: 0.42, h: 0.15, l: 0.72 },
34
+ wheelRadius: 0.08,
35
+ hasSpoiler: true,
36
+ hasLights: true,
37
+ };
38
+
39
+ /**
40
+ * 方向 → Y 轴旋转角度映射。
41
+ * 模型默认车头朝 -Z (ArrowDirection.Up = 0)。
42
+ */
43
+ export function directionToRotationY(direction: string): number {
44
+ switch (direction) {
45
+ case "up": return 0;
46
+ case "right": return -Math.PI / 2;
47
+ case "down": return Math.PI;
48
+ case "left": return Math.PI / 2;
49
+ default: return 0;
50
+ }
51
+ }
52
+
53
+ export class ProceduralCar {
54
+ // 共享几何体缓存
55
+ private static wheelGeo: THREE.CylinderGeometry | null = null;
56
+ private static rimGeo: THREE.CylinderGeometry | null = null;
57
+ private static headlightGeo: THREE.SphereGeometry | null = null;
58
+ private static taillightGeo: THREE.BoxGeometry | null = null;
59
+ private static spoilerGeo: THREE.BoxGeometry | null = null;
60
+ private static spoilerPostGeo: THREE.CylinderGeometry | null = null;
61
+
62
+ /**
63
+ * 创建一辆 3D 卡通赛车。
64
+ * @param color 车身颜色 (hex number, 如 0xe74c3c)
65
+ * @param direction 朝向 ("up"|"down"|"left"|"right"),默认 "up"
66
+ * @param scale 整体缩放基准(对应 cellSize * carScale),默认 0.7
67
+ * @param style 可选风格覆盖
68
+ */
69
+ static create(
70
+ color: number,
71
+ direction: string = "up",
72
+ scale: number = 0.7,
73
+ style?: CarStyle,
74
+ ): THREE.Group {
75
+ const cfg = { ...DEFAULT_STYLE, ...style };
76
+ const group = new THREE.Group();
77
+ const s = scale;
78
+
79
+ const bodyW = s * cfg.bodyRatio.w;
80
+ const bodyH = s * cfg.bodyRatio.h;
81
+ const bodyL = s * cfg.bodyRatio.l;
82
+
83
+ const baseColor = new THREE.Color(color);
84
+ const darkColor = baseColor.clone().multiplyScalar(0.6);
85
+ const lightColor = baseColor.clone().lerp(new THREE.Color(0xffffff), 0.3);
86
+
87
+ // ─── 车身 ───
88
+ const body = this.createBody(bodyW, bodyH, bodyL, baseColor);
89
+ body.position.y = bodyH / 2 + s * 0.08;
90
+ group.add(body);
91
+
92
+ // ─── 引擎盖 ───
93
+ const hoodGeo = new THREE.BoxGeometry(bodyW * 0.7, bodyH * 0.3, bodyL * 0.2);
94
+ const hoodMat = new THREE.MeshStandardMaterial({ color: lightColor, roughness: 0.3, metalness: 0.2 });
95
+ const hood = new THREE.Mesh(hoodGeo, hoodMat);
96
+ hood.position.set(0, bodyH + s * 0.08, -bodyL * 0.28);
97
+ hood.castShadow = true;
98
+ group.add(hood);
99
+
100
+ // ─── 座舱 ───
101
+ const cabinW = bodyW * 0.75;
102
+ const cabinH = bodyH * 0.7;
103
+ const cabinL = bodyL * 0.35;
104
+ const cabin = this.createCabin(cabinW, cabinH, cabinL, darkColor);
105
+ cabin.position.set(0, bodyH + cabinH / 2 + s * 0.08, bodyL * 0.05);
106
+ group.add(cabin);
107
+
108
+ // ─── 4 轮子 ───
109
+ const wheelR = s * cfg.wheelRadius;
110
+ const wheelW = s * 0.05;
111
+ const wheelOffsetX = bodyW / 2 + wheelW * 0.3;
112
+ const wheelY = wheelR;
113
+ const wheelFrontZ = -bodyL * 0.3;
114
+ const wheelRearZ = bodyL * 0.28;
115
+
116
+ const positions: [number, number, number][] = [
117
+ [-wheelOffsetX, wheelY, wheelFrontZ],
118
+ [wheelOffsetX, wheelY, wheelFrontZ],
119
+ [-wheelOffsetX, wheelY, wheelRearZ],
120
+ [wheelOffsetX, wheelY, wheelRearZ],
121
+ ];
122
+ for (const [wx, wy, wz] of positions) {
123
+ const wheel = this.createWheel(wheelR, wheelW);
124
+ wheel.position.set(wx, wy, wz);
125
+ group.add(wheel);
126
+ }
127
+
128
+ // ─── 车灯 ───
129
+ if (cfg.hasLights) {
130
+ const hlR = s * 0.035;
131
+ const hlZ = -bodyL / 2 - hlR * 0.3;
132
+ const hlY = bodyH * 0.7 + s * 0.08;
133
+
134
+ const hlMat = new THREE.MeshStandardMaterial({
135
+ color: 0xffffee, emissive: 0xffffaa, emissiveIntensity: 0.6,
136
+ roughness: 0.1, metalness: 0.3,
137
+ });
138
+ const hlGeo = this.getHeadlightGeo(hlR);
139
+
140
+ const hlL = new THREE.Mesh(hlGeo, hlMat);
141
+ hlL.position.set(-bodyW * 0.3, hlY, hlZ);
142
+ group.add(hlL);
143
+
144
+ const hlRight = new THREE.Mesh(hlGeo, hlMat.clone());
145
+ hlRight.position.set(bodyW * 0.3, hlY, hlZ);
146
+ group.add(hlRight);
147
+
148
+ // 尾灯
149
+ const tlGeo = this.getTaillightGeo(s);
150
+ const tlMat = new THREE.MeshStandardMaterial({
151
+ color: 0xff2200, emissive: 0xff0000, emissiveIntensity: 0.4, roughness: 0.2,
152
+ });
153
+ const tlL = new THREE.Mesh(tlGeo, tlMat);
154
+ tlL.position.set(-bodyW * 0.3, hlY * 0.9, bodyL / 2);
155
+ group.add(tlL);
156
+
157
+ const tlR = new THREE.Mesh(tlGeo, tlMat.clone());
158
+ tlR.position.set(bodyW * 0.3, hlY * 0.9, bodyL / 2);
159
+ group.add(tlR);
160
+ }
161
+
162
+ // ─── 尾翼 ───
163
+ if (cfg.hasSpoiler) {
164
+ const spoiler = this.createSpoiler(s, darkColor);
165
+ spoiler.position.set(0, bodyH + cabinH * 0.4 + s * 0.08, bodyL * 0.38);
166
+ group.add(spoiler);
167
+ }
168
+
169
+ // ─── 地面阴影 ───
170
+ const shadowGeo = new THREE.PlaneGeometry(bodyW * 1.2, bodyL * 1.1);
171
+ const shadowMat = new THREE.MeshBasicMaterial({
172
+ color: 0x000000, transparent: true, opacity: 0.2, depthWrite: false,
173
+ });
174
+ const shadow = new THREE.Mesh(shadowGeo, shadowMat);
175
+ shadow.rotation.x = -Math.PI / 2;
176
+ shadow.position.y = 0.003;
177
+ group.add(shadow);
178
+
179
+ // ─── 方向旋转 ───
180
+ group.rotation.y = directionToRotationY(direction);
181
+ group.userData = { type: "car", color };
182
+
183
+ return group;
184
+ }
185
+
186
+ /**
187
+ * 设置阻挡红光效果
188
+ */
189
+ static setBlocked(car: THREE.Group, blocked: boolean): void {
190
+ car.traverse((child) => {
191
+ if (child instanceof THREE.Mesh) {
192
+ const mats = Array.isArray(child.material) ? child.material : [child.material];
193
+ for (const mat of mats) {
194
+ if (mat instanceof THREE.MeshStandardMaterial) {
195
+ if (blocked) {
196
+ mat.emissive.setHex(0xff0000);
197
+ mat.emissiveIntensity = 0.6;
198
+ } else {
199
+ mat.emissive.setHex(0x000000);
200
+ mat.emissiveIntensity = 0;
201
+ }
202
+ }
203
+ }
204
+ }
205
+ });
206
+ }
207
+
208
+ /**
209
+ * 释放缓存的几何体
210
+ */
211
+ static dispose(): void {
212
+ this.wheelGeo?.dispose(); this.wheelGeo = null;
213
+ this.rimGeo?.dispose(); this.rimGeo = null;
214
+ this.headlightGeo?.dispose(); this.headlightGeo = null;
215
+ this.taillightGeo?.dispose(); this.taillightGeo = null;
216
+ this.spoilerGeo?.dispose(); this.spoilerGeo = null;
217
+ this.spoilerPostGeo?.dispose(); this.spoilerPostGeo = null;
218
+ }
219
+
220
+ // ─── 部件构建 ───
221
+
222
+ private static createBody(w: number, h: number, l: number, color: THREE.Color): THREE.Mesh {
223
+ const geo = new THREE.BoxGeometry(w, h, l, 2, 1, 3);
224
+ this.roundEdges(geo, Math.min(w, h, l) * 0.12);
225
+ const mat = new THREE.MeshStandardMaterial({ color, roughness: 0.3, metalness: 0.25 });
226
+ const mesh = new THREE.Mesh(geo, mat);
227
+ mesh.castShadow = true;
228
+ mesh.receiveShadow = true;
229
+ return mesh;
230
+ }
231
+
232
+ private static createCabin(w: number, h: number, l: number, color: THREE.Color): THREE.Group {
233
+ const g = new THREE.Group();
234
+
235
+ const frameGeo = new THREE.BoxGeometry(w, h, l);
236
+ const frameMat = new THREE.MeshStandardMaterial({ color, roughness: 0.4, metalness: 0.2 });
237
+ const frame = new THREE.Mesh(frameGeo, frameMat);
238
+ frame.castShadow = true;
239
+ g.add(frame);
240
+
241
+ const glassMat = new THREE.MeshStandardMaterial({
242
+ color: 0x88ccff, roughness: 0.05, metalness: 0.3, transparent: true, opacity: 0.6,
243
+ });
244
+ const glassGeo = new THREE.PlaneGeometry(w * 0.85, h * 0.8);
245
+
246
+ const front = new THREE.Mesh(glassGeo, glassMat);
247
+ front.position.set(0, 0, -l / 2 - 0.001);
248
+ front.rotation.x = -0.1;
249
+ g.add(front);
250
+
251
+ const rear = new THREE.Mesh(glassGeo, glassMat.clone());
252
+ rear.position.set(0, 0, l / 2 + 0.001);
253
+ rear.rotation.y = Math.PI;
254
+ g.add(rear);
255
+
256
+ return g;
257
+ }
258
+
259
+ private static createWheel(radius: number, width: number): THREE.Group {
260
+ const g = new THREE.Group();
261
+
262
+ const tireGeo = this.getWheelGeo(radius, width);
263
+ const tireMat = new THREE.MeshStandardMaterial({ color: 0x222222, roughness: 0.9, metalness: 0 });
264
+ const tire = new THREE.Mesh(tireGeo, tireMat);
265
+ tire.rotation.z = Math.PI / 2;
266
+ tire.castShadow = true;
267
+ g.add(tire);
268
+
269
+ const rimGeo = this.getRimGeo(radius * 0.6, width * 0.3);
270
+ const rimMat = new THREE.MeshStandardMaterial({ color: 0xcccccc, roughness: 0.15, metalness: 0.8 });
271
+ const rim = new THREE.Mesh(rimGeo, rimMat);
272
+ rim.rotation.z = Math.PI / 2;
273
+ g.add(rim);
274
+
275
+ return g;
276
+ }
277
+
278
+ private static createSpoiler(s: number, color: THREE.Color): THREE.Group {
279
+ const g = new THREE.Group();
280
+
281
+ const wingGeo = this.getSpoilerGeo(s);
282
+ const wingMat = new THREE.MeshStandardMaterial({ color, roughness: 0.3, metalness: 0.2 });
283
+ const wing = new THREE.Mesh(wingGeo, wingMat);
284
+ wing.castShadow = true;
285
+ g.add(wing);
286
+
287
+ const postGeo = this.getSpoilerPostGeo(s);
288
+ const postMat = new THREE.MeshStandardMaterial({ color: 0x444444, roughness: 0.4, metalness: 0.5 });
289
+ const pL = new THREE.Mesh(postGeo, postMat);
290
+ pL.position.set(-s * 0.12, -s * 0.04, 0);
291
+ g.add(pL);
292
+
293
+ const pR = new THREE.Mesh(postGeo, postMat.clone());
294
+ pR.position.set(s * 0.12, -s * 0.04, 0);
295
+ g.add(pR);
296
+
297
+ return g;
298
+ }
299
+
300
+ // ─── 边缘圆角 ───
301
+
302
+ private static roundEdges(geo: THREE.BoxGeometry, radius: number): void {
303
+ const pos = geo.attributes.position;
304
+ const params = geo.parameters;
305
+ const halfW = (params.width ?? 1) / 2;
306
+ const halfH = (params.height ?? 1) / 2;
307
+ const halfD = (params.depth ?? 1) / 2;
308
+
309
+ for (let i = 0; i < pos.count; i++) {
310
+ let x = pos.getX(i);
311
+ let y = pos.getY(i);
312
+ let z = pos.getZ(i);
313
+
314
+ const fx = Math.abs(x) / halfW;
315
+ const fy = Math.abs(y) / halfH;
316
+ const fz = Math.abs(z) / halfD;
317
+ const cornerness = fx * fy + fy * fz + fx * fz;
318
+
319
+ if (cornerness > 1.5) {
320
+ const shrink = 1 - radius * 0.5 * (cornerness - 1.5);
321
+ x *= shrink;
322
+ y *= shrink;
323
+ z *= shrink;
324
+ pos.setXYZ(i, x, y, z);
325
+ }
326
+ }
327
+ pos.needsUpdate = true;
328
+ geo.computeVertexNormals();
329
+ }
330
+
331
+ // ─── 几何体缓存 ───
332
+
333
+ private static getWheelGeo(r: number, w: number): THREE.CylinderGeometry {
334
+ if (!this.wheelGeo) this.wheelGeo = new THREE.CylinderGeometry(r, r, w, 12);
335
+ return this.wheelGeo;
336
+ }
337
+ private static getRimGeo(r: number, w: number): THREE.CylinderGeometry {
338
+ if (!this.rimGeo) this.rimGeo = new THREE.CylinderGeometry(r, r, w, 8);
339
+ return this.rimGeo;
340
+ }
341
+ private static getHeadlightGeo(r: number): THREE.SphereGeometry {
342
+ if (!this.headlightGeo) this.headlightGeo = new THREE.SphereGeometry(r, 8, 6);
343
+ return this.headlightGeo;
344
+ }
345
+ private static getTaillightGeo(s: number): THREE.BoxGeometry {
346
+ if (!this.taillightGeo) this.taillightGeo = new THREE.BoxGeometry(s * 0.06, s * 0.03, s * 0.02);
347
+ return this.taillightGeo;
348
+ }
349
+ private static getSpoilerGeo(s: number): THREE.BoxGeometry {
350
+ if (!this.spoilerGeo) this.spoilerGeo = new THREE.BoxGeometry(s * 0.38, s * 0.02, s * 0.06);
351
+ return this.spoilerGeo;
352
+ }
353
+ private static getSpoilerPostGeo(s: number): THREE.CylinderGeometry {
354
+ if (!this.spoilerPostGeo) this.spoilerPostGeo = new THREE.CylinderGeometry(s * 0.012, s * 0.012, s * 0.08, 6);
355
+ return this.spoilerPostGeo;
356
+ }
357
+ }
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: bottom_ui_bar.aicomponent
3
+ description: 底部 UI 条 Phaser 占位容器,导出 GAME_BOTTOM_UI_BAR_HEIGHT(与 GameConfig 同源)并与棋盘可用高度扣减对齐。布局合同见 playable_hud_layout。
4
+ triggers: 需要底区垂直占位、与顶栏对称的 HUD 区,或避免棋盘侵入底部 CTA/品牌区时触发。
5
+ ---
6
+
7
+ # 底部 UI 条(Bottom UI Bar)
8
+
9
+ ## 说明
10
+
11
+ - **高度常量** `GAME_BOTTOM_UI_BAR_HEIGHT` 取自 `GameConfig.GAME_BOTTOM_UI_BAR_HEIGHT`,与 `grid_board_layout` / `path_input_handler` 等扣底公式一致。
12
+ - **分区与 z-order** 见 `playable_hud_layout.aicomponent`;**缩放**见 `responsive_2d_layout.aicomponent` 第一节。
13
+
14
+ ## Scaffold
15
+
16
+ | 目标路径 | 来源 | 说明 |
17
+ |---------|------|------|
18
+ | `src/game/scenes/GameUI/GameBottomUI.ts` | `ref/GameBottomUI.ts` | 底栏占位 Container + 导出常量 |
19
+
20
+ ## Recipe
21
+
22
+ | 决策 | 原因 |
23
+ |------|------|
24
+ | **对称于 TopUI 的占位 Container** | 底部 CTA 区(下载按钮、品牌 logo)需要专属高度预留;与顶栏高度常量对称管理,确保棋盘不侵入两端 UI 区 |
25
+ | **高度从 GameConfig 读取** | 与 `grid_board_layout`、`path_input_handler` 使用同一 `GameConfig.GAME_BOTTOM_UI_BAR_HEIGHT`;单点定义防止底栏高度在多处不一致 |
26
+
27
+ ## Adapter
28
+
29
+ - **Role**: `bottomUiBar` — 底部 HUD 区域占位容器及高度常量提供者
30
+ - **Provides**: `GameBottomUI` 类、`GAME_BOTTOM_UI_BAR_HEIGHT` 常量(与 GameConfig 同源)
31
+ - **Requires**: `phaser.aicomponent`、`responsive_2d_layout.aicomponent`
32
+ - **Consumed by**: `game_scene.aicomponent`(实例化 BottomUI)、`grid_board_layout.aicomponent`(棋盘可用高度扣减)
33
+ - **Integration point**: `src/game/scenes/GameUI/GameBottomUI.ts` → `Game.create()` 中实例化
34
+
35
+ ## Imports
36
+
37
+ - `phaser.aicomponent`(硬依赖)
38
+ - `responsive_2d_layout.aicomponent`(硬依赖)
39
+
40
+ ## Skill Definition
41
+
42
+ ```yaml
43
+ tools:
44
+ - read_file
45
+ - write_file
46
+ inputs:
47
+ - source: src/game/scenes/GameUI/GameBottomUI.ts
48
+ outputs:
49
+ - gameBottomUI: GameBottomUI class + GAME_BOTTOM_UI_BAR_HEIGHT constant aligned with GameConfig
50
+ ```
@@ -0,0 +1,31 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "atomId": "bottom_ui_bar.aicomponent",
4
+ "bundleType": "aicomponent",
5
+ "category": "component",
6
+ "mode": "fixed",
7
+ "label": { "zh": "底部 UI 条", "en": "Bottom UI bar" },
8
+ "tags": ["ui", "bottom-bar", "hud", "phaser", "layout"],
9
+ "bindingRoles": ["bottomUiBar"],
10
+ "scaffold": {
11
+ "files": {
12
+ "src/game/scenes/GameUI/GameBottomUI.ts": { "source": "ref/GameBottomUI.ts", "mode": "full", "weight": 10 }
13
+ }
14
+ },
15
+ "imports": [
16
+ { "slot": "engine", "pinAtomId": "phaser.aicomponent", "edgeKind": "requires", "bindAs": "engine" },
17
+ { "slot": "layout", "pinAtomId": "responsive_2d_layout.aicomponent", "edgeKind": "requires", "bindAs": "layout" }
18
+ ],
19
+ "exports": [
20
+ { "name": "GameBottomUI", "kind": "class", "location": "src/game/scenes/GameUI/GameBottomUI.ts" },
21
+ { "name": "GAME_BOTTOM_UI_BAR_HEIGHT", "kind": "constant", "location": "src/game/scenes/GameUI/GameBottomUI.ts" }
22
+ ],
23
+ "neutralDescriptor": {
24
+ "geometry": "bottom band placeholder aligned with GameConfig bottom height; depth above board for future CTA/branding"
25
+ },
26
+ "usageHints": [
27
+ "GAME_BOTTOM_UI_BAR_HEIGHT 与 GameConfig 同源;棋盘计算须扣除同一高度",
28
+ "屏幕分区与 z-order 优先读 playable_hud_layout.aicomponent"
29
+ ],
30
+ "files": { "skill": "SKILL.md", "gameBottomUI": "ref/GameBottomUI.ts" }
31
+ }
@@ -0,0 +1,27 @@
1
+ import * as Phaser from "phaser";
2
+ import { computeUiLayout } from "../../utils/UiLayout";
3
+ import { GameConfig } from "../../GameConfig";
4
+
5
+ /**
6
+ * 底部 UI 区设计高度(dp),与 `GameConfig.GAME_BOTTOM_UI_BAR_HEIGHT` 同源,
7
+ * 供棋盘布局、输入边界与本条同时引用,避免魔法数漂移。
8
+ */
9
+ export const GAME_BOTTOM_UI_BAR_HEIGHT = GameConfig.GAME_BOTTOM_UI_BAR_HEIGHT;
10
+
11
+ /**
12
+ * 底部 UI 条占位容器:保留与 `GameConfig` 一致的垂直占位,便于与 `BoardLayout` 扣减对齐。
13
+ * 可扩展为品牌条、次要 CTA;默认仅透明占位(不占视觉焦点)。
14
+ */
15
+ export class GameBottomUI extends Phaser.GameObjects.Container {
16
+ constructor(scene: Phaser.Scene) {
17
+ super(scene);
18
+ scene.add.existing(this);
19
+ this.setDepth(500);
20
+
21
+ const { width, height, vScale } = computeUiLayout(scene);
22
+ const barH = GAME_BOTTOM_UI_BAR_HEIGHT * vScale;
23
+ const cy = height - barH / 2;
24
+ const bg = scene.add.rectangle(width / 2, cy, width, barH, 0x000000, 0);
25
+ this.add(bg);
26
+ }
27
+ }
@@ -0,0 +1,129 @@
1
+ ---
2
+ name: bubble_shooter.aigameplay
3
+ description: 泡泡射击消除玩法封包 - 瞄准发射泡泡、消除同色簇、触发悬空掉落的 PGS 实现
4
+ triggers: 泡泡,射击,消除,泡泡龙,bubble,shooter,pop,cluster,aim,cannon,color,弹射,悬空
5
+ ---
6
+
7
+ # bubble_shooter.aigameplay
8
+
9
+ 泡泡射击消除核心玩法封包。实现泡泡射击规则的 PGS (PlayCraft Gameplay Schema, 玩法定义规范) JSON 和 reducer,玩家在底部瞄准发射泡泡,命中相同颜色的连通簇(≥3 个)后整簇消除,与簇相连但悬空的泡泡也随之掉落得分,目标是清空所有泡泡。
10
+
11
+ ## Recipe
12
+
13
+ - **玩法类型**:bubble_shooter(泡泡射击消除)
14
+ - **参考文件**:
15
+ - `ref/pgs-schema.json`:PGS (PlayCraft Gameplay Schema, 玩法定义规范) 规则骨架(entities、rules、algorithm、testCases)
16
+ - `ref/reducer.template.ts`:reducer 接口约束模板(`init` / `dispatch` / `getState` + 分步函数)
17
+ - **核心规则**:
18
+ - `minClusterSize`: 3(≥3 个相连同色泡泡才能触发消除)
19
+ - `wallBounceEnabled`: true(泡泡可在左右墙壁反弹)
20
+ - `orphanDropEnabled`: true(失去顶部连接的泡泡自动掉落)
21
+ - `advanceRowAfterShots`: 5(每发射 5 次后顶部新增一排泡泡)
22
+ - `colorCount`: 6(泡泡颜色总数)
23
+ - **PGS Agent 操作流程**:
24
+ 1. 读取 `ref/pgs-schema.json` 作为规则骨架起点
25
+ 2. 读取 `ref/reducer.template.ts` 了解接口约束
26
+ 3. 实现 `reducer.ts`,导出 `init(config)`、`dispatch(state, action)`、`getState(state)` 以及**全部分步函数**
27
+ 4. 运行 `ref/pgs-schema.json` 中的所有 `testCases`,全部通过后才算完成
28
+ 5. 更新 manifest 的 `generation.pgsVersion` 和 `result.outputFile`
29
+ - **可 fork 变体**:
30
+ - 特殊泡泡:彩虹泡泡(匹配任意颜色)、炸弹泡泡(范围消除)
31
+ - 六边形网格:将方形网格改为六边形(hex grid)排列
32
+ - 无限模式:持续生成新排,以 moves 为限制而非清空
33
+
34
+ ## Result
35
+
36
+ - **产物文件**:`reducer.ts`
37
+ - **格式**:TypeScript,导出 `init(config)`、`dispatch(action)`、`getState()` + 分步函数接口
38
+ - **验证**:所有 testCases 必须通过
39
+
40
+ ## 渲染集成(⚠️ 场景层必读)
41
+
42
+ ### 设计原则:逻辑与动画分离
43
+
44
+ reducer 提供两套接口:
45
+
46
+ | 接口 | 适用场景 | 特点 |
47
+ |------|---------|------|
48
+ | `dispatch()` | 无头测试、AI 模拟、跳过动画 | 一步到位,只返回最终状态 |
49
+ | 分步函数 | **渲染层/GameScene** | 逐步执行,返回中间过程数据 |
50
+
51
+ ### ⚠️ 禁止在渲染层使用 dispatch() 然后全量重建场景
52
+
53
+ 正确做法是**分步驱动动画链**:
54
+
55
+ ```ts
56
+ // ✅ 正确做法:逐步调用分步函数,每步之间插入动画
57
+
58
+ // Step 1: 计算弹道轨迹(含反弹)
59
+ const trajectory = calculateTrajectory(state, aimAngle);
60
+ await playBubbleFlyAnimation(trajectory); // 泡泡沿轨迹飞行动画
61
+
62
+ // Step 2: 吸附到网格
63
+ const snapPos = snapToGrid(trajectory.landingPosition);
64
+ const boardWithNew = addBubbleToBoard(state.board, snapPos, state.cannon.currentColor);
65
+
66
+ // Step 3: 查找同色连通簇
67
+ const cluster = findCluster(boardWithNew, snapPos.col, snapPos.row);
68
+
69
+ if (cluster.length >= state.config.minClusterSize) {
70
+ // Step 4: 消除整簇
71
+ const { newState, popped } = popCluster(state, cluster);
72
+ await playPopAnimation(popped); // 泡泡爆炸消除动画
73
+
74
+ // Step 5: 查找并掉落孤立泡泡
75
+ const orphans = findOrphans(newState.board);
76
+ if (orphans.length > 0) {
77
+ const { finalState, dropped } = dropOrphans(newState, orphans);
78
+ await playDropAnimation(dropped); // 泡泡掉落动画
79
+
80
+ // Step 6: 计算得分
81
+ const score = calculateScore(popped.length, dropped.length);
82
+ updateScoreUI(score);
83
+ }
84
+ }
85
+
86
+ // Step 7: 检查推进/胜败
87
+ if (shouldAdvanceBoard(state)) addNewRow();
88
+ if (checkLose(state)) showLosePanel();
89
+ ```
90
+
91
+ ### 分步函数返回值与动画映射
92
+
93
+ | 分步函数 | 返回值 | 场景层动画 |
94
+ |---------|--------|-----------|
95
+ | `calculateTrajectory()` | `TrajectoryPoint[]` | 泡泡沿轨迹飞行(含折射点) |
96
+ | `snapToGrid()` | `GridPosition` | 泡泡吸附到最近网格位置 |
97
+ | `findCluster()` | `GridPosition[]` | 高亮显示将要消除的同色簇 |
98
+ | `popCluster()` | `{ newState, popped }` | 泡泡爆炸缩小消失动画 |
99
+ | `findOrphans()` | `GridPosition[]` | 标记将要掉落的孤立泡泡 |
100
+ | `dropOrphans()` | `{ finalState, dropped }` | 孤立泡泡下落消失动画 |
101
+ | `calculateScore()` | `number` | 飘分 + 得分 UI 更新 |
102
+
103
+ ## Binding
104
+
105
+ - **Binding Role**:`gameplayRule`
106
+ - **挂载目标**:`game/gameplay/bubble_shooter/reducer.ts`
107
+ - **引用类型**:`gameplay-module-reference`
108
+ - **接口契约**:`init(config)` / `dispatch(action)` / `getState()` / `calculateTrajectory()` / `snapToGrid()` / `findCluster()` / `popCluster()` / `findOrphans()` / `dropOrphans()` / `calculateScore()`
109
+
110
+ ## Skill Definition
111
+
112
+ tools:
113
+ - bash
114
+ - write
115
+ - read
116
+ prompt_extension: |
117
+ You are implementing a bubble shooter gameplay module following the PGS specification.
118
+ Write the PGS JSON with entities (board with hex/grid positions, bubbles, cannon with current/next color, score, moves), rules, algorithm, and testCases.
119
+ Implement the reducer.ts with:
120
+ - init/dispatch/getState (一体化接口,用于测试)
121
+ - calculateTrajectory/snapToGrid/findCluster/popCluster/findOrphans/dropOrphans/calculateScore (分步函数,用于渲染层动画驱动)
122
+ Key constraints:
123
+ - Bubble trajectory uses angle-based line with wall reflections
124
+ - Cluster pop requires >= minClusterSize connected same-color bubbles
125
+ - Orphan detection uses flood-fill from top row; any bubble not reachable = orphan
126
+ - Win: all bubbles cleared; Lose: any bubble reaches cannon line
127
+ The step-by-step functions are CRITICAL — the rendering layer (GameScene) must use them to drive animations.
128
+ Run the testCases to verify the logic before finalizing.
129
+ Apply the Binding to wire the reducer into the game's gameplay module path.