pixi-particles-engine 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/behaviours/alpha-curve-behaviour.js +1 -1
- package/dist/esm/behaviours/curved-behaviour/curve-sampler.js +1 -1
- package/dist/esm/behaviours/movement-behaviours/gravity-behaviour.js +1 -1
- package/dist/esm/behaviours/movement-behaviours/movement-curve-behaviour.js +1 -1
- package/dist/esm/behaviours/movement-behaviours/radial-burst-behaviour.js +1 -1
- package/dist/esm/behaviours/scale-curve-behaviour.js +1 -1
- package/dist/esm/emitter.js +1 -1
- package/dist/esm/index.js +18 -18
- package/package.json +3 -2
- package/src/behaviour.ts +74 -0
- package/src/behaviours/alpha-behaviour.ts +29 -0
- package/src/behaviours/alpha-curve-behaviour.ts +34 -0
- package/src/behaviours/curved-behaviour/curve-key-frame.ts +23 -0
- package/src/behaviours/curved-behaviour/curve-sampler.ts +92 -0
- package/src/behaviours/movement-behaviours/gravity-behaviour.ts +48 -0
- package/src/behaviours/movement-behaviours/movement-curve-behaviour.ts +39 -0
- package/src/behaviours/movement-behaviours/radial-burst-behaviour.ts +57 -0
- package/src/behaviours/scale-curve-behaviour.ts +36 -0
- package/src/behaviours/spawn-behaviours/circle-spawn-behaviour.ts +24 -0
- package/src/behaviours/spawn-behaviours/rectangle-spawn-behaviour.ts +27 -0
- package/src/behaviours/static-behaviours/static-rotation-behaviour.ts +28 -0
- package/src/behaviours/static-behaviours/static-scale-behaviour.ts +21 -0
- package/src/emitter.ts +517 -0
- package/src/index.ts +18 -0
- package/src/px-particle.ts +108 -0
- package/src/texture-provider.ts +66 -0
- package/src/texture-providers/animated-texture-provider.ts +146 -0
- package/src/texture-providers/single-texture-provider.ts +22 -0
- package/src/texture-providers/weighted-texture-provider.ts +52 -0
- package/src/utils.ts +13 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { Texture } from "pixi.js";
|
|
2
|
+
import { TextureProvider } from "../texture-provider";
|
|
3
|
+
import { PxParticle } from "../px-particle";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Configuration for AnimatedTextureProvider.
|
|
7
|
+
*
|
|
8
|
+
* Frames are generated using:
|
|
9
|
+
* `${texturePrefix}${frameNumber}`
|
|
10
|
+
*
|
|
11
|
+
* Example:
|
|
12
|
+
* texturePrefix: "Explosion_"
|
|
13
|
+
* numberOfFrames: 16
|
|
14
|
+
* padLength: 3
|
|
15
|
+
*
|
|
16
|
+
* Generates:
|
|
17
|
+
* Explosion_000
|
|
18
|
+
* Explosion_001
|
|
19
|
+
* ...
|
|
20
|
+
* Explosion_015
|
|
21
|
+
*/
|
|
22
|
+
export interface AnimatedTextureProviderOptions {
|
|
23
|
+
/**
|
|
24
|
+
* Prefix used to construct frame aliases.
|
|
25
|
+
*/
|
|
26
|
+
texturePrefix: string;
|
|
27
|
+
|
|
28
|
+
/** Total number of frames in the animation sequence. */
|
|
29
|
+
numberOfFrames: number;
|
|
30
|
+
|
|
31
|
+
/** Optional starting frame index (default: 0). */
|
|
32
|
+
firstFrame?: number;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Optional zero-padding length.
|
|
36
|
+
* If omitted, defaults to numberOfFrames digit length.
|
|
37
|
+
*
|
|
38
|
+
* Example:
|
|
39
|
+
* numberOfFrames = 16 → default padLength = 2
|
|
40
|
+
* frame 3 → "03"
|
|
41
|
+
*/
|
|
42
|
+
padLength?: number;
|
|
43
|
+
|
|
44
|
+
/** Frames per second (default: 60). */
|
|
45
|
+
fps?: number;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* If true, animation loops.
|
|
49
|
+
* If false, animation stops at the last frame.
|
|
50
|
+
* Default: true.
|
|
51
|
+
*/
|
|
52
|
+
loop?: boolean;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Flipbook-style animated texture provider.
|
|
57
|
+
*
|
|
58
|
+
* Each particle cycles through a pre-generated array of textures
|
|
59
|
+
* based on elapsed time and configured FPS.
|
|
60
|
+
*
|
|
61
|
+
* This is NOT a Pixi AnimatedSprite.
|
|
62
|
+
* Instead, it swaps particle.texture manually each frame.
|
|
63
|
+
*
|
|
64
|
+
* Because UVs change when textures change, this provider declares:
|
|
65
|
+
* requires = { uvs: true }
|
|
66
|
+
*
|
|
67
|
+
* so the Emitter enables the correct ParticleContainer dynamicProperties.
|
|
68
|
+
*/
|
|
69
|
+
export class AnimatedTextureProvider implements TextureProvider {
|
|
70
|
+
/** UV updates are required because textures change during lifetime. */
|
|
71
|
+
public readonly requires = { uvs: true };
|
|
72
|
+
|
|
73
|
+
/** Preloaded frame textures. */
|
|
74
|
+
private readonly frames: Texture[];
|
|
75
|
+
|
|
76
|
+
/** Frames per second for animation playback. */
|
|
77
|
+
private readonly fps: number;
|
|
78
|
+
|
|
79
|
+
/** Whether animation loops. */
|
|
80
|
+
private readonly loop: boolean;
|
|
81
|
+
|
|
82
|
+
constructor(options: AnimatedTextureProviderOptions) {
|
|
83
|
+
const start = options.firstFrame ?? 0;
|
|
84
|
+
|
|
85
|
+
const padLength = options.padLength ?? options.numberOfFrames.toString().length;
|
|
86
|
+
|
|
87
|
+
this.frames = [];
|
|
88
|
+
|
|
89
|
+
for (let i = start; i < options.numberOfFrames + start; i++) {
|
|
90
|
+
const alias = `${options.texturePrefix}${i.toString().padStart(padLength, "0")}`;
|
|
91
|
+
this.frames.push(Texture.from(alias));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (this.frames.length === 0) {
|
|
95
|
+
throw new Error("AnimatedTextureProvider: no frames generated");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.fps = options.fps ?? 60;
|
|
99
|
+
this.loop = options.loop ?? true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Used when constructing pooled particles.
|
|
104
|
+
* Returns the first frame as a placeholder texture.
|
|
105
|
+
*/
|
|
106
|
+
public initialTexture(): Texture {
|
|
107
|
+
return this.frames[0];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Called each time a particle is spawned.
|
|
112
|
+
*
|
|
113
|
+
* Initializes per-particle animation state
|
|
114
|
+
* and resets animation to first frame.
|
|
115
|
+
*/
|
|
116
|
+
public textureForSpawn(p: PxParticle): Texture {
|
|
117
|
+
p.animatedParticleState = { t: 0 };
|
|
118
|
+
return this.frames[0];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Per-frame update hook.
|
|
123
|
+
*
|
|
124
|
+
* Advances animation time and selects the appropriate frame.
|
|
125
|
+
*/
|
|
126
|
+
public update(p: PxParticle, dt: number): void {
|
|
127
|
+
if (!p.animatedParticleState || this.frames.length <= 1) return;
|
|
128
|
+
|
|
129
|
+
p.animatedParticleState.t += dt;
|
|
130
|
+
|
|
131
|
+
const time = p.animatedParticleState.t;
|
|
132
|
+
const rawFrame = Math.floor(time * this.fps);
|
|
133
|
+
|
|
134
|
+
const idx = this.loop ? rawFrame % this.frames.length : Math.min(rawFrame, this.frames.length - 1);
|
|
135
|
+
|
|
136
|
+
p.texture = this.frames[idx];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Called when particle is recycled.
|
|
141
|
+
* Clears animation state to avoid stale data in pooled particles.
|
|
142
|
+
*/
|
|
143
|
+
public onKill(p: PxParticle): void {
|
|
144
|
+
p.animatedParticleState = undefined;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Texture } from "pixi.js";
|
|
2
|
+
import { TextureProvider } from "../texture-provider";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Always returns the same texture for every particle.
|
|
6
|
+
* Useful for simple effects (sparks, smoke puffs, etc).
|
|
7
|
+
*/
|
|
8
|
+
export class SingleTextureProvider implements TextureProvider {
|
|
9
|
+
/** Key/URL/alias passed to PixiJS Texture.from(). */
|
|
10
|
+
private readonly textureId: string;
|
|
11
|
+
|
|
12
|
+
private readonly texture: Texture;
|
|
13
|
+
|
|
14
|
+
constructor(textureId: string) {
|
|
15
|
+
this.textureId = textureId;
|
|
16
|
+
this.texture = Texture.from(textureId);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public initialTexture(): Texture {
|
|
20
|
+
return this.texture;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Texture } from "pixi.js";
|
|
2
|
+
import { TextureProvider } from "../texture-provider";
|
|
3
|
+
import { PxParticle } from "../px-particle";
|
|
4
|
+
|
|
5
|
+
type WeightedTexture = {
|
|
6
|
+
/** Key/URL/alias passed to PixiJS Texture.from(). */
|
|
7
|
+
textureId: string;
|
|
8
|
+
weight: number;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Chooses a random texture at spawn time using weighted probabilities.
|
|
13
|
+
*
|
|
14
|
+
* - Good for variety (different spark shapes, debris pieces, etc.)
|
|
15
|
+
* - Selection happens only on spawn (not per frame)
|
|
16
|
+
*/
|
|
17
|
+
export class WeightedTextureProvider implements TextureProvider {
|
|
18
|
+
private readonly fallback: Texture;
|
|
19
|
+
private readonly items: { texture: Texture; weight: number }[];
|
|
20
|
+
|
|
21
|
+
private totalWeight = 0;
|
|
22
|
+
|
|
23
|
+
constructor(items: WeightedTexture[], fallbackTextureId: string) {
|
|
24
|
+
this.fallback = Texture.from(fallbackTextureId);
|
|
25
|
+
|
|
26
|
+
// Pre-cache textures and compute total weight (ignoring negatives)
|
|
27
|
+
this.items = items.map((it) => ({
|
|
28
|
+
texture: Texture.from(it.textureId),
|
|
29
|
+
weight: Math.max(0, it.weight),
|
|
30
|
+
}));
|
|
31
|
+
|
|
32
|
+
for (const it of this.items) this.totalWeight += it.weight;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public initialTexture(): Texture {
|
|
36
|
+
return this.fallback;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public textureForSpawn(_p: PxParticle): Texture {
|
|
40
|
+
if (this.totalWeight <= 0 || this.items.length === 0) return this.fallback;
|
|
41
|
+
|
|
42
|
+
let r = Math.random() * this.totalWeight;
|
|
43
|
+
|
|
44
|
+
for (const it of this.items) {
|
|
45
|
+
r -= it.weight;
|
|
46
|
+
if (r <= 0) return it.texture;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Floating point edge-case fallback
|
|
50
|
+
return this.items[this.items.length - 1]!.texture;
|
|
51
|
+
}
|
|
52
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export class Utils {
|
|
2
|
+
public static lerp(a: number, b: number, t: number): number {
|
|
3
|
+
return a + (b - a) * t;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
public static clamp01(v: number) {
|
|
7
|
+
return v < 0 ? 0 : v > 1 ? 1 : v;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
public static rand(min: number, max: number) {
|
|
11
|
+
return min + Math.random() * (max - min);
|
|
12
|
+
}
|
|
13
|
+
}
|