@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,748 @@
1
+ import { Scene } from "phaser";
2
+ import * as Phaser from "phaser";
3
+ import { parseLevelJson } from "../levels/LevelParser";
4
+ import type {
5
+ ParsedLevel,
6
+ LevelPath,
7
+ RawLevelJson,
8
+ } from "../levels/LevelTypes";
9
+ import { safePlaySound } from "../utils/SoundUtils";
10
+ import { GameTopUI } from "./GameUI/GameTopUI";
11
+ import { DownloadButton } from "./GameUI/DownloadButton";
12
+ import { SettingsManager } from "./GameUI/SettingsManager";
13
+ import { ThemeManager } from "./GameUI/ThemeManager";
14
+ import { GameOverPanel } from "./GameUI/GameOverPanel";
15
+ import { ComboManager } from "./GameUI/ComboManager";
16
+ import { TutorialManager } from "./GameUI/TutorialManager";
17
+ import { LevelLifecycle } from "./GameUI/LevelLifecycle";
18
+ import { AnimationManager } from "./GameUI/AnimationManager";
19
+ import { BoardLayout } from "./GameUI/BoardLayout";
20
+ import { InputHandler } from "./GameUI/InputHandler";
21
+ import { PathRendererManager } from "./GameUI/PathRenderer";
22
+ import { LevelManager } from "../levels/LevelManager";
23
+ import {
24
+ getActiveRunContext,
25
+ clearActiveRunContext,
26
+ } from "../run/RunContextRuntime";
27
+ import type { RunFlags } from "../run/RunContextRuntime";
28
+ import {
29
+ ENABLE_TEST_LEVEL_PANEL,
30
+ CHALLENGE_LEVEL_MODE,
31
+ DEBUG_FORCED_LEVEL_TIME_SECONDS,
32
+ AUTO_USE_HINT_ON_START,
33
+ GAME_CANVAS_BACKGROUND_COLOR,
34
+ PATH_CORNER_STYLE,
35
+ } from "../DebugConfig";
36
+ import type {
37
+ PathTrackCell,
38
+ PathRenderer as IPathRenderer,
39
+ } from "../utils/PathRenderers";
40
+ import { computeUiLayout } from "../utils/UiLayout";
41
+ import {
42
+ getCurrentLevelData,
43
+ shouldDrawEliminationTrail,
44
+ } from "../LevelDataManager";
45
+
46
+ /**
47
+ * 游戏主场景类。
48
+ * 负责关卡加载、棋盘渲染、输入处理、动画播放等核心游戏逻辑的协调。
49
+ */
50
+ export class Game extends Scene {
51
+ /** 主相机引用 */
52
+ camera!: Phaser.Cameras.Scene2D.Camera;
53
+ /** 背景图片 */
54
+ background!: Phaser.GameObjects.Image;
55
+ /** 背景矩形,用于确保屏幕完全覆盖 */
56
+ public backgroundRect?: Phaser.GameObjects.Rectangle;
57
+ /** FPS 调试文本 */
58
+ private fpsText!: Phaser.GameObjects.Text;
59
+
60
+ /** 当前已解析的关卡数据 */
61
+ public level: ParsedLevel | null = null;
62
+ /** 当前关卡进度索引(从1开始) */
63
+ private progressIndex = 1;
64
+ /** 格子尺寸(用于布局和点击判定,竖屏或正方形格子) */
65
+ public cellSize = 32;
66
+ /** 格子宽度(横屏时可能与高度不同) */
67
+ public cellWidth = 32;
68
+ /** 格子高度(横屏时可能与宽度不同) */
69
+ public cellHeight = 32;
70
+ /** 视觉尺寸(用于箭头和线条渲染,保持原始大小) */
71
+ public visualSize = 32;
72
+ /** 棋盘总宽度(像素) */
73
+ public boardWidth = 0;
74
+ /** 棋盘总高度(像素) */
75
+ public boardHeight = 0;
76
+ /** 棋盘容器(包含棋盘图形和覆盖层) */
77
+ public boardContainer!: Phaser.GameObjects.Container;
78
+ /** 棋盘主绘图对象 */
79
+ public boardGraphics!: Phaser.GameObjects.Graphics;
80
+ /** 提示高亮覆盖层绘图对象 */
81
+ public hintOverlayGraphics?: Phaser.GameObjects.Graphics;
82
+ /** 关卡背景图片 */
83
+ public levelBackgroundImage: Phaser.GameObjects.Image | null = null;
84
+ /** 当前缩放倍数 */
85
+ public zoom = 1;
86
+ /** 最小缩放倍数 */
87
+ public readonly minZoom = 1;
88
+ /** 最大缩放倍数 */
89
+ public readonly maxZoom = 2.5;
90
+ /** 棋盘X轴偏移量 */
91
+ public boardOffsetX = 0;
92
+ /** 棋盘Y轴偏移量 */
93
+ public boardOffsetY = 0;
94
+
95
+ /** 路径拐角样式(圆角或方角) */
96
+ public pathCornerStyle: "rounded" | "square" = PATH_CORNER_STYLE;
97
+
98
+ /** 路径渲染管理器实例 */
99
+ public pathRenderer!: PathRendererManager;
100
+
101
+ /** 委托给 PathRendererManager 构建路径轨迹 */
102
+ public buildPathTrack(path: LevelPath): PathTrackCell[] {
103
+ return this.pathRenderer.buildPathTrack(path);
104
+ }
105
+
106
+ /** 委托给 PathRendererManager 获取路径渲染器 */
107
+ public getPathRendererForLineWidth(_lineWidth: number): IPathRenderer {
108
+ return this.pathRenderer.getPathRendererForLineWidth(_lineWidth);
109
+ }
110
+
111
+ /** 记录已经被成功"移动/移除"的路径索引,避免重复绘制与碰撞 */
112
+ public removedPaths = new Set<number>();
113
+ /** 记录曾经发生过"被阻挡"的路径,使其保持红色,直到成功移除 */
114
+ public blockedPaths = new Set<number>();
115
+ /** 记录当前正在播放动画的路径,在动画期间不参与静态绘制,避免出现重复箭头 */
116
+ public animatingPaths = new Set<number>();
117
+ /** 不可移动提示精灵(全屏红色闪光) */
118
+ public nomoveHintSprite?: Phaser.GameObjects.Image;
119
+ /** 不可移动提示动画 */
120
+ public nomoveHintTween: Phaser.Tweens.Tween | null = null;
121
+ /** 缩放动画 */
122
+ public zoomTween: Phaser.Tweens.Tween | null = null;
123
+
124
+ /** 连击管理器 */
125
+ public comboManager!: ComboManager;
126
+
127
+ /** 在某些动画期间(例如生命扣除后等待弹板)锁定输入,防止误操作 */
128
+ public isInputLocked = false;
129
+ /** 游戏结束面板 */
130
+ public gameOverPanel: GameOverPanel | undefined;
131
+
132
+ /** 是否为测试/预览模式 */
133
+ public isTestMode = false;
134
+ /** 运行模式标志 */
135
+ public runFlags: RunFlags = {
136
+ kind: "normal",
137
+ affectsProgression: true,
138
+ };
139
+
140
+ /** 顶部 UI(关卡文字、生命值、计时器等) */
141
+ public topUI?: GameTopUI;
142
+ /** 关卡入场动画持续时间(毫秒),增加50%时间(原650ms),额外时间用于箭头错开出现 */
143
+ private readonly levelIntroDurationMs = 975;
144
+ /** 入场动画已经过的时间(毫秒) */
145
+ private introElapsedMs = 0;
146
+ /** 入场动画是否正在播放 */
147
+ public introPlaying = true;
148
+ /** 最大生命数 */
149
+ public readonly maxLives = 3;
150
+ /** 当前剩余生命数 */
151
+ public currentLives = 3;
152
+ /** 是否为第一关 */
153
+ public isLevelOne = false;
154
+ /** 是否为第二关 */
155
+ public isLevelTwo = false;
156
+ /** 新手引导管理器 */
157
+ public tutorialManager!: TutorialManager;
158
+ /** 是否正在处理过关逻辑 */
159
+ public winProcessing = false;
160
+ /** 设置管理器单例 */
161
+ public readonly settings = SettingsManager.instance;
162
+
163
+ /** 关卡生命周期管理器 */
164
+ public levelLifecycle!: LevelLifecycle;
165
+ /** 动画管理器 */
166
+ public animationManager!: AnimationManager;
167
+ /** 棋盘布局管理器 */
168
+ public boardLayout!: BoardLayout;
169
+ /** 输入处理器 */
170
+ public inputHandler!: InputHandler;
171
+
172
+ /** 是否正在播放过关钻石动画 */
173
+ public isPlayingWinDiamond = false;
174
+
175
+ /** 是否绘制消除轨迹 */
176
+ public shouldDrawEliminationTrail: boolean;
177
+
178
+ constructor() {
179
+ super("Game");
180
+ }
181
+
182
+ /**
183
+ * 场景初始化回调。
184
+ * 将 runFlags 重置为默认值(在 create() 中会被正常模式的 getRunFlags 覆盖)。
185
+ */
186
+ init(): void {
187
+ this.runFlags = {
188
+ kind: "normal",
189
+ affectsProgression: true,
190
+ };
191
+ }
192
+
193
+ /**
194
+ * 场景创建回调。
195
+ * 负责初始化相机、主题、关卡数据、棋盘、UI 和各管理器。
196
+ */
197
+ create() {
198
+ // #region 重置状态
199
+ // 每次进入关卡时,生命重置为满值,确保 TopUI 显示满血
200
+ this.currentLives = this.maxLives;
201
+ this.isInputLocked = false;
202
+ // 重置棋盘缩放与偏移状态,确保每一局从默认视图开始
203
+ this.zoom = this.minZoom;
204
+ this.boardOffsetX = 0;
205
+ this.boardOffsetY = 0;
206
+ if (this.zoomTween) {
207
+ this.zoomTween.stop();
208
+ this.zoomTween = null;
209
+ }
210
+
211
+ this.comboManager?.resetState();
212
+ if (this.currentLives <= 0) {
213
+ this.currentLives = this.maxLives;
214
+ }
215
+ this.gameOverPanel = undefined;
216
+
217
+ this.removedPaths.clear();
218
+ this.blockedPaths.clear();
219
+ this.animatingPaths.clear();
220
+ this.tutorialManager?.resetState();
221
+ // #endregion
222
+
223
+ this.camera = this.cameras.main;
224
+
225
+ const themeManager = ThemeManager.instance;
226
+ themeManager.init(this);
227
+
228
+ // 若配置了自定义画布背景颜色则使用配置值,否则使用主题颜色
229
+ const bgColor = themeManager.getBackgroundColorNumber();
230
+ const finalBgColor =
231
+ GAME_CANVAS_BACKGROUND_COLOR >= 0
232
+ ? GAME_CANVAS_BACKGROUND_COLOR
233
+ : bgColor;
234
+ this.camera.setBackgroundColor(finalBgColor);
235
+
236
+ // 创建全屏背景矩形,确保在所有情况下背景都能完全覆盖;设置为最底层(深度为负值)
237
+ const { width, height } = this.scale;
238
+ this.backgroundRect = this.add
239
+ .rectangle(width / 2, height / 2, width, height, finalBgColor)
240
+ .setDepth(-9999)
241
+ .setScrollFactor(0);
242
+
243
+ // 创建全屏红色闪光覆盖层,用于危险反馈
244
+ this.nomoveHintSprite = this.add
245
+ .image(width / 2, height / 2, "nomove_hint")
246
+ .setDisplaySize(width, height)
247
+ .setScrollFactor(0)
248
+ .setDepth(1600)
249
+ .setVisible(false)
250
+ .setAlpha(0);
251
+
252
+ this.settings.applyToSceneSound(this);
253
+ this.input.once("pointerdown", () => {
254
+ this.settings.playBgm(this);
255
+ });
256
+
257
+ const levelManager = LevelManager.instance;
258
+
259
+ // 挑战模式:使用 CHALLENGE_LEVEL_MODE 指定的关卡编号初始化
260
+ if (CHALLENGE_LEVEL_MODE !== 0) {
261
+ levelManager.setCurrentIndex(CHALLENGE_LEVEL_MODE);
262
+ }
263
+
264
+ const levelIndex = levelManager.getCurrentIndex();
265
+ this.progressIndex = levelIndex;
266
+
267
+ const activeRunContext = getActiveRunContext();
268
+ this.isTestMode = this.runFlags.kind === "test";
269
+
270
+ const testPayload =
271
+ activeRunContext?.mode === "test" ? activeRunContext : null;
272
+
273
+ // 挑战模式下隐藏关卡文字
274
+ let levelDisplayText =
275
+ CHALLENGE_LEVEL_MODE !== 0 ? "" : `Level ${this.progressIndex}`;
276
+ let level: ParsedLevel;
277
+
278
+ // 是否绘制消除轨迹
279
+ this.shouldDrawEliminationTrail = shouldDrawEliminationTrail();
280
+
281
+ // #region 加载关卡数据
282
+ let raw: RawLevelJson;
283
+ if (testPayload && testPayload.raw) {
284
+ // 测试/预览模式:使用来自运行上下文的关卡数据
285
+ console.log(`[Game] Loading level from test/preview context`);
286
+ raw = testPayload.raw;
287
+ levelDisplayText = testPayload.displayName || "Preview";
288
+ } else {
289
+ const LevelData = getCurrentLevelData();
290
+ console.log(`[Game] Loading level, progressIndex=${this.progressIndex}`, {
291
+ levelDataLength: LevelData?.length,
292
+ requestedIndex: this.progressIndex - 1,
293
+ rawType: typeof LevelData?.[this.progressIndex - 1],
294
+ rawIsArray: Array.isArray(LevelData?.[this.progressIndex - 1]),
295
+ });
296
+ raw = LevelData[this.progressIndex - 1];
297
+ console.log(`raw data: ${JSON.stringify(raw)}`);
298
+ if (!raw) {
299
+ // All levels completed — show win panel instead of crashing
300
+ console.warn(
301
+ `[Game] No level data at index ${
302
+ this.progressIndex - 1
303
+ }. LevelData has ${LevelData?.length} items. Showing win panel.`,
304
+ );
305
+ this.gameOverPanel = new GameOverPanel(this as any, {
306
+ type: "win",
307
+ onClose: () => {
308
+ this.gameOverPanel = undefined;
309
+ },
310
+ });
311
+ return;
312
+ }
313
+ }
314
+ level = parseLevelJson(raw);
315
+ this.level = level;
316
+ // #endregion
317
+
318
+ this.isLevelOne = level.index === 1;
319
+ this.isLevelTwo = level.index === 2;
320
+ if (!this.tutorialManager) {
321
+ this.tutorialManager = new TutorialManager(this as any);
322
+ }
323
+ this.tutorialManager.resetState();
324
+
325
+ const initialZoom = this.minZoom;
326
+ this.zoom = initialZoom;
327
+
328
+ this.introElapsedMs = 0;
329
+ this.introPlaying = true;
330
+
331
+ this.boardContainer = this.add.container(0, 0);
332
+ this.boardGraphics = this.add.graphics();
333
+ this.boardContainer.add(this.boardGraphics);
334
+ this.hintOverlayGraphics = this.add.graphics();
335
+ this.boardContainer.add(this.hintOverlayGraphics);
336
+
337
+ // 提前初始化各管理器,需在 buildBoard / playIntroZoomAnimation 之前完成
338
+ this.pathRenderer = new PathRendererManager(this as any);
339
+ const themeArrowColor = themeManager.getFixedArrowColorNumber();
340
+ this.pathRenderer.setupThemeColors(level, themeArrowColor);
341
+ this.pathRenderer.initPathTracks(level);
342
+ this.levelLifecycle = new LevelLifecycle(this as any);
343
+ this.animationManager = new AnimationManager(this as any);
344
+ this.boardLayout = new BoardLayout(this as any);
345
+ this.inputHandler = new InputHandler(this as any);
346
+ this.inputHandler.resetState();
347
+
348
+ if (this.settings.soundOn) {
349
+ this.time.addEvent({
350
+ delay: 100, // 每100ms执行一次
351
+ callback: () => {
352
+ safePlaySound(this, "appear", { volume: 0.5 });
353
+ },
354
+ repeat: 5,
355
+ });
356
+ }
357
+
358
+ this.buildBoard(level, 0); // 初始化时重置偏移
359
+ if (!this.isLevelOne && !this.isLevelTwo) {
360
+ this.animationManager.playIntroZoomAnimation(initialZoom);
361
+ }
362
+
363
+ // 使棋盘在窗口大小变化时自适应布局
364
+ this.scale.on("resize", (gameSize: Phaser.Structs.Size) => {
365
+ const { width, height } = gameSize;
366
+ this.cameras.resize(width, height);
367
+ this.relayoutBoard();
368
+ });
369
+
370
+ // 绑定所有输入事件(滚轮、指针、双指缩放)
371
+ this.inputHandler.bindEvents();
372
+
373
+ if (ENABLE_TEST_LEVEL_PANEL) {
374
+ this.fpsText = this.add
375
+ .text(10, 10, "FPS: 0", {
376
+ fontFamily: "Poppins",
377
+ fontSize: "16px",
378
+ color: "#000000",
379
+ })
380
+ .setDepth(1000);
381
+ }
382
+
383
+ const initialSeconds = DEBUG_FORCED_LEVEL_TIME_SECONDS
384
+ ? DEBUG_FORCED_LEVEL_TIME_SECONDS
385
+ : level.timeSeconds > 0
386
+ ? level.timeSeconds
387
+ : 4 * 60;
388
+
389
+ this.topUI = new GameTopUI(this, {
390
+ levelText: levelDisplayText,
391
+ initialLives: this.currentLives,
392
+ maxLives: this.maxLives,
393
+ initialTimeSeconds: initialSeconds,
394
+ onTimeout: () => this.levelLifecycle.handleTimeOut(),
395
+ });
396
+
397
+ // 在测试/预览模式下,显示"← 返回"按钮用于返回编辑器
398
+ if (this.isTestMode) {
399
+ const layout = computeUiLayout(this);
400
+ const { uiScale, vScale } = layout;
401
+ const btnX = 60 * uiScale;
402
+ const btnY = 44 * vScale;
403
+
404
+ const backBg = this.add.graphics();
405
+ backBg.fillStyle(0x000000, 0.45);
406
+ backBg.fillRoundedRect(
407
+ btnX - 52 * uiScale,
408
+ btnY - 20 * vScale,
409
+ 104 * uiScale,
410
+ 40 * vScale,
411
+ 10 * uiScale,
412
+ );
413
+ backBg.setScrollFactor(0).setDepth(1700);
414
+
415
+ const backText = this.add.text(btnX, btnY, "← Back", {
416
+ fontFamily: "Poppins",
417
+ fontSize: `${22 * uiScale}px`,
418
+ color: "#ffffff",
419
+ fontStyle: "bold",
420
+ });
421
+ backText.setOrigin(0.5).setScrollFactor(0).setDepth(1701);
422
+
423
+ const backHit = this.add
424
+ .rectangle(btnX, btnY, 104 * uiScale, 40 * vScale, 0x000000, 0)
425
+ .setScrollFactor(0)
426
+ .setDepth(1702)
427
+ .setInteractive({ useHandCursor: true });
428
+
429
+ backHit.on("pointerup", () => {
430
+ clearActiveRunContext();
431
+ this.scene.start("Editor");
432
+ });
433
+ }
434
+
435
+ // 连击 UI
436
+ const layout = computeUiLayout(this);
437
+ this.comboManager = new ComboManager(this);
438
+ this.comboManager.createUi(layout);
439
+
440
+ // 创建下载按钮
441
+ new DownloadButton(this);
442
+
443
+ this.comboManager.maybeShowComboPraiseText(
444
+ this.comboManager.clickCount,
445
+ 0,
446
+ 0,
447
+ false,
448
+ );
449
+ }
450
+
451
+ /**
452
+ * 每帧更新回调。
453
+ * 处理 FPS 显示、计时器更新、新手引导触发和入场动画播放。
454
+ * @param time 当前时间戳(毫秒)
455
+ * @param delta 上一帧到当前帧的间隔时间(毫秒)
456
+ */
457
+ override update(time: number, delta: number): void {
458
+ if (ENABLE_TEST_LEVEL_PANEL && this.fpsText) {
459
+ const fps = this.game.loop.actualFps;
460
+ this.fpsText.setText(`FPS: ${fps.toFixed(1)}`);
461
+ }
462
+
463
+ let pausedByUI = false;
464
+ if (this.topUI) {
465
+ pausedByUI = this.isInputLocked || !!this.gameOverPanel;
466
+
467
+ if (pausedByUI) {
468
+ if (this.nomoveHintTween) {
469
+ this.nomoveHintTween.stop();
470
+ this.nomoveHintTween = null;
471
+ }
472
+ if (this.nomoveHintSprite) {
473
+ this.nomoveHintSprite.setVisible(false);
474
+ this.nomoveHintSprite.setAlpha(0);
475
+ }
476
+ } else if (this.topUI) {
477
+ this.topUI.updateTimer(delta, time);
478
+ }
479
+ }
480
+
481
+ if (!pausedByUI && this.level && !this.introPlaying) {
482
+ const isNormalMode = this.runFlags.kind === "normal";
483
+ if (
484
+ isNormalMode &&
485
+ this.isLevelTwo &&
486
+ !this.tutorialManager.hasLevelTwoZoomGuideShown
487
+ ) {
488
+ this.tutorialManager.showLevelTwoZoomGuide();
489
+ }
490
+ if (
491
+ isNormalMode &&
492
+ this.isLevelOne &&
493
+ !this.tutorialManager.isLevelOneTutorialActive
494
+ ) {
495
+ this.tutorialManager.startLevelOneTutorial();
496
+ }
497
+ }
498
+
499
+ if (this.introPlaying && this.level) {
500
+ this.introElapsedMs += delta;
501
+ const t = Phaser.Math.Clamp(
502
+ this.introElapsedMs / this.levelIntroDurationMs,
503
+ 0,
504
+ 1,
505
+ );
506
+ this.buildBoard(this.level, t);
507
+ if (t >= 1) {
508
+ this.introPlaying = false;
509
+
510
+ // 自动使用提示(新手引导)
511
+ if (AUTO_USE_HINT_ON_START) {
512
+ this.tutorialManager.autoUseHintOnStart();
513
+ }
514
+ }
515
+ }
516
+ }
517
+
518
+ /**
519
+ * 绘制箭头头部。
520
+ * 委托给 PathRendererManager 执行实际绘制。
521
+ * @param g 目标 Graphics 对象
522
+ * @param cx 中心X坐标
523
+ * @param cy 中心Y坐标
524
+ * @param angle 旋转角度(弧度,0 = 朝上)
525
+ * @param color 填充颜色
526
+ * @param scale 额外缩放因子(默认1)
527
+ */
528
+ public drawArrowHead(
529
+ g: Phaser.GameObjects.Graphics,
530
+ cx: number,
531
+ cy: number,
532
+ angle: number,
533
+ color: number,
534
+ scale: number = 1,
535
+ ): void {
536
+ this.pathRenderer.drawArrowHead(g, cx, cy, angle, color, scale);
537
+ }
538
+
539
+ /**
540
+ * 将方向字符串转换为单位增量 { dx, dy }(静态方法)。
541
+ * @param direction 方向字符串("left" | "right" | "up" | "down")
542
+ * @returns 单位增量对象
543
+ */
544
+ public static directionToDelta(direction: string): {
545
+ dx: number;
546
+ dy: number;
547
+ } {
548
+ return PathRendererManager.directionToDelta(direction);
549
+ }
550
+
551
+ /**
552
+ * 将方向字符串转换为角度(弧度,0 = 朝上)(静态方法)。
553
+ * @param direction 方向字符串("left" | "right" | "up" | "down")
554
+ * @returns 角度(弧度)
555
+ */
556
+ public static directionToAngle(direction: string): number {
557
+ return PathRendererManager.directionToAngle(direction);
558
+ }
559
+
560
+ /**
561
+ * 将方向字符串转换为单位增量 { dx, dy }(实例方法包装)。
562
+ * 供 AnimationManager 等模块通过接口调用。
563
+ * @param direction 方向字符串
564
+ * @returns 单位增量对象
565
+ */
566
+ public directionToDelta(direction: string): { dx: number; dy: number } {
567
+ return PathRendererManager.directionToDelta(direction);
568
+ }
569
+
570
+ /**
571
+ * 渲染关卡中的所有网格路径。
572
+ * 委托给 PathRendererManager 执行实际渲染(含入场错开动画)。
573
+ * @param level 关卡数据
574
+ * @param clampedProgress 入场动画进度(0-1)
575
+ */
576
+ public renderGridPaths(level: ParsedLevel, clampedProgress: number): void {
577
+ this.pathRenderer.renderGridPaths(level, clampedProgress);
578
+ }
579
+
580
+ /**
581
+ * 构建棋盘。
582
+ * 委托给 BoardLayout 管理器执行棋盘布局和路径绘制。
583
+ * @param level 关卡数据
584
+ * @param drawProgress 绘制进度(0-1,用于入场动画)
585
+ */
586
+ private buildBoard(level: ParsedLevel, drawProgress: number = 1) {
587
+ this.boardLayout.buildBoard(level, drawProgress);
588
+ }
589
+
590
+ /**
591
+ * 渲染提示高亮覆盖层。
592
+ * 委托给 PathRendererManager 执行实际渲染(带脉冲缩放效果)。
593
+ */
594
+ public renderHintOverlay(): void {
595
+ this.pathRenderer.renderHintOverlay();
596
+ }
597
+
598
+ /**
599
+ * 获取指定路径的基础颜色。
600
+ * 委托给 PathRendererManager 根据主题和关卡数据返回颜色值。
601
+ * @param pathIndex 路径索引
602
+ * @returns 颜色值(十六进制数字)
603
+ */
604
+ public getPathBaseColor(pathIndex: number): number {
605
+ return this.pathRenderer.getPathBaseColor(pathIndex);
606
+ }
607
+
608
+ /**
609
+ * 查找当前可移除的路径索引。
610
+ * 遍历所有路径,找到第一条沿方向可以直接滑出棋盘而不被其它路径阻挡的路径。
611
+ * @returns 可移除的路径索引,如果没有则返回 null
612
+ */
613
+ public findRemovablePathIndex(): number | null {
614
+ if (!this.level) return null;
615
+ const level = this.level;
616
+
617
+ for (let i = 0; i < level.paths.length; i++) {
618
+ if (this.removedPaths.has(i)) {
619
+ console.log("[Hint] skip path", i, "because it is already removed");
620
+ continue;
621
+ }
622
+ if (this.animatingPaths.has(i)) {
623
+ console.log("[Hint] skip path", i, "because it is animating");
624
+ continue;
625
+ }
626
+
627
+ const path = level.paths[i]!;
628
+ const { dx, dy } = Game.directionToDelta(path.direction);
629
+
630
+ if (dx === 0 && dy === 0) {
631
+ console.log("[Hint] skip path", i, "because direction is (0,0)");
632
+ continue;
633
+ }
634
+
635
+ let x = path.head.x;
636
+ let y = path.head.y;
637
+ const maxSteps = Math.max(level.cols, level.rows) + 1;
638
+
639
+ for (let step = 0; step < maxSteps; step++) {
640
+ x += dx;
641
+ y += dy;
642
+
643
+ // 能直接走出棋盘,说明是可移除路径
644
+ if (x < 0 || y < 0 || x >= level.cols || y >= level.rows) {
645
+ console.log(
646
+ "[Hint] path",
647
+ i,
648
+ "is removable: exits board at step",
649
+ step + 1,
650
+ "pos =",
651
+ x,
652
+ y,
653
+ );
654
+ return i;
655
+ }
656
+
657
+ // 被其它路径阻挡,则本路径当前不可直接移除
658
+ if (this.isCellOccupiedByAnyPath(x, y, i)) {
659
+ console.log(
660
+ "[Hint] path",
661
+ i,
662
+ "blocked by another path at cell",
663
+ x,
664
+ y,
665
+ "step",
666
+ step + 1,
667
+ );
668
+ break;
669
+ }
670
+ }
671
+ }
672
+
673
+ console.log(
674
+ "[Hint] No removable path found (all paths either removed, animating, or blocked)",
675
+ );
676
+ return null;
677
+ }
678
+
679
+ /**
680
+ * 判断指定格子是否被任意路径占据。
681
+ * @param col 列号
682
+ * @param row 行号
683
+ * @param ignorePathIndex 需要忽略的路径索引(可选,用于排除自身)
684
+ * @returns 如果被占据返回 true,否则返回 false
685
+ */
686
+ public isCellOccupiedByAnyPath(
687
+ col: number,
688
+ row: number,
689
+ ignorePathIndex?: number,
690
+ ): boolean {
691
+ if (!this.level) return false;
692
+ const level = this.level;
693
+ const idx = row * level.cols + col;
694
+ return level.paths.some((p, i) => {
695
+ if (this.removedPaths.has(i)) return false;
696
+ if (ignorePathIndex !== undefined && i === ignorePathIndex) return false;
697
+ return p.indices.includes(idx);
698
+ });
699
+ }
700
+
701
+ /**
702
+ * 计算指定格子的中心坐标。
703
+ * 委托给 PathRendererManager 执行计算。
704
+ * @param col 列号
705
+ * @param row 行号
706
+ * @returns 中心坐标 { x, y }
707
+ */
708
+ public cellCenter(col: number, row: number): { x: number; y: number } {
709
+ return this.pathRenderer.cellCenter(col, row);
710
+ }
711
+
712
+ /**
713
+ * 绘制轴对齐的线段矩形(用于路径体渲染)。
714
+ * 委托给 PathRendererManager 执行实际绘制,支持亚像素抗锯齿。
715
+ * @param g 目标 Graphics 对象
716
+ * @param x1 起点X坐标
717
+ * @param y1 起点Y坐标
718
+ * @param x2 终点X坐标
719
+ * @param y2 终点Y坐标
720
+ * @param lineWidth 线宽
721
+ */
722
+ public fillAxisAlignedSegmentRect(
723
+ g: Phaser.GameObjects.Graphics,
724
+ x1: number,
725
+ y1: number,
726
+ x2: number,
727
+ y2: number,
728
+ lineWidth: number,
729
+ ) {
730
+ this.pathRenderer.fillAxisAlignedSegmentRect(g, x1, y1, x2, y2, lineWidth);
731
+ }
732
+
733
+ /**
734
+ * 重新布局棋盘。
735
+ * 在窗口大小变化时调用,委托给 BoardLayout 管理器。
736
+ */
737
+ public relayoutBoard() {
738
+ this.boardLayout.relayoutBoard();
739
+ }
740
+
741
+ /**
742
+ * 定位棋盘容器。
743
+ * 根据当前缩放和偏移重新计算容器位置,委托给 BoardLayout 管理器。
744
+ */
745
+ public positionBoardContainer() {
746
+ this.boardLayout.positionBoardContainer();
747
+ }
748
+ }