minimojs 1.0.0-alpha.2 → 1.0.0-alpha.21

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 (55) hide show
  1. package/README.md +82 -285
  2. package/dist/internal/AnimationSystem.js +345 -0
  3. package/dist/internal/AssetSystem.d.ts +1 -0
  4. package/dist/internal/AssetSystem.js +101 -0
  5. package/dist/internal/BackgroundSystem.d.ts +1 -0
  6. package/dist/internal/BackgroundSystem.js +26 -0
  7. package/dist/internal/CanvasSystem.d.ts +1 -0
  8. package/dist/internal/CanvasSystem.js +51 -0
  9. package/dist/internal/ExplosionSystem.d.ts +1 -0
  10. package/dist/internal/ExplosionSystem.js +540 -0
  11. package/dist/internal/InputSystem.d.ts +1 -0
  12. package/dist/internal/InputSystem.js +265 -0
  13. package/dist/internal/LoopSystem.d.ts +1 -0
  14. package/dist/internal/LoopSystem.js +61 -0
  15. package/dist/internal/PhysicsSystem.d.ts +1 -0
  16. package/dist/internal/PhysicsSystem.js +174 -0
  17. package/dist/internal/RenderSystem.d.ts +1 -0
  18. package/dist/internal/RenderSystem.js +910 -0
  19. package/dist/internal/SoundSystem.d.ts +1 -0
  20. package/dist/internal/SoundSystem.js +55 -0
  21. package/dist/internal/SpriteSystem.d.ts +1 -0
  22. package/dist/internal/SpriteSystem.js +32 -0
  23. package/dist/internal/TextSystem.d.ts +1 -0
  24. package/dist/internal/TextSystem.js +16 -0
  25. package/dist/internal/TimerSystem.d.ts +1 -0
  26. package/dist/internal/TimerSystem.js +43 -0
  27. package/dist/internal/TrailSystem.d.ts +1 -0
  28. package/dist/internal/TrailSystem.js +116 -0
  29. package/dist/internal/TransitionSystem.d.ts +1 -0
  30. package/dist/internal/TransitionSystem.js +74 -0
  31. package/dist/internal/arcade-racer/ArcadeRacerCollisionSystem.d.ts +1 -0
  32. package/dist/internal/arcade-racer/ArcadeRacerCollisionSystem.js +198 -0
  33. package/dist/internal/arcade-racer/ArcadeRacerLaneSystem.d.ts +1 -0
  34. package/dist/internal/arcade-racer/ArcadeRacerLaneSystem.js +120 -0
  35. package/dist/internal/arcade-racer/ArcadeRacerRenderSystem.d.ts +1 -0
  36. package/dist/internal/arcade-racer/ArcadeRacerRenderSystem.js +599 -0
  37. package/dist/internal/arcade-racer/ArcadeRacerRoadSprite.d.ts +1 -0
  38. package/dist/internal/arcade-racer/ArcadeRacerRoadSprite.js +13 -0
  39. package/dist/internal/arcade-racer/ArcadeRacerTrackSystem.d.ts +1 -0
  40. package/dist/internal/arcade-racer/ArcadeRacerTrackSystem.js +447 -0
  41. package/dist/minimo-arcaderacer.d.ts +1431 -0
  42. package/dist/minimo-arcaderacer.js +2060 -0
  43. package/dist/minimo.d.ts +1412 -162
  44. package/dist/minimo.js +2083 -816
  45. package/package.json +3 -2
  46. package/dist/animations.js +0 -30
  47. package/dist/audio.js +0 -17
  48. package/dist/game.js +0 -1105
  49. package/dist/input.js +0 -185
  50. package/dist/internal-types.js +0 -4
  51. package/dist/physics.js +0 -10
  52. package/dist/render.js +0 -75
  53. package/dist/sprite.js +0 -149
  54. package/dist/timers.js +0 -23
  55. /package/dist/{pointer-info.js → internal/AnimationSystem.d.ts} +0 -0
@@ -0,0 +1,540 @@
1
+ const DEFAULT_EXPLODE_OPTIONS = {
2
+ rows: 3,
3
+ cols: 3,
4
+ durationMs: 500,
5
+ speed: 260,
6
+ gravityY: 900,
7
+ spin: 220,
8
+ fade: true,
9
+ destroySprite: true,
10
+ };
11
+ const DEFAULT_ASSEMBLE_OPTIONS = {
12
+ rows: 3,
13
+ cols: 3,
14
+ durationMs: 500,
15
+ speed: 260,
16
+ gravityY: 900,
17
+ spin: 220,
18
+ fade: true,
19
+ };
20
+ const DEFAULT_DISINTEGRATE_OPTIONS = {
21
+ rows: 4,
22
+ cols: 4,
23
+ durationMs: 420,
24
+ direction: "left-to-right",
25
+ distance: 42,
26
+ spin: 120,
27
+ fade: true,
28
+ destroySprite: true,
29
+ };
30
+ const DEFAULT_INTEGRATE_OPTIONS = {
31
+ rows: 4,
32
+ cols: 4,
33
+ durationMs: 420,
34
+ direction: "left-to-right",
35
+ distance: 42,
36
+ spin: 120,
37
+ fade: true,
38
+ };
39
+ const DEFAULT_WIPE_OPTIONS = {
40
+ mode: "reveal",
41
+ direction: "left-to-right",
42
+ durationMs: 360,
43
+ destroySprite: true,
44
+ };
45
+ /** @internal */
46
+ export class ExplosionSystem {
47
+ constructor() {
48
+ /** @internal */
49
+ this._pieceEffects = [];
50
+ /** @internal */
51
+ this._wipes = [];
52
+ }
53
+ animateExplode(sprite, glyphCanvas, options, onComplete) {
54
+ const context = this.buildPieceSpriteContext(sprite, glyphCanvas);
55
+ this.spawnRadialEffect("explode", sprite, glyphCanvas, context, {
56
+ rows: this.sanitizeCount(options?.rows, DEFAULT_EXPLODE_OPTIONS.rows),
57
+ cols: this.sanitizeCount(options?.cols, DEFAULT_EXPLODE_OPTIONS.cols),
58
+ durationMs: this.sanitizeDuration(options?.durationMs, DEFAULT_EXPLODE_OPTIONS.durationMs),
59
+ speed: this.sanitizeNonNegative(options?.speed, DEFAULT_EXPLODE_OPTIONS.speed),
60
+ gravityY: this.sanitizeNumber(options?.gravityY, DEFAULT_EXPLODE_OPTIONS.gravityY),
61
+ spin: this.sanitizeNonNegative(options?.spin, DEFAULT_EXPLODE_OPTIONS.spin),
62
+ fade: options?.fade ?? DEFAULT_EXPLODE_OPTIONS.fade,
63
+ }, false, options?.destroySprite === false, options?.destroySprite === false ? sprite.visible : false, onComplete);
64
+ }
65
+ animateAssemble(sprite, glyphCanvas, options, onComplete) {
66
+ const context = this.buildPieceSpriteContext(sprite, glyphCanvas);
67
+ this.spawnRadialEffect("assemble", sprite, glyphCanvas, context, {
68
+ rows: this.sanitizeCount(options?.rows, DEFAULT_ASSEMBLE_OPTIONS.rows),
69
+ cols: this.sanitizeCount(options?.cols, DEFAULT_ASSEMBLE_OPTIONS.cols),
70
+ durationMs: this.sanitizeDuration(options?.durationMs, DEFAULT_ASSEMBLE_OPTIONS.durationMs),
71
+ speed: this.sanitizeNonNegative(options?.speed, DEFAULT_ASSEMBLE_OPTIONS.speed),
72
+ gravityY: this.sanitizeNumber(options?.gravityY, DEFAULT_ASSEMBLE_OPTIONS.gravityY),
73
+ spin: this.sanitizeNonNegative(options?.spin, DEFAULT_ASSEMBLE_OPTIONS.spin),
74
+ fade: options?.fade ?? DEFAULT_ASSEMBLE_OPTIONS.fade,
75
+ }, true, true, true, onComplete);
76
+ }
77
+ animateDisintegrate(sprite, glyphCanvas, options, onComplete) {
78
+ const context = this.buildPieceSpriteContext(sprite, glyphCanvas);
79
+ this.spawnDirectionalEffect("disintegrate", sprite, glyphCanvas, context, {
80
+ rows: this.sanitizeCount(options?.rows, DEFAULT_DISINTEGRATE_OPTIONS.rows),
81
+ cols: this.sanitizeCount(options?.cols, DEFAULT_DISINTEGRATE_OPTIONS.cols),
82
+ durationMs: this.sanitizeDuration(options?.durationMs, DEFAULT_DISINTEGRATE_OPTIONS.durationMs),
83
+ direction: options?.direction ?? DEFAULT_DISINTEGRATE_OPTIONS.direction,
84
+ distance: this.sanitizeNonNegative(options?.distance, DEFAULT_DISINTEGRATE_OPTIONS.distance),
85
+ spin: this.sanitizeNonNegative(options?.spin, DEFAULT_DISINTEGRATE_OPTIONS.spin),
86
+ fade: options?.fade ?? DEFAULT_DISINTEGRATE_OPTIONS.fade,
87
+ }, false, options?.destroySprite === false, false, onComplete);
88
+ }
89
+ animateIntegrate(sprite, glyphCanvas, options, onComplete) {
90
+ const context = this.buildPieceSpriteContext(sprite, glyphCanvas);
91
+ this.spawnDirectionalEffect("integrate", sprite, glyphCanvas, context, {
92
+ rows: this.sanitizeCount(options?.rows, DEFAULT_INTEGRATE_OPTIONS.rows),
93
+ cols: this.sanitizeCount(options?.cols, DEFAULT_INTEGRATE_OPTIONS.cols),
94
+ durationMs: this.sanitizeDuration(options?.durationMs, DEFAULT_INTEGRATE_OPTIONS.durationMs),
95
+ direction: options?.direction ?? DEFAULT_INTEGRATE_OPTIONS.direction,
96
+ distance: this.sanitizeNonNegative(options?.distance, DEFAULT_INTEGRATE_OPTIONS.distance),
97
+ spin: this.sanitizeNonNegative(options?.spin, DEFAULT_INTEGRATE_OPTIONS.spin),
98
+ fade: options?.fade ?? DEFAULT_INTEGRATE_OPTIONS.fade,
99
+ }, true, true, true, onComplete);
100
+ }
101
+ animateWipe(sprite, snapshot, options, onComplete) {
102
+ this.clearSpriteEffects(sprite);
103
+ const mode = options?.mode ?? DEFAULT_WIPE_OPTIONS.mode;
104
+ const durationMs = this.sanitizeDuration(options?.durationMs, DEFAULT_WIPE_OPTIONS.durationMs);
105
+ const direction = options?.direction ?? DEFAULT_WIPE_OPTIONS.direction;
106
+ const destroySprite = options?.destroySprite ?? DEFAULT_WIPE_OPTIONS.destroySprite;
107
+ const restoreVisibility = mode === "reveal";
108
+ sprite.visible = false;
109
+ this._wipes.push({
110
+ sprite,
111
+ canvas: snapshot.canvas,
112
+ x: snapshot.x,
113
+ y: snapshot.y,
114
+ rotation: snapshot.rotation,
115
+ alpha: snapshot.alpha,
116
+ flipX: snapshot.flipX,
117
+ flipY: snapshot.flipY,
118
+ drawWidth: snapshot.drawWidth,
119
+ drawHeight: snapshot.drawHeight,
120
+ layer: snapshot.layer,
121
+ ignoreScroll: snapshot.ignoreScroll,
122
+ mode,
123
+ direction,
124
+ progress: mode === "reveal" ? 0 : 1,
125
+ elapsedMs: 0,
126
+ durationMs,
127
+ restoreVisibility,
128
+ finalVisible: mode === "reveal",
129
+ onComplete,
130
+ });
131
+ }
132
+ update(_dt, dtMs) {
133
+ const pieceToRemove = [];
134
+ for (let i = 0; i < this._pieceEffects.length; i++) {
135
+ const effect = this._pieceEffects[i];
136
+ effect.elapsedMs += dtMs;
137
+ const t = Math.min(effect.elapsedMs / effect.durationMs, 1);
138
+ for (const piece of effect.pieces) {
139
+ const localT = t <= piece.delayT ? 0 : Math.min(1, (t - piece.delayT) / (1 - piece.delayT));
140
+ const eased = this.easePieceProgress(effect.mode, localT);
141
+ piece.x = this.lerp(piece.startX, piece.endX, eased);
142
+ piece.y = this.lerp(piece.startY, piece.endY, eased);
143
+ piece.rotation = this.lerp(piece.startRotation, piece.endRotation, eased);
144
+ piece.alpha = this.lerp(piece.startAlpha, piece.endAlpha, eased);
145
+ }
146
+ if (t >= 1) {
147
+ pieceToRemove.push(i);
148
+ if (effect.restoreVisibility) {
149
+ effect.sprite.visible = effect.finalVisible;
150
+ }
151
+ effect.onComplete?.();
152
+ }
153
+ }
154
+ for (let i = pieceToRemove.length - 1; i >= 0; i--) {
155
+ this._pieceEffects.splice(pieceToRemove[i], 1);
156
+ }
157
+ const wipeToRemove = [];
158
+ for (let i = 0; i < this._wipes.length; i++) {
159
+ const wipe = this._wipes[i];
160
+ wipe.elapsedMs += dtMs;
161
+ const t = Math.min(wipe.elapsedMs / wipe.durationMs, 1);
162
+ wipe.progress = wipe.mode === "reveal" ? t : 1 - t;
163
+ if (t >= 1) {
164
+ wipeToRemove.push(i);
165
+ if (wipe.restoreVisibility) {
166
+ wipe.sprite.visible = wipe.finalVisible;
167
+ }
168
+ wipe.onComplete?.();
169
+ }
170
+ }
171
+ for (let i = wipeToRemove.length - 1; i >= 0; i--) {
172
+ this._wipes.splice(wipeToRemove[i], 1);
173
+ }
174
+ }
175
+ getRenderEntries() {
176
+ return this._pieceEffects;
177
+ }
178
+ getWipeEntries() {
179
+ return this._wipes;
180
+ }
181
+ clearAll() {
182
+ for (const effect of this._pieceEffects) {
183
+ if (effect.restoreVisibility) {
184
+ effect.sprite.visible = effect.finalVisible;
185
+ }
186
+ }
187
+ for (const wipe of this._wipes) {
188
+ if (wipe.restoreVisibility) {
189
+ wipe.sprite.visible = wipe.finalVisible;
190
+ }
191
+ }
192
+ this._pieceEffects = [];
193
+ this._wipes = [];
194
+ }
195
+ /** @internal */
196
+ spawnRadialEffect(mode, sprite, glyphCanvas, context, options, forceHideSprite, restoreVisibility, finalVisible, onComplete) {
197
+ this.clearSpriteEffects(sprite);
198
+ if (forceHideSprite || restoreVisibility) {
199
+ sprite.visible = false;
200
+ }
201
+ const durationSeconds = options.durationMs / 1000;
202
+ const pieces = this.buildPieceGrid(glyphCanvas, context, options.rows, options.cols, (_row, _col, sx, sy, sw, sh, centerX, centerY) => {
203
+ const velocity = this.getRadialVelocity(centerX, centerY);
204
+ const distance = options.speed * durationSeconds * (0.65 + Math.random() * 0.7);
205
+ const targetX = context.baseX + centerX + velocity.x * distance;
206
+ const targetY = context.baseY +
207
+ centerY +
208
+ velocity.y * distance +
209
+ 0.5 * options.gravityY * durationSeconds * durationSeconds;
210
+ const assembledX = context.baseX + centerX;
211
+ const assembledY = context.baseY + centerY;
212
+ const startRotation = mode === "explode"
213
+ ? context.rotation
214
+ : context.rotation + (Math.random() * 2 - 1) * options.spin * durationSeconds;
215
+ const endRotation = mode === "explode"
216
+ ? context.rotation + (Math.random() * 2 - 1) * options.spin * durationSeconds
217
+ : context.rotation;
218
+ return {
219
+ sx,
220
+ sy,
221
+ sw,
222
+ sh,
223
+ assembledX,
224
+ assembledY,
225
+ offsetX: targetX - assembledX,
226
+ offsetY: targetY - assembledY,
227
+ startRotation,
228
+ endRotation,
229
+ delayT: 0,
230
+ fade: options.fade,
231
+ };
232
+ }, mode);
233
+ this._pieceEffects.push({
234
+ sprite,
235
+ canvas: glyphCanvas,
236
+ layer: context.layer,
237
+ ignoreScroll: context.ignoreScroll,
238
+ pieces,
239
+ elapsedMs: 0,
240
+ durationMs: options.durationMs,
241
+ mode,
242
+ restoreVisibility,
243
+ finalVisible,
244
+ onComplete,
245
+ });
246
+ }
247
+ /** @internal */
248
+ spawnDirectionalEffect(mode, sprite, glyphCanvas, context, options, forceHideSprite, restoreVisibility, finalVisible, onComplete) {
249
+ this.clearSpriteEffects(sprite);
250
+ if (forceHideSprite || restoreVisibility) {
251
+ sprite.visible = false;
252
+ }
253
+ const durationSeconds = options.durationMs / 1000;
254
+ const maxDelayT = 0.58;
255
+ const inPlace = options.direction === "in-place";
256
+ const directionalFlow = inPlace
257
+ ? "left-to-right"
258
+ : options.direction;
259
+ const directionVector = inPlace ? { x: 0, y: 0 } : this.getDirectionVector(directionalFlow);
260
+ const perpendicular = inPlace ? { x: 0, y: 0 } : { x: -directionVector.y, y: directionVector.x };
261
+ const pieces = this.buildPieceGrid(glyphCanvas, context, options.rows, options.cols, (row, col, sx, sy, sw, sh, centerX, centerY) => {
262
+ const baseDistance = inPlace ? 0 : options.distance * (0.45 + Math.random() * 0.75);
263
+ const sidewaysDistance = inPlace ? 0 : options.distance * 0.22 * (Math.random() * 2 - 1);
264
+ const offsetX = directionVector.x * baseDistance + perpendicular.x * sidewaysDistance;
265
+ const offsetY = directionVector.y * baseDistance + perpendicular.y * sidewaysDistance;
266
+ const assembledX = context.baseX + centerX;
267
+ const assembledY = context.baseY + centerY;
268
+ const delayT = inPlace
269
+ ? Math.random() * (maxDelayT + 0.05)
270
+ : this.getDirectionalProgress(row, col, options.rows, options.cols, directionalFlow) *
271
+ maxDelayT +
272
+ Math.random() * 0.05;
273
+ const rotationOffset = inPlace
274
+ ? 0
275
+ : (Math.random() * 2 - 1) * options.spin * durationSeconds;
276
+ return {
277
+ sx,
278
+ sy,
279
+ sw,
280
+ sh,
281
+ assembledX,
282
+ assembledY,
283
+ offsetX,
284
+ offsetY,
285
+ startRotation: mode === "disintegrate" ? context.rotation : context.rotation + rotationOffset,
286
+ endRotation: mode === "disintegrate" ? context.rotation + rotationOffset : context.rotation,
287
+ delayT: Math.min(maxDelayT + 0.05, delayT),
288
+ fade: options.fade,
289
+ };
290
+ }, mode);
291
+ this._pieceEffects.push({
292
+ sprite,
293
+ canvas: glyphCanvas,
294
+ layer: context.layer,
295
+ ignoreScroll: context.ignoreScroll,
296
+ pieces,
297
+ elapsedMs: 0,
298
+ durationMs: options.durationMs,
299
+ mode,
300
+ restoreVisibility,
301
+ finalVisible,
302
+ onComplete,
303
+ });
304
+ }
305
+ /** @internal */
306
+ buildPieceGrid(glyphCanvas, context, rows, cols, builder, mode) {
307
+ const pieces = [];
308
+ const rotationRad = (context.rotation * Math.PI) / 180;
309
+ for (let row = 0; row < rows; row++) {
310
+ const sy = Math.floor((row * glyphCanvas.height) / rows);
311
+ const nextSy = Math.floor(((row + 1) * glyphCanvas.height) / rows);
312
+ const sh = Math.max(1, nextSy - sy);
313
+ for (let col = 0; col < cols; col++) {
314
+ const sx = Math.floor((col * glyphCanvas.width) / cols);
315
+ const nextSx = Math.floor(((col + 1) * glyphCanvas.width) / cols);
316
+ const sw = Math.max(1, nextSx - sx);
317
+ const localX = (sx + sw / 2 - glyphCanvas.width / 2) * context.signedScaleX;
318
+ const localY = (sy + sh / 2 - glyphCanvas.height / 2) * context.signedScaleY;
319
+ const rotated = this.rotate(localX, localY, rotationRad);
320
+ const generated = builder(row, col, sx, sy, sw, sh, rotated.x, rotated.y);
321
+ const startX = mode === "explode" || mode === "disintegrate"
322
+ ? generated.assembledX
323
+ : generated.assembledX + generated.offsetX;
324
+ const startY = mode === "explode" || mode === "disintegrate"
325
+ ? generated.assembledY
326
+ : generated.assembledY + generated.offsetY;
327
+ const endX = mode === "explode" || mode === "disintegrate"
328
+ ? generated.assembledX + generated.offsetX
329
+ : generated.assembledX;
330
+ const endY = mode === "explode" || mode === "disintegrate"
331
+ ? generated.assembledY + generated.offsetY
332
+ : generated.assembledY;
333
+ const startAlpha = mode === "explode" || mode === "disintegrate"
334
+ ? context.baseAlpha
335
+ : generated.fade
336
+ ? 0
337
+ : context.baseAlpha;
338
+ const endAlpha = mode === "explode" || mode === "disintegrate"
339
+ ? generated.fade
340
+ ? 0
341
+ : context.baseAlpha
342
+ : context.baseAlpha;
343
+ pieces.push({
344
+ x: startX,
345
+ y: startY,
346
+ rotation: generated.startRotation,
347
+ alpha: startAlpha,
348
+ flipX: context.flipX,
349
+ flipY: context.flipY,
350
+ sx: generated.sx,
351
+ sy: generated.sy,
352
+ sw: generated.sw,
353
+ sh: generated.sh,
354
+ drawWidth: generated.sw * context.absScaleX,
355
+ drawHeight: generated.sh * context.absScaleY,
356
+ startX,
357
+ startY,
358
+ endX,
359
+ endY,
360
+ startRotation: generated.startRotation,
361
+ endRotation: generated.endRotation,
362
+ startAlpha,
363
+ endAlpha,
364
+ delayT: generated.delayT,
365
+ });
366
+ }
367
+ }
368
+ return pieces;
369
+ }
370
+ /** @internal */
371
+ buildPieceSpriteContext(sprite, glyphCanvas) {
372
+ const renderData = sprite._renderData;
373
+ const deformScaleX = this.getSafeScale(renderData?.scaleX);
374
+ const deformScaleY = this.getSafeScale(renderData?.scaleY);
375
+ const pivotX = this.getSafePivot(renderData?.pivotX);
376
+ const pivotY = this.getSafePivot(renderData?.pivotY);
377
+ const offsetX = this.getSafeNumber(renderData?.offsetX, 0);
378
+ const offsetY = this.getSafeNumber(renderData?.offsetY, 0);
379
+ const alphaMultiplier = this.getSafeNumber(renderData?.alphaMultiplier, 1);
380
+ const baseDisplayWidth = sprite.displayWidth;
381
+ const baseDisplayHeight = sprite.displayHeight;
382
+ const pivotOffsetX = (pivotX - 0.5) * baseDisplayWidth * (1 - deformScaleX);
383
+ const pivotOffsetY = (pivotY - 0.5) * baseDisplayHeight * (1 - deformScaleY);
384
+ const signedScaleX = this.getSafeScale(sprite.scale) * deformScaleX * (sprite.flipX ? -1 : 1);
385
+ const signedScaleY = this.getSafeScale(sprite.scale) * deformScaleY * (sprite.flipY ? -1 : 1);
386
+ return {
387
+ layer: sprite.layer,
388
+ ignoreScroll: sprite.ignoreScroll,
389
+ baseX: sprite.renderX + pivotOffsetX + offsetX,
390
+ baseY: sprite.renderY + pivotOffsetY + offsetY,
391
+ rotation: sprite.rotation,
392
+ baseAlpha: Math.max(0, Math.min(1, sprite.alpha * alphaMultiplier)),
393
+ flipX: sprite.flipX,
394
+ flipY: sprite.flipY,
395
+ signedScaleX,
396
+ signedScaleY,
397
+ absScaleX: Math.abs(signedScaleX),
398
+ absScaleY: Math.abs(signedScaleY),
399
+ };
400
+ }
401
+ /** @internal */
402
+ clearSpriteEffects(sprite) {
403
+ const remainingPieces = [];
404
+ for (const effect of this._pieceEffects) {
405
+ if (effect.sprite === sprite) {
406
+ if (effect.restoreVisibility) {
407
+ effect.sprite.visible = effect.finalVisible;
408
+ }
409
+ }
410
+ else {
411
+ remainingPieces.push(effect);
412
+ }
413
+ }
414
+ this._pieceEffects = remainingPieces;
415
+ const remainingWipes = [];
416
+ for (const wipe of this._wipes) {
417
+ if (wipe.sprite === sprite) {
418
+ if (wipe.restoreVisibility) {
419
+ wipe.sprite.visible = wipe.finalVisible;
420
+ }
421
+ }
422
+ else {
423
+ remainingWipes.push(wipe);
424
+ }
425
+ }
426
+ this._wipes = remainingWipes;
427
+ }
428
+ /** @internal */
429
+ getDirectionalProgress(row, col, rows, cols, direction) {
430
+ const rowProgress = rows <= 1 ? 0 : row / (rows - 1);
431
+ const colProgress = cols <= 1 ? 0 : col / (cols - 1);
432
+ switch (direction) {
433
+ case "left-to-right":
434
+ return colProgress;
435
+ case "right-to-left":
436
+ return 1 - colProgress;
437
+ case "top-to-bottom":
438
+ return rowProgress;
439
+ case "bottom-to-top":
440
+ return 1 - rowProgress;
441
+ }
442
+ }
443
+ /** @internal */
444
+ getDirectionVector(direction) {
445
+ switch (direction) {
446
+ case "left-to-right":
447
+ return { x: 1, y: 0 };
448
+ case "right-to-left":
449
+ return { x: -1, y: 0 };
450
+ case "top-to-bottom":
451
+ return { x: 0, y: 1 };
452
+ case "bottom-to-top":
453
+ return { x: 0, y: -1 };
454
+ }
455
+ }
456
+ /** @internal */
457
+ getRadialVelocity(x, y) {
458
+ const magnitude = Math.hypot(x, y);
459
+ let dirX = 0;
460
+ let dirY = 0;
461
+ if (magnitude > 0.001) {
462
+ dirX = x / magnitude;
463
+ dirY = y / magnitude;
464
+ }
465
+ else {
466
+ const angle = Math.random() * Math.PI * 2;
467
+ dirX = Math.cos(angle);
468
+ dirY = Math.sin(angle);
469
+ }
470
+ const jitterAngle = (Math.random() - 0.5) * (Math.PI / 2);
471
+ return this.rotate(dirX, dirY, jitterAngle);
472
+ }
473
+ /** @internal */
474
+ easePieceProgress(mode, t) {
475
+ const clamped = Math.max(0, Math.min(1, t));
476
+ switch (mode) {
477
+ case "explode":
478
+ case "disintegrate":
479
+ return 1 - (1 - clamped) * (1 - clamped);
480
+ case "assemble":
481
+ case "integrate":
482
+ return clamped * clamped * (3 - 2 * clamped);
483
+ }
484
+ }
485
+ /** @internal */
486
+ rotate(x, y, radians) {
487
+ const cos = Math.cos(radians);
488
+ const sin = Math.sin(radians);
489
+ return {
490
+ x: x * cos - y * sin,
491
+ y: x * sin + y * cos,
492
+ };
493
+ }
494
+ /** @internal */
495
+ lerp(from, to, t) {
496
+ return from + (to - from) * t;
497
+ }
498
+ /** @internal */
499
+ getSafeScale(value) {
500
+ if (!Number.isFinite(value))
501
+ return 1;
502
+ return Math.max(0, value);
503
+ }
504
+ /** @internal */
505
+ getSafePivot(value) {
506
+ if (!Number.isFinite(value))
507
+ return 0.5;
508
+ return Math.max(0, Math.min(1, value));
509
+ }
510
+ /** @internal */
511
+ getSafeNumber(value, fallback) {
512
+ if (!Number.isFinite(value))
513
+ return fallback;
514
+ return value;
515
+ }
516
+ /** @internal */
517
+ sanitizeCount(value, fallback) {
518
+ if (!Number.isFinite(value))
519
+ return fallback;
520
+ return Math.max(1, Math.round(value));
521
+ }
522
+ /** @internal */
523
+ sanitizeDuration(value, fallback) {
524
+ if (!Number.isFinite(value))
525
+ return fallback;
526
+ return Math.max(1, value);
527
+ }
528
+ /** @internal */
529
+ sanitizeNonNegative(value, fallback) {
530
+ if (!Number.isFinite(value))
531
+ return fallback;
532
+ return Math.max(0, value);
533
+ }
534
+ /** @internal */
535
+ sanitizeNumber(value, fallback) {
536
+ if (!Number.isFinite(value))
537
+ return fallback;
538
+ return value;
539
+ }
540
+ }
@@ -0,0 +1 @@
1
+ export {};