@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.
- package/README.md +333 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/skills.loader.d.ts +31 -0
- package/dist/src/skills.loader.d.ts.map +1 -0
- package/dist/src/skills.loader.js +200 -0
- package/dist/src/skills.loader.js.map +1 -0
- package/dist/src/skills.types.d.ts +44 -0
- package/dist/src/skills.types.d.ts.map +1 -0
- package/dist/src/skills.types.js +9 -0
- package/dist/src/skills.types.js.map +1 -0
- package/package.json +35 -0
- package/skills/2048_core.aigameplay/SKILL.md +123 -0
- package/skills/2048_core.aigameplay/manifest.json +159 -0
- package/skills/2048_core.aigameplay/ref/pgs-schema.json +194 -0
- package/skills/2048_core.aigameplay/ref/reducer.template.ts +189 -0
- package/skills/SKILL.md +46 -0
- package/skills/ad_compliance_rules.aiconfig/SKILL.md +85 -0
- package/skills/ad_compliance_rules.aiconfig/manifest.json +60 -0
- package/skills/agent_remix_orchestrator.aicomponent/SKILL.md +257 -0
- package/skills/agent_remix_orchestrator.aicomponent/manifest.json +12 -0
- package/skills/app_metadata.aiconfig/SKILL.md +53 -0
- package/skills/app_metadata.aiconfig/manifest.json +32 -0
- package/skills/appear_sfx.aiaudio/SKILL.md +59 -0
- package/skills/appear_sfx.aiaudio/manifest.json +45 -0
- package/skills/appear_sfx.aiaudio/ref/appear.mp3 +0 -0
- package/skills/arrow_move_error_sfx.aiaudio/SKILL.md +59 -0
- package/skills/arrow_move_error_sfx.aiaudio/manifest.json +45 -0
- package/skills/arrow_move_error_sfx.aiaudio/ref/arrow_move_error.mp3 +0 -0
- package/skills/arrow_path_data_format.aicomponent/SKILL.md +152 -0
- package/skills/arrow_path_data_format.aicomponent/manifest.json +57 -0
- package/skills/arrow_path_data_format.aicomponent/ref/LevelParser.ts +188 -0
- package/skills/arrow_path_data_format.aicomponent/ref/LevelTypes.ts +131 -0
- package/skills/arrow_pick_match_rules.aigameplay/SKILL.md +117 -0
- package/skills/arrow_pick_match_rules.aigameplay/manifest.json +105 -0
- package/skills/arrow_pick_match_rules.aigameplay/ref/pgs-schema.json +180 -0
- package/skills/asset_pipeline_scripts.aicomponent/SKILL.md +117 -0
- package/skills/asset_pipeline_scripts.aicomponent/manifest.json +17 -0
- package/skills/asset_pipeline_scripts.aicomponent/ref/gen-sprite.sh +105 -0
- package/skills/ball_sort.aigameplay/SKILL.md +109 -0
- package/skills/ball_sort.aigameplay/manifest.json +155 -0
- package/skills/ball_sort.aigameplay/ref/pgs-schema.json +192 -0
- package/skills/ball_sort.aigameplay/ref/reducer.template.ts +156 -0
- package/skills/basketball_shot.aigameplay/SKILL.md +94 -0
- package/skills/basketball_shot.aigameplay/manifest.json +150 -0
- package/skills/basketball_shot.aigameplay/ref/pgs-schema.json +229 -0
- package/skills/basketball_shot.aigameplay/ref/reducer.template.ts +189 -0
- package/skills/bg_music.aiaudio/SKILL.md +61 -0
- package/skills/bg_music.aiaudio/manifest.json +48 -0
- package/skills/bg_music.aiaudio/ref/bg.mp3 +0 -0
- package/skills/big_watermelon.aigameplay/SKILL.md +94 -0
- package/skills/big_watermelon.aigameplay/manifest.json +155 -0
- package/skills/big_watermelon.aigameplay/ref/pgs-schema.json +191 -0
- package/skills/big_watermelon.aigameplay/ref/reducer.template.ts +202 -0
- package/skills/block_puzzle.aigameplay/SKILL.md +121 -0
- package/skills/block_puzzle.aigameplay/manifest.json +154 -0
- package/skills/block_puzzle.aigameplay/ref/pgs-schema.json +170 -0
- package/skills/block_puzzle.aigameplay/ref/reducer.template.ts +182 -0
- package/skills/board_entity_sprite.aiimage/SKILL.md +255 -0
- package/skills/board_entity_sprite.aiimage/manifest.json +153 -0
- package/skills/board_entity_sprite.aiimage/ref/ProceduralCar.ts +357 -0
- package/skills/board_entity_sprite.aiimage/ref/car.png +0 -0
- package/skills/board_entity_sprite.aiimage/ref/car.webp +0 -0
- package/skills/bottom_ui_bar.aicomponent/SKILL.md +50 -0
- package/skills/bottom_ui_bar.aicomponent/manifest.json +31 -0
- package/skills/bottom_ui_bar.aicomponent/ref/GameBottomUI.ts +27 -0
- package/skills/bubble_shooter.aigameplay/SKILL.md +129 -0
- package/skills/bubble_shooter.aigameplay/manifest.json +181 -0
- package/skills/bubble_shooter.aigameplay/ref/pgs-schema.json +226 -0
- package/skills/bubble_shooter.aigameplay/ref/reducer.template.ts +228 -0
- package/skills/button_click_sfx.aiaudio/SKILL.md +59 -0
- package/skills/button_click_sfx.aiaudio/manifest.json +45 -0
- package/skills/button_click_sfx.aiaudio/ref/button_click.mp3 +0 -0
- package/skills/calm_piano.aiaudio/SKILL.md +68 -0
- package/skills/calm_piano.aiaudio/manifest.json +50 -0
- package/skills/camera_controller_3d.aicomponent/SKILL.md +100 -0
- package/skills/camera_controller_3d.aicomponent/manifest.json +52 -0
- package/skills/camera_controller_3d.aicomponent/ref/CameraController.ts +199 -0
- package/skills/camera_controller_3d.aicomponent/ref/OrbitControlsAdapter.ts +152 -0
- package/skills/candy_tile.aiimage/SKILL.md +62 -0
- package/skills/candy_tile.aiimage/manifest.json +49 -0
- package/skills/car_parking.aigameplay/SKILL.md +105 -0
- package/skills/car_parking.aigameplay/manifest.json +164 -0
- package/skills/car_parking.aigameplay/ref/pgs-schema.json +163 -0
- package/skills/car_parking.aigameplay/ref/reducer.template.ts +166 -0
- package/skills/castle.aiimage/SKILL.md +64 -0
- package/skills/castle.aiimage/manifest.json +48 -0
- package/skills/cheerful_ukulele.aiaudio/SKILL.md +72 -0
- package/skills/cheerful_ukulele.aiaudio/manifest.json +50 -0
- package/skills/click_sfx.aiaudio/SKILL.md +59 -0
- package/skills/click_sfx.aiaudio/manifest.json +45 -0
- package/skills/click_sfx.aiaudio/ref/click.mp3 +0 -0
- package/skills/combo_display.aicomponent/SKILL.md +45 -0
- package/skills/combo_display.aicomponent/manifest.json +31 -0
- package/skills/combo_display.aicomponent/ref/ComboManager.ts +362 -0
- package/skills/combo_display.aicomponent/ref/ComboSmallUI.ts +232 -0
- package/skills/combo_praise_text.aicomponent/SKILL.md +56 -0
- package/skills/combo_praise_text.aicomponent/manifest.json +34 -0
- package/skills/combo_praise_text.aicomponent/ref/ComboManager.ts +362 -0
- package/skills/countdown_timer.aicomponent/SKILL.md +44 -0
- package/skills/countdown_timer.aicomponent/manifest.json +35 -0
- package/skills/countdown_timer.aicomponent/ref/CountdownDisplay.ts +213 -0
- package/skills/cta_platform_config.aiconfig/SKILL.md +72 -0
- package/skills/cta_platform_config.aiconfig/manifest.json +56 -0
- package/skills/debug_overlay.aicomponent/SKILL.md +75 -0
- package/skills/debug_overlay.aicomponent/manifest.json +17 -0
- package/skills/debug_overlay.aicomponent/ref/DebugOverlay.ts +144 -0
- package/skills/desert.aiimage/SKILL.md +63 -0
- package/skills/desert.aiimage/manifest.json +49 -0
- package/skills/difficulty_curve_designer.aiconfig/SKILL.md +68 -0
- package/skills/difficulty_curve_designer.aiconfig/manifest.json +36 -0
- package/skills/digit_renderer.aicomponent/SKILL.md +43 -0
- package/skills/digit_renderer.aicomponent/manifest.json +25 -0
- package/skills/digit_renderer.aicomponent/ref/DigitRenderer.ts +237 -0
- package/skills/download_button.aicomponent/SKILL.md +44 -0
- package/skills/download_button.aicomponent/manifest.json +25 -0
- package/skills/download_button.aicomponent/ref/DownloadButton.ts +137 -0
- package/skills/draw_line_puzzle.aigameplay/SKILL.md +84 -0
- package/skills/draw_line_puzzle.aigameplay/manifest.json +152 -0
- package/skills/draw_line_puzzle.aigameplay/ref/pgs-schema.json +189 -0
- package/skills/draw_line_puzzle.aigameplay/ref/reducer.template.ts +194 -0
- package/skills/easy_to_hard.aiconfig/SKILL.md +52 -0
- package/skills/easy_to_hard.aiconfig/manifest.json +33 -0
- package/skills/eight_ball_pool.aigameplay/SKILL.md +104 -0
- package/skills/eight_ball_pool.aigameplay/manifest.json +152 -0
- package/skills/eight_ball_pool.aigameplay/ref/pgs-schema.json +205 -0
- package/skills/eight_ball_pool.aigameplay/ref/reducer.template.ts +198 -0
- package/skills/energetic_electronic.aiaudio/SKILL.md +69 -0
- package/skills/energetic_electronic.aiaudio/manifest.json +51 -0
- package/skills/fail_sfx.aiaudio/SKILL.md +59 -0
- package/skills/fail_sfx.aiaudio/manifest.json +44 -0
- package/skills/fail_sfx.aiaudio/ref/fail.mp3 +0 -0
- package/skills/figer_icon.aiimage/SKILL.md +58 -0
- package/skills/figer_icon.aiimage/manifest.json +48 -0
- package/skills/figer_icon.aiimage/ref/figer.png +0 -0
- package/skills/figer_icon.aiimage/ref/figer.webp +0 -0
- package/skills/forest.aiimage/SKILL.md +74 -0
- package/skills/forest.aiimage/manifest.json +48 -0
- package/skills/fruit_tile.aiimage/SKILL.md +68 -0
- package/skills/fruit_tile.aiimage/manifest.json +48 -0
- package/skills/game_over_panel.aicomponent/SKILL.md +47 -0
- package/skills/game_over_panel.aicomponent/manifest.json +61 -0
- package/skills/game_over_panel.aicomponent/ref/GameOverPanel.ts +74 -0
- package/skills/game_scene.aicomponent/SKILL.md +57 -0
- package/skills/game_scene.aicomponent/manifest.json +36 -0
- package/skills/game_scene.aicomponent/ref/Game.ts +748 -0
- package/skills/gameplay_balance_check.aivalidator/SKILL.md +69 -0
- package/skills/gameplay_balance_check.aivalidator/manifest.json +21 -0
- package/skills/gameplay_unit_test.aivalidator/SKILL.md +89 -0
- package/skills/gameplay_unit_test.aivalidator/manifest.json +17 -0
- package/skills/gameplay_unit_test.aivalidator/ref/gameplay.test.ts +202 -0
- package/skills/gameplay_unit_test.aivalidator/ref/vitest.config.ts +13 -0
- package/skills/grid_board_layout.aicomponent/SKILL.md +85 -0
- package/skills/grid_board_layout.aicomponent/manifest.json +69 -0
- package/skills/grid_board_layout.aicomponent/ref/BoardLayout.ts +416 -0
- package/skills/grid_board_layout.aicomponent/ref/BoardLayout3D.ts +125 -0
- package/skills/grid_board_layout.aicomponent/ref/BoardLayoutMath.ts +85 -0
- package/skills/grid_board_layout.aicomponent/ref/BoardRenderer3D.ts +298 -0
- package/skills/heart_lives.aicomponent/SKILL.md +42 -0
- package/skills/heart_lives.aicomponent/manifest.json +25 -0
- package/skills/heart_lives.aicomponent/ref/HeartDisplay.ts +96 -0
- package/skills/idle-breathe.aicomponent/SKILL.md +27 -0
- package/skills/idle-breathe.aicomponent/manifest.json +20 -0
- package/skills/idle-breathe.aicomponent/ref/phaser.js +25 -0
- package/skills/idle-breathe.aicomponent/ref/playcanvas.js +29 -0
- package/skills/jewel_tile.aiimage/SKILL.md +63 -0
- package/skills/jewel_tile.aiimage/manifest.json +49 -0
- package/skills/knife_hit.aigameplay/SKILL.md +103 -0
- package/skills/knife_hit.aigameplay/manifest.json +151 -0
- package/skills/knife_hit.aigameplay/ref/pgs-schema.json +202 -0
- package/skills/knife_hit.aigameplay/ref/reducer.template.ts +196 -0
- package/skills/left_right_parkour.aigameplay/SKILL.md +120 -0
- package/skills/left_right_parkour.aigameplay/manifest.json +165 -0
- package/skills/left_right_parkour.aigameplay/ref/pgs-schema.json +200 -0
- package/skills/left_right_parkour.aigameplay/ref/reducer.template.ts +194 -0
- package/skills/level_data_pack.aiconfig/SKILL.md +64 -0
- package/skills/level_data_pack.aiconfig/manifest.json +37 -0
- package/skills/level_data_validator.aivalidator/SKILL.md +85 -0
- package/skills/level_data_validator.aivalidator/manifest.json +17 -0
- package/skills/level_data_validator.aivalidator/ref/LevelValidator.ts +113 -0
- package/skills/level_lifecycle.aicomponent/SKILL.md +81 -0
- package/skills/level_lifecycle.aicomponent/manifest.json +87 -0
- package/skills/level_lifecycle.aicomponent/ref/LevelLifecycle.ts +235 -0
- package/skills/level_solvability_validator.aivalidator/SKILL.md +74 -0
- package/skills/level_solvability_validator.aivalidator/manifest.json +23 -0
- package/skills/level_solvability_validator.aivalidator/ref/LevelValidator.ts +186 -0
- package/skills/level_state.aicomponent/SKILL.md +55 -0
- package/skills/level_state.aicomponent/manifest.json +34 -0
- package/skills/level_state.aicomponent/ref/LevelDataManager.ts +26 -0
- package/skills/level_state.aicomponent/ref/LevelManager.ts +26 -0
- package/skills/loading_screen.aicomponent/SKILL.md +57 -0
- package/skills/loading_screen.aicomponent/manifest.json +43 -0
- package/skills/loading_screen.aicomponent/ref/LoadingUI.ts +339 -0
- package/skills/lose_result_panel.aiimage/SKILL.md +58 -0
- package/skills/lose_result_panel.aiimage/manifest.json +47 -0
- package/skills/lose_result_panel.aiimage/ref/lose.png +0 -0
- package/skills/lose_result_panel.aiimage/ref/lose.webp +0 -0
- package/skills/lose_sfx.aiaudio/SKILL.md +59 -0
- package/skills/lose_sfx.aiaudio/manifest.json +45 -0
- package/skills/lose_sfx.aiaudio/ref/lose.mp3 +0 -0
- package/skills/match-pop.aicomponent/SKILL.md +29 -0
- package/skills/match-pop.aicomponent/manifest.json +19 -0
- package/skills/match-pop.aicomponent/ref/phaser.js +30 -0
- package/skills/match-pop.aicomponent/ref/playcanvas.js +22 -0
- package/skills/match3_core.aigameplay/SKILL.md +125 -0
- package/skills/match3_core.aigameplay/manifest.json +107 -0
- package/skills/match3_core.aigameplay/ref/pgs-schema.json +154 -0
- package/skills/match3_core.aigameplay/ref/reducer.template.ts +191 -0
- package/skills/match_engine.aicomponent/SKILL.md +84 -0
- package/skills/match_engine.aicomponent/manifest.json +23 -0
- package/skills/match_engine.aicomponent/ref/MatchEngine.ts +75 -0
- package/skills/memory_match.aigameplay/SKILL.md +111 -0
- package/skills/memory_match.aigameplay/manifest.json +164 -0
- package/skills/memory_match.aigameplay/ref/pgs-schema.json +190 -0
- package/skills/memory_match.aigameplay/ref/reducer.template.ts +162 -0
- package/skills/merge_core.aigameplay/SKILL.md +112 -0
- package/skills/merge_core.aigameplay/manifest.json +154 -0
- package/skills/merge_core.aigameplay/ref/pgs-schema.json +202 -0
- package/skills/merge_core.aigameplay/ref/reducer.template.ts +179 -0
- package/skills/mistake_sfx.aiaudio/SKILL.md +59 -0
- package/skills/mistake_sfx.aiaudio/manifest.json +45 -0
- package/skills/mistake_sfx.aiaudio/ref/mistake.mp3 +0 -0
- package/skills/nomove_hint_overlay.aiimage/SKILL.md +58 -0
- package/skills/nomove_hint_overlay.aiimage/manifest.json +48 -0
- package/skills/nomove_hint_overlay.aiimage/ref/nomove_hint.png +0 -0
- package/skills/nomove_hint_overlay.aiimage/ref/nomove_hint.webp +0 -0
- package/skills/normal_dot.aiimage/SKILL.md +58 -0
- package/skills/normal_dot.aiimage/manifest.json +46 -0
- package/skills/normal_dot.aiimage/ref/normal_dot.png +0 -0
- package/skills/normal_dot.aiimage/ref/normal_dot.webp +0 -0
- package/skills/ocean.aiimage/SKILL.md +71 -0
- package/skills/ocean.aiimage/manifest.json +49 -0
- package/skills/particle-confetti.aicomponent/SKILL.md +32 -0
- package/skills/particle-confetti.aicomponent/manifest.json +21 -0
- package/skills/particle-confetti.aicomponent/ref/html5-spritesheet.js +17 -0
- package/skills/particle-confetti.aicomponent/ref/phaser.js +38 -0
- package/skills/particle-explosion.aicomponent/SKILL.md +37 -0
- package/skills/particle-explosion.aicomponent/manifest.json +24 -0
- package/skills/particle-explosion.aicomponent/ref/html5-spritesheet.js +40 -0
- package/skills/particle-explosion.aicomponent/ref/phaser.js +46 -0
- package/skills/particle-explosion.aicomponent/ref/playcanvas.js +33 -0
- package/skills/particle-trail.aicomponent/SKILL.md +25 -0
- package/skills/particle-trail.aicomponent/manifest.json +22 -0
- package/skills/particle-trail.aicomponent/ref/phaser.js +31 -0
- package/skills/path_animation.aicomponent/SKILL.md +82 -0
- package/skills/path_animation.aicomponent/manifest.json +77 -0
- package/skills/path_animation.aicomponent/ref/AnimationManager.ts +694 -0
- package/skills/path_animation.aicomponent/ref/AnimationManager3D.ts +317 -0
- package/skills/path_elimination_rules.aigameplay/SKILL.md +88 -0
- package/skills/path_elimination_rules.aigameplay/manifest.json +119 -0
- package/skills/path_elimination_rules.aigameplay/ref/pgs-schema.json +227 -0
- package/skills/path_input_handler.aicomponent/SKILL.md +87 -0
- package/skills/path_input_handler.aicomponent/manifest.json +97 -0
- package/skills/path_input_handler.aicomponent/ref/InputHandler.ts +714 -0
- package/skills/path_input_handler.aicomponent/ref/InputHandler3D.ts +204 -0
- package/skills/path_renderer.aicomponent/SKILL.md +101 -0
- package/skills/path_renderer.aicomponent/manifest.json +69 -0
- package/skills/path_renderer.aicomponent/ref/PathRenderer.ts +509 -0
- package/skills/path_renderer.aicomponent/ref/PathRenderer3D.ts +176 -0
- package/skills/path_renderer.aicomponent/ref/PathRenderers.ts +640 -0
- package/skills/phaser.aicomponent/SKILL.md +315 -0
- package/skills/phaser.aicomponent/manifest.json +156 -0
- package/skills/phaser.aicomponent/ref/BootScene.ts +29 -0
- package/skills/phaser.aicomponent/ref/GameConfig.ts +29 -0
- package/skills/phaser.aicomponent/ref/GameScene.ts +88 -0
- package/skills/phaser.aicomponent/ref/PreloaderScene.ts +78 -0
- package/skills/phaser.aicomponent/ref/SceneKeys.ts +7 -0
- package/skills/phaser.aicomponent/ref/SoundUtils.ts +21 -0
- package/skills/phaser.aicomponent/ref/UiLayout.ts +74 -0
- package/skills/phaser.aicomponent/ref/globals.d.ts +52 -0
- package/skills/phaser.aicomponent/ref/index.css +40 -0
- package/skills/phaser.aicomponent/ref/index.html +14 -0
- package/skills/phaser.aicomponent/ref/index.ts +48 -0
- package/skills/phaser.aicomponent/ref/main.ts +16 -0
- package/skills/phaser.aicomponent/ref/package.json +22 -0
- package/skills/phaser.aicomponent/ref/tsconfig.json +25 -0
- package/skills/phaser.aicomponent/ref/webpack.config.js +57 -0
- package/skills/phaser_scene_lifecycle.aicomponent/SKILL.md +63 -0
- package/skills/phaser_scene_lifecycle.aicomponent/manifest.json +33 -0
- package/skills/pick_and_match_rules.aigameplay/SKILL.md +113 -0
- package/skills/pick_and_match_rules.aigameplay/manifest.json +121 -0
- package/skills/pick_and_match_rules.aigameplay/ref/pgs-schema.json +354 -0
- package/skills/pin_pull.aigameplay/SKILL.md +110 -0
- package/skills/pin_pull.aigameplay/manifest.json +164 -0
- package/skills/pin_pull.aigameplay/ref/pgs-schema.json +201 -0
- package/skills/pin_pull.aigameplay/ref/reducer.template.ts +216 -0
- package/skills/playable_app_logo.aiimage/SKILL.md +58 -0
- package/skills/playable_app_logo.aiimage/manifest.json +47 -0
- package/skills/playable_app_logo.aiimage/ref/logo.png +0 -0
- package/skills/playable_app_logo.aiimage/ref/logo.webp +0 -0
- package/skills/playable_end_screen_layout.aicomponent/SKILL.md +75 -0
- package/skills/playable_end_screen_layout.aicomponent/manifest.json +24 -0
- package/skills/playable_guidance_layer.aicomponent/SKILL.md +89 -0
- package/skills/playable_guidance_layer.aicomponent/manifest.json +24 -0
- package/skills/playable_hud_layout.aicomponent/SKILL.md +96 -0
- package/skills/playable_hud_layout.aicomponent/manifest.json +24 -0
- package/skills/playable_scripts_build.aicomponent/SKILL.md +69 -0
- package/skills/playable_scripts_build.aicomponent/manifest.json +53 -0
- package/skills/playable_scripts_build.aicomponent/ref/builds.config.js +257 -0
- package/skills/playcraft-3d-flip-sprite/SKILL.md +336 -0
- package/skills/playcraft-3d-flip-sprite/renderer/flatten_glb.mjs +62 -0
- package/skills/playcraft-3d-flip-sprite/renderer/render.mjs +325 -0
- package/skills/playcraft-3d-flip-sprite/renderer/render_single.mjs +138 -0
- package/skills/playcraft-asset-management/SKILL.md +73 -0
- package/skills/playcraft-audio-generation/SKILL.md +126 -0
- package/skills/playcraft-build/SKILL.md +44 -0
- package/skills/playcraft-code-editor/SKILL.md +71 -0
- package/skills/playcraft-create-remix/SKILL.md +62 -0
- package/skills/playcraft-deploy/SKILL.md +59 -0
- package/skills/playcraft-image-generation/SKILL.md +148 -0
- package/skills/playcraft-image-processing/SKILL.md +216 -0
- package/skills/playcraft-platform-intro/SKILL.md +41 -0
- package/skills/playcraft-prefab/SKILL.md +98 -0
- package/skills/playcraft-project-management/SKILL.md +57 -0
- package/skills/playcraft-remix-workflow/SKILL.md +119 -0
- package/skills/playcraft-remix-workflow/references/xplatform.schema.json5 +31 -0
- package/skills/playcraft-save/SKILL.md +46 -0
- package/skills/playcraft-skill-recommender/SKILL.md +152 -0
- package/skills/playcraft-sprite-generation/SKILL.md +534 -0
- package/skills/playcraft-sprite-remix/SKILL.md +155 -0
- package/skills/playcraft-sprite-sheet/SKILL.md +97 -0
- package/skills/playtest_report.aivalidator/SKILL.md +103 -0
- package/skills/playtest_report.aivalidator/manifest.json +21 -0
- package/skills/preloader_scene.aicomponent/SKILL.md +58 -0
- package/skills/preloader_scene.aicomponent/manifest.json +43 -0
- package/skills/preloader_scene.aicomponent/ref/Preloader.ts +339 -0
- package/skills/progress_bar.aicomponent/SKILL.md +38 -0
- package/skills/progress_bar.aicomponent/manifest.json +25 -0
- package/skills/progress_bar.aicomponent/ref/ProgressDisplay.ts +140 -0
- package/skills/references/xplatform.schema.json5 +31 -0
- package/skills/responsive_2d_layout.aicomponent/SKILL.md +161 -0
- package/skills/responsive_2d_layout.aicomponent/manifest.json +43 -0
- package/skills/responsive_2d_layout.aicomponent/ref/UiLayout.ts +56 -0
- package/skills/run_context_state.aicomponent/SKILL.md +54 -0
- package/skills/run_context_state.aicomponent/manifest.json +40 -0
- package/skills/run_context_state.aicomponent/ref/RunContextRuntime.ts +30 -0
- package/skills/score-fly.aicomponent/SKILL.md +31 -0
- package/skills/score-fly.aicomponent/manifest.json +21 -0
- package/skills/score-fly.aicomponent/ref/phaser.js +26 -0
- package/skills/score-fly.aicomponent/ref/playcanvas.js +28 -0
- package/skills/score_goal.aiconfig/SKILL.md +46 -0
- package/skills/score_goal.aiconfig/manifest.json +33 -0
- package/skills/screen-flash.aicomponent/SKILL.md +30 -0
- package/skills/screen-flash.aicomponent/manifest.json +20 -0
- package/skills/screen-flash.aicomponent/ref/phaser.js +48 -0
- package/skills/screen-shake.aicomponent/SKILL.md +30 -0
- package/skills/screen-shake.aicomponent/manifest.json +19 -0
- package/skills/screen-shake.aicomponent/ref/phaser.js +23 -0
- package/skills/screen-shake.aicomponent/ref/playcanvas.js +44 -0
- package/skills/screw_puzzle.aigameplay/SKILL.md +116 -0
- package/skills/screw_puzzle.aigameplay/manifest.json +164 -0
- package/skills/screw_puzzle.aigameplay/ref/pgs-schema.json +235 -0
- package/skills/screw_puzzle.aigameplay/ref/reducer.template.ts +213 -0
- package/skills/settings_state.aicomponent/SKILL.md +61 -0
- package/skills/settings_state.aicomponent/manifest.json +33 -0
- package/skills/settings_state.aicomponent/ref/SettingsManager.ts +130 -0
- package/skills/slide_out_to_tray_animation.aicomponent/SKILL.md +64 -0
- package/skills/slide_out_to_tray_animation.aicomponent/manifest.json +58 -0
- package/skills/slide_out_to_tray_animation.aicomponent/ref/AnimationManager.ts +164 -0
- package/skills/slide_out_to_tray_animation.aicomponent/ref/AnimationManager3D.ts +198 -0
- package/skills/slide_out_to_tray_animation.aicomponent/ref/BezierUtils.ts +59 -0
- package/skills/slot_machine.aigameplay/SKILL.md +119 -0
- package/skills/slot_machine.aigameplay/manifest.json +166 -0
- package/skills/slot_machine.aigameplay/ref/pgs-schema.json +212 -0
- package/skills/slot_machine.aigameplay/ref/reducer.template.ts +212 -0
- package/skills/sniper_shot.aigameplay/SKILL.md +84 -0
- package/skills/sniper_shot.aigameplay/manifest.json +153 -0
- package/skills/sniper_shot.aigameplay/ref/pgs-schema.json +211 -0
- package/skills/sniper_shot.aigameplay/ref/reducer.template.ts +211 -0
- package/skills/solitaire.aigameplay/SKILL.md +101 -0
- package/skills/solitaire.aigameplay/manifest.json +151 -0
- package/skills/solitaire.aigameplay/ref/pgs-schema.json +200 -0
- package/skills/solitaire.aigameplay/ref/reducer.template.ts +176 -0
- package/skills/sound-effects/SKILL.md +46 -0
- package/skills/sound_utils.aicomponent/SKILL.md +52 -0
- package/skills/sound_utils.aicomponent/manifest.json +30 -0
- package/skills/sound_utils.aicomponent/ref/SoundUtils.ts +29 -0
- package/skills/sprite-animation-2d.aicomponent/SKILL.md +45 -0
- package/skills/sprite-animation-2d.aicomponent/manifest.json +28 -0
- package/skills/sprite-animation-2d.aicomponent/ref/html5.js +83 -0
- package/skills/sprite-animation-2d.aicomponent/ref/phaser.js +38 -0
- package/skills/sprite-animation-2d.aicomponent/ref/playcanvas.js +67 -0
- package/skills/sprite_entity_renderer.aicomponent/SKILL.md +148 -0
- package/skills/sprite_entity_renderer.aicomponent/manifest.json +17 -0
- package/skills/sprite_entity_renderer.aicomponent/ref/SpriteEntityRenderer.ts +126 -0
- package/skills/success_sfx.aiaudio/SKILL.md +59 -0
- package/skills/success_sfx.aiaudio/manifest.json +45 -0
- package/skills/success_sfx.aiaudio/ref/success.mp3 +0 -0
- package/skills/tap_blast.aigameplay/SKILL.md +116 -0
- package/skills/tap_blast.aigameplay/manifest.json +153 -0
- package/skills/tap_blast.aigameplay/ref/pgs-schema.json +208 -0
- package/skills/tap_blast.aigameplay/ref/reducer.template.ts +202 -0
- package/skills/theme_state.aicomponent/SKILL.md +53 -0
- package/skills/theme_state.aicomponent/manifest.json +33 -0
- package/skills/theme_state.aicomponent/ref/ThemeManager.ts +174 -0
- package/skills/theme_switcher_build.aicomponent/SKILL.md +62 -0
- package/skills/theme_switcher_build.aicomponent/manifest.json +38 -0
- package/skills/theme_switcher_build.aicomponent/ref/theme-index.ts +8 -0
- package/skills/theme_variant.aiconfig/SKILL.md +78 -0
- package/skills/theme_variant.aiconfig/manifest.json +39 -0
- package/skills/theme_variant.aiconfig/ref/ExampleTheme/index.ts +16 -0
- package/skills/theme_variant.aiconfig/ref/ExampleTheme/levelEasy.json +141 -0
- package/skills/threejs.aicomponent/SKILL.md +422 -0
- package/skills/threejs.aicomponent/manifest.json +166 -0
- package/skills/threejs.aicomponent/ref/AssetLoader.ts +158 -0
- package/skills/threejs.aicomponent/ref/BaseScene.ts +88 -0
- package/skills/threejs.aicomponent/ref/GameConfig.ts +47 -0
- package/skills/threejs.aicomponent/ref/MainScene.ts +170 -0
- package/skills/threejs.aicomponent/ref/PreloaderScene.ts +93 -0
- package/skills/threejs.aicomponent/ref/SceneKeys.ts +6 -0
- package/skills/threejs.aicomponent/ref/SceneManager.ts +69 -0
- package/skills/threejs.aicomponent/ref/ViewportManager.ts +62 -0
- package/skills/threejs.aicomponent/ref/globals.d.ts +74 -0
- package/skills/threejs.aicomponent/ref/index.css +80 -0
- package/skills/threejs.aicomponent/ref/index.html +20 -0
- package/skills/threejs.aicomponent/ref/index.ts +117 -0
- package/skills/threejs.aicomponent/ref/main.ts +10 -0
- package/skills/threejs.aicomponent/ref/package.json +23 -0
- package/skills/threejs.aicomponent/ref/tsconfig.json +24 -0
- package/skills/threejs.aicomponent/ref/webpack.config.js +61 -0
- package/skills/time_clear_goal.aiconfig/SKILL.md +46 -0
- package/skills/time_clear_goal.aiconfig/manifest.json +32 -0
- package/skills/time_icon.aiimage/SKILL.md +58 -0
- package/skills/time_icon.aiimage/manifest.json +47 -0
- package/skills/time_icon.aiimage/ref/time.png +0 -0
- package/skills/time_icon.aiimage/ref/time.webp +0 -0
- package/skills/top_ui_bar.aicomponent/SKILL.md +45 -0
- package/skills/top_ui_bar.aicomponent/manifest.json +27 -0
- package/skills/top_ui_bar.aicomponent/ref/GameTopUI.ts +229 -0
- package/skills/tower_defence.aigameplay/SKILL.md +117 -0
- package/skills/tower_defence.aigameplay/manifest.json +175 -0
- package/skills/tower_defence.aigameplay/ref/pgs-schema.json +247 -0
- package/skills/tower_defence.aigameplay/ref/reducer.template.ts +239 -0
- package/skills/tray_container.aicomponent/SKILL.md +143 -0
- package/skills/tray_container.aicomponent/manifest.json +58 -0
- package/skills/tray_container.aicomponent/ref/TrayRenderer.ts +155 -0
- package/skills/tray_container.aicomponent/ref/TrayRenderer3D.ts +281 -0
- package/skills/tray_container.aicomponent/ref/TrayRendererHtmlOverlay.ts +228 -0
- package/skills/tutorial_overlay.aicomponent/SKILL.md +46 -0
- package/skills/tutorial_overlay.aicomponent/manifest.json +34 -0
- package/skills/tutorial_overlay.aicomponent/ref/TutorialManager.ts +367 -0
- package/skills/tween-animation-2d.aicomponent/SKILL.md +35 -0
- package/skills/tween-animation-2d.aicomponent/manifest.json +28 -0
- package/skills/tween-animation-2d.aicomponent/ref/phaser.js +49 -0
- package/skills/tween-animation-2d.aicomponent/ref/playcanvas.js +36 -0
- package/skills/typescript_module_patterns.aicomponent/SKILL.md +209 -0
- package/skills/typescript_module_patterns.aicomponent/manifest.json +28 -0
- package/skills/typescript_module_patterns.aicomponent/ref/globals.d.ts +31 -0
- package/skills/ui-transition.aicomponent/SKILL.md +33 -0
- package/skills/ui-transition.aicomponent/manifest.json +19 -0
- package/skills/ui-transition.aicomponent/ref/phaser.js +45 -0
- package/skills/ux_flow_spec.aiconfig/SKILL.md +82 -0
- package/skills/ux_flow_spec.aiconfig/manifest.json +39 -0
- package/skills/wave_difficulty.aiconfig/SKILL.md +46 -0
- package/skills/wave_difficulty.aiconfig/manifest.json +33 -0
- package/skills/webpack_build.aicomponent/SKILL.md +204 -0
- package/skills/webpack_build.aicomponent/manifest.json +29 -0
- package/skills/webpack_build.aicomponent/ref/package.json +16 -0
- package/skills/webpack_build.aicomponent/ref/webpack.config.js +53 -0
- package/skills/win_anim_sfx.aiaudio/SKILL.md +59 -0
- package/skills/win_anim_sfx.aiaudio/manifest.json +46 -0
- package/skills/win_anim_sfx.aiaudio/ref/win_anim.mp3 +0 -0
- package/skills/win_dot.aiimage/SKILL.md +58 -0
- package/skills/win_dot.aiimage/manifest.json +47 -0
- package/skills/win_dot.aiimage/ref/win_dot.png +0 -0
- package/skills/win_dot.aiimage/ref/win_dot.webp +0 -0
- package/skills/win_result_panel.aiimage/SKILL.md +58 -0
- package/skills/win_result_panel.aiimage/manifest.json +47 -0
- package/skills/win_result_panel.aiimage/ref/win.png +0 -0
- package/skills/win_result_panel.aiimage/ref/win.webp +0 -0
- package/skills/word_connect.aigameplay/SKILL.md +86 -0
- package/skills/word_connect.aigameplay/manifest.json +154 -0
- package/skills/word_connect.aigameplay/ref/pgs-schema.json +212 -0
- package/skills/word_connect.aigameplay/ref/reducer.template.ts +186 -0
- package/src/index.ts +10 -0
- package/src/skills.loader.ts +225 -0
- package/src/skills.types.ts +42 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "PGS (PlayCraft Gameplay Schema) 参考骨架 - 经典塔防玩法。Agent 以此为起点编写或 fork 玩法规则。",
|
|
3
|
+
"version": "1.0",
|
|
4
|
+
"gameplayType": "tower_defence",
|
|
5
|
+
"entities": {
|
|
6
|
+
"grid": {
|
|
7
|
+
"type": "tile-map",
|
|
8
|
+
"description": "游戏地图格子",
|
|
9
|
+
"fields": {
|
|
10
|
+
"width": { "type": "integer", "description": "地图列数" },
|
|
11
|
+
"height": { "type": "integer", "description": "地图行数" },
|
|
12
|
+
"cells": { "type": "array", "description": "格子类型数组 CellType[][],path=路径,buildable=可建,empty=不可建" },
|
|
13
|
+
"path": { "type": "array", "description": "敌人行进路径坐标序列 {x, y}[],从入口到出口" },
|
|
14
|
+
"path_entry": { "type": "vector2", "description": "敌人入口坐标" },
|
|
15
|
+
"path_exit": { "type": "vector2", "description": "敌人出口坐标" }
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"tower": {
|
|
19
|
+
"type": "defense-unit",
|
|
20
|
+
"description": "防御塔",
|
|
21
|
+
"fields": {
|
|
22
|
+
"id": { "type": "string", "description": "唯一ID" },
|
|
23
|
+
"type": { "type": "enum", "values": ["arrow", "cannon", "magic"] },
|
|
24
|
+
"position": { "type": "vector2", "description": "格子坐标 {x, y}" },
|
|
25
|
+
"level": { "type": "integer", "range": [1, 3], "default": 1 },
|
|
26
|
+
"damage": { "type": "number", "description": "每次攻击伤害" },
|
|
27
|
+
"range": { "type": "number", "description": "攻击范围(格子数)" },
|
|
28
|
+
"attack_speed": { "type": "number", "description": "攻击间隔(毫秒)" },
|
|
29
|
+
"last_attack_ms":{ "type": "number", "description": "上次攻击时间戳" },
|
|
30
|
+
"splash_radius": { "type": "number", "default": 0, "description": "范围伤害半径(仅 cannon)" },
|
|
31
|
+
"slow_factor": { "type": "number", "default": 1.0, "description": "减速因子(仅 magic,< 1.0)" },
|
|
32
|
+
"cost": { "type": "integer", "description": "建造费用(金币)" },
|
|
33
|
+
"upgrade_cost": { "type": "integer", "description": "升级费用" },
|
|
34
|
+
"sell_value": { "type": "integer", "description": "出售返还金币(约建造价 50%)" }
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"enemy": {
|
|
38
|
+
"type": "moving-unit",
|
|
39
|
+
"description": "敌人单位,沿路径行进",
|
|
40
|
+
"fields": {
|
|
41
|
+
"id": { "type": "string", "description": "唯一ID" },
|
|
42
|
+
"type": { "type": "enum", "values": ["basic", "fast", "armored", "boss"] },
|
|
43
|
+
"hp": { "type": "number", "description": "当前血量" },
|
|
44
|
+
"max_hp": { "type": "number", "description": "最大血量" },
|
|
45
|
+
"speed": { "type": "number", "description": "移动速度(格子/秒)" },
|
|
46
|
+
"path_index": { "type": "integer", "description": "当前目标路径点索引" },
|
|
47
|
+
"progress": { "type": "number", "range": [0, 1], "description": "到下一路径点的进度" },
|
|
48
|
+
"position": { "type": "vector2", "description": "当前插值位置(用于渲染)" },
|
|
49
|
+
"reward": { "type": "integer", "description": "击杀奖励金币" },
|
|
50
|
+
"armor": { "type": "number", "default": 0, "description": "装甲值,减少物理伤害百分比" },
|
|
51
|
+
"slow_until_ms":{ "type": "number", "default": 0, "description": "减速效果持续到的时间戳" },
|
|
52
|
+
"alive": { "type": "boolean", "default": true }
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"waves": {
|
|
56
|
+
"type": "spawn-config",
|
|
57
|
+
"description": "波次定义列表",
|
|
58
|
+
"fields": {
|
|
59
|
+
"wave_index": { "type": "integer", "description": "当前波次索引(0-based)" },
|
|
60
|
+
"total_waves": { "type": "integer" },
|
|
61
|
+
"wave_in_progress":{ "type": "boolean" },
|
|
62
|
+
"spawn_queue": { "type": "array", "description": "当前波次待生成的敌人队列 {type, count, interval_ms}[]" },
|
|
63
|
+
"last_spawn_ms": { "type": "number" },
|
|
64
|
+
"definitions": {
|
|
65
|
+
"type": "array",
|
|
66
|
+
"description": "每波次定义 [{enemies: [{type, count}], spawn_interval_ms}]"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"resources": {
|
|
71
|
+
"type": "player-resources",
|
|
72
|
+
"fields": {
|
|
73
|
+
"gold": { "type": "integer", "initial": 150, "description": "当前金币" },
|
|
74
|
+
"lives": { "type": "integer", "initial": 20, "description": "剩余生命" }
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"rules": {
|
|
79
|
+
"place_tower": {
|
|
80
|
+
"description": "在可建格子放置防御塔",
|
|
81
|
+
"conditions": [
|
|
82
|
+
"目标格子类型 == buildable",
|
|
83
|
+
"目标格子没有已有塔",
|
|
84
|
+
"resources.gold >= tower_type.cost"
|
|
85
|
+
],
|
|
86
|
+
"effect": "resources.gold -= cost; grid.cell = occupied; towers.push(new_tower)"
|
|
87
|
+
},
|
|
88
|
+
"upgrade_tower": {
|
|
89
|
+
"description": "升级已有防御塔(最高3级)",
|
|
90
|
+
"conditions": [
|
|
91
|
+
"tower.level < 3",
|
|
92
|
+
"resources.gold >= tower.upgrade_cost"
|
|
93
|
+
],
|
|
94
|
+
"effect": "resources.gold -= upgrade_cost; tower.level++; tower.damage *= 1.5; tower.range += 0.5"
|
|
95
|
+
},
|
|
96
|
+
"sell_tower": {
|
|
97
|
+
"description": "出售防御塔,返还部分金币",
|
|
98
|
+
"effect": "resources.gold += tower.sell_value; 移除塔; 格子恢复 buildable"
|
|
99
|
+
},
|
|
100
|
+
"auto_attack": {
|
|
101
|
+
"description": "每次 tick,塔检查冷却时间,若冷却结束则攻击范围内最近的敌人",
|
|
102
|
+
"target_priority": "nearest_enemy_in_range",
|
|
103
|
+
"cooldown_check": "current_ms - tower.last_attack_ms >= tower.attack_speed",
|
|
104
|
+
"damage_formula": {
|
|
105
|
+
"arrow": "damage(单体,穿甲弱)",
|
|
106
|
+
"cannon": "damage × (1 - armor_reduction),splash_radius 范围内所有敌人受 50% 伤害",
|
|
107
|
+
"magic": "damage × (1 + armor_bonus_factor if armored),命中后施加减速效果 slow_factor"
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
"enemy_move": {
|
|
111
|
+
"description": "每 tick 敌人按速度沿路径推进",
|
|
112
|
+
"formula": {
|
|
113
|
+
"advance": "progress += speed × (1 if not slowed else slow_factor) × dt / path_segment_length",
|
|
114
|
+
"next_point": "if progress >= 1: path_index++; progress -= 1",
|
|
115
|
+
"escape": "if path_index >= path.length: 敌人到达出口"
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"enemy_death": {
|
|
119
|
+
"description": "hp <= 0 时敌人死亡,掉落金币",
|
|
120
|
+
"effect": "enemy.alive = false; resources.gold += enemy.reward"
|
|
121
|
+
},
|
|
122
|
+
"enemy_escape": {
|
|
123
|
+
"description": "敌人到达路径终点(出口),扣除生命",
|
|
124
|
+
"effect": "resources.lives -= 1; remove enemy"
|
|
125
|
+
},
|
|
126
|
+
"wave_spawn": {
|
|
127
|
+
"description": "按波次配置定时生成敌人到路径入口",
|
|
128
|
+
"interval": "spawn_queue.current.interval_ms"
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"algorithm": {
|
|
132
|
+
"description": "固定 tick 主循环(每 100ms)",
|
|
133
|
+
"steps": [
|
|
134
|
+
"1. 波次生成:若 wave_in_progress,按 spawn_interval 从 spawn_queue 取出敌人,添加到 path 入口",
|
|
135
|
+
"2. 敌人移动:每个存活敌人按速度(含减速状态)沿路径推进",
|
|
136
|
+
"3. 逃跑检测:到达出口的敌人扣除生命 lives--,检测是否 lives<=0 → 失败",
|
|
137
|
+
"4. 塔攻击:检查每个塔的冷却,对范围内最近存活敌人发动攻击(含范围/减速效果)",
|
|
138
|
+
"5. 死亡结算:hp<=0 的敌人标记 dead,掉落金币,从列表移除",
|
|
139
|
+
"6. 波次完成检测:所有敌人死亡或逃跑 → 当前波次结束,准备下一波",
|
|
140
|
+
"7. 胜利检测:all waves 完成 且 lives > 0 → 胜利"
|
|
141
|
+
]
|
|
142
|
+
},
|
|
143
|
+
"winCondition": {
|
|
144
|
+
"type": "survive_all_waves",
|
|
145
|
+
"description": "所有波次的敌人全部被消灭或逃跑处理完毕,且 resources.lives > 0"
|
|
146
|
+
},
|
|
147
|
+
"loseCondition": {
|
|
148
|
+
"type": "lives_depleted",
|
|
149
|
+
"description": "resources.lives <= 0(敌人到达出口次数超过初始生命值)"
|
|
150
|
+
},
|
|
151
|
+
"testCases": [
|
|
152
|
+
{
|
|
153
|
+
"id": "tc_place_tower_kills_enemy",
|
|
154
|
+
"description": "放置弓箭塔后,敌人进入范围内被击杀,获得金币奖励",
|
|
155
|
+
"initialState": {
|
|
156
|
+
"grid": {
|
|
157
|
+
"path": [{"x":0,"y":2},{"x":1,"y":2},{"x":2,"y":2},{"x":3,"y":2},{"x":4,"y":2}],
|
|
158
|
+
"cells": "3x5 地图,path在y=2,buildable在y=1和y=3"
|
|
159
|
+
},
|
|
160
|
+
"towers": [],
|
|
161
|
+
"enemies": [
|
|
162
|
+
{ "id": "e1", "type": "basic", "hp": 100, "max_hp": 100, "speed": 1, "path_index": 0, "progress": 0, "reward": 20, "armor": 0, "alive": true }
|
|
163
|
+
],
|
|
164
|
+
"resources": { "gold": 150, "lives": 20 },
|
|
165
|
+
"waves": { "wave_index": 0, "wave_in_progress": false }
|
|
166
|
+
},
|
|
167
|
+
"actions": [
|
|
168
|
+
{ "type": "place_tower", "position": {"x": 2, "y": 1}, "tower_type": "arrow" },
|
|
169
|
+
{ "type": "tick_game_loop", "times": 30, "deltaMs": 100 }
|
|
170
|
+
],
|
|
171
|
+
"expectedState": {
|
|
172
|
+
"enemies[e1].alive": false,
|
|
173
|
+
"resources.gold": { "greaterThan": 100 },
|
|
174
|
+
"resources.lives": 20
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"id": "tc_enemy_escapes_loses_life",
|
|
179
|
+
"description": "无塔时敌人到达出口,生命-1",
|
|
180
|
+
"initialState": {
|
|
181
|
+
"grid": {
|
|
182
|
+
"path": [{"x":0,"y":2},{"x":1,"y":2},{"x":2,"y":2}]
|
|
183
|
+
},
|
|
184
|
+
"towers": [],
|
|
185
|
+
"enemies": [
|
|
186
|
+
{ "id": "e1", "type": "basic", "hp": 100, "max_hp": 100, "speed": 3, "path_index": 0, "progress": 0.9, "reward": 20, "armor": 0, "alive": true }
|
|
187
|
+
],
|
|
188
|
+
"resources": { "gold": 150, "lives": 20 }
|
|
189
|
+
},
|
|
190
|
+
"actions": [
|
|
191
|
+
{ "type": "tick_game_loop", "times": 5, "deltaMs": 100 }
|
|
192
|
+
],
|
|
193
|
+
"expectedState": {
|
|
194
|
+
"resources.lives": 19,
|
|
195
|
+
"enemies": []
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"id": "tc_wave_completion",
|
|
200
|
+
"description": "波次通过:所有敌人被消灭,波次计数推进",
|
|
201
|
+
"initialState": {
|
|
202
|
+
"grid": {
|
|
203
|
+
"path": [{"x":0,"y":2},{"x":1,"y":2},{"x":2,"y":2},{"x":3,"y":2}]
|
|
204
|
+
},
|
|
205
|
+
"towers": [
|
|
206
|
+
{ "id": "t1", "type": "arrow", "position": {"x":2,"y":1}, "level": 1, "damage": 30, "range": 2, "attack_speed": 500, "last_attack_ms": 0 }
|
|
207
|
+
],
|
|
208
|
+
"enemies": [
|
|
209
|
+
{ "id": "e1", "type": "basic", "hp": 60, "max_hp": 100, "speed": 1, "path_index": 1, "progress": 0, "reward": 20, "armor": 0, "alive": true }
|
|
210
|
+
],
|
|
211
|
+
"resources": { "gold": 100, "lives": 20 },
|
|
212
|
+
"waves": { "wave_index": 0, "total_waves": 3, "wave_in_progress": true }
|
|
213
|
+
},
|
|
214
|
+
"actions": [
|
|
215
|
+
{ "type": "tick_game_loop", "times": 20, "deltaMs": 100 }
|
|
216
|
+
],
|
|
217
|
+
"expectedState": {
|
|
218
|
+
"enemies": [],
|
|
219
|
+
"waves.wave_index": 1,
|
|
220
|
+
"waves.wave_in_progress": false,
|
|
221
|
+
"resources.gold": { "greaterThan": 100 }
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"id": "tc_game_over_lives_zero",
|
|
226
|
+
"description": "失败:生命值耗尽",
|
|
227
|
+
"initialState": {
|
|
228
|
+
"grid": {
|
|
229
|
+
"path": [{"x":0,"y":2},{"x":1,"y":2}]
|
|
230
|
+
},
|
|
231
|
+
"towers": [],
|
|
232
|
+
"enemies": [
|
|
233
|
+
{ "id": "e1", "type": "basic", "hp": 100, "max_hp": 100, "speed": 5, "path_index": 0, "progress": 0.9, "reward": 20, "armor": 0, "alive": true }
|
|
234
|
+
],
|
|
235
|
+
"resources": { "gold": 0, "lives": 1 }
|
|
236
|
+
},
|
|
237
|
+
"actions": [
|
|
238
|
+
{ "type": "tick_game_loop", "times": 5, "deltaMs": 100 }
|
|
239
|
+
],
|
|
240
|
+
"expectedState": {
|
|
241
|
+
"resources.lives": 0,
|
|
242
|
+
"gameOver": true,
|
|
243
|
+
"win": false
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
]
|
|
247
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tower_defence.aigameplay — reducer 接口模板
|
|
3
|
+
*
|
|
4
|
+
* Agent 生成实际 reducer 时,必须导出以下函数。
|
|
5
|
+
* 此文件是接口约束模板,不是可执行代码。
|
|
6
|
+
*
|
|
7
|
+
* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
8
|
+
* ⚠️ 重要:渲染层(GameScene)不应直接调用 dispatch()
|
|
9
|
+
*
|
|
10
|
+
* 塔防游戏的核心是固定帧率的游戏循环(tickGameLoop),
|
|
11
|
+
* 渲染层必须每帧(或每 tickRateMs)调用 tickGameLoop,
|
|
12
|
+
* 然后根据返回的 lastAttackEvents/lastDeathEvents/lastEscapeEvents
|
|
13
|
+
* 播放对应的视觉效果(攻击特效、死亡动画、逃跑动画)。
|
|
14
|
+
*
|
|
15
|
+
* 不要在每帧全量重建所有精灵——只更新有变化的对象。
|
|
16
|
+
*
|
|
17
|
+
* dispatch() 的用途:无头测试、AI 模拟、关卡预演等场景。
|
|
18
|
+
* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
// ─── 配置类型 ─────────────────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
export type TowerDefenceConfig = {
|
|
24
|
+
/** 初始生命值,默认 20 */
|
|
25
|
+
initialLives: number;
|
|
26
|
+
/** 初始金币,默认 150 */
|
|
27
|
+
initialGold: number;
|
|
28
|
+
/** 游戏逻辑帧率(毫秒/帧),默认 100 */
|
|
29
|
+
tickRateMs: number;
|
|
30
|
+
/** 地图格子数组(宽×高) */
|
|
31
|
+
gridWidth: number;
|
|
32
|
+
gridHeight: number;
|
|
33
|
+
/** 敌人路径坐标序列 */
|
|
34
|
+
path: Vector2[];
|
|
35
|
+
/** 波次定义列表 */
|
|
36
|
+
waves: WaveDefinition[];
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// ─── 核心类型 ─────────────────────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
export type Vector2 = { x: number; y: number };
|
|
42
|
+
export type CellType = 'path' | 'buildable' | 'occupied' | 'empty';
|
|
43
|
+
|
|
44
|
+
export type TowerType = 'arrow' | 'cannon' | 'magic';
|
|
45
|
+
export type EnemyType = 'basic' | 'fast' | 'armored' | 'boss';
|
|
46
|
+
|
|
47
|
+
export type TowerStats = {
|
|
48
|
+
damage: number;
|
|
49
|
+
range: number; // 攻击范围(格子数)
|
|
50
|
+
attackSpeed: number; // 攻击间隔(毫秒)
|
|
51
|
+
cost: number;
|
|
52
|
+
upgradeCost: number;
|
|
53
|
+
sellValue: number;
|
|
54
|
+
splashRadius: number; // 范围伤害半径(仅 cannon > 0)
|
|
55
|
+
slowFactor: number; // 减速因子(仅 magic < 1.0,其他为 1.0)
|
|
56
|
+
slowDurationMs: number;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export type Tower = {
|
|
60
|
+
id: string;
|
|
61
|
+
type: TowerType;
|
|
62
|
+
position: Vector2;
|
|
63
|
+
level: 1 | 2 | 3;
|
|
64
|
+
stats: TowerStats;
|
|
65
|
+
lastAttackMs: number; // 上次攻击的游戏时间戳
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export type Enemy = {
|
|
69
|
+
id: string;
|
|
70
|
+
type: EnemyType;
|
|
71
|
+
hp: number;
|
|
72
|
+
maxHp: number;
|
|
73
|
+
speed: number; // 格子/秒
|
|
74
|
+
pathIndex: number; // 当前目标路径点索引
|
|
75
|
+
progress: number; // 到下一路径点的进度 [0, 1)
|
|
76
|
+
position: Vector2; // 当前插值位置(用于渲染)
|
|
77
|
+
reward: number; // 击杀奖励金币
|
|
78
|
+
armor: number; // 装甲减伤百分比 [0, 1)
|
|
79
|
+
slowUntilMs: number; // 减速效果结束时间戳
|
|
80
|
+
alive: boolean;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export type WaveDefinition = {
|
|
84
|
+
enemies: Array<{ type: EnemyType; count: number }>;
|
|
85
|
+
spawnIntervalMs: number; // 每个敌人之间的生成间隔
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// ─── 动作类型 ─────────────────────────────────────────────────────────────────
|
|
89
|
+
|
|
90
|
+
export type TowerDefenceAction =
|
|
91
|
+
| { type: 'place_tower'; position: Vector2; towerType: TowerType }
|
|
92
|
+
| { type: 'upgrade_tower'; towerId: string }
|
|
93
|
+
| { type: 'sell_tower'; towerId: string }
|
|
94
|
+
| { type: 'tick'; deltaMs: number } // 游戏循环帧
|
|
95
|
+
| { type: 'start_wave' } // 开始下一波次
|
|
96
|
+
| { type: 'reset' };
|
|
97
|
+
|
|
98
|
+
// ─── 状态类型 ─────────────────────────────────────────────────────────────────
|
|
99
|
+
|
|
100
|
+
export type TowerDefenceState = {
|
|
101
|
+
grid: CellType[][]; // grid[x][y]
|
|
102
|
+
path: Vector2[];
|
|
103
|
+
towers: Tower[];
|
|
104
|
+
enemies: Enemy[];
|
|
105
|
+
resources: { gold: number; lives: number };
|
|
106
|
+
waves: {
|
|
107
|
+
waveIndex: number;
|
|
108
|
+
totalWaves: number;
|
|
109
|
+
waveInProgress: boolean;
|
|
110
|
+
spawnQueue: Array<{ type: EnemyType; count: number }>;
|
|
111
|
+
lastSpawnMs: number;
|
|
112
|
+
spawnIntervalMs: number;
|
|
113
|
+
};
|
|
114
|
+
currentTimeMs: number; // 游戏逻辑时间(累计毫秒)
|
|
115
|
+
gameOver: boolean;
|
|
116
|
+
win: boolean;
|
|
117
|
+
/** 本帧攻击事件(渲染层播放特效) */
|
|
118
|
+
lastAttackEvents: AttackEvent[];
|
|
119
|
+
/** 本帧死亡事件(渲染层播放死亡动画) */
|
|
120
|
+
lastDeathEvents: DeathEvent[];
|
|
121
|
+
/** 本帧逃跑事件(渲染层扣血UI) */
|
|
122
|
+
lastEscapeEvents: EscapeEvent[];
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// ─── 事件类型(渲染层驱动) ──────────────────────────────────────────────────
|
|
126
|
+
|
|
127
|
+
export type AttackEvent = {
|
|
128
|
+
towerId: string;
|
|
129
|
+
towerType: TowerType;
|
|
130
|
+
targetEnemyId: string;
|
|
131
|
+
damage: number;
|
|
132
|
+
isSplash: boolean;
|
|
133
|
+
splashTargets?: string[]; // cannon 范围伤害的其他目标 id
|
|
134
|
+
appliedSlow: boolean; // magic 是否施加了减速
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export type DeathEvent = {
|
|
138
|
+
enemyId: string;
|
|
139
|
+
enemyType: EnemyType;
|
|
140
|
+
position: Vector2;
|
|
141
|
+
reward: number;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export type EscapeEvent = {
|
|
145
|
+
enemyId: string;
|
|
146
|
+
livesAfter: number;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
150
|
+
// 必须导出的函数
|
|
151
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
152
|
+
|
|
153
|
+
// ─── 初始化 ──────────────────────────────────────────────────────────────────
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* init:根据关卡配置初始化游戏状态
|
|
157
|
+
*/
|
|
158
|
+
export declare function init(config: TowerDefenceConfig): TowerDefenceState;
|
|
159
|
+
|
|
160
|
+
// ─── 一体化接口(测试/AI 模拟用) ───────────────────────────────────────────
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* dispatch:接收动作,返回新状态(纯函数)
|
|
164
|
+
* ⚠️ 仅用于无头测试和 AI 模拟。渲染层请使用下方分步函数。
|
|
165
|
+
*/
|
|
166
|
+
export declare function dispatch(state: TowerDefenceState, action: TowerDefenceAction): TowerDefenceState;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* getState:返回当前状态快照
|
|
170
|
+
*/
|
|
171
|
+
export declare function getState(state: TowerDefenceState): TowerDefenceState;
|
|
172
|
+
|
|
173
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
174
|
+
// 分步函数(渲染层/场景层必须使用这些函数)
|
|
175
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* placeTower:在指定格子放置防御塔
|
|
179
|
+
* 验证:格子为 buildable、金币充足
|
|
180
|
+
* 若不合法则返回原 state(不抛出异常)
|
|
181
|
+
*
|
|
182
|
+
* 渲染层在玩家点击放塔时调用,若 state 发生变化则创建新塔精灵
|
|
183
|
+
*/
|
|
184
|
+
export declare function placeTower(
|
|
185
|
+
state: TowerDefenceState,
|
|
186
|
+
position: Vector2,
|
|
187
|
+
towerType: TowerType,
|
|
188
|
+
): TowerDefenceState;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* upgradeTower:升级指定防御塔
|
|
192
|
+
* 验证:塔存在、level < 3、金币充足
|
|
193
|
+
* 升级后 damage × 1.5,range += 0.5
|
|
194
|
+
*
|
|
195
|
+
* 渲染层调用后更新塔精灵的视觉
|
|
196
|
+
*/
|
|
197
|
+
export declare function upgradeTower(
|
|
198
|
+
state: TowerDefenceState,
|
|
199
|
+
towerId: string,
|
|
200
|
+
): TowerDefenceState;
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* tickGameLoop:执行一个完整的游戏逻辑帧
|
|
204
|
+
* 按顺序执行:波次生成 → 敌人移动 → 逃跑检测 → 塔攻击 → 死亡结算 → 胜负检测
|
|
205
|
+
* 返回含 lastAttackEvents/lastDeathEvents/lastEscapeEvents 的新状态
|
|
206
|
+
*
|
|
207
|
+
* 渲染层每帧调用(或按 tickRateMs 节流调用)
|
|
208
|
+
*/
|
|
209
|
+
export declare function tickGameLoop(
|
|
210
|
+
state: TowerDefenceState,
|
|
211
|
+
deltaMs: number,
|
|
212
|
+
): TowerDefenceState;
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* processAttacks:仅执行塔的攻击阶段(不移动敌人,不生成波次)
|
|
216
|
+
* 渲染层可用于精细控制各步骤的执行顺序
|
|
217
|
+
*/
|
|
218
|
+
export declare function processAttacks(
|
|
219
|
+
state: TowerDefenceState,
|
|
220
|
+
): TowerDefenceState;
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* moveEnemies:仅执行敌人移动阶段
|
|
224
|
+
* - 敌人按速度(含减速)沿路径推进
|
|
225
|
+
* - 到达出口的敌人触发逃跑事件
|
|
226
|
+
* - 更新所有敌人的插值位置(供渲染层同步精灵)
|
|
227
|
+
*/
|
|
228
|
+
export declare function moveEnemies(
|
|
229
|
+
state: TowerDefenceState,
|
|
230
|
+
deltaMs: number,
|
|
231
|
+
): TowerDefenceState;
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* spawnNextWave:手动触发下一波次生成(若上一波已结束)
|
|
235
|
+
* 更新 waves.waveIndex,初始化 spawnQueue
|
|
236
|
+
*/
|
|
237
|
+
export declare function spawnNextWave(
|
|
238
|
+
state: TowerDefenceState,
|
|
239
|
+
): TowerDefenceState;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tray_container.aicomponent
|
|
3
|
+
description: 底部篮子/托盘 UI 组件。提供 N 格槽位容器,支持同类聚合插入动画、消除动画(放大淡出)、满溢抖动、重新排列。通过 textureKeyFn 回调注入纹理映射,可用于任何需要收集+消除的玩法。
|
|
4
|
+
triggers: 需要底部篮子、托盘、收集槽、物品容器 UI 时触发。
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 底部篮子/托盘容器(Tray Container)
|
|
8
|
+
|
|
9
|
+
## 说明
|
|
10
|
+
|
|
11
|
+
固定在屏幕底部的 N 格槽位容器,用于收集从棋盘进入的物品。支持:
|
|
12
|
+
|
|
13
|
+
- **同类聚合插入**:新物品自动插到最后一个同色物品旁边
|
|
14
|
+
- **消除动画**:匹配成功时物品放大+淡出消失
|
|
15
|
+
- **重新排列**:物品增删后自动滑动到正确位置
|
|
16
|
+
- **满溢抖动**:篮子满时水平震动反馈
|
|
17
|
+
|
|
18
|
+
## Scaffold
|
|
19
|
+
|
|
20
|
+
| 目标路径 | 来源 | 说明 |
|
|
21
|
+
|---------|-----|------|
|
|
22
|
+
| `src/game/ui/TrayRenderer.ts` | `ref/TrayRenderer.ts` | 完整的篮子渲染器 |
|
|
23
|
+
|
|
24
|
+
## Recipe
|
|
25
|
+
|
|
26
|
+
| 决策 | 原因 |
|
|
27
|
+
|------|------|
|
|
28
|
+
| **三模式统一接口** | Phaser 精灵、HTML CSS、Three.js Mesh 三种实现对 GameScene 暴露相同方法(`addItem`、`rearrangeItems`、`removeMatchedItems`、`shake`),GameScene 无需感知底层模式 |
|
|
29
|
+
| **textureKeyFn 回调注入** | 纹理/颜色映射由调用方提供,TrayRenderer 不绑定具体资产;不同 Remix 变体可用不同颜色映射,组件可复用 |
|
|
30
|
+
| **同类聚合插入位置** | 新物品插到最后一个同类旁边(非末尾),视觉上更直观地表达"同类靠近"语义,是三消类游戏标准 UX |
|
|
31
|
+
| **HTML Overlay 在 Three.js 中** | 3D 项目中 2D UI 用 DOM 比 Three.js Plane Mesh 更简单(CSS transition 动画免费),不占 WebGL 渲染管线 |
|
|
32
|
+
|
|
33
|
+
## Adapter
|
|
34
|
+
|
|
35
|
+
- **Role**: `trayContainerRenderer` — 底部 N 格槽位篮子 UI(Phaser/HTML/Three.js 三模式)
|
|
36
|
+
- **Provides**: `TrayRenderer`(Phaser 精灵)、`TrayRendererHtmlOverlay`(CSS DOM)、`TrayRenderer3D`(Three.js Mesh)
|
|
37
|
+
- **Requires**: `phaser.aicomponent`(Phaser 模式);`threejs.aicomponent`(3D Mesh 模式)
|
|
38
|
+
- **Consumed by**: `game_scene.aicomponent`(持有 trayRenderer 实例)、`slide_out_to_tray_animation.aicomponent`(飞入动画的目标槽位)
|
|
39
|
+
- **Integration point**: `src/game/ui/TrayRenderer.ts` → `Game.ts` 初始化后调用 `setup(areaRect, capacity)`
|
|
40
|
+
|
|
41
|
+
## Imports
|
|
42
|
+
|
|
43
|
+
- `phaser.aicomponent`(硬依赖:Phaser.Scene, Phaser.GameObjects, Phaser.Tweens)
|
|
44
|
+
|
|
45
|
+
## 关键接口
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
class TrayRenderer {
|
|
49
|
+
setup(areaRect: Rect, capacity: number): void;
|
|
50
|
+
getSlotWorldPos(index: number): { x: number; y: number };
|
|
51
|
+
addItemSprite(item: TrayItem, index: number): Phaser.GameObjects.Image;
|
|
52
|
+
rearrangeItems(tray: TrayItem[], animate?: boolean): void;
|
|
53
|
+
removeMatchedItems(matchedIds: string[], onComplete: () => void): void;
|
|
54
|
+
shake(): void;
|
|
55
|
+
destroy(): void;
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 配置参数
|
|
60
|
+
|
|
61
|
+
| 参数 | 默认 | 说明 |
|
|
62
|
+
|------|------|------|
|
|
63
|
+
| capacity | 7 | 槽位数量 |
|
|
64
|
+
| matchDuration | 300ms | 消除动画时长 |
|
|
65
|
+
| rearrangeDuration | 200ms | 重排动画时长 |
|
|
66
|
+
| shakeAmount | 8px | 抖动幅度 |
|
|
67
|
+
|
|
68
|
+
## 集成模式
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// 初始化
|
|
72
|
+
const trayRenderer = new TrayRenderer(scene);
|
|
73
|
+
trayRenderer.setup({ x, y, width, height }, 7);
|
|
74
|
+
|
|
75
|
+
// 物品飞入后
|
|
76
|
+
const sprite = trayRenderer.addItemSprite(item, insertIndex);
|
|
77
|
+
trayRenderer.rearrangeItems(currentTray, true);
|
|
78
|
+
|
|
79
|
+
// 匹配消除
|
|
80
|
+
trayRenderer.removeMatchedItems(matchedIds, () => {
|
|
81
|
+
trayRenderer.rearrangeItems(newTray, true);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// 满溢
|
|
85
|
+
trayRenderer.shake();
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## HTML Overlay 模式(Three.js 推荐)
|
|
89
|
+
|
|
90
|
+
用 CSS + DOM 实现的篮子,固定在屏幕底部。适用于 Three.js 3D 项目中不需要 3D 深度的 UI 组件。
|
|
91
|
+
|
|
92
|
+
**优点**:不占用 WebGL 渲染管线 / CSS transition 动画流畅 / 不受 3D 相机变换影响
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { TrayRendererHtmlOverlay } from "../ui/TrayRendererHtmlOverlay";
|
|
96
|
+
|
|
97
|
+
const tray = new TrayRendererHtmlOverlay({
|
|
98
|
+
capacity: 7,
|
|
99
|
+
colorToHex: (color) => CAR_COLOR_CSS_MAP[color],
|
|
100
|
+
});
|
|
101
|
+
tray.setup("game-container");
|
|
102
|
+
|
|
103
|
+
// 物品飞入后
|
|
104
|
+
tray.addItem(item, insertIndex);
|
|
105
|
+
tray.rearrangeItems(currentTray);
|
|
106
|
+
|
|
107
|
+
// 消除
|
|
108
|
+
tray.removeMatchedItems(matchedIds, () => {
|
|
109
|
+
tray.rearrangeItems(newTray);
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## 3D Mesh 模式(完全沉浸式)
|
|
114
|
+
|
|
115
|
+
在 Three.js 场景内用 3D Mesh 排列表示物品。需要每帧调用 `update(dt)` 驱动动画。
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import { TrayRenderer3D } from "../ui/TrayRenderer3D";
|
|
119
|
+
|
|
120
|
+
const tray = new TrayRenderer3D(scene, {
|
|
121
|
+
capacity: 7,
|
|
122
|
+
cellSize: 1.0,
|
|
123
|
+
colorToHex: (color) => CAR_COLOR_HEX_MAP[color],
|
|
124
|
+
});
|
|
125
|
+
tray.setup(new THREE.Vector3(boardCenterX, 0, boardHeight + 2));
|
|
126
|
+
|
|
127
|
+
// 每帧更新
|
|
128
|
+
onUpdate(dt) { tray.update(dt); }
|
|
129
|
+
|
|
130
|
+
// 物品飞入后
|
|
131
|
+
tray.addItem(item, insertIndex);
|
|
132
|
+
tray.rearrangeItems(currentTray);
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## 模式对比
|
|
136
|
+
|
|
137
|
+
| 维度 | phaser-sprite | html-overlay | threejs-mesh |
|
|
138
|
+
|------|--------------|-------------|-------------|
|
|
139
|
+
| 引擎 | Phaser 3 | 任意(DOM) | Three.js |
|
|
140
|
+
| 性能 | 好 | 最好 | 中等 |
|
|
141
|
+
| 沉浸感 | 2D | 2D(覆盖) | 完全 3D |
|
|
142
|
+
| 动画 | Phaser Tween | CSS transition | 手写插值 |
|
|
143
|
+
| 复杂度 | 低 | 低 | 中 |
|