@guinetik/gcanvas 1.0.2 → 1.0.4
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/gcanvas.es.js +25656 -0
- package/dist/gcanvas.es.min.js +1 -0
- package/dist/gcanvas.umd.js +1 -0
- package/dist/gcanvas.umd.min.js +1 -0
- package/package.json +23 -6
- package/src/game/objects/index.js +1 -0
- package/src/game/objects/spritesheet.js +260 -0
- package/src/game/ui/theme.js +6 -0
- package/src/io/keys.js +9 -1
- package/src/math/boolean.js +481 -0
- package/src/math/index.js +1 -0
- package/.github/workflows/release.yaml +0 -70
- package/.jshintrc +0 -4
- package/.vscode/settings.json +0 -22
- package/CLAUDE.md +0 -310
- package/blackhole.jpg +0 -0
- package/demo.png +0 -0
- package/demos/CNAME +0 -1
- package/demos/animations.html +0 -31
- package/demos/basic.html +0 -38
- package/demos/baskara.html +0 -31
- package/demos/bezier.html +0 -35
- package/demos/beziersignature.html +0 -29
- package/demos/blackhole.html +0 -28
- package/demos/blob.html +0 -35
- package/demos/coordinates.html +0 -698
- package/demos/cube3d.html +0 -23
- package/demos/demos.css +0 -303
- package/demos/dino.html +0 -42
- package/demos/easing.html +0 -28
- package/demos/events.html +0 -195
- package/demos/fluent.html +0 -647
- package/demos/fluid-simple.html +0 -22
- package/demos/fluid.html +0 -37
- package/demos/fractals.html +0 -36
- package/demos/gameobjects.html +0 -626
- package/demos/genart.html +0 -26
- package/demos/gendream.html +0 -26
- package/demos/group.html +0 -36
- package/demos/home.html +0 -587
- package/demos/index.html +0 -376
- package/demos/isometric.html +0 -34
- package/demos/js/animations.js +0 -452
- package/demos/js/basic.js +0 -204
- package/demos/js/baskara.js +0 -751
- package/demos/js/bezier.js +0 -692
- package/demos/js/beziersignature.js +0 -241
- package/demos/js/blackhole/accretiondisk.obj.js +0 -379
- package/demos/js/blackhole/blackhole.obj.js +0 -318
- package/demos/js/blackhole/index.js +0 -409
- package/demos/js/blackhole/particle.js +0 -56
- package/demos/js/blackhole/starfield.obj.js +0 -218
- package/demos/js/blob.js +0 -2276
- package/demos/js/coordinates.js +0 -840
- package/demos/js/cube3d.js +0 -789
- package/demos/js/dino.js +0 -1420
- package/demos/js/easing.js +0 -477
- package/demos/js/fluent.js +0 -183
- package/demos/js/fluid-simple.js +0 -253
- package/demos/js/fluid.js +0 -527
- package/demos/js/fractals.js +0 -931
- package/demos/js/fractalworker.js +0 -93
- package/demos/js/gameobjects.js +0 -176
- package/demos/js/genart.js +0 -268
- package/demos/js/gendream.js +0 -209
- package/demos/js/group.js +0 -140
- package/demos/js/info-toggle.js +0 -25
- package/demos/js/isometric.js +0 -863
- package/demos/js/kerr.js +0 -1556
- package/demos/js/lavalamp.js +0 -590
- package/demos/js/layout.js +0 -354
- package/demos/js/mondrian.js +0 -285
- package/demos/js/opacity.js +0 -275
- package/demos/js/painter.js +0 -484
- package/demos/js/particles-showcase.js +0 -514
- package/demos/js/particles.js +0 -299
- package/demos/js/patterns.js +0 -397
- package/demos/js/penrose/artifact.js +0 -69
- package/demos/js/penrose/blackhole.js +0 -121
- package/demos/js/penrose/constants.js +0 -73
- package/demos/js/penrose/game.js +0 -943
- package/demos/js/penrose/lore.js +0 -278
- package/demos/js/penrose/penrosescene.js +0 -892
- package/demos/js/penrose/ship.js +0 -216
- package/demos/js/penrose/sounds.js +0 -211
- package/demos/js/penrose/voidparticle.js +0 -55
- package/demos/js/penrose/voidscene.js +0 -258
- package/demos/js/penrose/voidship.js +0 -144
- package/demos/js/penrose/wormhole.js +0 -46
- package/demos/js/pipeline.js +0 -555
- package/demos/js/plane3d.js +0 -256
- package/demos/js/platformer.js +0 -1579
- package/demos/js/scene.js +0 -304
- package/demos/js/scenes.js +0 -320
- package/demos/js/schrodinger.js +0 -410
- package/demos/js/schwarzschild.js +0 -1023
- package/demos/js/shapes.js +0 -628
- package/demos/js/space/alien.js +0 -171
- package/demos/js/space/boom.js +0 -98
- package/demos/js/space/boss.js +0 -353
- package/demos/js/space/buff.js +0 -73
- package/demos/js/space/bullet.js +0 -102
- package/demos/js/space/constants.js +0 -85
- package/demos/js/space/game.js +0 -1884
- package/demos/js/space/hud.js +0 -112
- package/demos/js/space/laserbeam.js +0 -179
- package/demos/js/space/lightning.js +0 -277
- package/demos/js/space/minion.js +0 -192
- package/demos/js/space/missile.js +0 -212
- package/demos/js/space/player.js +0 -430
- package/demos/js/space/powerup.js +0 -90
- package/demos/js/space/starfield.js +0 -58
- package/demos/js/space/starpower.js +0 -90
- package/demos/js/spacetime.js +0 -559
- package/demos/js/sphere3d.js +0 -229
- package/demos/js/sprite.js +0 -473
- package/demos/js/svgtween.js +0 -204
- package/demos/js/tde/accretiondisk.js +0 -471
- package/demos/js/tde/blackhole.js +0 -219
- package/demos/js/tde/blackholescene.js +0 -209
- package/demos/js/tde/config.js +0 -59
- package/demos/js/tde/index.js +0 -820
- package/demos/js/tde/jets.js +0 -290
- package/demos/js/tde/lensedstarfield.js +0 -154
- package/demos/js/tde/tdestar.js +0 -297
- package/demos/js/tde/tidalstream.js +0 -372
- package/demos/js/tde_old/blackhole.obj.js +0 -354
- package/demos/js/tde_old/debris.obj.js +0 -791
- package/demos/js/tde_old/flare.obj.js +0 -239
- package/demos/js/tde_old/index.js +0 -448
- package/demos/js/tde_old/star.obj.js +0 -812
- package/demos/js/tiles.js +0 -312
- package/demos/js/tweendemo.js +0 -79
- package/demos/js/visibility.js +0 -102
- package/demos/kerr.html +0 -28
- package/demos/lavalamp.html +0 -27
- package/demos/layouts.html +0 -37
- package/demos/logo.svg +0 -4
- package/demos/loop.html +0 -84
- package/demos/mondrian.html +0 -32
- package/demos/og_image.png +0 -0
- package/demos/opacity.html +0 -36
- package/demos/painter.html +0 -39
- package/demos/particles-showcase.html +0 -28
- package/demos/particles.html +0 -24
- package/demos/patterns.html +0 -33
- package/demos/penrose-game.html +0 -31
- package/demos/pipeline.html +0 -737
- package/demos/plane3d.html +0 -24
- package/demos/platformer.html +0 -43
- package/demos/scene.html +0 -33
- package/demos/scenes.html +0 -96
- package/demos/schrodinger.html +0 -27
- package/demos/schwarzschild.html +0 -27
- package/demos/shapes.html +0 -16
- package/demos/space.html +0 -85
- package/demos/spacetime.html +0 -27
- package/demos/sphere3d.html +0 -24
- package/demos/sprite.html +0 -18
- package/demos/svgtween.html +0 -29
- package/demos/tde.html +0 -28
- package/demos/tiles.html +0 -28
- package/demos/transforms.html +0 -400
- package/demos/tween.html +0 -45
- package/demos/visibility.html +0 -33
- package/docs/README.md +0 -230
- package/docs/api/FluidSystem.md +0 -173
- package/docs/concepts/architecture-overview.md +0 -204
- package/docs/concepts/coordinate-system.md +0 -384
- package/docs/concepts/lifecycle.md +0 -255
- package/docs/concepts/rendering-pipeline.md +0 -279
- package/docs/concepts/shapes-vs-gameobjects.md +0 -187
- package/docs/concepts/tde-zorder.md +0 -106
- package/docs/concepts/two-layer-architecture.md +0 -229
- package/docs/fluid-dynamics.md +0 -99
- package/docs/getting-started/first-game.md +0 -354
- package/docs/getting-started/hello-world.md +0 -269
- package/docs/getting-started/installation.md +0 -175
- package/docs/modules/collision/README.md +0 -453
- package/docs/modules/fluent/README.md +0 -1075
- package/docs/modules/game/README.md +0 -303
- package/docs/modules/isometric-camera.md +0 -210
- package/docs/modules/isometric.md +0 -275
- package/docs/modules/painter/README.md +0 -328
- package/docs/modules/particle/README.md +0 -559
- package/docs/modules/shapes/README.md +0 -221
- package/docs/modules/shapes/base/euclidian.md +0 -123
- package/docs/modules/shapes/base/geometry2d.md +0 -204
- package/docs/modules/shapes/base/renderable.md +0 -215
- package/docs/modules/shapes/base/shape.md +0 -262
- package/docs/modules/shapes/base/transformable.md +0 -243
- package/docs/modules/shapes/hierarchy.md +0 -218
- package/docs/modules/state/README.md +0 -577
- package/docs/modules/util/README.md +0 -99
- package/docs/modules/util/camera3d.md +0 -412
- package/docs/modules/util/scene3d.md +0 -395
- package/index.html +0 -17
- package/jsdoc.json +0 -50
- package/scripts/build-demo.js +0 -69
- package/scripts/bundle4llm.js +0 -276
- package/scripts/clearconsole.js +0 -48
- package/test/math/orbital.test.js +0 -61
- package/test/math/tensor.test.js +0 -114
- package/test/particle/emitter.test.js +0 -204
- package/test/particle/particle-system.test.js +0 -310
- package/test/particle/particle.test.js +0 -116
- package/test/particle/updaters.test.js +0 -386
- package/test/setup.js +0 -120
- package/test/shapes/euclidian.test.js +0 -44
- package/test/shapes/geometry.test.js +0 -86
- package/test/shapes/group.test.js +0 -86
- package/test/shapes/rectangle.test.js +0 -64
- package/test/shapes/transform.test.js +0 -379
- package/test/util/camera3d.test.js +0 -428
- package/test/util/scene3d.test.js +0 -352
- package/vite.config.js +0 -50
- package/vitest.config.js +0 -13
|
@@ -1,310 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
-
import { ParticleSystem } from "../../src/particle/particle-system";
|
|
3
|
-
import { ParticleEmitter } from "../../src/particle/emitter";
|
|
4
|
-
import { Updaters } from "../../src/particle/updaters";
|
|
5
|
-
import { Particle } from "../../src/particle/particle";
|
|
6
|
-
|
|
7
|
-
// Mock the game object
|
|
8
|
-
const createMockGame = () => ({
|
|
9
|
-
width: 800,
|
|
10
|
-
height: 600,
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
describe("ParticleSystem", () => {
|
|
14
|
-
let mockGame;
|
|
15
|
-
|
|
16
|
-
beforeEach(() => {
|
|
17
|
-
mockGame = createMockGame();
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
describe("constructor", () => {
|
|
21
|
-
it("should initialize with default values", () => {
|
|
22
|
-
const system = new ParticleSystem(mockGame);
|
|
23
|
-
|
|
24
|
-
expect(system.particles).toEqual([]);
|
|
25
|
-
expect(system.pool).toEqual([]);
|
|
26
|
-
expect(system.maxParticles).toBe(5000);
|
|
27
|
-
expect(system.emitters).toBeInstanceOf(Map);
|
|
28
|
-
expect(system.emitters.size).toBe(0);
|
|
29
|
-
expect(system.camera).toBeNull();
|
|
30
|
-
expect(system.depthSort).toBe(false);
|
|
31
|
-
expect(system.blendMode).toBe("source-over");
|
|
32
|
-
expect(system.worldSpace).toBe(false);
|
|
33
|
-
expect(system.particleCount).toBe(0);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it("should accept custom options", () => {
|
|
37
|
-
const mockCamera = { project: vi.fn() };
|
|
38
|
-
const system = new ParticleSystem(mockGame, {
|
|
39
|
-
maxParticles: 1000,
|
|
40
|
-
camera: mockCamera,
|
|
41
|
-
depthSort: true,
|
|
42
|
-
blendMode: "screen",
|
|
43
|
-
worldSpace: true,
|
|
44
|
-
updaters: [Updaters.velocity],
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
expect(system.maxParticles).toBe(1000);
|
|
48
|
-
expect(system.camera).toBe(mockCamera);
|
|
49
|
-
expect(system.depthSort).toBe(true);
|
|
50
|
-
expect(system.blendMode).toBe("screen");
|
|
51
|
-
expect(system.worldSpace).toBe(true);
|
|
52
|
-
expect(system.updaters).toEqual([Updaters.velocity]);
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
describe("emitter management", () => {
|
|
57
|
-
it("should add emitters", () => {
|
|
58
|
-
const system = new ParticleSystem(mockGame);
|
|
59
|
-
const emitter = new ParticleEmitter({ rate: 10 });
|
|
60
|
-
|
|
61
|
-
system.addEmitter("fire", emitter);
|
|
62
|
-
|
|
63
|
-
expect(system.emitters.has("fire")).toBe(true);
|
|
64
|
-
expect(system.getEmitter("fire")).toBe(emitter);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it("should remove emitters", () => {
|
|
68
|
-
const system = new ParticleSystem(mockGame);
|
|
69
|
-
const emitter = new ParticleEmitter({ rate: 10 });
|
|
70
|
-
|
|
71
|
-
system.addEmitter("fire", emitter);
|
|
72
|
-
system.removeEmitter("fire");
|
|
73
|
-
|
|
74
|
-
expect(system.emitters.has("fire")).toBe(false);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it("should return undefined for non-existent emitter", () => {
|
|
78
|
-
const system = new ParticleSystem(mockGame);
|
|
79
|
-
|
|
80
|
-
expect(system.getEmitter("nonexistent")).toBeUndefined();
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it("should support chaining on addEmitter/removeEmitter", () => {
|
|
84
|
-
const system = new ParticleSystem(mockGame);
|
|
85
|
-
const emitter = new ParticleEmitter();
|
|
86
|
-
|
|
87
|
-
const result1 = system.addEmitter("test", emitter);
|
|
88
|
-
const result2 = system.removeEmitter("test");
|
|
89
|
-
|
|
90
|
-
expect(result1).toBe(system);
|
|
91
|
-
expect(result2).toBe(system);
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
describe("object pooling", () => {
|
|
96
|
-
it("should acquire particles from pool when available", () => {
|
|
97
|
-
const system = new ParticleSystem(mockGame);
|
|
98
|
-
|
|
99
|
-
// Add particle to pool
|
|
100
|
-
const pooledParticle = new Particle();
|
|
101
|
-
system.pool.push(pooledParticle);
|
|
102
|
-
|
|
103
|
-
const acquired = system.acquire();
|
|
104
|
-
|
|
105
|
-
expect(acquired).toBe(pooledParticle);
|
|
106
|
-
expect(system.pool.length).toBe(0);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it("should create new particle when pool is empty", () => {
|
|
110
|
-
const system = new ParticleSystem(mockGame);
|
|
111
|
-
|
|
112
|
-
const acquired = system.acquire();
|
|
113
|
-
|
|
114
|
-
expect(acquired).toBeInstanceOf(Particle);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it("should release particles back to pool", () => {
|
|
118
|
-
const system = new ParticleSystem(mockGame);
|
|
119
|
-
const particle = new Particle();
|
|
120
|
-
particle.x = 100;
|
|
121
|
-
particle.y = 200;
|
|
122
|
-
|
|
123
|
-
system.release(particle);
|
|
124
|
-
|
|
125
|
-
expect(system.pool.length).toBe(1);
|
|
126
|
-
expect(system.pool[0]).toBe(particle);
|
|
127
|
-
// Particle should be reset
|
|
128
|
-
expect(particle.x).toBe(0);
|
|
129
|
-
expect(particle.y).toBe(0);
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
describe("emit", () => {
|
|
134
|
-
it("should emit particles using emitter", () => {
|
|
135
|
-
const system = new ParticleSystem(mockGame);
|
|
136
|
-
const emitter = new ParticleEmitter({
|
|
137
|
-
position: { x: 100, y: 200 },
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
system.emit(5, emitter);
|
|
141
|
-
|
|
142
|
-
expect(system.particles.length).toBe(5);
|
|
143
|
-
// particleCount is updated after update() call
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it("should not exceed maxParticles", () => {
|
|
147
|
-
const system = new ParticleSystem(mockGame, { maxParticles: 3 });
|
|
148
|
-
const emitter = new ParticleEmitter();
|
|
149
|
-
|
|
150
|
-
system.emit(10, emitter);
|
|
151
|
-
|
|
152
|
-
expect(system.particles.length).toBe(3);
|
|
153
|
-
});
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
describe("burst", () => {
|
|
157
|
-
it("should burst spawn with emitter instance", () => {
|
|
158
|
-
const system = new ParticleSystem(mockGame);
|
|
159
|
-
const emitter = new ParticleEmitter();
|
|
160
|
-
|
|
161
|
-
system.burst(5, emitter);
|
|
162
|
-
|
|
163
|
-
expect(system.particles.length).toBe(5);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it("should burst spawn with emitter name", () => {
|
|
167
|
-
const system = new ParticleSystem(mockGame);
|
|
168
|
-
const emitter = new ParticleEmitter();
|
|
169
|
-
system.addEmitter("explosion", emitter);
|
|
170
|
-
|
|
171
|
-
system.burst(5, "explosion");
|
|
172
|
-
|
|
173
|
-
expect(system.particles.length).toBe(5);
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it("should do nothing with invalid emitter name", () => {
|
|
177
|
-
const system = new ParticleSystem(mockGame);
|
|
178
|
-
|
|
179
|
-
system.burst(5, "nonexistent");
|
|
180
|
-
|
|
181
|
-
expect(system.particles.length).toBe(0);
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
describe("update", () => {
|
|
186
|
-
it("should update particles with all updaters", () => {
|
|
187
|
-
const customUpdater = vi.fn();
|
|
188
|
-
const system = new ParticleSystem(mockGame, {
|
|
189
|
-
updaters: [customUpdater],
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
const emitter = new ParticleEmitter({ lifetime: { min: 10, max: 10 } });
|
|
193
|
-
system.emit(2, emitter);
|
|
194
|
-
|
|
195
|
-
system.update(0.016);
|
|
196
|
-
|
|
197
|
-
expect(customUpdater).toHaveBeenCalledTimes(2);
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
it("should remove dead particles", () => {
|
|
201
|
-
const system = new ParticleSystem(mockGame, {
|
|
202
|
-
updaters: [Updaters.lifetime],
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
const emitter = new ParticleEmitter({
|
|
206
|
-
lifetime: { min: 0.1, max: 0.1 },
|
|
207
|
-
});
|
|
208
|
-
system.emit(3, emitter);
|
|
209
|
-
|
|
210
|
-
// Large time step to kill particles
|
|
211
|
-
system.update(1);
|
|
212
|
-
|
|
213
|
-
expect(system.particles.length).toBe(0);
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
it("should return dead particles to pool", () => {
|
|
217
|
-
const system = new ParticleSystem(mockGame, {
|
|
218
|
-
updaters: [Updaters.lifetime],
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
const emitter = new ParticleEmitter({
|
|
222
|
-
lifetime: { min: 0.1, max: 0.1 },
|
|
223
|
-
});
|
|
224
|
-
system.emit(3, emitter);
|
|
225
|
-
|
|
226
|
-
system.update(1);
|
|
227
|
-
|
|
228
|
-
expect(system.pool.length).toBe(3);
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
it("should spawn particles from active emitters", () => {
|
|
232
|
-
const system = new ParticleSystem(mockGame);
|
|
233
|
-
const emitter = new ParticleEmitter({
|
|
234
|
-
rate: 100, // 100 per second
|
|
235
|
-
lifetime: { min: 10, max: 10 },
|
|
236
|
-
});
|
|
237
|
-
system.addEmitter("continuous", emitter);
|
|
238
|
-
|
|
239
|
-
system.update(0.1); // 10 particles expected
|
|
240
|
-
|
|
241
|
-
expect(system.particles.length).toBe(10);
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
it("should not spawn from inactive emitters", () => {
|
|
245
|
-
const system = new ParticleSystem(mockGame);
|
|
246
|
-
const emitter = new ParticleEmitter({
|
|
247
|
-
rate: 100,
|
|
248
|
-
active: false,
|
|
249
|
-
});
|
|
250
|
-
system.addEmitter("disabled", emitter);
|
|
251
|
-
|
|
252
|
-
system.update(0.1);
|
|
253
|
-
|
|
254
|
-
expect(system.particles.length).toBe(0);
|
|
255
|
-
});
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
describe("clear", () => {
|
|
259
|
-
it("should remove all particles", () => {
|
|
260
|
-
const system = new ParticleSystem(mockGame);
|
|
261
|
-
const emitter = new ParticleEmitter();
|
|
262
|
-
system.emit(10, emitter);
|
|
263
|
-
|
|
264
|
-
system.clear();
|
|
265
|
-
|
|
266
|
-
expect(system.particles.length).toBe(0);
|
|
267
|
-
expect(system.particleCount).toBe(0);
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
it("should return particles to pool", () => {
|
|
271
|
-
const system = new ParticleSystem(mockGame);
|
|
272
|
-
const emitter = new ParticleEmitter();
|
|
273
|
-
system.emit(10, emitter);
|
|
274
|
-
|
|
275
|
-
system.clear();
|
|
276
|
-
|
|
277
|
-
expect(system.pool.length).toBe(10);
|
|
278
|
-
});
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
describe("stats", () => {
|
|
282
|
-
it("should track particle count", () => {
|
|
283
|
-
const system = new ParticleSystem(mockGame);
|
|
284
|
-
const emitter = new ParticleEmitter({
|
|
285
|
-
lifetime: { min: 10, max: 10 },
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
expect(system.particleCount).toBe(0);
|
|
289
|
-
|
|
290
|
-
system.emit(5, emitter);
|
|
291
|
-
system.update(0);
|
|
292
|
-
|
|
293
|
-
expect(system.particleCount).toBe(5);
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
it("should track pool size", () => {
|
|
297
|
-
const system = new ParticleSystem(mockGame);
|
|
298
|
-
|
|
299
|
-
expect(system.poolSize).toBe(0);
|
|
300
|
-
|
|
301
|
-
const emitter = new ParticleEmitter({
|
|
302
|
-
lifetime: { min: 0.01, max: 0.01 },
|
|
303
|
-
});
|
|
304
|
-
system.emit(5, emitter);
|
|
305
|
-
system.update(1); // Kill all
|
|
306
|
-
|
|
307
|
-
expect(system.poolSize).toBe(5);
|
|
308
|
-
});
|
|
309
|
-
});
|
|
310
|
-
});
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { Particle } from "../../src/particle/particle";
|
|
3
|
-
|
|
4
|
-
describe("Particle", () => {
|
|
5
|
-
describe("constructor", () => {
|
|
6
|
-
it("should initialize with default values", () => {
|
|
7
|
-
const p = new Particle();
|
|
8
|
-
|
|
9
|
-
// Position
|
|
10
|
-
expect(p.x).toBe(0);
|
|
11
|
-
expect(p.y).toBe(0);
|
|
12
|
-
expect(p.z).toBe(0);
|
|
13
|
-
|
|
14
|
-
// Velocity
|
|
15
|
-
expect(p.vx).toBe(0);
|
|
16
|
-
expect(p.vy).toBe(0);
|
|
17
|
-
expect(p.vz).toBe(0);
|
|
18
|
-
|
|
19
|
-
// Appearance
|
|
20
|
-
expect(p.size).toBe(1);
|
|
21
|
-
expect(p.color).toEqual({ r: 255, g: 255, b: 255, a: 1 });
|
|
22
|
-
expect(p.shape).toBe("circle");
|
|
23
|
-
|
|
24
|
-
// Lifecycle
|
|
25
|
-
expect(p.age).toBe(0);
|
|
26
|
-
expect(p.lifetime).toBe(1);
|
|
27
|
-
expect(p.alive).toBe(true);
|
|
28
|
-
|
|
29
|
-
// Custom data
|
|
30
|
-
expect(p.custom).toEqual({});
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
describe("reset", () => {
|
|
35
|
-
it("should reset all properties to defaults", () => {
|
|
36
|
-
const p = new Particle();
|
|
37
|
-
|
|
38
|
-
// Modify all properties
|
|
39
|
-
p.x = 100;
|
|
40
|
-
p.y = 200;
|
|
41
|
-
p.z = 300;
|
|
42
|
-
p.vx = 10;
|
|
43
|
-
p.vy = 20;
|
|
44
|
-
p.vz = 30;
|
|
45
|
-
p.size = 5;
|
|
46
|
-
p.color = { r: 100, g: 50, b: 25, a: 0.5 };
|
|
47
|
-
p.shape = "square";
|
|
48
|
-
p.age = 2;
|
|
49
|
-
p.lifetime = 5;
|
|
50
|
-
p.alive = false;
|
|
51
|
-
p.custom.foo = "bar";
|
|
52
|
-
|
|
53
|
-
// Reset
|
|
54
|
-
p.reset();
|
|
55
|
-
|
|
56
|
-
// Verify defaults
|
|
57
|
-
expect(p.x).toBe(0);
|
|
58
|
-
expect(p.y).toBe(0);
|
|
59
|
-
expect(p.z).toBe(0);
|
|
60
|
-
expect(p.vx).toBe(0);
|
|
61
|
-
expect(p.vy).toBe(0);
|
|
62
|
-
expect(p.vz).toBe(0);
|
|
63
|
-
expect(p.size).toBe(1);
|
|
64
|
-
expect(p.color).toEqual({ r: 255, g: 255, b: 255, a: 1 });
|
|
65
|
-
expect(p.shape).toBe("circle");
|
|
66
|
-
expect(p.age).toBe(0);
|
|
67
|
-
expect(p.lifetime).toBe(1);
|
|
68
|
-
expect(p.alive).toBe(true);
|
|
69
|
-
expect(p.custom).toEqual({});
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it("should clear custom data", () => {
|
|
73
|
-
const p = new Particle();
|
|
74
|
-
p.custom.key1 = "value1";
|
|
75
|
-
p.custom.key2 = "value2";
|
|
76
|
-
|
|
77
|
-
p.reset();
|
|
78
|
-
|
|
79
|
-
expect(Object.keys(p.custom).length).toBe(0);
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
describe("progress", () => {
|
|
84
|
-
it("should calculate progress as age/lifetime", () => {
|
|
85
|
-
const p = new Particle();
|
|
86
|
-
p.lifetime = 4;
|
|
87
|
-
p.age = 1;
|
|
88
|
-
|
|
89
|
-
expect(p.progress).toBe(0.25);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it("should return 0 at birth", () => {
|
|
93
|
-
const p = new Particle();
|
|
94
|
-
p.lifetime = 2;
|
|
95
|
-
p.age = 0;
|
|
96
|
-
|
|
97
|
-
expect(p.progress).toBe(0);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it("should return 1 at death", () => {
|
|
101
|
-
const p = new Particle();
|
|
102
|
-
p.lifetime = 2;
|
|
103
|
-
p.age = 2;
|
|
104
|
-
|
|
105
|
-
expect(p.progress).toBe(1);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it("should handle zero lifetime", () => {
|
|
109
|
-
const p = new Particle();
|
|
110
|
-
p.lifetime = 0;
|
|
111
|
-
p.age = 0;
|
|
112
|
-
|
|
113
|
-
expect(p.progress).toBe(1);
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
});
|