@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,228 @@
1
+ /**
2
+ * HTML Overlay 模式的篮子/托盘渲染器
3
+ * 使用 CSS + DOM 实现,固定在屏幕底部。
4
+ * 适用于 Three.js 3D 项目中不需要 3D 深度的 UI 组件。
5
+ *
6
+ * 优点:
7
+ * - 性能好(不占用 WebGL 渲染管线)
8
+ * - CSS transition 动画流畅
9
+ * - 易于样式定制
10
+ * - 不受 3D 相机变换影响
11
+ */
12
+
13
+ export interface TrayItem {
14
+ id: string;
15
+ color: string; // 颜色标识
16
+ }
17
+
18
+ export interface TrayConfig {
19
+ capacity: number;
20
+ matchDuration?: number; // 消除动画时长 ms,默认 300
21
+ rearrangeDuration?: number; // 重排动画时长 ms,默认 200
22
+ shakeAmount?: number; // 抖动幅度 px,默认 8
23
+ slotSize?: number; // 槽位大小 px,默认 48
24
+ trayPadding?: number; // 篮子内边距 px,默认 8
25
+ colorToHex: (color: string) => string; // 颜色标识 → CSS hex 颜色
26
+ }
27
+
28
+ export class TrayRendererHtmlOverlay {
29
+ private container!: HTMLDivElement;
30
+ private slotsContainer!: HTMLDivElement;
31
+ private items: Map<string, HTMLDivElement> = new Map();
32
+ private config: Required<TrayConfig>;
33
+ private capacity: number;
34
+
35
+ constructor(config: TrayConfig) {
36
+ this.capacity = config.capacity;
37
+ this.config = {
38
+ capacity: config.capacity,
39
+ matchDuration: config.matchDuration ?? 300,
40
+ rearrangeDuration: config.rearrangeDuration ?? 200,
41
+ shakeAmount: config.shakeAmount ?? 8,
42
+ slotSize: config.slotSize ?? 48,
43
+ trayPadding: config.trayPadding ?? 8,
44
+ colorToHex: config.colorToHex,
45
+ };
46
+ }
47
+
48
+ /**
49
+ * 创建 DOM 结构并注入到页面
50
+ * @param parentId 父容器 ID(通常是 'game-container')
51
+ */
52
+ setup(parentId: string = "game-container"): void {
53
+ const parent = document.getElementById(parentId) || document.body;
54
+
55
+ // 创建外层容器
56
+ this.container = document.createElement("div");
57
+ this.container.id = "tray-overlay";
58
+ this.container.style.cssText = `
59
+ position: fixed;
60
+ bottom: env(safe-area-inset-bottom, 16px);
61
+ left: 50%;
62
+ transform: translateX(-50%);
63
+ display: flex;
64
+ align-items: center;
65
+ justify-content: center;
66
+ z-index: 1000;
67
+ pointer-events: none;
68
+ `;
69
+
70
+ // 创建篮子背景
71
+ const bg = document.createElement("div");
72
+ bg.style.cssText = `
73
+ background: rgba(22, 33, 62, 0.9);
74
+ border-radius: 12px;
75
+ padding: ${this.config.trayPadding}px;
76
+ backdrop-filter: blur(8px);
77
+ border: 1px solid rgba(61, 61, 92, 0.5);
78
+ `;
79
+
80
+ // 创建槽位容器
81
+ this.slotsContainer = document.createElement("div");
82
+ this.slotsContainer.style.cssText = `
83
+ display: flex;
84
+ gap: 4px;
85
+ min-width: ${this.capacity * (this.config.slotSize + 4)}px;
86
+ height: ${this.config.slotSize}px;
87
+ position: relative;
88
+ `;
89
+
90
+ // 绘制槽位分隔线
91
+ for (let i = 0; i < this.capacity; i++) {
92
+ const slot = document.createElement("div");
93
+ slot.style.cssText = `
94
+ width: ${this.config.slotSize}px;
95
+ height: ${this.config.slotSize}px;
96
+ border-right: ${i < this.capacity - 1 ? "1px solid rgba(61, 61, 92, 0.5)" : "none"};
97
+ flex-shrink: 0;
98
+ `;
99
+ this.slotsContainer.appendChild(slot);
100
+ }
101
+
102
+ bg.appendChild(this.slotsContainer);
103
+ this.container.appendChild(bg);
104
+ parent.appendChild(this.container);
105
+ }
106
+
107
+ /**
108
+ * 获取指定槽位的屏幕位置(相对于视口)
109
+ */
110
+ getSlotScreenPos(index: number): { x: number; y: number } {
111
+ const slotEl = this.slotsContainer.children[index] as HTMLElement;
112
+ if (!slotEl) return { x: 0, y: 0 };
113
+ const rect = slotEl.getBoundingClientRect();
114
+ return {
115
+ x: rect.left + rect.width / 2,
116
+ y: rect.top + rect.height / 2,
117
+ };
118
+ }
119
+
120
+ /**
121
+ * 添加物品到指定槽位
122
+ */
123
+ addItem(item: TrayItem, index: number): HTMLDivElement {
124
+ const el = document.createElement("div");
125
+ el.dataset.itemId = item.id;
126
+ const size = this.config.slotSize * 0.75;
127
+ el.style.cssText = `
128
+ position: absolute;
129
+ width: ${size}px;
130
+ height: ${size}px;
131
+ border-radius: 50%;
132
+ background: ${this.config.colorToHex(item.color)};
133
+ box-shadow: 0 2px 8px rgba(0,0,0,0.3), inset 0 -2px 4px rgba(0,0,0,0.2);
134
+ transition: transform ${this.config.rearrangeDuration}ms ease, left ${this.config.rearrangeDuration}ms ease;
135
+ transform: scale(0);
136
+ top: ${(this.config.slotSize - size) / 2}px;
137
+ left: ${this.getSlotLeft(index, size)}px;
138
+ `;
139
+
140
+ this.slotsContainer.appendChild(el);
141
+ this.items.set(item.id, el);
142
+
143
+ // 弹入动画
144
+ requestAnimationFrame(() => {
145
+ el.style.transform = "scale(1)";
146
+ });
147
+
148
+ return el;
149
+ }
150
+
151
+ /**
152
+ * 重新排列所有物品到正确位置
153
+ */
154
+ rearrangeItems(tray: TrayItem[]): void {
155
+ const size = this.config.slotSize * 0.75;
156
+ for (let i = 0; i < tray.length; i++) {
157
+ const el = this.items.get(tray[i].id);
158
+ if (!el) continue;
159
+ el.style.left = `${this.getSlotLeft(i, size)}px`;
160
+ }
161
+ }
162
+
163
+ /**
164
+ * 消除匹配的物品(放大 + 淡出)
165
+ */
166
+ removeMatchedItems(matchedIds: string[], onComplete: () => void): void {
167
+ let completed = 0;
168
+ const total = matchedIds.length;
169
+
170
+ for (const id of matchedIds) {
171
+ const el = this.items.get(id);
172
+ if (!el) {
173
+ completed++;
174
+ if (completed >= total) onComplete();
175
+ continue;
176
+ }
177
+
178
+ el.style.transition = `transform ${this.config.matchDuration}ms ease, opacity ${this.config.matchDuration}ms ease`;
179
+ el.style.transform = "scale(1.3)";
180
+ el.style.opacity = "0";
181
+
182
+ setTimeout(() => {
183
+ el.remove();
184
+ this.items.delete(id);
185
+ completed++;
186
+ if (completed >= total) onComplete();
187
+ }, this.config.matchDuration);
188
+ }
189
+ }
190
+
191
+ /**
192
+ * 满溢抖动动画
193
+ */
194
+ shake(): void {
195
+ const amount = this.config.shakeAmount;
196
+ this.container.style.transition = "none";
197
+ let shakeCount = 0;
198
+ const maxShakes = 6;
199
+ const interval = 50;
200
+
201
+ const doShake = () => {
202
+ if (shakeCount >= maxShakes) {
203
+ this.container.style.transform = "translateX(-50%)";
204
+ return;
205
+ }
206
+ const offset = shakeCount % 2 === 0 ? amount : -amount;
207
+ this.container.style.transform = `translateX(calc(-50% + ${offset}px))`;
208
+ shakeCount++;
209
+ setTimeout(doShake, interval);
210
+ };
211
+ doShake();
212
+ }
213
+
214
+ /**
215
+ * 销毁 DOM 元素
216
+ */
217
+ destroy(): void {
218
+ this.container?.remove();
219
+ this.items.clear();
220
+ }
221
+
222
+ // ── 内部方法 ──
223
+
224
+ private getSlotLeft(index: number, itemSize: number): number {
225
+ const slotWidth = this.config.slotSize + 4; // gap included
226
+ return index * slotWidth + (this.config.slotSize - itemSize) / 2;
227
+ }
228
+ }
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: tutorial_overlay.aicomponent
3
+ description: 新手引导浮层。在第一、二关展示步进式操作引导(高亮指定路径 + 手指动画),帮助玩家快速理解点击消除玩法。
4
+ triggers: 需要实现试玩广告的新手引导或操作提示浮层时触发。
5
+ ---
6
+
7
+ # 新手引导浮层(Tutorial Overlay)
8
+
9
+ **指引层深度、遮罩/挖洞/手指缩放合同** 见 `playable_guidance_layer.aicomponent`;与顶栏关系见 `playable_hud_layout.aicomponent`。
10
+
11
+ ## Scaffold
12
+
13
+ `src/game/scenes/GameUI/TutorialManager.ts`
14
+
15
+ ## Recipe
16
+
17
+ | 决策 | 原因 |
18
+ |------|------|
19
+ | **仅在前 1-2 关激活** | 新手引导覆盖太多关卡会让熟悉玩法的用户烦躁;仅第一、二关引导,之后让玩家自由探索 |
20
+ | **高亮+手指组合** | 单独高亮目标路径告诉玩家"点哪里",手指动画告诉玩家"怎么操作";两者配合降低学习门槛 |
21
+ | **软槽位 tutorialPointer** | 不同 Remix 可以有不同风格的引导手指图(卡通、写实等);软槽位允许资产替换 |
22
+
23
+ ## Adapter
24
+
25
+ - **Role**: `tutorialOverlay` — 前 1-2 关步进式新手引导浮层(高亮路径 + 手指动画)
26
+ - **Provides**: `TutorialManager` 类(步进状态机,`startTutorial(level)`、`onPathEliminated(pathIndex)`)
27
+ - **Requires**: `phaser.aicomponent`、`tutorialPointer`(软槽位:引导手指图标)
28
+ - **Consumed by**: `game_scene.aicomponent`(在 `create()` 中实例化,前两关激活;InputHandler 的消除回调中调用 `onPathEliminated`)
29
+ - **Integration point**: `src/game/scenes/GameUI/TutorialManager.ts` → `Game.create()` 中条件初始化
30
+
31
+ ## Imports
32
+
33
+ - `phaser.aicomponent`(硬依赖)
34
+ - `tutorialPointer`(软槽位:引导手指图标,可替换)
35
+
36
+ ## Skill Definition
37
+
38
+ ```yaml
39
+ tools:
40
+ - read_file
41
+ - write_file
42
+ inputs:
43
+ - source: src/game/scenes/GameUI/TutorialManager.ts
44
+ outputs:
45
+ - tutorialManager: TutorialManager class
46
+ ```
@@ -0,0 +1,34 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "atomId": "tutorial_overlay.aicomponent",
4
+ "bundleType": "aicomponent",
5
+ "category": "component",
6
+ "mode": "fixed",
7
+ "label": { "zh": "新手引导浮层", "en": "Tutorial overlay" },
8
+ "tags": ["ui", "tutorial", "onboarding", "guide", "first-level"],
9
+ "bindingRoles": ["tutorialOverlay"],
10
+ "scaffold": {
11
+ "files": {
12
+ "src/game/scenes/GameUI/TutorialManager.ts": { "source": "ref/TutorialManager.ts", "mode": "full", "weight": 10 }
13
+ }
14
+ },
15
+ "imports": [
16
+ { "slot": "engine", "pinAtomId": "phaser.aicomponent", "edgeKind": "requires", "bindAs": "engine" },
17
+ {
18
+ "slot": "tutorialPointer",
19
+ "description": "引导手指图标",
20
+ "bindAs": "fingerTexture",
21
+ "required": false,
22
+ "edgeKind": "compatibleWith",
23
+ "matchBindingRoles": ["tutorialPointer"],
24
+ "allowedBundleTypes": ["aiimage"]
25
+ }
26
+ ],
27
+ "exports": [
28
+ { "name": "TutorialManager", "kind": "class", "location": "src/game/scenes/GameUI/TutorialManager.ts" }
29
+ ],
30
+ "neutralDescriptor": {
31
+ "geometry": "step-by-step tutorial overlay for the first 1-2 levels, highlighting specific paths to tap with animated finger indicator"
32
+ },
33
+ "files": { "skill": "SKILL.md", "tutorialManager": "ref/TutorialManager.ts" }
34
+ }
@@ -0,0 +1,367 @@
1
+ import * as Phaser from "phaser";
2
+ import { GAME_TOP_UI_BAR_HEIGHT } from "./GameTopUI";
3
+ import { computeUiLayout } from "../../utils/UiLayout";
4
+ import {
5
+ ENABLE_ZOOM_GESTURE_GUIDE,
6
+ AUTO_USE_HINT_ON_START,
7
+ } from "../../DebugConfig";
8
+
9
+ /**
10
+ * 描述 TutorialManager 从 Game 场景中所需内容的最小接口。
11
+ * 避免模块级别的循环导入。
12
+ */
13
+ export interface TutorialGameRef extends Phaser.Scene {
14
+ level: any; // ParsedLevel | null
15
+ boardContainer: Phaser.GameObjects.Container | null;
16
+ visualSize: number;
17
+ isLevelOne: boolean;
18
+ isLevelTwo: boolean;
19
+ removedPaths: Set<number>;
20
+ animatingPaths: Set<number>;
21
+ cellCenter(col: number, row: number): { x: number; y: number };
22
+ renderHintOverlay(): void;
23
+ findRemovablePathIndex(): number | null;
24
+ isCellOccupiedByAnyPath(
25
+ col: number,
26
+ row: number,
27
+ ignorePath: number,
28
+ ): boolean;
29
+ }
30
+
31
+ /**
32
+ * 教程管理器。
33
+ * 负责管理第一关教程引导、提示高亮、第二关缩放手势引导等。
34
+ */
35
+ export class TutorialManager {
36
+ private scene: TutorialGameRef;
37
+
38
+ // ── 提示高亮状态 ──
39
+ hintHighlightTween: Phaser.Tweens.Tween | null = null;
40
+ hintTargetIndex: number | null = null;
41
+ hintPulseScale = 1;
42
+ hintFingerContainer: Phaser.GameObjects.Container | null = null;
43
+ hintFingerTween: Phaser.Tweens.Tween | null = null;
44
+ hintFingerMoveTween: Phaser.Tweens.Tween | null = null;
45
+
46
+ // ── 第一关教程状态 ──
47
+ isLevelOneTutorialActive = false;
48
+ levelOneTutorialExpectedPathIndex: number | null = null;
49
+
50
+ // ── 第二关缩放引导状态 ──
51
+ isLevelTwoZoomGuideActive = false;
52
+ hasLevelTwoZoomGuideShown = false;
53
+ private levelTwoZoomGuideBoardContainer: Phaser.GameObjects.Container | null =
54
+ null;
55
+ private levelTwoZoomGuideTextContainer: Phaser.GameObjects.Container | null =
56
+ null;
57
+
58
+ constructor(scene: TutorialGameRef) {
59
+ this.scene = scene;
60
+ }
61
+
62
+ // ── 生命周期 ──────────────────────────────────────────────
63
+
64
+ /**
65
+ * 重置所有教程状态。在每关开始时调用。
66
+ */
67
+ resetState(): void {
68
+ this.clearHintHighlight();
69
+ this.hideLevelTwoZoomGuide();
70
+ this.isLevelOneTutorialActive = false;
71
+ this.levelOneTutorialExpectedPathIndex = null;
72
+ this.hasLevelTwoZoomGuideShown = false;
73
+ this.isLevelTwoZoomGuideActive = false;
74
+ }
75
+
76
+ // ── 提示高亮 ─────────────────────────────────────────
77
+
78
+ /** 清除当前的提示高亮效果及手指动画。 */
79
+ clearHintHighlight(): void {
80
+ if (this.hintHighlightTween) {
81
+ this.hintHighlightTween.stop();
82
+ this.hintHighlightTween = null;
83
+ }
84
+ if (this.hintFingerTween) {
85
+ this.hintFingerTween.stop();
86
+ this.hintFingerTween = null;
87
+ }
88
+ if (this.hintFingerMoveTween) {
89
+ this.hintFingerMoveTween.stop();
90
+ this.hintFingerMoveTween = null;
91
+ }
92
+ if (this.hintFingerContainer) {
93
+ this.hintFingerContainer.destroy();
94
+ this.hintFingerContainer = null;
95
+ }
96
+ if (this.hintTargetIndex !== null) {
97
+ this.hintTargetIndex = null;
98
+ this.hintPulseScale = 1;
99
+ this.scene.renderHintOverlay();
100
+ }
101
+ }
102
+
103
+ /**
104
+ * 显示指定路径的提示高亮效果,包括手指图标和脉冲动画。
105
+ * @param pathIndex 需要高亮的路径索引
106
+ */
107
+ showHintHighlight(pathIndex: number): void {
108
+ const scene = this.scene;
109
+ if (!scene.level) return;
110
+
111
+ // 清除旧的提示效果(如果有)
112
+ this.clearHintHighlight();
113
+
114
+ const isTutorial = this.isLevelOneTutorialActive;
115
+
116
+ this.hintTargetIndex = pathIndex;
117
+ this.hintPulseScale = isTutorial ? 1 : 1.25;
118
+ scene.renderHintOverlay();
119
+
120
+ const level = scene.level;
121
+
122
+ let hintDirection: "left" | "right" | "up" | "down" = "right";
123
+ let headCenter: { x: number; y: number } | null = null;
124
+
125
+ const path = level.paths[pathIndex]!;
126
+ const headCell = path.head;
127
+ headCenter = scene.cellCenter(headCell.x, headCell.y);
128
+ hintDirection = path.direction;
129
+
130
+ if (!headCenter) return;
131
+
132
+ // 所有提示(包括教程和道具提示)都显示手指+光环;
133
+ // 但只有非教程提示会对箭头/路径进行脉冲缩放。
134
+ if (scene.boardContainer) {
135
+ const fingerContainer = scene.add.container(headCenter.x, headCenter.y);
136
+ scene.boardContainer.add(fingerContainer);
137
+ scene.boardContainer.bringToTop(fingerContainer);
138
+ this.hintFingerContainer = fingerContainer;
139
+
140
+ const finger = scene.add.image(0, 0, "figer");
141
+ finger.setOrigin(0, 0);
142
+ // 使用 visualSize 而非 cellSize 来放大手指显示
143
+ const fingerMaxSize = scene.visualSize * 5;
144
+ const fingerBaseScale = Math.min(
145
+ fingerMaxSize / (finger.width || 1),
146
+ fingerMaxSize / (finger.height || 1),
147
+ );
148
+ let fingerScale = fingerBaseScale;
149
+ if (isTutorial) {
150
+ // 教程模式下手指缩小 1/3
151
+ fingerScale *= 2 / 3;
152
+ }
153
+ finger.setScale(fingerScale);
154
+
155
+ const moveOffsetX = scene.visualSize * 0.4;
156
+ const moveOffsetY = scene.visualSize * 0.4;
157
+ let fingerRotation = 0;
158
+
159
+ if (hintDirection === "down") {
160
+ fingerRotation = Math.PI;
161
+ }
162
+
163
+ finger.setRotation(fingerRotation);
164
+
165
+ const fingerOffsetX = moveOffsetX;
166
+ finger.setFlipX(false);
167
+ finger.setPosition(fingerOffsetX, moveOffsetY);
168
+
169
+ // 仅添加手指,不添加黄色圆圈
170
+ fingerContainer.add([finger]);
171
+
172
+ // Google 渠道不显示手指移动动画
173
+ const isGoogleChannel =
174
+ (window as any).PlayableSDK?.getCurChannel?.() === "google";
175
+ if (!isGoogleChannel) {
176
+ this.hintFingerMoveTween = scene.tweens.add({
177
+ targets: finger,
178
+ x: { from: fingerOffsetX, to: 0 },
179
+ y: { from: moveOffsetY, to: 0 },
180
+ duration: 650,
181
+ ease: "Sine.easeInOut",
182
+ yoyo: true,
183
+ repeat: -1,
184
+ });
185
+ } else {
186
+ // Google 渠道:手指静止在目标位置
187
+ finger.setPosition(0, 0);
188
+ }
189
+ }
190
+
191
+ // 非教程模式下添加脉冲缩放动画
192
+ if (!isTutorial) {
193
+ this.hintHighlightTween = scene.tweens.add({
194
+ targets: this,
195
+ hintPulseScale: { from: 1.25, to: 0.9 },
196
+ duration: 450,
197
+ ease: "Sine.easeInOut",
198
+ yoyo: true,
199
+ repeat: -1,
200
+ onUpdate: () => {
201
+ scene.renderHintOverlay();
202
+ },
203
+ });
204
+ }
205
+ }
206
+
207
+ // ── 第一关教程 ─────────────────────────────────────
208
+
209
+ /** 启动第一关教程引导,显示第一个可消除路径的提示。 */
210
+ startLevelOneTutorial(): void {
211
+ const scene = this.scene;
212
+ if (!scene.level || !scene.isLevelOne) {
213
+ return;
214
+ }
215
+
216
+ this.isLevelOneTutorialActive = true;
217
+
218
+ const nextIndex = this.findNextLevelOneTutorialPathIndex();
219
+ if (nextIndex === null) {
220
+ this.isLevelOneTutorialActive = false;
221
+ this.levelOneTutorialExpectedPathIndex = null;
222
+ return;
223
+ }
224
+
225
+ this.levelOneTutorialExpectedPathIndex = nextIndex;
226
+ this.showHintHighlight(nextIndex);
227
+ }
228
+
229
+ /** 推进第一关教程到下一个可消除路径。 */
230
+ advanceLevelOneTutorial(): void {
231
+ const scene = this.scene;
232
+ if (!scene.level || !scene.isLevelOne) {
233
+ return;
234
+ }
235
+
236
+ const nextIndex = this.findNextLevelOneTutorialPathIndex();
237
+ if (nextIndex === null) {
238
+ this.isLevelOneTutorialActive = false;
239
+ this.levelOneTutorialExpectedPathIndex = null;
240
+ this.clearHintHighlight();
241
+ return;
242
+ }
243
+
244
+ this.levelOneTutorialExpectedPathIndex = nextIndex;
245
+ this.showHintHighlight(nextIndex);
246
+ }
247
+
248
+ /**
249
+ * 查找下一个可消除的路径索引(用于教程引导)。
250
+ * @returns 下一个可消除的路径索引,未找到返回 null
251
+ */
252
+ private findNextLevelOneTutorialPathIndex(): number | null {
253
+ return this.scene.findRemovablePathIndex();
254
+ }
255
+
256
+ // ── 开始时自动使用提示 ────────────────────────────────────
257
+
258
+ /** 关卡开始时自动显示一个可消除路径的提示高亮。 */
259
+ autoUseHintOnStart(): void {
260
+ const scene = this.scene;
261
+ if (!scene.level) return;
262
+
263
+ console.log(
264
+ "[提示] autoUseHintOnStart 调用, levelIndex =",
265
+ scene.level.index,
266
+ );
267
+
268
+ const targetIndex = scene.findRemovablePathIndex();
269
+ console.log("[提示] 自动提示 - findRemovablePathIndex 结果 =", targetIndex);
270
+
271
+ if (targetIndex === null) {
272
+ console.log("[提示] 自动提示 - 未找到可消除的路径");
273
+ return;
274
+ }
275
+
276
+ // 直接显示提示高亮,不调用服务器API
277
+ this.showHintHighlight(targetIndex);
278
+ console.log("[提示] 自动提示已显示,路径索引:", targetIndex);
279
+ }
280
+
281
+ // ── 第二关缩放手势引导 ──────────────────────────────────
282
+
283
+ /** 显示第二关的缩放手势引导(双指缩放提示文字)。 */
284
+ showLevelTwoZoomGuide(): void {
285
+ const scene = this.scene;
286
+ // 检查配置中是否启用了手势引导
287
+ if (!ENABLE_ZOOM_GESTURE_GUIDE) {
288
+ return;
289
+ }
290
+
291
+ if (!scene.level || !scene.boardContainer) {
292
+ return;
293
+ }
294
+ console.log("hasLevelTwoZoomGuideShown", this.hasLevelTwoZoomGuideShown);
295
+
296
+ if (!scene.isLevelTwo || this.hasLevelTwoZoomGuideShown) {
297
+ return;
298
+ }
299
+
300
+ this.isLevelTwoZoomGuideActive = true;
301
+ this.hasLevelTwoZoomGuideShown = true;
302
+
303
+ const boardGuide = scene.add.container(0, 0);
304
+ scene.boardContainer.add(boardGuide);
305
+ scene.boardContainer.bringToTop(boardGuide);
306
+ this.levelTwoZoomGuideBoardContainer = boardGuide;
307
+
308
+ const layout = computeUiLayout(scene);
309
+ const { width, uiScale, vScale } = layout;
310
+ const textY = GAME_TOP_UI_BAR_HEIGHT * vScale + 55 * vScale;
311
+
312
+ const textContainer = scene.add.container(width / 2, textY);
313
+ textContainer.setScrollFactor(0);
314
+ textContainer.setDepth(1500);
315
+
316
+ const message = "双指捏合可以缩放棋盘。";
317
+ const text = scene.add.text(0, 0, message, {
318
+ fontFamily: "Poppins",
319
+ fontSize: `${34 * uiScale}px`,
320
+ color: "#ffffff",
321
+ fontStyle: "bold",
322
+ align: "center",
323
+ });
324
+ text.setOrigin(0.5, 0.5);
325
+
326
+ const paddingX = 18 * uiScale;
327
+ const paddingY = 8 * vScale;
328
+ const maxBgWidth = width * 0.9;
329
+ const maxTextWidth = Math.max(10, maxBgWidth - paddingX * 2);
330
+
331
+ if (text.displayWidth > maxTextWidth) {
332
+ text.setWordWrapWidth(maxTextWidth);
333
+ text.setAlign("center");
334
+ }
335
+
336
+ const bgWidth = Math.min(maxBgWidth, text.displayWidth + paddingX * 2);
337
+ const bgHeight = text.displayHeight + paddingY * 2;
338
+
339
+ const bg = scene.add.rectangle(0, 0, bgWidth, bgHeight, 0xff7a3c, 0.96);
340
+ textContainer.add([bg, text]);
341
+
342
+ this.levelTwoZoomGuideTextContainer = textContainer;
343
+ }
344
+
345
+ /** 隐藏第二关缩放手势引导,销毁相关容器。 */
346
+ hideLevelTwoZoomGuide(): void {
347
+ if (
348
+ !this.isLevelTwoZoomGuideActive &&
349
+ !this.levelTwoZoomGuideBoardContainer &&
350
+ !this.levelTwoZoomGuideTextContainer
351
+ ) {
352
+ return;
353
+ }
354
+
355
+ this.isLevelTwoZoomGuideActive = false;
356
+
357
+ if (this.levelTwoZoomGuideBoardContainer) {
358
+ this.levelTwoZoomGuideBoardContainer.destroy();
359
+ this.levelTwoZoomGuideBoardContainer = null;
360
+ }
361
+
362
+ if (this.levelTwoZoomGuideTextContainer) {
363
+ this.levelTwoZoomGuideTextContainer.destroy();
364
+ this.levelTwoZoomGuideTextContainer = null;
365
+ }
366
+ }
367
+ }