@fps-games/vfx 0.1.1

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 (375) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/EffectPackageService.d.ts +26 -0
  3. package/dist/SceneVfxService.d.ts +27 -0
  4. package/dist/chunks/legacy-particle-runtime-CbJYVxdd.js +75 -0
  5. package/dist/chunks/manifestRuntimePackage-CXQFSTo2.js +356 -0
  6. package/dist/chunks/rendering-CV3nhygX.js +13 -0
  7. package/dist/chunks/space-shared-BXV1hc0k.js +124 -0
  8. package/dist/chunks/wood-sawdust-effect-factory-DlETNaBn.js +129 -0
  9. package/dist/effects/building-upgrade/effect.json.d.ts +9 -0
  10. package/dist/effects/building-upgrade/index.d.ts +20 -0
  11. package/dist/effects/building-upgrade/index.js +337 -0
  12. package/dist/effects/character-entrance/effect.json.d.ts +9 -0
  13. package/dist/effects/character-entrance/index.d.ts +18 -0
  14. package/dist/effects/character-entrance/index.js +271 -0
  15. package/dist/effects/coin-burst/index.d.ts +6 -0
  16. package/dist/effects/coin-burst/index.js +45 -0
  17. package/dist/effects/comet-trail-flame/index.d.ts +11 -0
  18. package/dist/effects/comet-trail-flame/index.js +103 -0
  19. package/dist/effects/conveyor-upgrade/effect.json.d.ts +9 -0
  20. package/dist/effects/conveyor-upgrade/index.d.ts +20 -0
  21. package/dist/effects/conveyor-upgrade/index.js +349 -0
  22. package/dist/effects/debris-smoke/index.d.ts +10 -0
  23. package/dist/effects/debris-smoke/index.js +108 -0
  24. package/dist/effects/door_open_gold_flakes/door_open_gold_flakes.json.d.ts +501 -0
  25. package/dist/effects/door_open_gold_flakes/index.d.ts +1 -0
  26. package/dist/effects/door_open_gold_flakes/index.js +524 -0
  27. package/dist/effects/electric-arc/index.d.ts +8 -0
  28. package/dist/effects/electric-arc/index.js +71 -0
  29. package/dist/effects/energy-shield/index.d.ts +46 -0
  30. package/dist/effects/energy-shield/index.js +365 -0
  31. package/dist/effects/explosion/index.d.ts +11 -0
  32. package/dist/effects/explosion/index.js +129 -0
  33. package/dist/effects/ground-tile-upgrade/effect.json.d.ts +9 -0
  34. package/dist/effects/ground-tile-upgrade/index.d.ts +20 -0
  35. package/dist/effects/ground-tile-upgrade/index.js +357 -0
  36. package/dist/effects/hit-flash/index.d.ts +8 -0
  37. package/dist/effects/hit-flash/index.js +71 -0
  38. package/dist/effects/laser-beam/index.d.ts +1 -0
  39. package/dist/effects/laser-beam/index.js +152 -0
  40. package/dist/effects/laser-beam-factory.d.ts +12 -0
  41. package/dist/effects/lumber-cart-suction/effect.json.d.ts +9 -0
  42. package/dist/effects/lumber-cart-suction/index.d.ts +26 -0
  43. package/dist/effects/lumber-cart-suction/index.js +322 -0
  44. package/dist/effects/lumber-debris-scatter/effect.json.d.ts +231 -0
  45. package/dist/effects/lumber-debris-scatter/index.d.ts +20 -0
  46. package/dist/effects/lumber-debris-scatter/index.js +637 -0
  47. package/dist/effects/lumber_vehicle_gear_spin/index.d.ts +1 -0
  48. package/dist/effects/lumber_vehicle_gear_spin/index.js +363 -0
  49. package/dist/effects/lumber_vehicle_gear_spin/lumber_vehicle_gear_spin.json.d.ts +341 -0
  50. package/dist/effects/lumber_vehicle_upgrade_aura/index.d.ts +1 -0
  51. package/dist/effects/lumber_vehicle_upgrade_aura/index.js +391 -0
  52. package/dist/effects/lumber_vehicle_upgrade_aura/lumber_vehicle_upgrade_aura.json.d.ts +368 -0
  53. package/dist/effects/lumber_vehicle_wood_chips/index.d.ts +1 -0
  54. package/dist/effects/lumber_vehicle_wood_chips/index.js +360 -0
  55. package/dist/effects/lumber_vehicle_wood_chips/lumber_vehicle_wood_chips.json.d.ts +338 -0
  56. package/dist/effects/monster-hit/index.d.ts +15 -0
  57. package/dist/effects/monster-hit/index.js +156 -0
  58. package/dist/effects/player-upgrade/effect.json.d.ts +9 -0
  59. package/dist/effects/player-upgrade/index.d.ts +24 -0
  60. package/dist/effects/player-upgrade/index.js +539 -0
  61. package/dist/effects/pulse-laser-volley/index.d.ts +17 -0
  62. package/dist/effects/pulse-laser-volley/index.js +173 -0
  63. package/dist/effects/resource-collect-sparkles/effect.json.d.ts +9 -0
  64. package/dist/effects/resource-collect-sparkles/index.d.ts +21 -0
  65. package/dist/effects/resource-collect-sparkles/index.js +222 -0
  66. package/dist/effects/run-footstep-dust/effect.json.d.ts +186 -0
  67. package/dist/effects/run-footstep-dust/index.d.ts +23 -0
  68. package/dist/effects/run-footstep-dust/index.js +343 -0
  69. package/dist/effects/space-shared.d.ts +44 -0
  70. package/dist/effects/thruster-flame/index.d.ts +15 -0
  71. package/dist/effects/thruster-flame/index.js +301 -0
  72. package/dist/effects/tree-chop-dust/effect.json.d.ts +11 -0
  73. package/dist/effects/tree-chop-dust/index.d.ts +17 -0
  74. package/dist/effects/tree-chop-dust/index.js +165 -0
  75. package/dist/effects/tree-leaf-chop-burst/index.d.ts +19 -0
  76. package/dist/effects/tree-leaf-chop-burst/index.js +219 -0
  77. package/dist/effects/tree_chop_dust_burst/index.d.ts +1 -0
  78. package/dist/effects/tree_chop_dust_burst/index.js +443 -0
  79. package/dist/effects/tree_chop_dust_burst/tree_chop_dust_burst.json.d.ts +415 -0
  80. package/dist/effects/ufo-thread-flame/index.d.ts +21 -0
  81. package/dist/effects/ufo-thread-flame/index.js +140 -0
  82. package/dist/effects/vehicle-exhaust-smoke/effect.json.d.ts +11 -0
  83. package/dist/effects/vehicle-exhaust-smoke/index.d.ts +19 -0
  84. package/dist/effects/vehicle-exhaust-smoke/index.js +242 -0
  85. package/dist/effects/vehicle-upgrade/effect.json.d.ts +9 -0
  86. package/dist/effects/vehicle-upgrade/index.d.ts +20 -0
  87. package/dist/effects/vehicle-upgrade/index.js +349 -0
  88. package/dist/effects/weapon-trail/index.d.ts +26 -0
  89. package/dist/effects/weapon-trail/index.js +351 -0
  90. package/dist/effects/wood-crusher-sawdust/index.d.ts +2 -0
  91. package/dist/effects/wood-crusher-sawdust/index.js +648 -0
  92. package/dist/effects/wood-crusher-sawdust/wood_crusher_sawdust.json.d.ts +595 -0
  93. package/dist/effects/wood-cutter-sawdust/index.d.ts +2 -0
  94. package/dist/effects/wood-cutter-sawdust/index.js +648 -0
  95. package/dist/effects/wood-cutter-sawdust/wood_cutter_sawdust.json.d.ts +595 -0
  96. package/dist/effects/wood-sawdust-effect-factory.d.ts +36 -0
  97. package/dist/effects/wood_crusher_sawdust/index.d.ts +16 -0
  98. package/dist/effects/wood_crusher_sawdust/index.js +634 -0
  99. package/dist/effects/wood_crusher_sawdust/wood_crusher_sawdust.json.d.ts +595 -0
  100. package/dist/effects/wood_cutter_sawdust/index.d.ts +16 -0
  101. package/dist/effects/wood_cutter_sawdust/index.js +634 -0
  102. package/dist/effects/wood_cutter_sawdust/wood_cutter_sawdust.json.d.ts +595 -0
  103. package/dist/effects/wood_peel_material_test/index.d.ts +1 -0
  104. package/dist/effects/wood_peel_material_test/index.js +157 -0
  105. package/dist/effects/wood_peel_material_test/wood_peel_material_test.json.d.ts +139 -0
  106. package/dist/generation.d.ts +7 -0
  107. package/dist/index.d.ts +8 -0
  108. package/dist/index.js +309 -0
  109. package/dist/legacy-particle-runtime.d.ts +30 -0
  110. package/dist/manifestRuntimePackage.d.ts +68 -0
  111. package/dist/registry.d.ts +20 -0
  112. package/dist/rendering.d.ts +5 -0
  113. package/dist/types.d.ts +83 -0
  114. package/docs/AUTHORING_EFFECTS.md +297 -0
  115. package/docs/VFX_LIBRARY_ARCHITECTURE_chatgpt.md +1580 -0
  116. package/docs/VFX_LIBRARY_EXECUTION_PLAN.md +229 -0
  117. package/docs/VFX_LIBRARY_PLAN.md +546 -0
  118. package/docs/vfx-ab/RESULTS.md +35 -0
  119. package/docs/vfx-ab/lumber-order/vehicle-exhaust-smoke/after.png +0 -0
  120. package/docs/vfx-ab/lumber-order/vehicle-exhaust-smoke/before.png +0 -0
  121. package/docs/vfx-ab/lumber-truck/vehicle-exhaust-smoke/after.png +0 -0
  122. package/docs/vfx-ab/lumber-truck/vehicle-exhaust-smoke/before.png +0 -0
  123. package/docs/vfx-integration_chatgpt.md +462 -0
  124. package/docs/weapon-trail-visualization.html +241 -0
  125. package/index.json +381 -0
  126. package/package.json +51 -0
  127. package/packages/EffectPackageService.ts +240 -0
  128. package/packages/SceneVfxService.ts +96 -0
  129. package/packages/build.mesh.yellow_build_upgrade_indicator/assets/runtime/simpleMeshEffect.v1.js +333 -0
  130. package/packages/build.mesh.yellow_build_upgrade_indicator/assets/shaders/mesh-effect-preview.frag.glsl +25 -0
  131. package/packages/build.mesh.yellow_build_upgrade_indicator/assets/shaders/mesh-effect-preview.vert.glsl +11 -0
  132. package/packages/build.mesh.yellow_build_upgrade_indicator/assets/textures/effect_jianbian.png +0 -0
  133. package/packages/build.mesh.yellow_build_upgrade_indicator/effect.json +927 -0
  134. package/packages/build.mesh.yellow_build_upgrade_indicator/media/contact-sheet.png +0 -0
  135. package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.gif +0 -0
  136. package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.mp4 +0 -0
  137. package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.webm +0 -0
  138. package/packages/build.mesh.yellow_build_upgrade_indicator/media/thumbnail.png +0 -0
  139. package/packages/build.mesh.yellow_build_upgrade_indicator/metadata/description.json +197 -0
  140. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/03-effect.original.json +895 -0
  141. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/03-normalized-vfx-to-babylon-report.json +241 -0
  142. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/04-preview-overrides.json +542 -0
  143. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/04-preview-tuning-report.json +69 -0
  144. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/asset-map.json +125 -0
  145. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/lineage.json +44 -0
  146. package/packages/build.particle.golden_upgrade_starburst/assets/runtime/particleEmitter.v1.js +210 -0
  147. package/packages/build.particle.golden_upgrade_starburst/assets/textures/effect_guangdian.png +0 -0
  148. package/packages/build.particle.golden_upgrade_starburst/effect.json +880 -0
  149. package/packages/build.particle.golden_upgrade_starburst/media/contact-sheet.png +0 -0
  150. package/packages/build.particle.golden_upgrade_starburst/media/preview.gif +0 -0
  151. package/packages/build.particle.golden_upgrade_starburst/media/preview.mp4 +0 -0
  152. package/packages/build.particle.golden_upgrade_starburst/media/preview.webm +0 -0
  153. package/packages/build.particle.golden_upgrade_starburst/media/thumbnail.png +0 -0
  154. package/packages/build.particle.golden_upgrade_starburst/metadata/description.json +161 -0
  155. package/packages/build.particle.golden_upgrade_starburst/provenance/03-effect.original.json +762 -0
  156. package/packages/build.particle.golden_upgrade_starburst/provenance/03-normalized-vfx-to-babylon-report.json +260 -0
  157. package/packages/build.particle.golden_upgrade_starburst/provenance/04-preview-overrides.json +436 -0
  158. package/packages/build.particle.golden_upgrade_starburst/provenance/04-preview-tuning-report.json +40 -0
  159. package/packages/build.particle.golden_upgrade_starburst/provenance/asset-map.json +115 -0
  160. package/packages/build.particle.golden_upgrade_starburst/provenance/lineage.json +40 -0
  161. package/packages/build.particle.orange_upgrade_transform_sparks/assets/runtime/particleEmitter.v1.js +210 -0
  162. package/packages/build.particle.orange_upgrade_transform_sparks/assets/textures/b5b27ab1-e740-4398-b407-848fc2b2c897.png +0 -0
  163. package/packages/build.particle.orange_upgrade_transform_sparks/effect.json +887 -0
  164. package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.gif +0 -0
  165. package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.mp4 +0 -0
  166. package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.webm +0 -0
  167. package/packages/build.particle.orange_upgrade_transform_sparks/media/thumbnail.png +0 -0
  168. package/packages/build.particle.orange_upgrade_transform_sparks/metadata/description.json +179 -0
  169. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/03-effect.original.json +859 -0
  170. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/03-normalized-vfx-to-babylon-report.json +260 -0
  171. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/04-preview-overrides.json +478 -0
  172. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/04-preview-tuning-report.json +40 -0
  173. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/asset-map.json +114 -0
  174. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/lineage.json +41 -0
  175. package/packages/build.particle.wood_chip_dust_burst/assets/runtime/particleEmitter.v1.js +210 -0
  176. package/packages/build.particle.wood_chip_dust_burst/assets/textures/effect_yanwu4.png +0 -0
  177. package/packages/build.particle.wood_chip_dust_burst/assets/textures/suipian3.png +0 -0
  178. package/packages/build.particle.wood_chip_dust_burst/effect.json +1400 -0
  179. package/packages/build.particle.wood_chip_dust_burst/media/contact-sheet.png +0 -0
  180. package/packages/build.particle.wood_chip_dust_burst/media/preview.gif +0 -0
  181. package/packages/build.particle.wood_chip_dust_burst/media/preview.mp4 +0 -0
  182. package/packages/build.particle.wood_chip_dust_burst/media/preview.webm +0 -0
  183. package/packages/build.particle.wood_chip_dust_burst/media/thumbnail.png +0 -0
  184. package/packages/build.particle.wood_chip_dust_burst/metadata/description.json +173 -0
  185. package/packages/build.particle.wood_chip_dust_burst/provenance/03-effect.original.json +1277 -0
  186. package/packages/build.particle.wood_chip_dust_burst/provenance/03-normalized-vfx-to-babylon-report.json +329 -0
  187. package/packages/build.particle.wood_chip_dust_burst/provenance/04-preview-overrides.json +749 -0
  188. package/packages/build.particle.wood_chip_dust_burst/provenance/04-preview-tuning-report.json +60 -0
  189. package/packages/build.particle.wood_chip_dust_burst/provenance/asset-map.json +146 -0
  190. package/packages/build.particle.wood_chip_dust_burst/provenance/lineage.json +69 -0
  191. package/packages/effects/building-upgrade/effect.json +6 -0
  192. package/packages/effects/building-upgrade/index.ts +387 -0
  193. package/packages/effects/building-upgrade/vfx-params.json +24 -0
  194. package/packages/effects/character-entrance/effect.json +6 -0
  195. package/packages/effects/character-entrance/index.ts +308 -0
  196. package/packages/effects/character-entrance/vfx-params.json +24 -0
  197. package/packages/effects/coin-burst/index.ts +43 -0
  198. package/packages/effects/coin-burst/vfx-params.json +5 -0
  199. package/packages/effects/comet-trail-flame/assets/textures/trail_5x4.webp +0 -0
  200. package/packages/effects/comet-trail-flame/index.ts +106 -0
  201. package/packages/effects/comet-trail-flame/vfx-params.json +5 -0
  202. package/packages/effects/conveyor-upgrade/effect.json +6 -0
  203. package/packages/effects/conveyor-upgrade/index.ts +401 -0
  204. package/packages/effects/conveyor-upgrade/vfx-params.json +21 -0
  205. package/packages/effects/debris-smoke/assets/models/rock_debris.glb +0 -0
  206. package/packages/effects/debris-smoke/assets/textures/smoke22.webp +0 -0
  207. package/packages/effects/debris-smoke/index.ts +101 -0
  208. package/packages/effects/debris-smoke/vfx-params.json +5 -0
  209. package/packages/effects/door_open_gold_flakes/assets/runtime/goldFlakes.v1.js +397 -0
  210. package/packages/effects/door_open_gold_flakes/door_open_gold_flakes.json +498 -0
  211. package/packages/effects/door_open_gold_flakes/index.ts +11 -0
  212. package/packages/effects/door_open_gold_flakes/vfx-params.json +23 -0
  213. package/packages/effects/electric-arc/assets/textures/spark_4x4.webp +0 -0
  214. package/packages/effects/electric-arc/index.ts +62 -0
  215. package/packages/effects/electric-arc/vfx-params.json +5 -0
  216. package/packages/effects/energy-shield/effect.json +7 -0
  217. package/packages/effects/energy-shield/index.ts +431 -0
  218. package/packages/effects/energy-shield/vfx-params.json +29 -0
  219. package/packages/effects/explosion/assets/textures/baozha29.webp +0 -0
  220. package/packages/effects/explosion/assets/textures/glow01.webp +0 -0
  221. package/packages/effects/explosion/assets/textures/lizi01.webp +0 -0
  222. package/packages/effects/explosion/assets/textures/xulie_lizibaozha02_5x5.webp +0 -0
  223. package/packages/effects/explosion/index.ts +114 -0
  224. package/packages/effects/explosion/vfx-params.json +5 -0
  225. package/packages/effects/ground-tile-upgrade/effect.json +6 -0
  226. package/packages/effects/ground-tile-upgrade/index.ts +410 -0
  227. package/packages/effects/ground-tile-upgrade/vfx-params.json +21 -0
  228. package/packages/effects/hit-flash/index.ts +69 -0
  229. package/packages/effects/hit-flash/vfx-params.json +5 -0
  230. package/packages/effects/laser-beam/assets/textures/laser_glow.webp +0 -0
  231. package/packages/effects/laser-beam/assets/textures/laser_noise.webp +0 -0
  232. package/packages/effects/laser-beam/index.ts +6 -0
  233. package/packages/effects/laser-beam/vfx-params.json +5 -0
  234. package/packages/effects/laser-beam-factory.ts +135 -0
  235. package/packages/effects/lumber-cart-suction/effect.json +6 -0
  236. package/packages/effects/lumber-cart-suction/index.ts +399 -0
  237. package/packages/effects/lumber-cart-suction/vfx-params.json +30 -0
  238. package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb +0 -0
  239. package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb.versions/.active +1 -0
  240. package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb.versions/1781589063890_upload.glb +0 -0
  241. package/packages/effects/lumber-debris-scatter/assets/runtime/solidParticleScatter.v1.js +236 -0
  242. package/packages/effects/lumber-debris-scatter/effect.json +228 -0
  243. package/packages/effects/lumber-debris-scatter/index.ts +780 -0
  244. package/packages/effects/lumber-debris-scatter/vfx-params.json +19 -0
  245. package/packages/effects/lumber_vehicle_gear_spin/assets/runtime/gearSpin.v1.js +202 -0
  246. package/packages/effects/lumber_vehicle_gear_spin/index.ts +11 -0
  247. package/packages/effects/lumber_vehicle_gear_spin/lumber_vehicle_gear_spin.json +338 -0
  248. package/packages/effects/lumber_vehicle_gear_spin/vfx-params.json +21 -0
  249. package/packages/effects/lumber_vehicle_upgrade_aura/assets/runtime/upgradeAura.v1.js +353 -0
  250. package/packages/effects/lumber_vehicle_upgrade_aura/index.ts +11 -0
  251. package/packages/effects/lumber_vehicle_upgrade_aura/lumber_vehicle_upgrade_aura.json +365 -0
  252. package/packages/effects/lumber_vehicle_upgrade_aura/vfx-params.json +15 -0
  253. package/packages/effects/lumber_vehicle_wood_chips/assets/runtime/solidParticleScatter.v1.js +310 -0
  254. package/packages/effects/lumber_vehicle_wood_chips/index.ts +11 -0
  255. package/packages/effects/lumber_vehicle_wood_chips/lumber_vehicle_wood_chips.json +335 -0
  256. package/packages/effects/lumber_vehicle_wood_chips/vfx-params.json +11 -0
  257. package/packages/effects/monster-hit/index.ts +128 -0
  258. package/packages/effects/monster-hit/vfx-params.json +5 -0
  259. package/packages/effects/player-upgrade/effect.json +6 -0
  260. package/packages/effects/player-upgrade/index.ts +635 -0
  261. package/packages/effects/player-upgrade/vfx-params.json +28 -0
  262. package/packages/effects/pulse-laser-volley/assets/textures/bolt_guangshu.webp +0 -0
  263. package/packages/effects/pulse-laser-volley/index.ts +204 -0
  264. package/packages/effects/pulse-laser-volley/vfx-params.json +5 -0
  265. package/packages/effects/resource-collect-sparkles/effect.json +6 -0
  266. package/packages/effects/resource-collect-sparkles/index.ts +254 -0
  267. package/packages/effects/resource-collect-sparkles/vfx-params.json +25 -0
  268. package/packages/effects/run-footstep-dust/assets/runtime/runFootstepDust.v1.js +215 -0
  269. package/packages/effects/run-footstep-dust/effect.json +183 -0
  270. package/packages/effects/run-footstep-dust/index.ts +377 -0
  271. package/packages/effects/run-footstep-dust/vfx-params.json +27 -0
  272. package/packages/effects/space-shared.ts +120 -0
  273. package/packages/effects/thruster-flame/index.ts +305 -0
  274. package/packages/effects/thruster-flame/vfx-params.json +5 -0
  275. package/packages/effects/tree-chop-dust/assets/textures/tree_chop_dust_atlas.png +0 -0
  276. package/packages/effects/tree-chop-dust/effect.json +8 -0
  277. package/packages/effects/tree-chop-dust/index.ts +202 -0
  278. package/packages/effects/tree-chop-dust/vfx-params.json +21 -0
  279. package/packages/effects/tree-leaf-chop-burst/assets/runtime/particleEmitter.v1.js +303 -0
  280. package/packages/effects/tree-leaf-chop-burst/assets/textures/tree_leaf_chop_burst_leaf_atlas.png +0 -0
  281. package/packages/effects/tree-leaf-chop-burst/effect.json +498 -0
  282. package/packages/effects/tree-leaf-chop-burst/index.ts +294 -0
  283. package/packages/effects/tree-leaf-chop-burst/vfx-params.json +27 -0
  284. package/packages/effects/tree_chop_dust_burst/assets/runtime/particleEmitter.v1.js +318 -0
  285. package/packages/effects/tree_chop_dust_burst/assets/textures/tree_chop_dust_burst_dust.png +0 -0
  286. package/packages/effects/tree_chop_dust_burst/index.ts +13 -0
  287. package/packages/effects/tree_chop_dust_burst/tree_chop_dust_burst.json +412 -0
  288. package/packages/effects/tree_chop_dust_burst/vfx-params.json +9 -0
  289. package/packages/effects/ufo-thread-flame/assets/textures/flame_flow.webp +0 -0
  290. package/packages/effects/ufo-thread-flame/assets/textures/flame_spike.webp +0 -0
  291. package/packages/effects/ufo-thread-flame/index.ts +152 -0
  292. package/packages/effects/ufo-thread-flame/vfx-params.json +5 -0
  293. package/packages/effects/vehicle-exhaust-smoke/assets/textures/vehicle_exhaust_smoke_atlas.png +0 -0
  294. package/packages/effects/vehicle-exhaust-smoke/effect.json +8 -0
  295. package/packages/effects/vehicle-exhaust-smoke/index.ts +298 -0
  296. package/packages/effects/vehicle-exhaust-smoke/vfx-params.json +23 -0
  297. package/packages/effects/vehicle-upgrade/effect.json +6 -0
  298. package/packages/effects/vehicle-upgrade/index.ts +401 -0
  299. package/packages/effects/vehicle-upgrade/vfx-params.json +21 -0
  300. package/packages/effects/weapon-trail/assets/textures/trail_wedge.png +0 -0
  301. package/packages/effects/weapon-trail/index.ts +313 -0
  302. package/packages/effects/weapon-trail/vfx-params.json +5 -0
  303. package/packages/effects/wood-crusher-sawdust/assets/runtime/particleEmitter.v1.js +312 -0
  304. package/packages/effects/wood-crusher-sawdust/assets/textures/wood_crusher_sawdust_dust.png +0 -0
  305. package/packages/effects/wood-crusher-sawdust/assets/textures/wood_crusher_sawdust_fiber.png +0 -0
  306. package/packages/effects/wood-crusher-sawdust/index.ts +43 -0
  307. package/packages/effects/wood-crusher-sawdust/vfx-params.json +24 -0
  308. package/packages/effects/wood-crusher-sawdust/wood_crusher_sawdust.json +592 -0
  309. package/packages/effects/wood-cutter-sawdust/assets/runtime/particleEmitter.v1.js +312 -0
  310. package/packages/effects/wood-cutter-sawdust/assets/textures/wood_cutter_sawdust_chip.png +0 -0
  311. package/packages/effects/wood-cutter-sawdust/assets/textures/wood_cutter_sawdust_dust.png +0 -0
  312. package/packages/effects/wood-cutter-sawdust/index.ts +43 -0
  313. package/packages/effects/wood-cutter-sawdust/vfx-params.json +24 -0
  314. package/packages/effects/wood-cutter-sawdust/wood_cutter_sawdust.json +592 -0
  315. package/packages/effects/wood-sawdust-effect-factory.ts +194 -0
  316. package/packages/effects/wood_crusher_sawdust/assets/runtime/particleEmitter.v1.js +318 -0
  317. package/packages/effects/wood_crusher_sawdust/assets/textures/wood_crusher_sawdust_dust.png +0 -0
  318. package/packages/effects/wood_crusher_sawdust/assets/textures/wood_crusher_sawdust_fiber.png +0 -0
  319. package/packages/effects/wood_crusher_sawdust/index.ts +29 -0
  320. package/packages/effects/wood_crusher_sawdust/vfx-params.json +14 -0
  321. package/packages/effects/wood_crusher_sawdust/wood_crusher_sawdust.json +592 -0
  322. package/packages/effects/wood_cutter_sawdust/assets/runtime/particleEmitter.v1.js +318 -0
  323. package/packages/effects/wood_cutter_sawdust/assets/textures/wood_cutter_sawdust_chip.png +0 -0
  324. package/packages/effects/wood_cutter_sawdust/assets/textures/wood_cutter_sawdust_dust.png +0 -0
  325. package/packages/effects/wood_cutter_sawdust/index.ts +29 -0
  326. package/packages/effects/wood_cutter_sawdust/vfx-params.json +14 -0
  327. package/packages/effects/wood_cutter_sawdust/wood_cutter_sawdust.json +592 -0
  328. package/packages/effects/wood_peel_material_test/assets/runtime/woodPeelMaterialTest.v1.js +196 -0
  329. package/packages/effects/wood_peel_material_test/index.ts +11 -0
  330. package/packages/effects/wood_peel_material_test/vfx-params.json +9 -0
  331. package/packages/effects/wood_peel_material_test/wood_peel_material_test.json +136 -0
  332. package/packages/env.particle.forest_edge_fog/assets/runtime/particleEmitter.v1.js +210 -0
  333. package/packages/env.particle.forest_edge_fog/assets/textures/f12a23c4-b924-4322-a260-3d982428f1e8.png +0 -0
  334. package/packages/env.particle.forest_edge_fog/assets/textures/yuan.png +0 -0
  335. package/packages/env.particle.forest_edge_fog/effect.json +854 -0
  336. package/packages/env.particle.forest_edge_fog/media/preview.gif +0 -0
  337. package/packages/env.particle.forest_edge_fog/media/preview.mp4 +0 -0
  338. package/packages/env.particle.forest_edge_fog/media/preview.webm +0 -0
  339. package/packages/env.particle.forest_edge_fog/media/thumbnail.png +0 -0
  340. package/packages/env.particle.forest_edge_fog/metadata/description.json +148 -0
  341. package/packages/env.particle.forest_edge_fog/provenance/03-effect.original.json +827 -0
  342. package/packages/env.particle.forest_edge_fog/provenance/03-normalized-vfx-to-babylon-report.json +196 -0
  343. package/packages/env.particle.forest_edge_fog/provenance/04-preview-overrides.json +432 -0
  344. package/packages/env.particle.forest_edge_fog/provenance/04-preview-tuning-report.json +28 -0
  345. package/packages/env.particle.forest_edge_fog/provenance/asset-map.json +124 -0
  346. package/packages/env.particle.forest_edge_fog/provenance/lineage.json +41 -0
  347. package/packages/generation.ts +14 -0
  348. package/packages/index.ts +14 -0
  349. package/packages/legacy-particle-runtime.ts +113 -0
  350. package/packages/manifestRuntimePackage.ts +519 -0
  351. package/packages/registry.ts +85 -0
  352. package/packages/rendering.ts +13 -0
  353. package/packages/resource.particle.viscous_oil_suction/assets/runtime/top_disk_suction/particleEmitter.v1.js +424 -0
  354. package/packages/resource.particle.viscous_oil_suction/assets/textures/Glow ad.png +0 -0
  355. package/packages/resource.particle.viscous_oil_suction/effect.json +1254 -0
  356. package/packages/resource.particle.viscous_oil_suction/media/preview.gif +0 -0
  357. package/packages/resource.particle.viscous_oil_suction/media/preview.mp4 +0 -0
  358. package/packages/resource.particle.viscous_oil_suction/media/preview.webm +0 -0
  359. package/packages/resource.particle.viscous_oil_suction/media/thumbnail.png +0 -0
  360. package/packages/resource.particle.viscous_oil_suction/metadata/description.json +122 -0
  361. package/packages/resource.particle.viscous_oil_suction/provenance/03-effect.original.json +1051 -0
  362. package/packages/resource.particle.viscous_oil_suction/provenance/03-normalized-vfx-to-babylon-report.json +200 -0
  363. package/packages/resource.particle.viscous_oil_suction/provenance/04-preview-overrides.json +581 -0
  364. package/packages/resource.particle.viscous_oil_suction/provenance/04-preview-tuning-report.json +28 -0
  365. package/packages/resource.particle.viscous_oil_suction/provenance/asset-map.json +111 -0
  366. package/packages/resource.particle.viscous_oil_suction/provenance/lineage.json +45 -0
  367. package/packages/types.ts +107 -0
  368. package/tooling/check-dist-runtime.mjs +166 -0
  369. package/tooling/generate-index.mjs +55 -0
  370. package/tooling/test-guardrails.mjs +157 -0
  371. package/tooling/validate-boundary.mjs +92 -0
  372. package/tooling/validate-effects.mjs +304 -0
  373. package/tooling/validate.mjs +53 -0
  374. package/tooling/vfx-cli.mjs +232 -0
  375. package/tooling/vfx-package-resolution.mjs +28 -0
@@ -0,0 +1,462 @@
1
+ # 特效系统集成文档(VFX Integration)
2
+
3
+ 本文档面向无法直接访问代码库的工程师,描述项目中视觉特效(VFX)系统的整体架构、核心接口、完整调用链路,以及新增特效的标准步骤。渲染基于 Babylon.js(`SpriteManager` / `ParticleSystem`)。文中代码片段均摘自真实代码(个别处为突出主干有删减)。
4
+
5
+ ## 1. 架构总览
6
+
7
+ 特效系统分为四层:**特效包定义 → 服务层 → 触发层 → 驱动与销毁**。
8
+
9
+ ```
10
+ ┌─────────────────────────────────────────────────────────┐
11
+ │ 特效包定义层 src/assets/vfx/ │
12
+ │ 每个特效一个自包含目录:实现 + 参数 + 贴图 │
13
+ │ 在注册表中登记后即可被全局按 ID 调用 │
14
+ └─────────────────────────────────────────────────────────┘
15
+ ↓ 注册(编译期)
16
+ ┌─────────────────────────────────────────────────────────┐
17
+ │ 服务层 src/services/ │
18
+ │ SceneVfxService(门面) → EffectPackageService(核心) │
19
+ │ 负责:查包、参数合并、建 root 节点、追踪活跃 handle │
20
+ └─────────────────────────────────────────────────────────┘
21
+ ↓ 依赖注入(Game.init → gameplay)
22
+ ┌─────────────────────────────────────────────────────────┐
23
+ │ 触发层 src/systems/ │
24
+ │ 各 gameplay System 在 update() 中调用 │
25
+ │ sceneVfxService.playEffectPackage(id, params, spawn) │
26
+ └─────────────────────────────────────────────────────────┘
27
+ ↓ 返回 VfxEffectHandle
28
+ ┌─────────────────────────────────────────────────────────┐
29
+ │ 驱动与销毁 │
30
+ │ 每帧:scene.onBeforeRenderObservable(特效内部自驱动) │
31
+ │ 销毁:handle.dispose() / 超时定时器 / 场景卸载兜底 │
32
+ └─────────────────────────────────────────────────────────┘
33
+ ```
34
+
35
+ 数据流:**配置(json/tuning) → 加载(注册表) → 触发(System) → 更新(Babylon 帧回调) → 销毁(handle.dispose)**。
36
+
37
+ 设计上的两个核心约定:
38
+
39
+ - **特效包对宿主零感知**:特效只拿到一个 `root: TransformNode`,不知道也不关心自己挂在谁身上;跟随、定位全靠调用方操作 root。
40
+ - **统一参数模型**:所有特效参数是一个扁平字典,支持五层来源合并(默认值 → 落盘参数 → 调试覆盖 → 运行时传参),同一套参数同时服务于运行时调用和调试面板调参。
41
+
42
+ ## 2. 核心接口
43
+
44
+ 整个系统围绕三个接口运转(定义于 `src/assets/vfx/types.ts`):
45
+
46
+ ```typescript
47
+ /** 一个特效包:自包含、可注册、可参数化 */
48
+ export interface VfxEffectPackage<PParams extends VfxParamValues = VfxParamValues> {
49
+ id: string; // 全局唯一 ID,如 'vehicle-exhaust-smoke'
50
+ nameZh: string; // 中文名,如 '小车尾气'
51
+ manifest?: VfxEffectManifest; // 元数据(来自 effect.json)
52
+ defaultParams: PParams; // 代码内默认参数(全量)
53
+ savedParams?: Partial<VfxParamValues>; // 编辑器保存参数(来自 vfx-params.json)
54
+ debugParams: VfxParamDefinition[]; // 调试面板控件定义(滑杆/颜色/枚举)
55
+ debugAnchor?: VfxDebugAnchor; // 调试预览时的锚点('player' 等)
56
+ spawnParams?: VfxSpawnParamKeys; // 生成偏移参数的 key 映射(可选)
57
+ create(context: VfxEffectPackageContext<PParams>): VfxEffectHandle; // 工厂方法
58
+ }
59
+
60
+ /** create() 收到的上下文 */
61
+ export interface VfxEffectPackageContext<PParams> {
62
+ scene: Scene; // Babylon 场景
63
+ root: TransformNode; // 服务层已建好的根节点(位置/朝向已设置)
64
+ position: Vector3; // 世界坐标生成位置
65
+ rotationY: number; // Y 轴朝向
66
+ renderingGroupId?: number; // 渲染组(不传则用 VFX 默认组)
67
+ params: PParams; // 合并完成的最终参数
68
+ }
69
+
70
+ /** create() 的返回值:调用方拿到的控制句柄 */
71
+ export interface VfxEffectHandle {
72
+ root: TransformNode; // 可被 reparent 实现跟随
73
+ dispose(): void; // 销毁特效及其全部资源
74
+ }
75
+ ```
76
+
77
+ 参数值类型刻意收窄为三种,保证能被 JSON 落盘和调试面板编辑:
78
+
79
+ ```typescript
80
+ export type VfxParamValue = number | string | VfxColorValue; // VfxColorValue = { r, g, b }
81
+ export type VfxParamValues = Record<string, VfxParamValue>;
82
+ ```
83
+
84
+ `create()` 返回 `{ root, dispose }` 是整个系统的核心契约:调用方**只能**通过这两个成员与特效交互——用 root 控制空间关系,用 dispose 结束生命周期,没有第三种通道。
85
+
86
+ ## 3. 特效包定义层(`src/assets/vfx/`)
87
+
88
+ ### 3.1 目录结构
89
+
90
+ 每个特效是一个自包含目录,以卡车尾气为例:
91
+
92
+ ```
93
+ src/assets/vfx/effects/vehicle-exhaust-smoke/
94
+ ├── index.ts # 特效实现:导出一个 VfxEffectPackage 对象
95
+ ├── vfx-params.json # 调试面板调好后保存的参数(覆盖代码默认值)
96
+ ├── effect.json # 元数据 manifest(id / 中文名 / 资源清单)
97
+ └── assets/textures/ # 贴图资源(如 128x128 x 4 帧的烟雾图集)
98
+ ```
99
+
100
+ ### 3.2 注册表(`src/assets/vfx/index.ts`)
101
+
102
+ 新特效必须在注册表登记三处,之后即可在全项目按 ID 调用:
103
+
104
+ ```typescript
105
+ // ① import 特效包对象和它的参数文件
106
+ import { vehicleExhaustSmokeEffectPackage } from './effects/vehicle-exhaust-smoke';
107
+ import vehicleExhaustSmokeParams from './effects/vehicle-exhaust-smoke/vfx-params.json';
108
+
109
+ // ② 加入特效包数组
110
+ export const VFX_EFFECT_PACKAGES: VfxEffectPackage[] = [
111
+ /* ... 其他特效 ... */
112
+ vehicleExhaustSmokeEffectPackage,
113
+ ];
114
+
115
+ // ③ 登记落盘参数(key 为特效 ID)
116
+ export const VFX_EFFECT_SAVED_PARAMS: VfxDebugOverrides = {
117
+ /* ... */
118
+ 'vehicle-exhaust-smoke': sanitizeParamsFile(vehicleExhaustSmokeParams),
119
+ };
120
+ ```
121
+
122
+ 模块加载时注册表自动把 `savedParams` 回写到每个包对象上,并生成按 ID 索引的 `VFX_EFFECT_PACKAGE_MAP`。
123
+
124
+ ### 3.3 统一渲染配置(`src/assets/vfx/rendering.ts`)
125
+
126
+ - `VFX_RENDERING_GROUP_ID = 2`:所有特效默认走独立渲染组,与场景物体分层。
127
+ - `configureVfxSpriteManager()` / `configureVfxParticleSystem()`:统一关闭深度写入等设置。特效实现内创建 SpriteManager / ParticleSystem 后必须调用,保证全部特效渲染行为一致。
128
+
129
+ ## 4. 服务层(`src/services/`)
130
+
131
+ ### 4.1 两个类的分工
132
+
133
+ - **SceneVfxService**(门面,`src/services/SceneVfxService.ts`):对外统一入口。构造时内部创建 EffectPackageService 并转发 `playEffectPackage()`。另外支持从 `scene.json` 的 `tuning.sceneVfx` 配置创建**场景级常驻粒子**(环境氛围类,与特效包系统并行存在,走 `initFromConfig()`)。
134
+ - **EffectPackageService**(核心,`src/services/EffectPackageService.ts`):真正执行查包、参数合并、创建、追踪、销毁。
135
+
136
+ ### 4.2 播放一个特效时发生了什么
137
+
138
+ 调用方只看到一个方法:
139
+
140
+ ```typescript
141
+ playEffectPackage(
142
+ effectId: string, // 特效 ID
143
+ explicitParams?: Partial<VfxParamValues>, // 运行时参数覆盖(只传需要改的)
144
+ spawnTransform?: VfxSpawnTransform | Vector3, // 位置;或 { position, rotationY?, renderingGroupId? }
145
+ ): VfxEffectHandle | null
146
+ ```
147
+
148
+ 内部执行五步(摘自 EffectPackageService,有删减):
149
+
150
+ ```typescript
151
+ playEffectPackage(effectId, explicitParams?, spawnTransform?) {
152
+ // ① 查包:查不到打 warn 返回 null,不崩溃
153
+ const effectPackage = this.getEffectPackage(effectId);
154
+ if (!effectPackage) { console.warn(`Unknown VFX effect package: ${effectId}`); return null; }
155
+
156
+ // ② 参数合并(五层,后者覆盖前者,见 4.3)
157
+ const params = this.getMergedParams(effectId, explicitParams);
158
+
159
+ // ③ 建 root 节点,应用位置/朝向/生成偏移
160
+ const spawn = this.resolveSpawnTransform(effectPackage, params, spawnTransform);
161
+ const root = new TransformNode(`vfx_package_${effectId}`, this.scene);
162
+ root.position.copyFrom(spawn.position);
163
+ root.rotation.y = spawn.rotationY;
164
+
165
+ // ④ 调特效包的工厂方法
166
+ const handle = effectPackage.create({ scene: this.scene, root, /* position, rotationY, renderingGroupId, params */ });
167
+
168
+ // ⑤ 追踪 handle,并包装 dispose 使销毁时自动从追踪集合移除
169
+ this.activeHandles.add(handle);
170
+ const originalDispose = handle.dispose.bind(handle);
171
+ handle.dispose = () => {
172
+ this.activeHandles.delete(handle);
173
+ originalDispose();
174
+ };
175
+ return handle;
176
+ }
177
+ ```
178
+
179
+ `activeHandles: Set<VfxEffectHandle>` 是场景卸载时兜底清理的依据——`dispose()` 遍历销毁所有还活着的特效,杜绝泄漏。
180
+
181
+ ### 4.3 参数合并的五层优先级
182
+
183
+ `getMergedParams()` 按以下顺序 `Object.assign`,**后者覆盖前者**:
184
+
185
+ ```
186
+ ① VFX_DEFAULT_GENERATION_PARAMS 生成偏移参数(__generation.offsetX/Y/Z,默认 0)
187
+ ② effectPackage.defaultParams 代码内默认值(全量兜底)
188
+ ③ effectPackage.savedParams vfx-params.json(调试面板落盘的"美术定稿")
189
+ ④ 运行时调试面板覆盖 本次会话内临时调参
190
+ ⑤ explicitParams 调用方传入(最高优先级)
191
+ ```
192
+
193
+ 实际效果:美术在调试面板里调好的参数自动生效(③),游戏逻辑只需要覆盖与上下文相关的少数参数(⑤,如喷烟方向),互不干扰。
194
+
195
+ ### 4.4 接线:服务的创建与注入
196
+
197
+ 启动链路(`src/core/Game.ts` → `src/gameplay/createProjectGameplay.ts`):
198
+
199
+ 1. `Game.init()` 创建 `SceneVfxService` 并调 `initFromConfig()`;
200
+ 2. 服务实例放进 gameplay context;
201
+ 3. `createProjectGameplay.ts` 构造各 System 时以构造参数注入(CustomerTruckQueueSystem、UnlockSystem、WorkerAutomationSystem、PlayerFootstepDustSystem 等);
202
+ 4. Game 对外也暴露一个 `playEffectPackage()` 便捷入口;
203
+ 5. `Game.dispose()` 时调用 `sceneVfxService.dispose()` 兜底清理。
204
+
205
+ System 一律持有注入的服务实例,不自己 import 单例——便于测试和场景切换。
206
+
207
+ ## 5. 触发层:游戏逻辑如何播特效
208
+
209
+ ### 5.1 典型触发点
210
+
211
+ | 特效 | 触发方(src/systems/ 下) | 模式 |
212
+ |---|---|---|
213
+ | `run-footstep-dust` 脚步灰尘 | PlayerFootstepDustSystem | 移速超阈值时周期触发 |
214
+ | `vehicle-exhaust-smoke` 卡车尾气 | CustomerTruckQueueSystem | 持续型,挂载跟随 |
215
+ | `player-upgrade` NPC 升级金光 | WorkerAutomationSystem | 一次性,参数来自 tuning 文件 |
216
+ | `resource-collect-sparkles` 收集火花 | MoneyDropSystem | 一次性,全默认参数 |
217
+ | `ground-tile-upgrade` 区域解锁 | UnlockSystem | 一次性,参数按区域尺寸动态计算 |
218
+
219
+ ### 5.2 一次性特效:最简调用
220
+
221
+ 钱币到达支付区时播收集火花(摘自 MoneyDropSystem):
222
+
223
+ ```typescript
224
+ this.sceneVfxService?.playEffectPackage(
225
+ 'resource-collect-sparkles',
226
+ undefined, // 不覆盖任何参数,全部用默认/落盘值
227
+ arrivalPosition, // 直接传 Vector3 作为生成位置
228
+ );
229
+ // 不保留 handle:特效播完自动 dispose 自己
230
+ ```
231
+
232
+ 带参数覆盖的版本(摘自 PlayerFootstepDustSystem,玩家奔跑时的灰尘):
233
+
234
+ ```typescript
235
+ const handle = this.sceneVfxService.playEffectPackage(
236
+ 'run-footstep-dust',
237
+ {
238
+ emitMode: 'timed',
239
+ lifetime: 0.18,
240
+ directionX, directionZ, // 与移动方向相关,只能运行时算
241
+ },
242
+ { position, renderingGroupId },
243
+ );
244
+ ```
245
+
246
+ ### 5.3 持续跟随型特效:reparent 模式
247
+
248
+ 这是持续型特效的标准写法,以卡车尾气为范例(摘自 CustomerTruckQueueSystem)。要点:先按世界坐标播放,再把返回的 `handle.root` 重新挂到目标节点下、改为局部偏移:
249
+
250
+ ```typescript
251
+ private startExhaustSmoke(node: TransformNode): VfxEffectHandle | null {
252
+ const handle = this.sceneVfxService?.playEffectPackage(
253
+ 'vehicle-exhaust-smoke',
254
+ { directionX: 0, directionZ: -1 }, // 只覆盖喷烟方向
255
+ {
256
+ position: node.getAbsolutePosition().add(EXHAUST_LOCAL_OFFSET),
257
+ rotationY: node.rotation.y,
258
+ renderingGroupId: resolveNodeRenderingGroupId(node, OFFSET),
259
+ },
260
+ ) ?? null;
261
+ if (!handle?.root) return handle;
262
+
263
+ handle.root.parent = node; // 关键:挂到卡车节点下
264
+ handle.root.position.copyFrom(EXHAUST_LOCAL_OFFSET); // 世界坐标 → 局部偏移
265
+ handle.root.rotation.y = 0;
266
+ return handle;
267
+ }
268
+ ```
269
+
270
+ 之后卡车移动/转向,尾气自动跟随——特效内部每次发射烟团时用 `root.getWorldMatrix()` 把局部方向变换到世界空间,所以卡车转弯时喷烟方向也自动正确。特效完全不知道宿主的存在,这就是第 1 节说的"对宿主零感知"。
271
+
272
+ 调用方保留 handle,在宿主回收时负责销毁:
273
+
274
+ ```typescript
275
+ private recycleTruck(truck: TruckRecord): void {
276
+ truck.exhaustHandle?.dispose();
277
+ truck.exhaustHandle = null;
278
+ /* ... 其他回收逻辑 ... */
279
+ }
280
+ ```
281
+
282
+ ## 6. 特效内部实现模式
283
+
284
+ 以尾气(`src/assets/vfx/effects/vehicle-exhaust-smoke/index.ts`)为代表,一个特效包实现包含五个部分:
285
+
286
+ ### 6.1 参数接口与默认值
287
+
288
+ ```typescript
289
+ interface VehicleExhaustSmokeParams extends VfxParamValues {
290
+ lifetimeMode: string; // 'infinite' | 'duration'
291
+ scale: number;
292
+ color: VfxColorValue;
293
+ particleCount: number;
294
+ driftSpeed: number;
295
+ directionX: number;
296
+ directionZ: number;
297
+ /* ... 共 14 个参数 ... */
298
+ }
299
+
300
+ const DEFAULT_PARAMS: VehicleExhaustSmokeParams = {
301
+ lifetimeMode: 'infinite',
302
+ scale: 1.35,
303
+ particleCount: 82,
304
+ /* ... 全量默认值 ... */
305
+ };
306
+ ```
307
+
308
+ ### 6.2 debugParams:调试面板控件即代码
309
+
310
+ 每个参数声明一个控件定义,调试面板据此自动生成 UI:
311
+
312
+ ```typescript
313
+ debugParams: [
314
+ { key: 'lifetimeMode', label: '生命周期模式', kind: 'enum',
315
+ options: [{ value: 'infinite', label: '无限' }, { value: 'duration', label: '自定义时间' }] },
316
+ { key: 'scale', label: '整体缩放', kind: 'scale', min: 0.05, max: 8, step: 0.01 },
317
+ { key: 'color', label: '尾气颜色', kind: 'color' },
318
+ { key: 'particleCount', label: '粒子数量', kind: 'number', min: 1, max: 180, step: 1 },
319
+ /* ... */
320
+ ],
321
+ ```
322
+
323
+ 调完保存即落盘到该特效的 `vfx-params.json`,下次启动自动生效(参数合并第 ③ 层)。
324
+
325
+ ### 6.3 create():工厂方法骨架
326
+
327
+ ```typescript
328
+ create({ scene, root, position, renderingGroupId, params }) {
329
+ root.position.copyFrom(position).addInPlace(/* 初始高度偏移 */);
330
+ const smokeTrail = createExhaustSpriteTrail(scene, root, params, renderingGroupId);
331
+
332
+ // 'infinite' 模式不设定时器,依赖外部 dispose;'duration' 模式超时自动清理
333
+ const durationSeconds = readDurationSeconds(params); // infinite → null
334
+ const disposeTimer = durationSeconds == null
335
+ ? 0
336
+ : window.setTimeout(() => disposeAll(), getDisposeDelaySeconds(params) * 1000);
337
+
338
+ return {
339
+ root,
340
+ dispose() { disposeAll(); },
341
+ };
342
+
343
+ function disposeAll() {
344
+ if (disposed) return;
345
+ disposed = true;
346
+ if (disposeTimer) window.clearTimeout(disposeTimer);
347
+ smokeTrail.dispose(); // 摘帧观察器、销毁全部 sprite 和 SpriteManager
348
+ root.dispose();
349
+ }
350
+ }
351
+ ```
352
+
353
+ ### 6.4 每帧驱动与内部精灵池
354
+
355
+ 特效不依赖游戏的 tick,直接挂 Babylon 的帧回调自驱动:
356
+
357
+ ```typescript
358
+ const observer = scene.onBeforeRenderObservable.add(() => {
359
+ const deltaSeconds = Math.min(0.05, scene.getEngine().getDeltaTime() / 1000);
360
+
361
+ // 按发射间隔从池里取空闲 sprite 生成新烟团
362
+ emitAccumulator += deltaSeconds;
363
+ while (emitAccumulator >= emitInterval) {
364
+ emitAccumulator -= emitInterval;
365
+ const state = findAvailableState(states); // 找 active === false 的复用
366
+ if (!state) break;
367
+ spawnPuff(state, emissionIndex++);
368
+ }
369
+
370
+ // 更新所有活跃烟团:位移、旋转、放大、淡入淡出
371
+ for (const state of states) {
372
+ if (!state.active) continue;
373
+ state.age += deltaSeconds;
374
+ const t = Math.min(1, state.age / state.lifetime);
375
+ /* ... alpha = 淡入 × 淡出, size = base × (1 + t × 1.45) ... */
376
+ if (t >= 1) state.active = false; // 寿命结束归还池子
377
+ }
378
+ });
379
+ ```
380
+
381
+ 两个值得注意的实现约定:
382
+
383
+ - **内部精灵池**:持续型特效一次性创建 `particleCount` 个 Sprite,用 `active` 标志循环复用,运行期间零分配。handle 层面没有池化(每次 play 都新建),但特效内部应当池化。另有 warm start:创建时先点燃几团烟,避免宿主出场瞬间特效是空的。
384
+ - **确定性随机**:不用 `Math.random()`,用黄金分割步进序列 `sequence01(seed, axis)` 生成抖动,同样的输入产生同样的画面,便于回归对比。
385
+
386
+ ### 6.5 dispose:必须释放的清单
387
+
388
+ ```typescript
389
+ function dispose(): void {
390
+ scene.onBeforeRenderObservable.remove(observer); // ① 帧观察器
391
+ for (const state of states) state.sprite.dispose(); // ② 全部 sprite
392
+ manager.dispose(); // ③ SpriteManager(含贴图)
393
+ }
394
+ // 外层 disposeAll 再清掉定时器并 root.dispose() // ④⑤
395
+ ```
396
+
397
+ 帧观察器、Sprite/ParticleSystem、SpriteManager、贴图、root 节点,五样缺一不可,否则泄漏。
398
+
399
+ ## 7. 生命周期:三条销毁路径
400
+
401
+ 1. **手动**:调用方持有 handle,宿主结束时 `handle.dispose()`(如卡车驶出地图回收时销毁尾气)。
402
+ 2. **超时**:一次性特效内部 `setTimeout` 自动清理;或调用方侧定时(如区域解锁特效 3.6 秒后清理)。
403
+ 3. **兜底**:`Game.dispose()` → `SceneVfxService.dispose()` → `EffectPackageService.dispose()` 遍历 `activeHandles` 全部销毁。
404
+
405
+ 由于服务层包装过 dispose(见 4.2 第⑤步),任何一条路径触发后 handle 都会从追踪集合自动移除,重复调用 dispose 也安全(特效内部有 `disposed` 标志防重入)。
406
+
407
+ ## 8. 配置与调参工作流
408
+
409
+ - **专项 tuning 文件**(`src/config/` 下):复杂特效的参数集中在独立配置文件,带默认值与 sanitize 校验函数,游戏逻辑取参后传入 `playEffectPackage()`。例如 NPC 升级特效(19 个参数)、区域解锁特效、生成缩放动画、资源收集特效各有一个 tuning 文件。
410
+ - **场景级配置**:`scene.json` 的 `tuning.sceneVfx` 用于常驻环境粒子,由 `SceneVfxService.initFromConfig()` 加载,按 `effects → systems` 两级结构定义发射器位置与粒子系统。
411
+ - **调试面板**(`src/debug/` 下):
412
+ - 通用 VFX 面板:选任意特效包预览,按 `debugParams` 生成滑杆实时调参;
413
+ - 另有 NPC 升级、区域解锁两个专用面板;
414
+ - 会话内调参属于参数合并第 ④ 层;确认后落盘到特效包的 `vfx-params.json`(第 ③ 层),随代码提交。
415
+ - **编辑器适配层**(`src/fps-game-editor-adapter/`)与特效系统基本解耦,无直接集成。
416
+
417
+ ## 9. 新增特效的标准步骤
418
+
419
+ 1. 在 `src/assets/vfx/effects/<effect-id>/` 创建目录:
420
+ - `index.ts` — 导出 `VfxEffectPackage` 对象:定义参数接口、`DEFAULT_PARAMS`、`debugParams`,实现 `create(context)` 返回 `{ root, dispose }`;
421
+ - `vfx-params.json` — 初始可只含生成偏移,后续由调试面板写入;
422
+ - `effect.json` — manifest 元数据;
423
+ - `assets/textures/` — 贴图。
424
+ 2. 在 `src/assets/vfx/index.ts` 登记三处:import、`VFX_EFFECT_PACKAGES`、`VFX_EFFECT_SAVED_PARAMS`(见 3.2 的代码示例)。
425
+ 3. 实现注意事项:
426
+ - SpriteManager / ParticleSystem 创建后调 `configureVfxSpriteManager` / `configureVfxParticleSystem`,渲染组用 `renderingGroupId ?? VFX_RENDERING_GROUP_ID`;
427
+ - 每帧逻辑挂 `scene.onBeforeRenderObservable`,dispose 时务必 remove;
428
+ - 持续型特效内部池化精灵;方向类参数用 `root.getWorldMatrix()` 变换,以支持 reparent 跟随;
429
+ - 随机数用确定性序列,不用 `Math.random()`;
430
+ - dispose 按 6.5 的清单释放全部资源,并加 `disposed` 标志防重入。
431
+ 4. 在目标 System 中通过注入的 `sceneVfxService.playEffectPackage()` 触发;持续跟随型按 5.3 的 reparent 模式写。
432
+ 5. 用通用 VFX 调试面板调参,确认后保存到 `vfx-params.json` 随代码提交。
433
+
434
+ ## 10. 已集成特效清单
435
+
436
+ 注册顺序见 `src/assets/vfx/index.ts` 的 `VFX_EFFECT_PACKAGES`:
437
+
438
+ | 特效 ID | 说明 |
439
+ |---|---|
440
+ | `lumber-debris-scatter` | 木材碎片散落 |
441
+ | `player-upgrade` | 玩家/NPC 升级金光 |
442
+ | `run-footstep-dust` | 奔跑脚步灰尘 |
443
+ | `tree-leaf-chop-burst` | 砍树叶子飞散 |
444
+ | `tree-chop-dust` | 砍树烟尘 |
445
+ | `building-upgrade` | 建筑升级 |
446
+ | `character-entrance` | 角色入场 |
447
+ | `lumber-cart-suction` | 木材车吸取 |
448
+ | `resource-collect-sparkles` | 资源收集火花 |
449
+ | `lumber_vehicle_wood_chips` | 运木车木屑 |
450
+ | `tree_chop_dust_burst` | 砍树尘埃爆发 |
451
+ | `wood_crusher_sawdust` | 粉碎机锯屑(manifest 版) |
452
+ | `wood_cutter_sawdust` | 切割机锯屑(manifest 版) |
453
+ | `lumber_vehicle_upgrade_aura` | 运木车升级光环 |
454
+ | `lumber_vehicle_gear_spin` | 运木车齿轮旋转 |
455
+ | `door_open_gold_flakes` | 开门金色碎片 |
456
+ | `wood_peel_material_test` | 木材剥离材质测试 |
457
+ | `vehicle-exhaust-smoke` | 小车尾气 |
458
+ | `vehicle-upgrade` | 车辆升级 |
459
+ | `conveyor-upgrade` | 传送带升级 |
460
+ | `ground-tile-upgrade` | 地砖升级(区域解锁) |
461
+ | `wood-crusher-sawdust` | 粉碎机锯屑 |
462
+ | `wood-cutter-sawdust` | 切割机锯屑 |