@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
@@ -54,8 +54,11 @@ const DEFAULT_PARAMS: VehicleUpgradeParams = {
54
54
  export const vehicleUpgradeEffectPackage: VfxEffectPackage<VehicleUpgradeParams> = {
55
55
  id: 'vehicle-upgrade',
56
56
  nameZh: '建筑&地块&设备升级',
57
+ placement: 'socket',
57
58
  manifest,
58
59
  defaultParams: DEFAULT_PARAMS,
60
+ // initialHeight 走 service 存活的 Y 偏移通道(G6/M12)。
61
+ spawnParams: { offsetY: 'initialHeight' },
59
62
  debugAnchor: 'playerRight',
60
63
  debugParams: [
61
64
  { key: 'lifetime', label: '生命周期', kind: 'lifetime', min: 0.2, max: 6, step: 0.01 },
@@ -75,7 +78,7 @@ export const vehicleUpgradeEffectPackage: VfxEffectPackage<VehicleUpgradeParams>
75
78
  { key: 'glowOpacity', label: '光幕强度', kind: 'opacity', min: 0, max: 1, step: 0.01 },
76
79
  ],
77
80
  create({ scene, root, position, params }) {
78
- root.position.copyFrom(position).addInPlace(new Vector3(0, params.initialHeight, 0));
81
+ root.position.copyFrom(position); // 高度偏移由 service 经 spawnParams.offsetY 施加(存活)
79
82
 
80
83
  const centerStrands = createStrandSystem(scene, root, params, 'center');
81
84
  const outlineStrands = createStrandSystem(scene, root, params, 'outline');
@@ -31,7 +31,7 @@ interface WeaponTrailParams extends VfxParamValues {
31
31
  const DEFAULT_PARAMS: WeaponTrailParams = {
32
32
  ...LIFETIME_DEFAULTS,
33
33
  orientation: 'horizontal',
34
- orbitRadius: 1.6, orbitSpeed: 7, height: 0,
34
+ orbitRadius: 0, orbitSpeed: 7, height: 0, // 默认 0:真实跟随挂点(orbit>0 是演示用的幻影圆周轨道)
35
35
  trailLength: 16, worldLength: 4.0, width: 1.01, coreWidth: 0.4,
36
36
  tailFadeStrength: 0.58, tailFadeExponent: 1.35,
37
37
  opacity: 1.35, saturation: 1.45, contrast: 1.32,
@@ -95,6 +95,8 @@ function lerpSample(a: Sample, b: Sample, t: number, dst: Sample): void {
95
95
  export const weaponTrailEffectPackage: VfxEffectPackage<WeaponTrailParams> = {
96
96
  id: 'weapon-trail',
97
97
  nameZh: '武器拖尾',
98
+ placement: 'socket',
99
+ geometrySpace: 'world',
98
100
  debugAnchor: 'player',
99
101
  defaultParams: DEFAULT_PARAMS,
100
102
  debugParams: [
@@ -124,8 +126,9 @@ export const weaponTrailEffectPackage: VfxEffectPackage<WeaponTrailParams> = {
124
126
  { key: 'tint', label: '颜色', kind: 'color' },
125
127
  ],
126
128
 
127
- create({ scene, root, position, params }) {
129
+ create({ scene, root, position, params, renderingGroupId }) {
128
130
  root.position.copyFrom(position);
131
+ const rgid = renderingGroupId ?? 0;
129
132
  registerShaders();
130
133
  const blend = params.blendMode === 'combine' ? Constants.ALPHA_COMBINE : Constants.ALPHA_ADD;
131
134
 
@@ -159,7 +162,7 @@ export const weaponTrailEffectPackage: VfxEffectPackage<WeaponTrailParams> = {
159
162
  function makeMesh(name: string, mat: ShaderMaterial, ai: number): Mesh {
160
163
  const m = new Mesh(name, scene);
161
164
  m.material = mat; m.isPickable = false; m.alwaysSelectAsActiveMesh = true;
162
- m.useVertexColors = true; m.hasVertexAlpha = true; m.renderingGroupId = 0; m.alphaIndex = ai;
165
+ m.useVertexColors = true; m.hasVertexAlpha = true; m.renderingGroupId = rgid; m.alphaIndex = ai;
163
166
  return m;
164
167
  }
165
168
  const outer = makeMesh('vfx_weaponTrail_outer', outerMat, 10);
@@ -181,6 +184,7 @@ export const weaponTrailEffectPackage: VfxEffectPackage<WeaponTrailParams> = {
181
184
  const c255 = `${Math.round(params.tint.r * 255)},${Math.round(params.tint.g * 255)},${Math.round(params.tint.b * 255)}`;
182
185
  const flare = makeFlareTexture(scene, 'vfx_weaponTrail_sparkTex', '255,255,255', c255);
183
186
  sparkPs = new ParticleSystem('vfx_weaponTrail_sparks', 160, scene);
187
+ sparkPs.renderingGroupId = rgid;
184
188
  sparkPs.particleTexture = flare;
185
189
  sparkPs.emitter = sparkEmitter;
186
190
  sparkPs.minSize = 0.07; sparkPs.maxSize = 0.26;
package/packages/types.ts CHANGED
@@ -1,9 +1,35 @@
1
1
  import type { Scene } from '@babylonjs/core/scene';
2
2
  import type { Vector3 } from '@babylonjs/core/Maths/math.vector';
3
3
  import type { TransformNode } from '@babylonjs/core/Meshes/transformNode';
4
+ import type { AbstractMesh } from '@babylonjs/core/Meshes/abstractMesh';
4
5
 
5
6
  export type VfxDebugAnchor = 'playerRight' | 'player';
6
7
 
8
+ // ── 运行时外部信息(inputs)──────────────────────────────────────────────
9
+ // 与 params(设计期可调、保存)区分:inputs 是运行时由游戏逻辑提供的外部上下文,常动态。
10
+ // 值可为静态值或 provider(() => 值);动态目标(移动)用 provider 每帧取。见 docs/vfx-placement-design.md。
11
+ export type VfxInput<T> = T | (() => T);
12
+ export type VfxInputKey = 'aim' | 'normal' | 'endpoints' | 'target';
13
+
14
+ /** 调用方提供的 inputs(放在 VfxSpawnTransform.inputs)。 */
15
+ export interface VfxEffectInputs {
16
+ aim?: VfxInput<Vector3>; // 瞄准点(激光/定向武器)
17
+ normal?: VfxInput<Vector3>; // 表面法线(贴花/冲击)
18
+ endpoints?: Array<VfxInput<Vector3>>; // link/链式(≥2 端点)
19
+ target?: AbstractMesh; // target-material 类(改目标自身材质)
20
+ /** 运行时标量(throttle/intensity 等),值可静态或 provider;特效每帧读取做活改(G5)。 */
21
+ scalars?: Record<string, VfxInput<number>>;
22
+ }
23
+
24
+ /** create() 收到的、已归一化为访问器的 inputs(provider 与静态值都变成可调用的函数)。 */
25
+ export interface VfxResolvedInputs {
26
+ aim?: () => Vector3;
27
+ normal?: () => Vector3;
28
+ endpoints?: Array<() => Vector3>;
29
+ target?: AbstractMesh;
30
+ scalars?: Record<string, () => number>;
31
+ }
32
+
7
33
  export type VfxParamValue = number | string | VfxColorValue;
8
34
  export type VfxParamValues = Record<string, VfxParamValue>;
9
35
 
@@ -58,12 +84,22 @@ export interface VfxEffectPackageContext<PParams extends VfxParamValues = VfxPar
58
84
  rotationY: number;
59
85
  renderingGroupId?: number;
60
86
  params: PParams;
87
+ /**
88
+ * 解析后的三轴缩放(来自 spawnTransform.scale,默认 (1,1,1))。
89
+ * root 的缩放由 service 写好;但**几何不挂 root 的 world/detached 特效**(粒子/抛物池/世界坐标 emitter)
90
+ * root.scaling 作用不到,须自行把 ctx.scale 乘进几何尺寸/初速(G3)。
91
+ */
92
+ scale: Vector3;
93
+ /** 运行时外部信息(已归一化为访问器)。link/target/定向武器/活改标量等按 required/optionalInputs 读取。 */
94
+ inputs?: VfxResolvedInputs;
61
95
  }
62
96
 
63
97
  export interface VfxEffectHandle {
64
98
  root: TransformNode;
65
99
  ready?: Promise<void>;
66
100
  dispose(): void;
101
+ /** 可选:运行时活改 params(无须 dispose+replay,避免重置缓动/可见闪)。声明即纳入契约(G5)。 */
102
+ update?(params: Partial<VfxParamValues>): void;
67
103
  }
68
104
 
69
105
  export interface VfxEffectManifest {
@@ -79,10 +115,35 @@ export interface VfxSpawnParamKeys {
79
115
  offsetZ?: string;
80
116
  }
81
117
 
118
+ /** 欧拉角(弧度)/ 三轴缩放的纯数据三元组。 */
119
+ export interface VfxVector3Like {
120
+ x: number;
121
+ y: number;
122
+ z: number;
123
+ }
124
+
82
125
  export interface VfxSpawnTransform {
83
126
  position?: Vector3;
127
+ /**
128
+ * 兼容别名:绕 Y 轴旋转(弧度)。
129
+ * 若同时给了 `rotation`,以 `rotation` 为准;否则回退到 `rotationY`。
130
+ */
84
131
  rotationY?: number;
132
+ /** 完整欧拉角旋转(弧度);给了就覆盖 `rotationY`。 */
133
+ rotation?: VfxVector3Like;
134
+ /** 等比缩放(number)或三轴缩放;默认 1。 */
135
+ scale?: number | VfxVector3Like;
136
+ /** 挂载点节点;给了就把特效 root parent 到它(特效随之跟随)。 */
137
+ parent?: TransformNode;
138
+ /**
139
+ * position/rotation/scale 的坐标系解释:
140
+ * - 给了 `parent` 时默认 `true`:按相对 parent 的 **local** transform 解释;
141
+ * - 没给 `parent` 时默认 `false`:按 **世界坐标** 解释(保持现状行为)。
142
+ */
143
+ offsetIsLocal?: boolean;
85
144
  renderingGroupId?: number;
145
+ /** 运行时外部信息(瞄准点/法线/端点/目标 mesh);值可为静态或 provider(动态每帧取)。 */
146
+ inputs?: VfxEffectInputs;
86
147
  }
87
148
 
88
149
  export interface VfxParamsFile {
@@ -92,6 +153,16 @@ export interface VfxParamsFile {
92
153
  params?: Partial<VfxParamValues>;
93
154
  }
94
155
 
156
+ /**
157
+ * 特效的放置本质(内禀标记)。决定系统/binding/面板怎么放它,不靠猜。见 docs/vfx-placement-design.md。
158
+ * - 'socket' local:挂对象命名挂点、随它走(parent + follow)。
159
+ * - 'world' global:放世界某点、不跟随(fire-and-forget,可按法线定向)。
160
+ * - 'screen' global:屏幕/相机层(后处理/相机扰动/DOM 全屏),无 3D transform。
161
+ * - 'target' 改目标自身材质/渲染态,没有可 spawn 的 root。
162
+ * - 'link' 连 ≥2 个端点(每帧重建几何),单 parent 表达不了。
163
+ */
164
+ export type VfxPlacement = 'socket' | 'world' | 'screen' | 'target' | 'link';
165
+
95
166
  export interface VfxEffectPackage<PParams extends VfxParamValues = VfxParamValues> {
96
167
  id: string;
97
168
  nameZh: string;
@@ -101,6 +172,23 @@ export interface VfxEffectPackage<PParams extends VfxParamValues = VfxParamValue
101
172
  spawnParams?: VfxSpawnParamKeys;
102
173
  savedParams?: Partial<VfxParamValues>;
103
174
  debugParams: VfxParamDefinition[];
175
+ /** 放置本质标记(默认 'world')。 */
176
+ placement?: VfxPlacement;
177
+ /** 声明**必需**的运行时 inputs(link 必须给 endpoints/aim、target 类必须给 target mesh);service 缺失时 warn。 */
178
+ requiredInputs?: VfxInputKey[];
179
+ /** 声明**可选**的运行时 inputs(给了就用、不给走默认,如定向武器的 aim:给了朝目标、不给走挂点朝向);不触发缺失 warn(G2)。 */
180
+ optionalInputs?: VfxInputKey[];
181
+ /**
182
+ * 几何空间:'local'=几何挂 root 子节点随它刚性变换;'world'=几何用世界坐标、root 仅作每帧采样源(拖尾)。
183
+ * 默认随 placement 推断('socket'→local,其余→world)。
184
+ */
185
+ geometrySpace?: 'local' | 'world';
186
+ /**
187
+ * 构建特效。**约定(G6):root 的 transform(position/rotation/scaling/parent)归 service 独占** ——
188
+ * service 在 create() 后会二次 `applySpawnToRoot` 覆盖,create 内写 `root.position/rotation/scaling` 会被静默清掉。
189
+ * 需要内部局部偏移(如抬升)请用 root 下的**子 TransformNode** 承载,或声明 `spawnParams.offsetY` 走 service 存活通道。
190
+ * 几何挂 root 子树即随挂载跟随;world/拖尾类几何走世界坐标、读 ctx.scale 缩放。
191
+ */
104
192
  create(context: VfxEffectPackageContext<PParams>): VfxEffectHandle;
105
193
  }
106
194