@fps-games/vfx 0.1.1 → 0.3.3

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 (250) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/README.md +41 -0
  3. package/dist/effects/coin-burst/index.js +6 -2
  4. package/dist/effects/comet-trail-flame/index.js +3 -1
  5. package/dist/effects/debris-smoke/index.js +1 -0
  6. package/dist/effects/electric-arc/index.js +1 -0
  7. package/dist/effects/energy-shield/index.js +1 -0
  8. package/dist/effects/explosion/index.js +3 -2
  9. package/dist/effects/hit-flash/index.js +12 -4
  10. package/dist/effects/laser-beam/index.js +14 -2
  11. package/dist/effects/lumber_vehicle_upgrade_aura/index.js +1 -0
  12. package/dist/effects/monster-hit/index.js +2 -1
  13. package/dist/effects/player-upgrade/index.js +5 -3
  14. package/dist/effects/pulse-laser-volley/index.js +14 -4
  15. package/dist/effects/thruster-flame/index.js +3 -1
  16. package/dist/effects/treasure-attention/index.d.ts +54 -0
  17. package/dist/effects/treasure-attention/index.js +535 -0
  18. package/dist/effects/ufo-thread-flame/index.js +1 -0
  19. package/dist/effects/vehicle-upgrade/index.js +4 -1
  20. package/dist/effects/weapon-trail/index.js +8 -3
  21. package/dist/effects/wood_crusher_sawdust/index.d.ts +4 -0
  22. package/dist/effects/wood_cutter_sawdust/index.d.ts +4 -0
  23. package/dist/index.js +85 -17
  24. package/dist/types.d.ts +80 -0
  25. package/index.json +19 -1
  26. package/package.json +9 -4
  27. package/packages/effects/treasure-attention/vfx-params.json +49 -0
  28. package/tooling/vfx-cli.mjs +8 -1
  29. package/docs/AUTHORING_EFFECTS.md +0 -297
  30. package/docs/VFX_LIBRARY_ARCHITECTURE_chatgpt.md +0 -1580
  31. package/docs/VFX_LIBRARY_EXECUTION_PLAN.md +0 -229
  32. package/docs/VFX_LIBRARY_PLAN.md +0 -546
  33. package/docs/vfx-ab/RESULTS.md +0 -35
  34. package/docs/vfx-ab/lumber-order/vehicle-exhaust-smoke/after.png +0 -0
  35. package/docs/vfx-ab/lumber-order/vehicle-exhaust-smoke/before.png +0 -0
  36. package/docs/vfx-ab/lumber-truck/vehicle-exhaust-smoke/after.png +0 -0
  37. package/docs/vfx-ab/lumber-truck/vehicle-exhaust-smoke/before.png +0 -0
  38. package/docs/vfx-integration_chatgpt.md +0 -462
  39. package/docs/weapon-trail-visualization.html +0 -241
  40. package/packages/EffectPackageService.ts +0 -240
  41. package/packages/SceneVfxService.ts +0 -96
  42. package/packages/build.mesh.yellow_build_upgrade_indicator/assets/runtime/simpleMeshEffect.v1.js +0 -333
  43. package/packages/build.mesh.yellow_build_upgrade_indicator/assets/shaders/mesh-effect-preview.frag.glsl +0 -25
  44. package/packages/build.mesh.yellow_build_upgrade_indicator/assets/shaders/mesh-effect-preview.vert.glsl +0 -11
  45. package/packages/build.mesh.yellow_build_upgrade_indicator/assets/textures/effect_jianbian.png +0 -0
  46. package/packages/build.mesh.yellow_build_upgrade_indicator/effect.json +0 -927
  47. package/packages/build.mesh.yellow_build_upgrade_indicator/media/contact-sheet.png +0 -0
  48. package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.gif +0 -0
  49. package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.mp4 +0 -0
  50. package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.webm +0 -0
  51. package/packages/build.mesh.yellow_build_upgrade_indicator/media/thumbnail.png +0 -0
  52. package/packages/build.mesh.yellow_build_upgrade_indicator/metadata/description.json +0 -197
  53. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/03-effect.original.json +0 -895
  54. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/03-normalized-vfx-to-babylon-report.json +0 -241
  55. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/04-preview-overrides.json +0 -542
  56. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/04-preview-tuning-report.json +0 -69
  57. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/asset-map.json +0 -125
  58. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/lineage.json +0 -44
  59. package/packages/build.particle.golden_upgrade_starburst/assets/runtime/particleEmitter.v1.js +0 -210
  60. package/packages/build.particle.golden_upgrade_starburst/assets/textures/effect_guangdian.png +0 -0
  61. package/packages/build.particle.golden_upgrade_starburst/effect.json +0 -880
  62. package/packages/build.particle.golden_upgrade_starburst/media/contact-sheet.png +0 -0
  63. package/packages/build.particle.golden_upgrade_starburst/media/preview.gif +0 -0
  64. package/packages/build.particle.golden_upgrade_starburst/media/preview.mp4 +0 -0
  65. package/packages/build.particle.golden_upgrade_starburst/media/preview.webm +0 -0
  66. package/packages/build.particle.golden_upgrade_starburst/media/thumbnail.png +0 -0
  67. package/packages/build.particle.golden_upgrade_starburst/metadata/description.json +0 -161
  68. package/packages/build.particle.golden_upgrade_starburst/provenance/03-effect.original.json +0 -762
  69. package/packages/build.particle.golden_upgrade_starburst/provenance/03-normalized-vfx-to-babylon-report.json +0 -260
  70. package/packages/build.particle.golden_upgrade_starburst/provenance/04-preview-overrides.json +0 -436
  71. package/packages/build.particle.golden_upgrade_starburst/provenance/04-preview-tuning-report.json +0 -40
  72. package/packages/build.particle.golden_upgrade_starburst/provenance/asset-map.json +0 -115
  73. package/packages/build.particle.golden_upgrade_starburst/provenance/lineage.json +0 -40
  74. package/packages/build.particle.orange_upgrade_transform_sparks/assets/runtime/particleEmitter.v1.js +0 -210
  75. package/packages/build.particle.orange_upgrade_transform_sparks/assets/textures/b5b27ab1-e740-4398-b407-848fc2b2c897.png +0 -0
  76. package/packages/build.particle.orange_upgrade_transform_sparks/effect.json +0 -887
  77. package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.gif +0 -0
  78. package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.mp4 +0 -0
  79. package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.webm +0 -0
  80. package/packages/build.particle.orange_upgrade_transform_sparks/media/thumbnail.png +0 -0
  81. package/packages/build.particle.orange_upgrade_transform_sparks/metadata/description.json +0 -179
  82. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/03-effect.original.json +0 -859
  83. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/03-normalized-vfx-to-babylon-report.json +0 -260
  84. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/04-preview-overrides.json +0 -478
  85. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/04-preview-tuning-report.json +0 -40
  86. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/asset-map.json +0 -114
  87. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/lineage.json +0 -41
  88. package/packages/build.particle.wood_chip_dust_burst/assets/runtime/particleEmitter.v1.js +0 -210
  89. package/packages/build.particle.wood_chip_dust_burst/assets/textures/effect_yanwu4.png +0 -0
  90. package/packages/build.particle.wood_chip_dust_burst/assets/textures/suipian3.png +0 -0
  91. package/packages/build.particle.wood_chip_dust_burst/effect.json +0 -1400
  92. package/packages/build.particle.wood_chip_dust_burst/media/contact-sheet.png +0 -0
  93. package/packages/build.particle.wood_chip_dust_burst/media/preview.gif +0 -0
  94. package/packages/build.particle.wood_chip_dust_burst/media/preview.mp4 +0 -0
  95. package/packages/build.particle.wood_chip_dust_burst/media/preview.webm +0 -0
  96. package/packages/build.particle.wood_chip_dust_burst/media/thumbnail.png +0 -0
  97. package/packages/build.particle.wood_chip_dust_burst/metadata/description.json +0 -173
  98. package/packages/build.particle.wood_chip_dust_burst/provenance/03-effect.original.json +0 -1277
  99. package/packages/build.particle.wood_chip_dust_burst/provenance/03-normalized-vfx-to-babylon-report.json +0 -329
  100. package/packages/build.particle.wood_chip_dust_burst/provenance/04-preview-overrides.json +0 -749
  101. package/packages/build.particle.wood_chip_dust_burst/provenance/04-preview-tuning-report.json +0 -60
  102. package/packages/build.particle.wood_chip_dust_burst/provenance/asset-map.json +0 -146
  103. package/packages/build.particle.wood_chip_dust_burst/provenance/lineage.json +0 -69
  104. package/packages/effects/building-upgrade/effect.json +0 -6
  105. package/packages/effects/building-upgrade/index.ts +0 -387
  106. package/packages/effects/character-entrance/effect.json +0 -6
  107. package/packages/effects/character-entrance/index.ts +0 -308
  108. package/packages/effects/coin-burst/index.ts +0 -43
  109. package/packages/effects/comet-trail-flame/assets/textures/trail_5x4.webp +0 -0
  110. package/packages/effects/comet-trail-flame/index.ts +0 -106
  111. package/packages/effects/conveyor-upgrade/effect.json +0 -6
  112. package/packages/effects/conveyor-upgrade/index.ts +0 -401
  113. package/packages/effects/debris-smoke/assets/models/rock_debris.glb +0 -0
  114. package/packages/effects/debris-smoke/assets/textures/smoke22.webp +0 -0
  115. package/packages/effects/debris-smoke/index.ts +0 -101
  116. package/packages/effects/door_open_gold_flakes/assets/runtime/goldFlakes.v1.js +0 -397
  117. package/packages/effects/door_open_gold_flakes/door_open_gold_flakes.json +0 -498
  118. package/packages/effects/door_open_gold_flakes/index.ts +0 -11
  119. package/packages/effects/electric-arc/assets/textures/spark_4x4.webp +0 -0
  120. package/packages/effects/electric-arc/index.ts +0 -62
  121. package/packages/effects/energy-shield/effect.json +0 -7
  122. package/packages/effects/energy-shield/index.ts +0 -431
  123. package/packages/effects/explosion/assets/textures/baozha29.webp +0 -0
  124. package/packages/effects/explosion/assets/textures/glow01.webp +0 -0
  125. package/packages/effects/explosion/assets/textures/lizi01.webp +0 -0
  126. package/packages/effects/explosion/assets/textures/xulie_lizibaozha02_5x5.webp +0 -0
  127. package/packages/effects/explosion/index.ts +0 -114
  128. package/packages/effects/ground-tile-upgrade/effect.json +0 -6
  129. package/packages/effects/ground-tile-upgrade/index.ts +0 -410
  130. package/packages/effects/hit-flash/index.ts +0 -69
  131. package/packages/effects/laser-beam/assets/textures/laser_glow.webp +0 -0
  132. package/packages/effects/laser-beam/assets/textures/laser_noise.webp +0 -0
  133. package/packages/effects/laser-beam/index.ts +0 -6
  134. package/packages/effects/laser-beam-factory.ts +0 -135
  135. package/packages/effects/lumber-cart-suction/effect.json +0 -6
  136. package/packages/effects/lumber-cart-suction/index.ts +0 -399
  137. package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb +0 -0
  138. package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb.versions/.active +0 -1
  139. package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb.versions/1781589063890_upload.glb +0 -0
  140. package/packages/effects/lumber-debris-scatter/assets/runtime/solidParticleScatter.v1.js +0 -236
  141. package/packages/effects/lumber-debris-scatter/effect.json +0 -228
  142. package/packages/effects/lumber-debris-scatter/index.ts +0 -780
  143. package/packages/effects/lumber_vehicle_gear_spin/assets/runtime/gearSpin.v1.js +0 -202
  144. package/packages/effects/lumber_vehicle_gear_spin/index.ts +0 -11
  145. package/packages/effects/lumber_vehicle_gear_spin/lumber_vehicle_gear_spin.json +0 -338
  146. package/packages/effects/lumber_vehicle_upgrade_aura/assets/runtime/upgradeAura.v1.js +0 -353
  147. package/packages/effects/lumber_vehicle_upgrade_aura/index.ts +0 -11
  148. package/packages/effects/lumber_vehicle_upgrade_aura/lumber_vehicle_upgrade_aura.json +0 -365
  149. package/packages/effects/lumber_vehicle_wood_chips/assets/runtime/solidParticleScatter.v1.js +0 -310
  150. package/packages/effects/lumber_vehicle_wood_chips/index.ts +0 -11
  151. package/packages/effects/lumber_vehicle_wood_chips/lumber_vehicle_wood_chips.json +0 -335
  152. package/packages/effects/monster-hit/index.ts +0 -128
  153. package/packages/effects/player-upgrade/effect.json +0 -6
  154. package/packages/effects/player-upgrade/index.ts +0 -635
  155. package/packages/effects/pulse-laser-volley/assets/textures/bolt_guangshu.webp +0 -0
  156. package/packages/effects/pulse-laser-volley/index.ts +0 -204
  157. package/packages/effects/resource-collect-sparkles/effect.json +0 -6
  158. package/packages/effects/resource-collect-sparkles/index.ts +0 -254
  159. package/packages/effects/run-footstep-dust/assets/runtime/runFootstepDust.v1.js +0 -215
  160. package/packages/effects/run-footstep-dust/effect.json +0 -183
  161. package/packages/effects/run-footstep-dust/index.ts +0 -377
  162. package/packages/effects/space-shared.ts +0 -120
  163. package/packages/effects/thruster-flame/index.ts +0 -305
  164. package/packages/effects/tree-chop-dust/assets/textures/tree_chop_dust_atlas.png +0 -0
  165. package/packages/effects/tree-chop-dust/effect.json +0 -8
  166. package/packages/effects/tree-chop-dust/index.ts +0 -202
  167. package/packages/effects/tree-leaf-chop-burst/assets/runtime/particleEmitter.v1.js +0 -303
  168. package/packages/effects/tree-leaf-chop-burst/assets/textures/tree_leaf_chop_burst_leaf_atlas.png +0 -0
  169. package/packages/effects/tree-leaf-chop-burst/effect.json +0 -498
  170. package/packages/effects/tree-leaf-chop-burst/index.ts +0 -294
  171. package/packages/effects/tree_chop_dust_burst/assets/runtime/particleEmitter.v1.js +0 -318
  172. package/packages/effects/tree_chop_dust_burst/assets/textures/tree_chop_dust_burst_dust.png +0 -0
  173. package/packages/effects/tree_chop_dust_burst/index.ts +0 -13
  174. package/packages/effects/tree_chop_dust_burst/tree_chop_dust_burst.json +0 -412
  175. package/packages/effects/ufo-thread-flame/assets/textures/flame_flow.webp +0 -0
  176. package/packages/effects/ufo-thread-flame/assets/textures/flame_spike.webp +0 -0
  177. package/packages/effects/ufo-thread-flame/index.ts +0 -152
  178. package/packages/effects/vehicle-exhaust-smoke/assets/textures/vehicle_exhaust_smoke_atlas.png +0 -0
  179. package/packages/effects/vehicle-exhaust-smoke/effect.json +0 -8
  180. package/packages/effects/vehicle-exhaust-smoke/index.ts +0 -298
  181. package/packages/effects/vehicle-upgrade/effect.json +0 -6
  182. package/packages/effects/vehicle-upgrade/index.ts +0 -401
  183. package/packages/effects/weapon-trail/assets/textures/trail_wedge.png +0 -0
  184. package/packages/effects/weapon-trail/index.ts +0 -313
  185. package/packages/effects/wood-crusher-sawdust/assets/runtime/particleEmitter.v1.js +0 -312
  186. package/packages/effects/wood-crusher-sawdust/assets/textures/wood_crusher_sawdust_dust.png +0 -0
  187. package/packages/effects/wood-crusher-sawdust/assets/textures/wood_crusher_sawdust_fiber.png +0 -0
  188. package/packages/effects/wood-crusher-sawdust/index.ts +0 -43
  189. package/packages/effects/wood-crusher-sawdust/wood_crusher_sawdust.json +0 -592
  190. package/packages/effects/wood-cutter-sawdust/assets/runtime/particleEmitter.v1.js +0 -312
  191. package/packages/effects/wood-cutter-sawdust/assets/textures/wood_cutter_sawdust_chip.png +0 -0
  192. package/packages/effects/wood-cutter-sawdust/assets/textures/wood_cutter_sawdust_dust.png +0 -0
  193. package/packages/effects/wood-cutter-sawdust/index.ts +0 -43
  194. package/packages/effects/wood-cutter-sawdust/wood_cutter_sawdust.json +0 -592
  195. package/packages/effects/wood-sawdust-effect-factory.ts +0 -194
  196. package/packages/effects/wood_crusher_sawdust/assets/runtime/particleEmitter.v1.js +0 -318
  197. package/packages/effects/wood_crusher_sawdust/assets/textures/wood_crusher_sawdust_dust.png +0 -0
  198. package/packages/effects/wood_crusher_sawdust/assets/textures/wood_crusher_sawdust_fiber.png +0 -0
  199. package/packages/effects/wood_crusher_sawdust/index.ts +0 -29
  200. package/packages/effects/wood_crusher_sawdust/wood_crusher_sawdust.json +0 -592
  201. package/packages/effects/wood_cutter_sawdust/assets/runtime/particleEmitter.v1.js +0 -318
  202. package/packages/effects/wood_cutter_sawdust/assets/textures/wood_cutter_sawdust_chip.png +0 -0
  203. package/packages/effects/wood_cutter_sawdust/assets/textures/wood_cutter_sawdust_dust.png +0 -0
  204. package/packages/effects/wood_cutter_sawdust/index.ts +0 -29
  205. package/packages/effects/wood_cutter_sawdust/wood_cutter_sawdust.json +0 -592
  206. package/packages/effects/wood_peel_material_test/assets/runtime/woodPeelMaterialTest.v1.js +0 -196
  207. package/packages/effects/wood_peel_material_test/index.ts +0 -11
  208. package/packages/effects/wood_peel_material_test/wood_peel_material_test.json +0 -136
  209. package/packages/env.particle.forest_edge_fog/assets/runtime/particleEmitter.v1.js +0 -210
  210. package/packages/env.particle.forest_edge_fog/assets/textures/f12a23c4-b924-4322-a260-3d982428f1e8.png +0 -0
  211. package/packages/env.particle.forest_edge_fog/assets/textures/yuan.png +0 -0
  212. package/packages/env.particle.forest_edge_fog/effect.json +0 -854
  213. package/packages/env.particle.forest_edge_fog/media/preview.gif +0 -0
  214. package/packages/env.particle.forest_edge_fog/media/preview.mp4 +0 -0
  215. package/packages/env.particle.forest_edge_fog/media/preview.webm +0 -0
  216. package/packages/env.particle.forest_edge_fog/media/thumbnail.png +0 -0
  217. package/packages/env.particle.forest_edge_fog/metadata/description.json +0 -148
  218. package/packages/env.particle.forest_edge_fog/provenance/03-effect.original.json +0 -827
  219. package/packages/env.particle.forest_edge_fog/provenance/03-normalized-vfx-to-babylon-report.json +0 -196
  220. package/packages/env.particle.forest_edge_fog/provenance/04-preview-overrides.json +0 -432
  221. package/packages/env.particle.forest_edge_fog/provenance/04-preview-tuning-report.json +0 -28
  222. package/packages/env.particle.forest_edge_fog/provenance/asset-map.json +0 -124
  223. package/packages/env.particle.forest_edge_fog/provenance/lineage.json +0 -41
  224. package/packages/generation.ts +0 -14
  225. package/packages/index.ts +0 -14
  226. package/packages/legacy-particle-runtime.ts +0 -113
  227. package/packages/manifestRuntimePackage.ts +0 -519
  228. package/packages/registry.ts +0 -85
  229. package/packages/rendering.ts +0 -13
  230. package/packages/resource.particle.viscous_oil_suction/assets/runtime/top_disk_suction/particleEmitter.v1.js +0 -424
  231. package/packages/resource.particle.viscous_oil_suction/assets/textures/Glow ad.png +0 -0
  232. package/packages/resource.particle.viscous_oil_suction/effect.json +0 -1254
  233. package/packages/resource.particle.viscous_oil_suction/media/preview.gif +0 -0
  234. package/packages/resource.particle.viscous_oil_suction/media/preview.mp4 +0 -0
  235. package/packages/resource.particle.viscous_oil_suction/media/preview.webm +0 -0
  236. package/packages/resource.particle.viscous_oil_suction/media/thumbnail.png +0 -0
  237. package/packages/resource.particle.viscous_oil_suction/metadata/description.json +0 -122
  238. package/packages/resource.particle.viscous_oil_suction/provenance/03-effect.original.json +0 -1051
  239. package/packages/resource.particle.viscous_oil_suction/provenance/03-normalized-vfx-to-babylon-report.json +0 -200
  240. package/packages/resource.particle.viscous_oil_suction/provenance/04-preview-overrides.json +0 -581
  241. package/packages/resource.particle.viscous_oil_suction/provenance/04-preview-tuning-report.json +0 -28
  242. package/packages/resource.particle.viscous_oil_suction/provenance/asset-map.json +0 -111
  243. package/packages/resource.particle.viscous_oil_suction/provenance/lineage.json +0 -45
  244. package/packages/types.ts +0 -107
  245. package/tooling/check-dist-runtime.mjs +0 -166
  246. package/tooling/generate-index.mjs +0 -55
  247. package/tooling/test-guardrails.mjs +0 -157
  248. package/tooling/validate-boundary.mjs +0 -92
  249. package/tooling/validate-effects.mjs +0 -304
  250. package/tooling/validate.mjs +0 -53
@@ -1,410 +0,0 @@
1
- import { Color4 } from '@babylonjs/core/Maths/math.color';
2
- import { Matrix, Vector3 } from '@babylonjs/core/Maths/math.vector';
3
- import { DynamicTexture } from '@babylonjs/core/Materials/Textures/dynamicTexture';
4
- import type { TransformNode } from '@babylonjs/core/Meshes/transformNode';
5
- import type { Particle } from '@babylonjs/core/Particles/particle';
6
- import { ParticleSystem } from '@babylonjs/core/Particles/particleSystem';
7
- import type { Scene } from '@babylonjs/core/scene';
8
- import type { VfxColorValue, VfxEffectPackage, VfxParamValues } from '../../types';
9
- import { configureVfxParticleSystem } from '../../rendering';
10
- import manifest from './effect.json';
11
-
12
- interface GroundTileUpgradeParams extends VfxParamValues {
13
- lifetime: number;
14
- scale: number;
15
- initialHeight: number;
16
- color: VfxColorValue;
17
- opacity: number;
18
- scaleX: number;
19
- scaleY: number;
20
- scaleZ: number;
21
- centerCount: number;
22
- outlineCount: number;
23
- strandWidth: number;
24
- riseSpeed: number;
25
- centerSpread: number;
26
- outlineThickness: number;
27
- glowOpacity: number;
28
- }
29
-
30
- const BASE_FOOTPRINT_X = 3.2;
31
- const BASE_FOOTPRINT_Z = 2.6;
32
- const BASE_CENTER_HEIGHT = 2.2;
33
- const BASE_OUTLINE_HEIGHT = 3.1;
34
- const BASE_GLOW_THICKNESS = 0.38;
35
-
36
- const DEFAULT_PARAMS: GroundTileUpgradeParams = {
37
- lifetime: 1.8,
38
- scale: 1,
39
- initialHeight: 0.02,
40
- color: { r: 1, g: 0.84, b: 0.12 },
41
- opacity: 1,
42
- scaleX: 0.82,
43
- scaleY: 0.24,
44
- scaleZ: 0.82,
45
- centerCount: 46,
46
- outlineCount: 150,
47
- strandWidth: 0.035,
48
- riseSpeed: 1.15,
49
- centerSpread: 0.92,
50
- outlineThickness: 0.18,
51
- glowOpacity: 0.62,
52
- };
53
-
54
- export const groundTileUpgradeEffectPackage: VfxEffectPackage<GroundTileUpgradeParams> = {
55
- id: 'ground-tile-upgrade',
56
- nameZh: '地块升级光效',
57
- manifest,
58
- defaultParams: DEFAULT_PARAMS,
59
- debugAnchor: 'playerRight',
60
- debugParams: [
61
- { key: 'lifetime', label: '生命周期', kind: 'lifetime', min: 0.2, max: 6, step: 0.01 },
62
- { key: 'scale', label: '整体缩放', kind: 'scale', min: 0.1, max: 6, step: 0.01 },
63
- { key: 'initialHeight', label: '初始高度', kind: 'number', min: -1, max: 3, step: 0.01 },
64
- { key: 'color', label: '光效颜色', kind: 'color' },
65
- { key: 'opacity', label: '透明度', kind: 'opacity', min: 0, max: 1, step: 0.01 },
66
- { key: 'scaleX', label: 'X 轴缩放', kind: 'number', min: 0.1, max: 6, step: 0.01 },
67
- { key: 'scaleY', label: 'Y 轴缩放', kind: 'number', min: 0.1, max: 6, step: 0.01 },
68
- { key: 'scaleZ', label: 'Z 轴缩放', kind: 'number', min: 0.1, max: 6, step: 0.01 },
69
- { key: 'centerCount', label: '中心光丝数量', kind: 'number', min: 0, max: 240, step: 1 },
70
- { key: 'outlineCount', label: '轮廓光丝数量', kind: 'number', min: 0, max: 420, step: 1 },
71
- { key: 'strandWidth', label: '光丝粗细', kind: 'number', min: 0.005, max: 0.2, step: 0.001 },
72
- { key: 'riseSpeed', label: '上升速度', kind: 'number', min: 0, max: 5, step: 0.01 },
73
- { key: 'centerSpread', label: '中心散布', kind: 'number', min: 0, max: 1.5, step: 0.01 },
74
- { key: 'outlineThickness', label: '轮廓厚度', kind: 'number', min: 0, max: 1, step: 0.01 },
75
- { key: 'glowOpacity', label: '光幕强度', kind: 'opacity', min: 0, max: 1, step: 0.01 },
76
- ],
77
- create({ scene, root, position, params }) {
78
- root.position.copyFrom(position).addInPlace(new Vector3(0, params.initialHeight, 0));
79
-
80
- const centerStrands = createStrandSystem(scene, root, params, 'center');
81
- const outlineStrands = createStrandSystem(scene, root, params, 'outline');
82
- const glow = createOutlineGlow(scene, root, params);
83
- let disposed = false;
84
- const disposeTimer = window.setTimeout(
85
- () => disposeAll(),
86
- Math.max(0.05, params.lifetime + getMaxStrandHeight(params) / Math.max(0.1, params.riseSpeed) * 0.18 + 0.45) * 1000,
87
- );
88
-
89
- centerStrands.start();
90
- outlineStrands.start();
91
- glow.start();
92
-
93
- return {
94
- root,
95
- dispose() {
96
- disposeAll();
97
- },
98
- };
99
-
100
- function disposeAll(): void {
101
- if (disposed) return;
102
- disposed = true;
103
- window.clearTimeout(disposeTimer);
104
- centerStrands.dispose(false);
105
- outlineStrands.dispose(false);
106
- glow.dispose(false);
107
- root.dispose();
108
- }
109
- },
110
- };
111
-
112
- function createStrandSystem(
113
- scene: Scene,
114
- root: TransformNode,
115
- params: GroundTileUpgradeParams,
116
- mode: 'center' | 'outline',
117
- ): ParticleSystem {
118
- const count = Math.max(0, Math.round(mode === 'center' ? params.centerCount : params.outlineCount));
119
- const system = new ParticleSystem(`ground-tile-upgrade.${mode}-strands`, Math.max(1, count), scene);
120
- const color = params.color;
121
- const brightColor = getBrightColor(color);
122
- const height = mode === 'center' ? getCenterHeight(params) : getOutlineHeight(params);
123
- const width = params.strandWidth * getHorizontalScale(params) * (mode === 'center' ? 1.35 : 0.92);
124
-
125
- configureVfxParticleSystem(system);
126
- system.particleTexture = getStrandTexture(scene);
127
- system.emitter = root as any;
128
- system.manualEmitCount = count;
129
- system.emitRate = count * 60;
130
- system.disposeOnStop = false;
131
- system.updateSpeed = 1 / 60;
132
- system.minLifeTime = Math.max(0.12, params.lifetime * (mode === 'center' ? 0.48 : 0.62));
133
- system.maxLifeTime = Math.max(system.minLifeTime + 0.01, params.lifetime * (mode === 'center' ? 0.86 : 1.08));
134
- system.minSize = Math.max(0.01, height * 0.34);
135
- system.maxSize = Math.max(system.minSize, height * (mode === 'center' ? 0.72 : 0.98));
136
- system.minScaleX = Math.max(0.02, width);
137
- system.maxScaleX = Math.max(system.minScaleX, width * 1.8);
138
- system.minScaleY = 1;
139
- system.maxScaleY = mode === 'center' ? 1.45 : 1.75;
140
- system.minEmitPower = Math.max(0.01, params.riseSpeed * getVerticalScale(params) * (mode === 'center' ? 0.5 : 0.7));
141
- system.maxEmitPower = Math.max(system.minEmitPower, params.riseSpeed * getVerticalScale(params) * (mode === 'center' ? 1.15 : 1.65));
142
- system.gravity = new Vector3(0, 0.38 * getVerticalScale(params), 0);
143
- system.blendMode = ParticleSystem.BLENDMODE_ADD;
144
- system.color1 = toColor4(color, params.opacity * (mode === 'center' ? 0.72 : 0.86));
145
- system.color2 = toColor4(brightColor, params.opacity);
146
- system.colorDead = toColor4(color, 0);
147
- system.addColorGradient(0, toColor4(color, 0));
148
- system.addColorGradient(0.12, toColor4(brightColor, params.opacity));
149
- system.addColorGradient(0.72, toColor4(color, params.opacity * 0.62));
150
- system.addColorGradient(1, toColor4(color, 0));
151
- system.addVelocityGradient(0, 1);
152
- system.addVelocityGradient(0.65, 0.55);
153
- system.addVelocityGradient(1, 0.12);
154
-
155
- let positionIndex = 0;
156
- let directionIndex = 0;
157
- system.startPositionFunction = (worldMatrix: Matrix, positionToUpdate: Vector3, particle: Particle, isLocal: boolean) => {
158
- const index = particle.id + positionIndex;
159
- positionIndex += 1;
160
- const local = mode === 'center'
161
- ? sampleCenterPosition(index, params)
162
- : sampleOutlinePosition(index, params);
163
- if (isLocal) positionToUpdate.copyFrom(local);
164
- else Vector3.TransformCoordinatesToRef(local, worldMatrix, positionToUpdate);
165
- };
166
- system.startDirectionFunction = (worldMatrix: Matrix, directionToUpdate: Vector3, particle: Particle, isLocal: boolean) => {
167
- const index = particle.id + directionIndex;
168
- directionIndex += 1;
169
- const sway = (mode === 'center' ? 0.22 : 0.12) * getHorizontalScale(params);
170
- const local = new Vector3(
171
- (sequence01(index, 4) - 0.5) * sway,
172
- 0.8 + sequence01(index, 5) * 0.65,
173
- (sequence01(index, 6) - 0.5) * sway,
174
- );
175
- if (isLocal) directionToUpdate.copyFrom(local);
176
- else Vector3.TransformNormalToRef(local, worldMatrix, directionToUpdate);
177
- };
178
-
179
- return system;
180
- }
181
-
182
- function createOutlineGlow(scene: Scene, root: TransformNode, params: GroundTileUpgradeParams): ParticleSystem {
183
- const count = Math.max(1, Math.round(params.outlineCount * 0.82));
184
- const system = new ParticleSystem('ground-tile-upgrade.outline-glow-rays', count, scene);
185
- const height = getOutlineHeight(params) * 1.06;
186
- const glowWidth = Math.max(0.04, BASE_GLOW_THICKNESS * getHorizontalScale(params));
187
- const alpha = params.glowOpacity * params.opacity;
188
- const brightColor = getBrightColor(params.color);
189
-
190
- configureVfxParticleSystem(system);
191
- system.particleTexture = getOutlineGlowTexture(scene);
192
- system.emitter = root as any;
193
- system.manualEmitCount = count;
194
- system.emitRate = count * 60;
195
- system.disposeOnStop = false;
196
- system.updateSpeed = 1 / 60;
197
- system.minLifeTime = Math.max(0.12, params.lifetime * 0.62);
198
- system.maxLifeTime = Math.max(system.minLifeTime + 0.01, params.lifetime * 1.08);
199
- system.minSize = Math.max(0.01, height * 0.42);
200
- system.maxSize = Math.max(system.minSize, height * 1.08);
201
- system.minScaleX = glowWidth * 0.42;
202
- system.maxScaleX = glowWidth * 1.18;
203
- system.minScaleY = 1.05;
204
- system.maxScaleY = 1.75;
205
- system.minEmitPower = Math.max(0.01, params.riseSpeed * getVerticalScale(params) * 0.58);
206
- system.maxEmitPower = Math.max(system.minEmitPower, params.riseSpeed * getVerticalScale(params) * 1.38);
207
- system.gravity = new Vector3(0, 0.3 * getVerticalScale(params), 0);
208
- system.blendMode = ParticleSystem.BLENDMODE_ADD;
209
- system.color1 = toColor4(params.color, alpha * 0.62);
210
- system.color2 = toColor4(brightColor, alpha * 0.86);
211
- system.colorDead = toColor4(params.color, 0);
212
- system.addColorGradient(0, toColor4(params.color, 0));
213
- system.addColorGradient(0.1, toColor4(brightColor, alpha * 0.82));
214
- system.addColorGradient(0.56, toColor4(params.color, alpha * 0.52));
215
- system.addColorGradient(1, toColor4(params.color, 0));
216
- system.addVelocityGradient(0, 1);
217
- system.addVelocityGradient(0.65, 0.52);
218
- system.addVelocityGradient(1, 0.12);
219
-
220
- let positionIndex = 0;
221
- let directionIndex = 0;
222
- system.startPositionFunction = (worldMatrix: Matrix, positionToUpdate: Vector3, particle: Particle, isLocal: boolean) => {
223
- const index = particle.id + positionIndex + 31;
224
- positionIndex += 1;
225
- const local = sampleOutlinePosition(index, params);
226
- if (isLocal) positionToUpdate.copyFrom(local);
227
- else Vector3.TransformCoordinatesToRef(local, worldMatrix, positionToUpdate);
228
- };
229
- system.startDirectionFunction = (worldMatrix: Matrix, directionToUpdate: Vector3, particle: Particle, isLocal: boolean) => {
230
- const index = particle.id + directionIndex + 31;
231
- directionIndex += 1;
232
- const sway = 0.08 * getHorizontalScale(params);
233
- const local = new Vector3(
234
- (sequence01(index, 4) - 0.5) * sway,
235
- 0.82 + sequence01(index, 5) * 0.58,
236
- (sequence01(index, 6) - 0.5) * sway,
237
- );
238
- if (isLocal) directionToUpdate.copyFrom(local);
239
- else Vector3.TransformNormalToRef(local, worldMatrix, directionToUpdate);
240
- };
241
-
242
- return system;
243
- }
244
-
245
- function sampleCenterPosition(index: number, params: GroundTileUpgradeParams): Vector3 {
246
- const angle = sequence01(index, 0) * Math.PI * 2;
247
- const radius = Math.sqrt(0.16 + sequence01(index, 1) * 0.84);
248
- const xRadius = getFootprintX(params) * 0.5 * params.centerSpread;
249
- const zRadius = getFootprintZ(params) * 0.5 * params.centerSpread;
250
- const jitterX = (sequence01(index, 7) - 0.5) * xRadius * 0.18;
251
- const jitterZ = (sequence01(index, 8) - 0.5) * zRadius * 0.18;
252
- const x = Math.cos(angle) * radius * xRadius + jitterX;
253
- const z = Math.sin(angle) * radius * zRadius + jitterZ;
254
- const y = sequence01(index, 2) * 0.12 * getVerticalScale(params);
255
- return new Vector3(x, y, z);
256
- }
257
-
258
- function sampleOutlinePosition(index: number, params: GroundTileUpgradeParams): Vector3 {
259
- const width = getFootprintX(params);
260
- const depth = getFootprintZ(params);
261
- const perimeter = Math.max(0.001, width * 2 + depth * 2);
262
- const distance = sequence01(index, 0) * perimeter;
263
- const jitter = (sequence01(index, 1) - 0.5) * params.outlineThickness * getHorizontalScale(params);
264
- const y = sequence01(index, 2) * 0.16 * getVerticalScale(params);
265
-
266
- if (distance < width) return new Vector3(-width * 0.5 + distance, y, -depth * 0.5 + jitter);
267
- if (distance < width + depth) return new Vector3(width * 0.5 + jitter, y, -depth * 0.5 + distance - width);
268
- if (distance < width * 2 + depth) return new Vector3(width * 0.5 - (distance - width - depth), y, depth * 0.5 + jitter);
269
- return new Vector3(-width * 0.5 + jitter, y, depth * 0.5 - (distance - width * 2 - depth));
270
- }
271
-
272
- function getFootprintX(params: GroundTileUpgradeParams): number {
273
- return BASE_FOOTPRINT_X * Math.max(0.05, params.scale) * Math.max(0.05, params.scaleX);
274
- }
275
-
276
- function getFootprintZ(params: GroundTileUpgradeParams): number {
277
- return BASE_FOOTPRINT_Z * Math.max(0.05, params.scale) * Math.max(0.05, params.scaleZ);
278
- }
279
-
280
- function getVerticalScale(params: GroundTileUpgradeParams): number {
281
- return Math.max(0.05, params.scale) * Math.max(0.05, params.scaleY);
282
- }
283
-
284
- function getHorizontalScale(params: GroundTileUpgradeParams): number {
285
- return Math.max(0.05, params.scale) * Math.max(0.05, (params.scaleX + params.scaleZ) * 0.5);
286
- }
287
-
288
- function getCenterHeight(params: GroundTileUpgradeParams): number {
289
- return BASE_CENTER_HEIGHT * getVerticalScale(params);
290
- }
291
-
292
- function getOutlineHeight(params: GroundTileUpgradeParams): number {
293
- return BASE_OUTLINE_HEIGHT * getVerticalScale(params);
294
- }
295
-
296
- function getMaxStrandHeight(params: GroundTileUpgradeParams): number {
297
- return Math.max(getCenterHeight(params), getOutlineHeight(params));
298
- }
299
-
300
- function getStrandTexture(scene: Scene): DynamicTexture {
301
- const key = '__vfx_ground_tile_upgrade_strand_texture';
302
- const metadata = scene.metadata && typeof scene.metadata === 'object' ? scene.metadata as Record<string, unknown> : {};
303
- scene.metadata = metadata;
304
- const existing = metadata[key] as DynamicTexture | undefined;
305
- if (existing && !isTextureDisposed(existing)) return existing;
306
-
307
- const texture = new DynamicTexture('ground_tile_upgrade_strand_texture', { width: 48, height: 192 }, scene, true);
308
- const context = texture.getContext();
309
- context.clearRect(0, 0, 48, 192);
310
- const glow = context.createLinearGradient(0, 0, 0, 192);
311
- glow.addColorStop(0, 'rgba(255, 255, 255, 0)');
312
- glow.addColorStop(0.18, 'rgba(255, 255, 255, 0.92)');
313
- glow.addColorStop(0.62, 'rgba(255, 255, 255, 0.52)');
314
- glow.addColorStop(1, 'rgba(255, 255, 255, 0)');
315
- context.fillStyle = glow;
316
- context.fillRect(19, 0, 10, 192);
317
- context.fillStyle = 'rgba(255, 255, 255, 0.95)';
318
- context.fillRect(23, 8, 2, 168);
319
- const halo = context.createRadialGradient(24, 64, 0, 24, 64, 24);
320
- halo.addColorStop(0, 'rgba(255, 255, 255, 0.5)');
321
- halo.addColorStop(1, 'rgba(255, 255, 255, 0)');
322
- context.fillStyle = halo;
323
- context.fillRect(0, 16, 48, 96);
324
- texture.hasAlpha = true;
325
- texture.update(false);
326
- metadata[key] = texture;
327
- texture.onDisposeObservable.addOnce(() => {
328
- if (metadata[key] === texture) delete metadata[key];
329
- });
330
- return texture;
331
- }
332
-
333
- function getOutlineGlowTexture(scene: Scene): DynamicTexture {
334
- const key = '__vfx_ground_tile_upgrade_outline_glow_texture';
335
- const metadata = scene.metadata && typeof scene.metadata === 'object' ? scene.metadata as Record<string, unknown> : {};
336
- scene.metadata = metadata;
337
- const existing = metadata[key] as DynamicTexture | undefined;
338
- if (existing && !isTextureDisposed(existing)) return existing;
339
-
340
- const texture = new DynamicTexture('ground_tile_upgrade_outline_glow_texture', { width: 96, height: 192 }, scene, true);
341
- const context = texture.getContext();
342
- const compositeContext = context as unknown as CanvasRenderingContext2D;
343
- context.clearRect(0, 0, 96, 192);
344
- const sideFade = context.createLinearGradient(0, 0, 96, 0);
345
- sideFade.addColorStop(0, 'rgba(255, 255, 255, 0)');
346
- sideFade.addColorStop(0.28, 'rgba(255, 255, 255, 0.36)');
347
- sideFade.addColorStop(0.5, 'rgba(255, 255, 255, 0.78)');
348
- sideFade.addColorStop(0.72, 'rgba(255, 255, 255, 0.36)');
349
- sideFade.addColorStop(1, 'rgba(255, 255, 255, 0)');
350
- const verticalFade = context.createLinearGradient(0, 0, 0, 192);
351
- verticalFade.addColorStop(0, 'rgba(255, 255, 255, 0)');
352
- verticalFade.addColorStop(0.16, 'rgba(255, 255, 255, 0.65)');
353
- verticalFade.addColorStop(0.55, 'rgba(255, 255, 255, 0.46)');
354
- verticalFade.addColorStop(1, 'rgba(255, 255, 255, 0)');
355
- context.fillStyle = sideFade;
356
- context.fillRect(0, 0, 96, 192);
357
- compositeContext.globalCompositeOperation = 'source-in';
358
- context.fillStyle = verticalFade;
359
- context.fillRect(0, 0, 96, 192);
360
- compositeContext.globalCompositeOperation = 'source-over';
361
- const core = context.createLinearGradient(0, 0, 0, 192);
362
- core.addColorStop(0, 'rgba(255, 255, 255, 0)');
363
- core.addColorStop(0.22, 'rgba(255, 255, 255, 0.64)');
364
- core.addColorStop(0.66, 'rgba(255, 255, 255, 0.28)');
365
- core.addColorStop(1, 'rgba(255, 255, 255, 0)');
366
- context.fillStyle = core;
367
- context.fillRect(44, 8, 8, 166);
368
- texture.hasAlpha = true;
369
- texture.update(false);
370
- metadata[key] = texture;
371
- texture.onDisposeObservable.addOnce(() => {
372
- if (metadata[key] === texture) delete metadata[key];
373
- });
374
- return texture;
375
- }
376
-
377
- function getBrightColor(color: VfxColorValue): VfxColorValue {
378
- return {
379
- r: lerp(color.r, 1, 0.68),
380
- g: lerp(color.g, 1, 0.68),
381
- b: lerp(color.b, 1, 0.68),
382
- };
383
- }
384
-
385
- function toColor4(color: VfxColorValue, alpha: number): Color4 {
386
- return new Color4(clamp01(color.r), clamp01(color.g), clamp01(color.b), clamp01(alpha));
387
- }
388
-
389
- function isTextureDisposed(texture: DynamicTexture): boolean {
390
- const maybeTexture = texture as DynamicTexture & { isDisposed?: () => boolean; _isDisposed?: boolean };
391
- return maybeTexture.isDisposed?.() ?? maybeTexture._isDisposed === true;
392
- }
393
-
394
- function lerp(min: number, max: number, t: number): number {
395
- return min + (max - min) * t;
396
- }
397
-
398
- function clamp01(value: number): number {
399
- return Math.min(1, Math.max(0, value));
400
- }
401
-
402
- function fract(value: number): number {
403
- return value - Math.floor(value);
404
- }
405
-
406
- function sequence01(index: number, axis: number): number {
407
- if (index === 0) return 0.5;
408
- const strides = [0.618033988749895, 0.414213562373095, 0.732050807568877, 0.324717957244746, 0.754877666246693, 0.569840290998053];
409
- return fract(0.5 + index * strides[axis % strides.length] + axis * 0.173205080756888);
410
- }
@@ -1,69 +0,0 @@
1
- // 命中蓝白爆闪(移植自 babylon-laser createHitParticles/burstHit, 特效#3)。
2
- // 一次性 ParticleSystem 爆发:程序光斑贴图,蓝白渐变到透明,BLENDMODE_ADD 全向四散。
3
- import { ParticleSystem } from '@babylonjs/core/Particles/particleSystem';
4
- import { DynamicTexture } from '@babylonjs/core/Materials/Textures/dynamicTexture';
5
- import { Color4 } from '@babylonjs/core/Maths/math.color';
6
- import { Vector3 } from '@babylonjs/core/Maths/math.vector';
7
- import type { Scene } from '@babylonjs/core/scene';
8
- import type { VfxEffectPackage, VfxParamValues } from '../../types';
9
-
10
- interface HitFlashParams extends VfxParamValues {
11
- count: number;
12
- sizeMax: number;
13
- power: number;
14
- }
15
-
16
- const DEFAULT_PARAMS: HitFlashParams = { count: 24, sizeMax: 0.5, power: 7 };
17
-
18
- function makeFlareTexture(scene: Scene, inner = '255,255,255', outer = '90,160,255'): DynamicTexture {
19
- const dt = new DynamicTexture('vfx_hit_flare', 128, scene, false);
20
- const ctx = dt.getContext();
21
- const g = ctx.createRadialGradient(64, 64, 0, 64, 64, 64);
22
- g.addColorStop(0, `rgba(${inner},1)`);
23
- g.addColorStop(0.35, `rgba(${outer},0.55)`);
24
- g.addColorStop(1, `rgba(${outer},0)`);
25
- ctx.clearRect(0, 0, 128, 128);
26
- ctx.fillStyle = g; ctx.fillRect(0, 0, 128, 128);
27
- dt.update(); dt.hasAlpha = true;
28
- return dt;
29
- }
30
-
31
- export const hitFlashEffectPackage: VfxEffectPackage<HitFlashParams> = {
32
- id: 'hit-flash',
33
- nameZh: '命中蓝白爆闪',
34
- debugAnchor: 'playerRight',
35
- defaultParams: DEFAULT_PARAMS,
36
- debugParams: [
37
- { key: 'count', label: '粒子数', kind: 'number', min: 1, max: 200, step: 1 },
38
- { key: 'sizeMax', label: '最大尺寸', kind: 'scale', min: 0.1, max: 2, step: 0.01 },
39
- { key: 'power', label: '四散速度', kind: 'number', min: 0.5, max: 20, step: 0.5 },
40
- ],
41
-
42
- create({ scene, root, position, params }) {
43
- root.position.copyFrom(position);
44
- const flareTex = makeFlareTexture(scene);
45
- const ps = new ParticleSystem('vfx_hit_ps', 400, scene);
46
- ps.particleTexture = flareTex;
47
- ps.emitter = position.clone();
48
- ps.minEmitBox = new Vector3(-0.1, -0.1, -0.1); ps.maxEmitBox = new Vector3(0.1, 0.1, 0.1);
49
- ps.direction1 = new Vector3(-1, -1, -1); ps.direction2 = new Vector3(1, 1, 1);
50
- ps.color1 = new Color4(0.85, 0.95, 1, 1); ps.color2 = new Color4(0.35, 0.6, 1, 1); ps.colorDead = new Color4(0.1, 0.2, 0.6, 0);
51
- ps.minSize = 0.12; ps.maxSize = params.sizeMax;
52
- ps.minLifeTime = 0.15; ps.maxLifeTime = 0.45;
53
- ps.minEmitPower = params.power * 0.36; ps.maxEmitPower = params.power;
54
- ps.updateSpeed = 0.016;
55
- ps.blendMode = ParticleSystem.BLENDMODE_ADD;
56
- ps.emitRate = 0;
57
- ps.start();
58
- ps.manualEmitCount = Math.round(params.count); // 一次性爆发
59
-
60
- let disposed = false;
61
- const disposeTimer = window.setTimeout(() => disposeAll(), 800);
62
- function disposeAll(): void {
63
- if (disposed) return; disposed = true;
64
- window.clearTimeout(disposeTimer);
65
- ps.dispose(); flareTex.dispose(); root.dispose();
66
- }
67
- return { root, dispose() { disposeAll(); } };
68
- },
69
- };
@@ -1,6 +0,0 @@
1
- // 主激光束(特效#1)。共享实现见 ../laser-beam-factory;本包只定 id/中文名/默认参数(主束 width0.55/intensity1.0)。
2
- import { createLaserBeamEffectPackage } from '../laser-beam-factory';
3
-
4
- export const laserBeamEffectPackage = createLaserBeamEffectPackage('laser-beam', '激光束', {
5
- width: 0.55, intensity: 1.0, laserSpeed: 7, targetDistance: 12,
6
- });
@@ -1,135 +0,0 @@
1
- // 激光束共享工厂(移植自 babylon-laser LaserBeam,被 laser-beam(主#1)与 laser-splash-beam(副#2)复用)。
2
- // 非 effect(无 index.ts);两个特效 index.ts 经 `../laser-beam-factory` 引用,差异只在 defaultParams(width/intensity)。
3
- import { TransformNode } from '@babylonjs/core/Meshes/transformNode';
4
- import { Mesh } from '@babylonjs/core/Meshes/mesh';
5
- import { VertexData } from '@babylonjs/core/Meshes/mesh.vertexData';
6
- import { CreatePlane } from '@babylonjs/core/Meshes/Builders/planeBuilder';
7
- import { StandardMaterial } from '@babylonjs/core/Materials/standardMaterial';
8
- import { Texture } from '@babylonjs/core/Materials/Textures/texture';
9
- import { Color3 } from '@babylonjs/core/Maths/math.color';
10
- import { Constants } from '@babylonjs/core/Engines/constants';
11
- import type { Scene } from '@babylonjs/core/scene';
12
- import type { VfxEffectPackage, VfxParamValues } from '../types';
13
- import { makeFlareTexture, LIFETIME_DEBUG_PARAMS, LIFETIME_DEFAULTS, scheduleLifetime } from './space-shared';
14
- import arcTextureUrl from './laser-beam/assets/textures/laser_glow.webp?url';
15
- import noiseTextureUrl from './laser-beam/assets/textures/laser_noise.webp?url';
16
-
17
- export interface LaserBeamParams extends VfxParamValues {
18
- lifetimeMode: string;
19
- lifetime: number;
20
- width: number;
21
- intensity: number;
22
- laserSpeed: number;
23
- targetDistance: number;
24
- }
25
- type LaserCoreDefaults = Omit<LaserBeamParams, 'lifetimeMode' | 'lifetime'>;
26
-
27
- // 十字面片:局部 +Z 长度=1(beamRoot.scaling.z=dist 拉伸);U 沿长度 → uOffset 滚动即流动
28
- function createBeamPlaneGeo(name: string, width: number, axis: 'x' | 'y', scene: Scene): Mesh {
29
- const h = width / 2;
30
- const positions = axis === 'x'
31
- ? [-h, 0, 0, h, 0, 0, h, 0, 1, -h, 0, 1]
32
- : [0, -h, 0, 0, h, 0, 0, h, 1, 0, -h, 1];
33
- const normals = axis === 'x' ? [0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0] : [1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0];
34
- const uvs = [0, 0, 0, 1, 1, 1, 1, 0];
35
- const indices = [0, 1, 2, 0, 2, 3];
36
- const mesh = new Mesh(name, scene);
37
- const vd = new VertexData();
38
- vd.positions = positions; vd.normals = normals; vd.uvs = uvs; vd.indices = indices;
39
- vd.applyToMesh(mesh);
40
- return mesh;
41
- }
42
-
43
- export function createLaserBeamEffectPackage(id: string, nameZh: string, core: LaserCoreDefaults): VfxEffectPackage<LaserBeamParams> {
44
- const defaultParams = { ...LIFETIME_DEFAULTS, ...core } as LaserBeamParams;
45
- return {
46
- id, nameZh, defaultParams, debugAnchor: 'playerRight',
47
- debugParams: [
48
- ...LIFETIME_DEBUG_PARAMS,
49
- { key: 'width', label: '束宽', kind: 'scale', min: 0.05, max: 2, step: 0.01 },
50
- { key: 'intensity', label: '强度', kind: 'number', min: 0.1, max: 3, step: 0.05 },
51
- { key: 'laserSpeed', label: '纹理流速', kind: 'number', min: 0, max: 20, step: 0.5 },
52
- { key: 'targetDistance', label: '目标距离', kind: 'number', min: 2, max: 40, step: 0.5 },
53
- ],
54
- create({ scene, root, position, rotationY, params }) {
55
- root.position.copyFrom(position);
56
- root.rotation.y = rotationY;
57
- const { width, intensity } = params;
58
- const segLen = width * 5;
59
-
60
- const arcTex = new Texture(arcTextureUrl, scene); arcTex.wrapU = Texture.WRAP_ADDRESSMODE;
61
- const arcMat = new StandardMaterial('vfx_laser_arcMat', scene);
62
- arcMat.emissiveTexture = arcTex; arcMat.opacityTexture = arcTex;
63
- arcMat.emissiveColor = new Color3(0.45 * intensity, 0.62 * intensity, 1.35 * intensity);
64
- arcMat.disableLighting = true; arcMat.backFaceCulling = false; arcMat.alphaMode = Constants.ALPHA_ADD;
65
-
66
- const noiseTex = new Texture(noiseTextureUrl, scene); noiseTex.wrapU = Texture.WRAP_ADDRESSMODE;
67
- const noiseMat = new StandardMaterial('vfx_laser_noiseMat', scene);
68
- noiseMat.emissiveTexture = noiseTex; noiseMat.opacityTexture = noiseTex;
69
- noiseMat.opacityTexture.getAlphaFromRGB = true;
70
- noiseMat.emissiveColor = new Color3(0.2 * intensity, 0.35 * intensity, 0.9 * intensity);
71
- noiseMat.disableLighting = true; noiseMat.backFaceCulling = false; noiseMat.alphaMode = Constants.ALPHA_ADD;
72
-
73
- const beamRoot = new TransformNode('vfx_laser_beamRoot', scene);
74
- beamRoot.parent = root;
75
- const planes: Mesh[] = [];
76
- const layout: Array<['x' | 'y', StandardMaterial, number]> = [
77
- ['x', arcMat, width], ['y', arcMat, width], ['x', noiseMat, width * 1.9], ['y', noiseMat, width * 1.9],
78
- ];
79
- for (const [axis, mat, w] of layout) {
80
- const p = createBeamPlaneGeo(`vfx_laser_p${planes.length}`, w, axis, scene);
81
- p.material = mat; p.parent = beamRoot; p.isPickable = false;
82
- planes.push(p);
83
- }
84
-
85
- const flareTex = makeFlareTexture(scene, 'vfx_laser_flare');
86
- function makeFlare(name: string, size: number): Mesh {
87
- const f = CreatePlane(name, { size }, scene);
88
- f.billboardMode = Mesh.BILLBOARDMODE_ALL;
89
- const m = new StandardMaterial(name + 'Mat', scene);
90
- m.emissiveTexture = flareTex; m.opacityTexture = flareTex;
91
- m.emissiveColor = new Color3(0.7, 0.85, 1.6);
92
- m.disableLighting = true; m.alphaMode = Constants.ALPHA_ADD;
93
- f.material = m; f.isPickable = false; f.parent = root;
94
- return f;
95
- }
96
- const muzzleFlare = makeFlare('vfx_laser_muzzle', width * 3.2);
97
- const hitFlare = makeFlare('vfx_laser_hit', width * 3.2);
98
-
99
- let time = 0;
100
- const observer = scene.onBeforeRenderObservable.add(() => {
101
- const dt = Math.min(scene.getEngine().getDeltaTime() / 1000, 0.05);
102
- time += dt;
103
- const dist = params.targetDistance;
104
- beamRoot.scaling.z = dist;
105
- const tiles = Math.max(1, dist / segLen);
106
- (arcMat.emissiveTexture as Texture).uScale = tiles; (arcMat.opacityTexture as Texture).uScale = tiles;
107
- (arcMat.emissiveTexture as Texture).uOffset -= params.laserSpeed * dt;
108
- (arcMat.opacityTexture as Texture).uOffset = (arcMat.emissiveTexture as Texture).uOffset;
109
- (noiseMat.emissiveTexture as Texture).uScale = tiles * 0.6;
110
- (noiseMat.emissiveTexture as Texture).uOffset -= params.laserSpeed * 0.31 * dt;
111
- (noiseMat.opacityTexture as Texture).uScale = tiles * 0.6;
112
- (noiseMat.opacityTexture as Texture).uOffset = (noiseMat.emissiveTexture as Texture).uOffset;
113
- const pulse = 1 + Math.sin(time * 24) * 0.18;
114
- muzzleFlare.position.set(0, 0, 0); muzzleFlare.scaling.setAll(pulse);
115
- hitFlare.position.set(0, 0, dist); hitFlare.scaling.setAll(pulse * 1.4);
116
- });
117
-
118
- let disposed = false;
119
- let ltTimer = 0;
120
- const dispose = (): void => {
121
- if (disposed) return; disposed = true;
122
- if (ltTimer) window.clearTimeout(ltTimer);
123
- scene.onBeforeRenderObservable.remove(observer);
124
- for (const p of planes) p.dispose();
125
- muzzleFlare.material?.dispose(); muzzleFlare.dispose();
126
- hitFlare.material?.dispose(); hitFlare.dispose();
127
- beamRoot.dispose();
128
- arcMat.dispose(); arcTex.dispose(); noiseMat.dispose(); noiseTex.dispose(); flareTex.dispose();
129
- root.dispose();
130
- };
131
- ltTimer = scheduleLifetime(params, dispose); // 自定义时间模式:到时自动停;无限=循环
132
- return { root, dispose };
133
- },
134
- };
135
- }
@@ -1,6 +0,0 @@
1
- {
2
- "id": "lumber-cart-suction",
3
- "nameZh": "收集车吸入圆环",
4
- "assets": [],
5
- "source": "procedural"
6
- }