@fps-games/vfx 0.1.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +107 -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/docs/INTEGRATION.md +194 -0
  26. package/docs/hit-flash-red-method.md +155 -0
  27. package/docs/treasure_attention_fx_babylonjs_guide.md +901 -0
  28. package/docs/vfx-placement-design.md +164 -0
  29. package/index.json +19 -1
  30. package/package.json +5 -1
  31. package/packages/EffectPackageService.ts +123 -17
  32. package/packages/effects/coin-burst/index.ts +7 -2
  33. package/packages/effects/comet-trail-flame/index.ts +3 -2
  34. package/packages/effects/debris-smoke/index.ts +1 -0
  35. package/packages/effects/electric-arc/index.ts +1 -0
  36. package/packages/effects/energy-shield/index.ts +1 -0
  37. package/packages/effects/explosion/index.ts +3 -2
  38. package/packages/effects/hit-flash/index.ts +11 -3
  39. package/packages/effects/laser-beam-factory.ts +14 -3
  40. package/packages/effects/lumber_vehicle_upgrade_aura/index.ts +2 -0
  41. package/packages/effects/monster-hit/index.ts +2 -1
  42. package/packages/effects/player-upgrade/index.ts +8 -3
  43. package/packages/effects/pulse-laser-volley/index.ts +15 -4
  44. package/packages/effects/thruster-flame/index.ts +3 -2
  45. package/packages/effects/treasure-attention/effect.json +7 -0
  46. package/packages/effects/treasure-attention/index.ts +630 -0
  47. package/packages/effects/treasure-attention/vfx-params.json +49 -0
  48. package/packages/effects/ufo-thread-flame/index.ts +1 -0
  49. package/packages/effects/vehicle-upgrade/index.ts +4 -1
  50. package/packages/effects/weapon-trail/index.ts +7 -3
  51. package/packages/types.ts +88 -0
@@ -80,8 +80,11 @@ const DEFAULT_PARAMS: PlayerUpgradeParams = {
80
80
  export const playerUpgradeEffectPackage: VfxEffectPackage<PlayerUpgradeParams> = {
81
81
  id: 'player-upgrade',
82
82
  nameZh: '人物&NPC升级',
83
+ placement: 'socket',
83
84
  manifest,
84
85
  defaultParams: DEFAULT_PARAMS,
86
+ // initialHeight 走 service 存活的 Y 偏移通道(不写 root.position,避免被 applySpawnToRoot 覆盖)(G6/M13)。
87
+ spawnParams: { offsetY: 'initialHeight' },
85
88
  debugAnchor: 'player',
86
89
  debugParams: [
87
90
  { key: 'lifetime', label: '生命周期', kind: 'lifetime', min: 0.2, max: 6, step: 0.01 },
@@ -105,9 +108,8 @@ export const playerUpgradeEffectPackage: VfxEffectPackage<PlayerUpgradeParams> =
105
108
  { key: 'glowWidth', label: '光柱宽度', kind: 'number', min: 0.1, max: 4, step: 0.01 },
106
109
  ],
107
110
  create({ scene, root, position, params }) {
108
- const effectScale = Math.max(0.05, params.scale);
109
111
  markVfxRoot(root);
110
- root.position.copyFrom(position).addInPlace(new Vector3(0, params.initialHeight * effectScale, 0));
112
+ root.position.copyFrom(position); // 高度偏移由 service spawnParams.offsetY 施加(存活)
111
113
  const strands = createStrandSystem(scene, root, params);
112
114
  const strandMeshes = createStrandMeshes(scene, root, params);
113
115
  const rings = createExpandingRings(scene, root, params);
@@ -129,7 +131,10 @@ export const playerUpgradeEffectPackage: VfxEffectPackage<PlayerUpgradeParams> =
129
131
  disposed = true;
130
132
  window.clearTimeout(disposeTimer);
131
133
  strands.stop();
132
- strands.dispose();
134
+ // dispose(false):金丝粒子贴图是按 scene 缓存的共享 DynamicTexture(strandTextureByScene),
135
+ // ParticleSystem.dispose() 默认 disposeTexture=true 会销毁它,WeakMap 却仍持失效引用 →
136
+ // 二次升级金丝空白。纹理生命周期绑 scene、跨播放复用,故不随实例销毁。
137
+ strands.dispose(false);
133
138
  strandMeshes.dispose();
134
139
  rings.dispose();
135
140
  glowAura.dispose();
@@ -9,6 +9,8 @@ import { StandardMaterial } from '@babylonjs/core/Materials/standardMaterial';
9
9
  import { Effect } from '@babylonjs/core/Materials/effect';
10
10
  import { Texture } from '@babylonjs/core/Materials/Textures/texture';
11
11
  import { Color3 } from '@babylonjs/core/Maths/math.color';
12
+ import { Vector3 } from '@babylonjs/core/Maths/math.vector';
13
+ import { Space } from '@babylonjs/core/Maths/math.axis';
12
14
  import { Constants } from '@babylonjs/core/Engines/constants';
13
15
  import type { Mesh } from '@babylonjs/core/Meshes/mesh';
14
16
  import type { Scene } from '@babylonjs/core/scene';
@@ -88,6 +90,8 @@ interface Bolt { mesh: Mesh; left: number; }
88
90
  export const pulseLaserVolleyEffectPackage: VfxEffectPackage<PulseLaserParams> = {
89
91
  id: 'pulse-laser-volley',
90
92
  nameZh: '脉冲激光',
93
+ placement: 'socket',
94
+ optionalInputs: ['aim'],
91
95
  defaultParams: DEFAULT_PARAMS,
92
96
  debugAnchor: 'playerRight',
93
97
  debugParams: [
@@ -104,10 +108,17 @@ export const pulseLaserVolleyEffectPackage: VfxEffectPackage<PulseLaserParams> =
104
108
  { key: 'boltBright', label: '光弹亮度', kind: 'number', min: 0.2, max: 3, step: 0.05 },
105
109
  ],
106
110
 
107
- create({ scene, root, position, rotationY, params }) {
111
+ create({ scene, root, position, rotationY, params, inputs }) {
108
112
  root.position.copyFrom(position);
109
113
  root.rotation.y = rotationY;
110
114
  registerShaders();
115
+ // 有 inputs.aim:每帧朝目标(Space.WORLD,root 挂在炮口)+ 齐射射程=到目标距离;无 aim 回退挂点朝向 + params.targetDistance。
116
+ const effectiveDist = (): number => {
117
+ if (!inputs?.aim) return params.targetDistance;
118
+ const tgt = inputs.aim();
119
+ root.lookAt(tgt, 0, 0, 0, Space.WORLD);
120
+ return Vector3.Distance(root.getAbsolutePosition(), tgt);
121
+ };
111
122
 
112
123
  const boltTex = new Texture(boltTextureUrl, scene);
113
124
  boltTex.hasAlpha = true;
@@ -151,9 +162,8 @@ export const pulseLaserVolleyEffectPackage: VfxEffectPackage<PulseLaserParams> =
151
162
  muzzle.position.set(0, 0, 0);
152
163
  let muzzleFlash = 0;
153
164
 
154
- function fireVolley(): void {
165
+ function fireVolley(dist: number): void {
155
166
  const n = Math.max(1, Math.round(params.boltsPerVolley));
156
- const dist = params.targetDistance;
157
167
  let fired = 0;
158
168
  for (const b of pool) {
159
169
  if (fired >= n) break;
@@ -171,8 +181,9 @@ export const pulseLaserVolleyEffectPackage: VfxEffectPackage<PulseLaserParams> =
171
181
  let volleyTimer = 0;
172
182
  const observer = scene.onBeforeRenderObservable.add(() => {
173
183
  const dt = Math.min(scene.getEngine().getDeltaTime() / 1000, 0.05);
184
+ const dist = effectiveDist(); // 每帧:有 aim 则朝目标 + 取到目标距离
174
185
  volleyTimer += dt;
175
- if (volleyTimer >= params.volleyInterval) { volleyTimer = 0; fireVolley(); }
186
+ if (volleyTimer >= params.volleyInterval) { volleyTimer = 0; fireVolley(dist); }
176
187
 
177
188
  muzzleFlash = Math.max(0, muzzleFlash - dt * 6);
178
189
  const s = 1 + muzzleFlash * 0.6;
@@ -221,6 +221,7 @@ function excludeFromGlow(scene: Scene, mesh: AbstractMesh): void {
221
221
  export const thrusterFlameEffectPackage: VfxEffectPackage<ThrusterFlameParams> = {
222
222
  id: 'thruster-flame',
223
223
  nameZh: '战机尾焰',
224
+ placement: 'socket',
224
225
  defaultParams: DEFAULT_PARAMS,
225
226
  debugAnchor: 'playerRight',
226
227
  debugParams: [
@@ -236,7 +237,7 @@ export const thrusterFlameEffectPackage: VfxEffectPackage<ThrusterFlameParams> =
236
237
  { key: 'coreColor', label: '内核色', kind: 'color' },
237
238
  ],
238
239
 
239
- create({ scene, root, position, params }) {
240
+ create({ scene, root, position, params, renderingGroupId }) {
240
241
  root.position.copyFrom(position);
241
242
  registerShaders();
242
243
  const preset = PRESETS[(params.mode as EngineMode)] ?? PRESETS.ion;
@@ -245,7 +246,7 @@ export const thrusterFlameEffectPackage: VfxEffectPackage<ThrusterFlameParams> =
245
246
  const outer = buildFlameMesh('vfx_thruster_outer', scene, FLAME_LEN, FLAME_R, 30, 24);
246
247
  const core = buildFlameMesh('vfx_thruster_core', scene, FLAME_LEN * 0.68, FLAME_R * 0.5, 24, 18);
247
248
  const swirl = buildFlameMesh('vfx_thruster_swirl', scene, FLAME_LEN * 0.42, FLAME_R * 1.3, 14, 24);
248
- for (const m of [outer, core, swirl]) { m.parent = root; excludeFromGlow(scene, m); }
249
+ for (const m of [outer, core, swirl]) { m.parent = root; m.renderingGroupId = renderingGroupId ?? 0; excludeFromGlow(scene, m); }
249
250
 
250
251
  const outerMat = makeFXMaterial('vfx_thruster_outerMat', scene, 'vfxThrusterFlame', noiseTex);
251
252
  const coreMat = makeFXMaterial('vfx_thruster_coreMat', scene, 'vfxThrusterFlame', noiseTex);
@@ -0,0 +1,7 @@
1
+ {
2
+ "id": "treasure-attention",
3
+ "nameZh": "宝藏注意力光效",
4
+ "search": {
5
+ "tags": ["treasure", "attention", "pickup", "gold", "sparkle", "aura", "ring"]
6
+ }
7
+ }