littlejsengine 1.24.3 → 1.25.0
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/CHANGELOG.md +36 -0
- package/EDITOR.md +2 -2
- package/FAQ.md +6 -0
- package/REFERENCE.md +84 -40
- package/dist/littlejs.d.ts +474 -219
- package/dist/littlejs.esm.js +2318 -1743
- package/dist/littlejs.esm.min.js +38 -24
- package/dist/littlejs.js +2316 -1743
- package/dist/littlejs.min.js +37 -23
- package/dist/littlejs.release.js +2313 -1786
- package/package.json +1 -1
- package/plugins/box2d.js +32 -23
- package/plugins/drawUtilities.js +374 -380
- package/plugins/gltf.js +325 -54
- package/plugins/lightSystem.js +2 -2
- package/plugins/math3d.js +1013 -1014
- package/plugins/newgrounds.js +1 -4
- package/plugins/particleEffects.js +3 -4
- package/plugins/pathFinder.js +52 -28
- package/plugins/pluginExport.js +2 -0
- package/plugins/postProcess.js +196 -65
- package/plugins/render3d.js +8 -6
- package/plugins/render3dEditor.js +3 -3
- package/plugins/render3dExtras.js +19 -2
- package/plugins/render3dLevel.js +15 -4
- package/plugins/tweenSystem.js +43 -38
- package/plugins/uiSystem.js +25 -20
- package/src/engine.js +9 -5
- package/src/engineAudio.js +10 -6
- package/src/engineDebug.js +3 -2
- package/src/engineDraw.js +9 -9
- package/src/engineEditor.js +75 -23
- package/src/engineInput.js +4 -7
- package/src/engineMath.js +3 -6
- package/src/engineObject.js +8 -9
- package/src/engineParticles.js +8 -7
- package/src/engineRelease.js +17 -10
- package/src/engineTileLayer.js +33 -14
- package/src/engineUtilities.js +15 -2
- package/src/engineWebGL.js +31 -9
package/plugins/tweenSystem.js
CHANGED
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
|
|
12
12
|
///////////////////////////////////////////////////////////////////////////////
|
|
13
13
|
|
|
14
|
-
// Module-private list of tweens currently running, each with its active flag set while it is in it
|
|
14
|
+
// Module-private list of tweens currently running, each with its active flag set while it is in it; a stopped
|
|
15
|
+
// one stays listed, inactive, until the next update takes it out, so stopping many is not a search for each
|
|
15
16
|
const tweenActive = [];
|
|
16
17
|
const tweenUpdateList = []; // the tweens an update moves, the ones active when it began
|
|
17
18
|
let tweenUpdatePass = 0; // counts the updates, a tween started during one waits for the next
|
|
@@ -22,14 +23,10 @@ function tweenActivate(tween)
|
|
|
22
23
|
tween.activePass = tweenUpdatePass; // started again, even while active, so this update leaves it alone
|
|
23
24
|
if (tween.active) return;
|
|
24
25
|
tween.active = true;
|
|
25
|
-
tweenActive.push(tween);
|
|
26
|
-
|
|
27
|
-
function tweenDeactivate(tween)
|
|
28
|
-
{
|
|
29
|
-
if (!tween.active) return;
|
|
30
|
-
tween.active = false;
|
|
31
|
-
tweenActive.splice(tweenActive.indexOf(tween), 1);
|
|
26
|
+
tween.listed || tweenActive.push(tween); // one stopped this update is still listed, in its place
|
|
27
|
+
tween.listed = true;
|
|
32
28
|
}
|
|
29
|
+
function tweenDeactivate(tween) { tween.active = false; }
|
|
33
30
|
|
|
34
31
|
// True if the value is an instance of a class that exposes a numeric-percent
|
|
35
32
|
// `lerp(other, percent)` method (Vector2, Color, or any future class).
|
|
@@ -57,9 +54,9 @@ class Tween
|
|
|
57
54
|
* callback receives the interpolated value (a number, or a fresh instance
|
|
58
55
|
* for lerp-able types). Both endpoints must be the same type.
|
|
59
56
|
* @param {function(NonNullable<T>):void} callback - Called with the interpolated value each frame
|
|
60
|
-
* @param {T} [start
|
|
61
|
-
* @param {T} [end
|
|
62
|
-
* @param {number} [duration
|
|
57
|
+
* @param {T} [start] - Starting value
|
|
58
|
+
* @param {T} [end] - Ending value
|
|
59
|
+
* @param {number} [duration] - Duration in seconds
|
|
63
60
|
* @param {Object} [options]
|
|
64
61
|
* @param {function(number):number} [options.ease] - Easing function (defaults to LINEAR)
|
|
65
62
|
* @param {boolean} [options.useRealTime=false] - Advance even when the game is paused (matches Timer's useRealTime)
|
|
@@ -111,9 +108,12 @@ class Tween
|
|
|
111
108
|
/** Remaining iterations including the current run (loop/pingPong only).
|
|
112
109
|
* @private */
|
|
113
110
|
this.loopRemaining = 0;
|
|
114
|
-
/** Whether it is
|
|
111
|
+
/** Whether it is running, see isActive
|
|
115
112
|
* @private */
|
|
116
113
|
this.active = false;
|
|
114
|
+
/** Whether it is in the active list, which a stopped one leaves at the next update
|
|
115
|
+
* @private */
|
|
116
|
+
this.listed = false;
|
|
117
117
|
/** The update it was started in, it first moves on the one after
|
|
118
118
|
* @private */
|
|
119
119
|
this.activePass = 0;
|
|
@@ -134,7 +134,7 @@ class Tween
|
|
|
134
134
|
|
|
135
135
|
/** Set the easing curve and return this for chaining.
|
|
136
136
|
* @param {function(number):number} easeFn
|
|
137
|
-
* @
|
|
137
|
+
* @return {Tween<T>} */
|
|
138
138
|
setEase(easeFn)
|
|
139
139
|
{
|
|
140
140
|
this.ease = easeFn;
|
|
@@ -149,7 +149,7 @@ class Tween
|
|
|
149
149
|
* - It is kept by `restart`, so a restarted tween calls it again when it completes
|
|
150
150
|
* - `stop` and `tweenStopAll` end a tween without calling it
|
|
151
151
|
* @param {function():void} callback
|
|
152
|
-
* @
|
|
152
|
+
* @return {Tween<T>} */
|
|
153
153
|
then(callback)
|
|
154
154
|
{
|
|
155
155
|
this.onComplete = callback;
|
|
@@ -165,7 +165,7 @@ class Tween
|
|
|
165
165
|
* A `then` callback, set before or after, is called when the last
|
|
166
166
|
* iteration ends.
|
|
167
167
|
* @param {number} [count=Infinity]
|
|
168
|
-
* @
|
|
168
|
+
* @return {Tween<T>} */
|
|
169
169
|
loop(count = Infinity)
|
|
170
170
|
{
|
|
171
171
|
this.loopRemaining = count;
|
|
@@ -180,7 +180,7 @@ class Tween
|
|
|
180
180
|
* A `then` callback, set before or after, is called when the last
|
|
181
181
|
* iteration ends.
|
|
182
182
|
* @param {number} [count=Infinity]
|
|
183
|
-
* @
|
|
183
|
+
* @return {Tween<T>} */
|
|
184
184
|
pingPong(count = Infinity)
|
|
185
185
|
{
|
|
186
186
|
this.loopRemaining = count;
|
|
@@ -213,7 +213,7 @@ class Tween
|
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
/** True if this tween is in the active list and not paused.
|
|
216
|
-
* @
|
|
216
|
+
* @return {boolean} */
|
|
217
217
|
isActive()
|
|
218
218
|
{
|
|
219
219
|
return !this.paused && this.active;
|
|
@@ -221,7 +221,7 @@ class Tween
|
|
|
221
221
|
|
|
222
222
|
/** Get how far this tween has progressed, from 0 (just started) to 1
|
|
223
223
|
* (completed). Clamped — overshoot past completion still reads 1.
|
|
224
|
-
* @
|
|
224
|
+
* @return {number} */
|
|
225
225
|
getPercent()
|
|
226
226
|
{
|
|
227
227
|
return percent(this.duration - this.life, 0, this.duration);
|
|
@@ -230,7 +230,7 @@ class Tween
|
|
|
230
230
|
/** Get the current interpolated value (the value most recently passed to
|
|
231
231
|
* the callback). Returns a number, Vector2, Vector3 or Color depending on the
|
|
232
232
|
* tween's start/end types.
|
|
233
|
-
* @
|
|
233
|
+
* @return {T} */
|
|
234
234
|
getValue()
|
|
235
235
|
{
|
|
236
236
|
return this.interp(this.life);
|
|
@@ -242,7 +242,7 @@ class Tween
|
|
|
242
242
|
* - A vector goes past its ends as far as the easing does, as a number does; a Color stays between them,
|
|
243
243
|
* so its channels stay in range, and any other type goes as far as its own lerp takes it
|
|
244
244
|
* @param {number} life
|
|
245
|
-
* @
|
|
245
|
+
* @return {T} */
|
|
246
246
|
interp(life)
|
|
247
247
|
{
|
|
248
248
|
// the ends of whatever type it tweens, each kind is handled below
|
|
@@ -285,44 +285,44 @@ const Ease =
|
|
|
285
285
|
{
|
|
286
286
|
/** Linear (identity) curve.
|
|
287
287
|
* @param {number} x
|
|
288
|
-
* @
|
|
288
|
+
* @return {number}
|
|
289
289
|
* @memberof TweenSystem.Ease */
|
|
290
290
|
LINEAR: (x) => x,
|
|
291
291
|
|
|
292
292
|
/** Power curve factory: `Ease.POWER(n)` returns `x => x**n`.
|
|
293
293
|
* Use n=2 for quadratic, n=3 for cubic, etc.
|
|
294
294
|
* @param {number} n
|
|
295
|
-
* @
|
|
295
|
+
* @return {function(number):number}
|
|
296
296
|
* @memberof TweenSystem.Ease */
|
|
297
297
|
POWER: (n) => (x) => x ** n,
|
|
298
298
|
|
|
299
299
|
/** Sine ease-in curve: starts slow, ends fast.
|
|
300
300
|
* @param {number} x
|
|
301
|
-
* @
|
|
301
|
+
* @return {number}
|
|
302
302
|
* @memberof TweenSystem.Ease */
|
|
303
303
|
SINE: (x) => 1 - cos(x * (PI / 2)),
|
|
304
304
|
|
|
305
305
|
/** Circular ease-in curve.
|
|
306
306
|
* @param {number} x
|
|
307
|
-
* @
|
|
307
|
+
* @return {number}
|
|
308
308
|
* @memberof TweenSystem.Ease */
|
|
309
309
|
CIRC: (x) => 1 - (1 - x * x)**.5,
|
|
310
310
|
|
|
311
311
|
/** Exponential ease-in curve (`2^(10x-10)`).
|
|
312
312
|
* @param {number} x
|
|
313
|
-
* @
|
|
313
|
+
* @return {number}
|
|
314
314
|
* @memberof TweenSystem.Ease */
|
|
315
315
|
EXPO: (x) => x === 0 ? 0 : 2 ** (10 * x - 10),
|
|
316
316
|
|
|
317
317
|
/** Back ease-in: overshoots backward at the start before snapping forward.
|
|
318
318
|
* @param {number} x
|
|
319
|
-
* @
|
|
319
|
+
* @return {number}
|
|
320
320
|
* @memberof TweenSystem.Ease */
|
|
321
321
|
BACK: (x) => x * x * (2.70158 * x - 1.70158),
|
|
322
322
|
|
|
323
323
|
/** Elastic ease-in: oscillations that grow toward the end.
|
|
324
324
|
* @param {number} x
|
|
325
|
-
* @
|
|
325
|
+
* @return {number}
|
|
326
326
|
* @memberof TweenSystem.Ease */
|
|
327
327
|
ELASTIC: (x) =>
|
|
328
328
|
x === 0 ? 0 :
|
|
@@ -332,7 +332,7 @@ const Ease =
|
|
|
332
332
|
/** Spring ease-in: wobbles around the start before springing to the end;
|
|
333
333
|
* `Ease.OUT(Ease.SPRING)` overshoots and settles on the target.
|
|
334
334
|
* @param {number} x
|
|
335
|
-
* @
|
|
335
|
+
* @return {number}
|
|
336
336
|
* @memberof TweenSystem.Ease */
|
|
337
337
|
SPRING: (x) =>
|
|
338
338
|
1 -
|
|
@@ -346,7 +346,7 @@ const Ease =
|
|
|
346
346
|
* classic "object falls and hits the ground" shape (bounces near x=1),
|
|
347
347
|
* wrap with `Ease.OUT`: `Ease.OUT(Ease.BOUNCE)`.
|
|
348
348
|
* @param {number} x
|
|
349
|
-
* @
|
|
349
|
+
* @return {number}
|
|
350
350
|
* @memberof TweenSystem.Ease
|
|
351
351
|
* @example
|
|
352
352
|
* Ease.BOUNCE // ease-in bounce (bouncy at start)
|
|
@@ -369,7 +369,7 @@ const Ease =
|
|
|
369
369
|
* convention, so wrapping a curve in `IN` is a no-op — useful when
|
|
370
370
|
* picking the direction programmatically.
|
|
371
371
|
* @param {function(number):number} f - Curve to use as ease-in (returned unchanged)
|
|
372
|
-
* @
|
|
372
|
+
* @return {function(number):number}
|
|
373
373
|
* @memberof TweenSystem.Ease
|
|
374
374
|
* @example
|
|
375
375
|
* // Pick direction at runtime
|
|
@@ -380,7 +380,7 @@ const Ease =
|
|
|
380
380
|
|
|
381
381
|
/** Reverse a curve so it eases out instead of in: `x => 1 - f(1 - x)`.
|
|
382
382
|
* @param {function(number):number} f
|
|
383
|
-
* @
|
|
383
|
+
* @return {function(number):number}
|
|
384
384
|
* @memberof TweenSystem.Ease
|
|
385
385
|
* @example
|
|
386
386
|
* Ease.OUT(Ease.POWER(2)) // ease-out quadratic
|
|
@@ -389,7 +389,7 @@ const Ease =
|
|
|
389
389
|
|
|
390
390
|
/** Combine the first half of `f` with `Ease.OUT(f)` for a symmetric curve.
|
|
391
391
|
* @param {function(number):number} f
|
|
392
|
-
* @
|
|
392
|
+
* @return {function(number):number}
|
|
393
393
|
* @memberof TweenSystem.Ease */
|
|
394
394
|
IN_OUT: (f) => Ease.PIECEWISE(f, Ease.OUT(f)),
|
|
395
395
|
|
|
@@ -397,7 +397,7 @@ const Ease =
|
|
|
397
397
|
* Each curve is mapped to its section: section i runs over [i/n, (i+1)/n]
|
|
398
398
|
* and its output is mapped to [i/n, (i+1)/n] of the overall range.
|
|
399
399
|
* @param {...function(number):number} fns
|
|
400
|
-
* @
|
|
400
|
+
* @return {function(number):number}
|
|
401
401
|
* @memberof TweenSystem.Ease */
|
|
402
402
|
PIECEWISE: (...fns) =>
|
|
403
403
|
{
|
|
@@ -415,7 +415,7 @@ const Ease =
|
|
|
415
415
|
* @param {number} y1
|
|
416
416
|
* @param {number} x2
|
|
417
417
|
* @param {number} y2
|
|
418
|
-
* @
|
|
418
|
+
* @return {function(number):number}
|
|
419
419
|
* @memberof TweenSystem.Ease
|
|
420
420
|
* @example
|
|
421
421
|
* Ease.BEZIER(0.25, 0.1, 0.25, 1) // CSS "ease"
|
|
@@ -465,12 +465,12 @@ const Ease =
|
|
|
465
465
|
* @param {string} propertyPath - Dot-separated path, e.g. `'pos.x'` or `'color'`
|
|
466
466
|
* @param {T} start - Starting value
|
|
467
467
|
* @param {T} end - Ending value
|
|
468
|
-
* @param {number} [duration
|
|
468
|
+
* @param {number} [duration] - Duration in seconds
|
|
469
469
|
* @param {Object} [options] - Same options as the Tween constructor
|
|
470
470
|
* @param {function(number):number} [options.ease] - Easing function (defaults to LINEAR)
|
|
471
471
|
* @param {boolean} [options.useRealTime=false] - Advance even when the game is paused
|
|
472
472
|
* @param {boolean} [options.paused=false] - Start in paused state
|
|
473
|
-
* @
|
|
473
|
+
* @return {Tween<T>}
|
|
474
474
|
* @memberof TweenSystem
|
|
475
475
|
* @example
|
|
476
476
|
* // Numeric: slide an object's x with an ease-out sine curve
|
|
@@ -591,8 +591,13 @@ function tweenUpdate(gameDelta, realDelta)
|
|
|
591
591
|
// from the next update. Newest first, as the list has always been walked.
|
|
592
592
|
// a callback that calls tweenUpdate itself gets a list of its own, the outer update is still walking this one
|
|
593
593
|
const list = tweenUpdateList.length ? [] : tweenUpdateList, pass = ++tweenUpdatePass;
|
|
594
|
+
let kept = 0;
|
|
594
595
|
for (const t of tweenActive)
|
|
595
|
-
|
|
596
|
+
if (t.active)
|
|
597
|
+
list.push(tweenActive[kept++] = t);
|
|
598
|
+
else
|
|
599
|
+
t.listed = false; // stopped since the last update, out of the list now
|
|
600
|
+
tweenActive.length = kept;
|
|
596
601
|
// the list is let go however the walk ends: a callback that throws must not leave it held, or every
|
|
597
602
|
// update after would take it for an update still going and make a list of its own
|
|
598
603
|
try
|
|
@@ -645,7 +650,7 @@ function tweenUpdate(gameDelta, realDelta)
|
|
|
645
650
|
function tweenStopAll()
|
|
646
651
|
{
|
|
647
652
|
for (const t of tweenActive)
|
|
648
|
-
t.thenCallback = undefined, t.active = false;
|
|
653
|
+
t.thenCallback = undefined, t.active = t.listed = false;
|
|
649
654
|
tweenActive.length = 0;
|
|
650
655
|
}
|
|
651
656
|
|
package/plugins/uiSystem.js
CHANGED
|
@@ -35,8 +35,14 @@ let uiDebug = 0;
|
|
|
35
35
|
function uiSetDebug(debugMode)
|
|
36
36
|
{ uiDebug = typeof debugMode === 'boolean' ? (debugMode ? 1 : 0) : debugMode; }
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* @callback DragAndDropCallback - Callback for drag and drop events
|
|
40
|
+
* @param {DragEvent} event - The drag event
|
|
41
|
+
* @memberof UISystem
|
|
42
|
+
*/
|
|
43
|
+
|
|
38
44
|
///////////////////////////////////////////////////////////////////////////////
|
|
39
|
-
/**
|
|
45
|
+
/**
|
|
40
46
|
* UI System Global Object
|
|
41
47
|
* @memberof UISystem
|
|
42
48
|
*/
|
|
@@ -513,7 +519,7 @@ class UISystemPlugin
|
|
|
513
519
|
* @param {'left'|'center'|'right'} [align]
|
|
514
520
|
* @param {string} [font=uiSystem.defaultFont]
|
|
515
521
|
* @param {string} [fontStyle]
|
|
516
|
-
* @param {boolean} [applyMaxWidth
|
|
522
|
+
* @param {boolean} [applyMaxWidth]
|
|
517
523
|
* @param {Vector2} [textShadow]
|
|
518
524
|
* @param {Color} [shadowColor]
|
|
519
525
|
* @param {number} [shadowBlur]
|
|
@@ -528,12 +534,6 @@ class UISystemPlugin
|
|
|
528
534
|
context.shadowColor = '#0000';
|
|
529
535
|
}
|
|
530
536
|
|
|
531
|
-
/**
|
|
532
|
-
* @callback DragAndDropCallback - Callback for drag and drop events
|
|
533
|
-
* @param {DragEvent} event - The drag event
|
|
534
|
-
* @memberof UISystem
|
|
535
|
-
*/
|
|
536
|
-
|
|
537
537
|
/** Setup drag and drop event handlers
|
|
538
538
|
* Automatically prevents defaults and calls the given functions
|
|
539
539
|
* @param {DragAndDropCallback} [onDrop] - when a file is dropped
|
|
@@ -1212,19 +1212,24 @@ class UIObject
|
|
|
1212
1212
|
/** Called when the navigation button is pressed on this object */
|
|
1213
1213
|
navigatePressed() { this.click(); }
|
|
1214
1214
|
|
|
1215
|
-
/**
|
|
1215
|
+
/** Is the mouse hovering over this element
|
|
1216
|
+
* @return {boolean} */
|
|
1216
1217
|
isHoverObject() { return uiSystem.hoverObject === this; }
|
|
1217
1218
|
|
|
1218
|
-
/**
|
|
1219
|
+
/** Is the mouse held onto this element
|
|
1220
|
+
* @return {boolean} */
|
|
1219
1221
|
isActiveObject() { return uiSystem.activeObject === this; }
|
|
1220
1222
|
|
|
1221
|
-
/**
|
|
1223
|
+
/** Is the gamepad or keyboard navigation object
|
|
1224
|
+
* @return {boolean} */
|
|
1222
1225
|
isNavigationObject() { return uiSystem.navigationObject === this; }
|
|
1223
1226
|
|
|
1224
|
-
/**
|
|
1227
|
+
/** Is this object in keyboard input mode
|
|
1228
|
+
* @return {boolean} */
|
|
1225
1229
|
isKeyInputObject() { return uiSystem.keyInputObject === this; }
|
|
1226
1230
|
|
|
1227
|
-
/**
|
|
1231
|
+
/** Can it be interacted with, it and every parent visible and enabled
|
|
1232
|
+
* @return {boolean} */
|
|
1228
1233
|
isInteractive() { return this.interactive && uiObjectIsUsable(this); }
|
|
1229
1234
|
|
|
1230
1235
|
/** Returns string containing info about this object for debugging
|
|
@@ -1755,9 +1760,9 @@ class UIVideo extends UIObject
|
|
|
1755
1760
|
* @param {Vector2} pos
|
|
1756
1761
|
* @param {Vector2} size
|
|
1757
1762
|
* @param {string} src - Video file path or URL
|
|
1758
|
-
* @param {boolean} [autoplay
|
|
1759
|
-
* @param {boolean} [loop
|
|
1760
|
-
* @param {number} [volume
|
|
1763
|
+
* @param {boolean} [autoplay] - Start playing immediately?
|
|
1764
|
+
* @param {boolean} [loop] - Loop the video?
|
|
1765
|
+
* @param {number} [volume] - Volume percent scaled by global volume (0-1)
|
|
1761
1766
|
*/
|
|
1762
1767
|
constructor(pos, size, src, autoplay=false, loop=false, volume=1)
|
|
1763
1768
|
{
|
|
@@ -1912,10 +1917,10 @@ class UILayout extends UIObject
|
|
|
1912
1917
|
{
|
|
1913
1918
|
/** Create a UILayout container that auto-arranges children
|
|
1914
1919
|
* @param {Vector2} [pos]
|
|
1915
|
-
* @param {number} [columns
|
|
1916
|
-
* @param {number} [gap
|
|
1917
|
-
* @param {number} [padding
|
|
1918
|
-
* @param {boolean} [transparent
|
|
1920
|
+
* @param {number} [columns] - Number of columns (1 = vertical list)
|
|
1921
|
+
* @param {number} [gap] - Space between children
|
|
1922
|
+
* @param {number} [padding] - Space between container border and children
|
|
1923
|
+
* @param {boolean} [transparent] - If true, draws no background, outline, or shadow
|
|
1919
1924
|
*/
|
|
1920
1925
|
constructor(pos, columns=1, gap=10, padding=10, transparent=false)
|
|
1921
1926
|
{
|
package/src/engine.js
CHANGED
|
@@ -32,7 +32,7 @@ const engineName = 'LittleJS';
|
|
|
32
32
|
* @type {string}
|
|
33
33
|
* @default
|
|
34
34
|
* @memberof Engine */
|
|
35
|
-
const engineVersion = '1.
|
|
35
|
+
const engineVersion = '1.25.0';
|
|
36
36
|
|
|
37
37
|
/** Frames per second to update
|
|
38
38
|
* @type {number}
|
|
@@ -319,7 +319,8 @@ function engineLoadingScreenDraw(elapsed)
|
|
|
319
319
|
* ()=> { drawHUD(); }, // gameRenderPost
|
|
320
320
|
* ['tiles.png', 'tilesLevel.png'] // images to load
|
|
321
321
|
* );
|
|
322
|
-
* @memberof Engine
|
|
322
|
+
* @memberof Engine
|
|
323
|
+
* @return {Promise<void>} - Done when the images have loaded and gameInit has run */
|
|
323
324
|
async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, imageSources=[], rootElement)
|
|
324
325
|
{
|
|
325
326
|
showEngineVersion && console.log(`${engineName} Engine v${engineVersion}`);
|
|
@@ -819,9 +820,12 @@ function engineObjectsUpdate()
|
|
|
819
820
|
const start = engineChildStack.length;
|
|
820
821
|
for (const child of children)
|
|
821
822
|
engineChildStack.push(child);
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
823
|
+
try
|
|
824
|
+
{
|
|
825
|
+
for (let i = start; i < engineChildStack.length; ++i)
|
|
826
|
+
updateChildObject(engineChildStack[i]);
|
|
827
|
+
}
|
|
828
|
+
finally { engineChildStack.length = start; } // put back when an update throws too, or it keeps them
|
|
825
829
|
}
|
|
826
830
|
const pass = engineObjectsUpdateCount;
|
|
827
831
|
function updateChildObject(o)
|
package/src/engineAudio.js
CHANGED
|
@@ -20,6 +20,9 @@
|
|
|
20
20
|
* @memberof Audio */
|
|
21
21
|
let audioContext = typeof AudioContext == 'undefined' ? undefined : new AudioContext;
|
|
22
22
|
|
|
23
|
+
// resume the audio, a refusal caught so it is not an uncaught error in the console, the next gesture tries again
|
|
24
|
+
function audioResume() { audioContext?.resume()?.catch?.(()=> {}); }
|
|
25
|
+
|
|
23
26
|
/** Master gain node for all audio to pass through, made at load so effects can connect to it any time
|
|
24
27
|
* @type {GainNode}
|
|
25
28
|
* @memberof Audio */
|
|
@@ -76,6 +79,7 @@ function audioSetSession()
|
|
|
76
79
|
let audioSuspendedWhenHidden = false;
|
|
77
80
|
function audioVisibilityChange()
|
|
78
81
|
{
|
|
82
|
+
if (!audioContext) return; // a browser with no audio has none to pause
|
|
79
83
|
if (document.hidden)
|
|
80
84
|
{
|
|
81
85
|
if (!soundPauseWhenHidden || audioContext.state != 'running') return;
|
|
@@ -85,7 +89,7 @@ function audioVisibilityChange()
|
|
|
85
89
|
else if (audioSuspendedWhenHidden)
|
|
86
90
|
{
|
|
87
91
|
audioSuspendedWhenHidden = false;
|
|
88
|
-
|
|
92
|
+
audioResume();
|
|
89
93
|
}
|
|
90
94
|
}
|
|
91
95
|
|
|
@@ -224,7 +228,7 @@ function audioParamRamp(param, value, fadeTime=0)
|
|
|
224
228
|
class Sound
|
|
225
229
|
{
|
|
226
230
|
/** Create a sound object and cache the audio for later use
|
|
227
|
-
* @param {string|URL|Array} [asset] - Filename or URL of an audio file, or a zzfx array
|
|
231
|
+
* @param {string|URL|Array<number|undefined>} [asset] - Filename or URL of an audio file, or a zzfx array
|
|
228
232
|
* @param {number} [randomness] - How much to randomize frequency each time sound plays, for zzfx sounds it overrides the array's own randomness, which is used if undefined
|
|
229
233
|
* @param {number} [range=soundDefaultRange] - World space max range of sound
|
|
230
234
|
* @param {number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering
|
|
@@ -795,7 +799,7 @@ function getNoteFrequency(semitoneOffset, rootFrequency=220)
|
|
|
795
799
|
* @param {number} [rate] - The playback rate to use
|
|
796
800
|
* @param {number} [pan] - How much to apply stereo panning
|
|
797
801
|
* @param {boolean} [loop] - True if the sound should loop when it reaches the end
|
|
798
|
-
* @param {number} [sampleRate=
|
|
802
|
+
* @param {number} [sampleRate=audioDefaultSampleRate] - Sample rate for the sound
|
|
799
803
|
* @param {GainNode} [gainNode] - Optional gain node for volume control while playing (disconnected when the sound ends)
|
|
800
804
|
* @param {number} [offset] - Where to start in the sound, in its own seconds whatever the rate
|
|
801
805
|
* @param {AudioEndedCallback} [onended] - Callback for when the sound ends
|
|
@@ -812,7 +816,7 @@ function playSamples(sampleChannels, volume=1, rate=1, pan=0, loop=false, sample
|
|
|
812
816
|
// fix stalled audio, don't build a buffer that can't be played;
|
|
813
817
|
// but a context suspended because the page is hidden stays suspended until it shows
|
|
814
818
|
if (!audioSuspendedWhenHidden)
|
|
815
|
-
|
|
819
|
+
audioResume();
|
|
816
820
|
return;
|
|
817
821
|
}
|
|
818
822
|
|
|
@@ -822,7 +826,7 @@ function playSamples(sampleChannels, volume=1, rate=1, pan=0, loop=false, sample
|
|
|
822
826
|
|
|
823
827
|
/** Copy arrays of samples into a new audio buffer
|
|
824
828
|
* @param {Array} sampleChannels - Array of arrays of samples (for stereo playback)
|
|
825
|
-
* @param {number} [sampleRate=
|
|
829
|
+
* @param {number} [sampleRate=audioDefaultSampleRate] - Sample rate for the sound
|
|
826
830
|
* @return {AudioBuffer} - The audio buffer holding the samples
|
|
827
831
|
* @memberof Audio */
|
|
828
832
|
function createAudioBuffer(sampleChannels, sampleRate=audioDefaultSampleRate)
|
|
@@ -857,7 +861,7 @@ function playAudioBuffer(buffer, volume=1, rate=1, pan=0, loop=false, gainNode,
|
|
|
857
861
|
// fix stalled audio, this sound won't be able to play;
|
|
858
862
|
// but a context suspended because the page is hidden stays suspended until it shows
|
|
859
863
|
if (!audioSuspendedWhenHidden)
|
|
860
|
-
|
|
864
|
+
audioResume();
|
|
861
865
|
return;
|
|
862
866
|
}
|
|
863
867
|
|
package/src/engineDebug.js
CHANGED
|
@@ -94,7 +94,7 @@ function LOG(...output) { console.log(...output); }
|
|
|
94
94
|
|
|
95
95
|
/** Draw a debug rectangle in world space, or on the screen with screenSpace
|
|
96
96
|
* @param {Vector2} pos
|
|
97
|
-
* @param {Vector2} [size=vec2(
|
|
97
|
+
* @param {Vector2} [size=vec2()]
|
|
98
98
|
* @param {Color|string} [color]
|
|
99
99
|
* @param {number} [time]
|
|
100
100
|
* @param {number} [angle]
|
|
@@ -766,7 +766,8 @@ function debugRenderPost() { debugVideoCaptureIsActive() && debugVideoCaptureUpd
|
|
|
766
766
|
let debugVideoCapture, debugVideoCaptureIcon;
|
|
767
767
|
|
|
768
768
|
/** Check if video capture is active
|
|
769
|
-
* @memberof Debug
|
|
769
|
+
* @memberof Debug
|
|
770
|
+
* @return {boolean} */
|
|
770
771
|
function debugVideoCaptureIsActive() { return !!debugVideoCapture; }
|
|
771
772
|
|
|
772
773
|
/** Start capturing video
|
package/src/engineDraw.js
CHANGED
|
@@ -105,7 +105,7 @@ function isBlack(c) { return c.r <= 0 && c.g <= 0 && c.b <= 0 && c.a <= 0; }
|
|
|
105
105
|
* Create a tile info object using a grid based system
|
|
106
106
|
* - This can take vecs or floats for easier use and conversion
|
|
107
107
|
* - If an index is passed in, the tile size and index will determine the position
|
|
108
|
-
* @param {Vector2|number} [index
|
|
108
|
+
* @param {Vector2|number} [index] - Index of the tile in 1d or 2d form
|
|
109
109
|
* @param {Vector2|number} [size] - Size of tile in pixels
|
|
110
110
|
* @param {TextureInfo|number} [texture] - Texture index or info to use
|
|
111
111
|
* @param {number} [padding] - How many pixels padding around tiles
|
|
@@ -589,10 +589,10 @@ class Shader
|
|
|
589
589
|
* @param {TileInfo} [tileInfo] - Tile info to use, untextured if undefined
|
|
590
590
|
* @param {Color} [color=WHITE] - Color to modulate with
|
|
591
591
|
* @param {number} [angle] - Angle to rotate by
|
|
592
|
-
* @param {boolean} [mirror] - Is image flipped
|
|
592
|
+
* @param {boolean} [mirror] - Is the image flipped left to right?
|
|
593
593
|
* @param {Color} [additiveColor] - Additive color to be applied if any
|
|
594
594
|
* @param {boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering?
|
|
595
|
-
* @param {boolean} [screenSpace=drawScreenSpace] - Are the pos and size
|
|
595
|
+
* @param {boolean} [screenSpace=drawScreenSpace] - Are the pos and size in screen space?
|
|
596
596
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context] - Canvas 2D context to draw to
|
|
597
597
|
* @memberof Draw */
|
|
598
598
|
function drawTile(pos, size=vec2(1), tileInfo, color=WHITE,
|
|
@@ -762,9 +762,9 @@ function drawRectGradient(pos, size=vec2(1), colorTop=WHITE, colorBottom=CLEAR_W
|
|
|
762
762
|
* @param {Vector2} pos - Center of the rect in world space
|
|
763
763
|
* @param {Vector2} size - Size of the rect in world space
|
|
764
764
|
* @param {Vector2} wrapCount - How many times the texture repeats (x, y)
|
|
765
|
-
* @param {TextureInfo|number} [texture
|
|
765
|
+
* @param {TextureInfo|number} [texture] - TextureInfo or texture index into textureInfos
|
|
766
766
|
* @param {Color} [color=WHITE] - Color to modulate with
|
|
767
|
-
* @param {number} [angle
|
|
767
|
+
* @param {number} [angle] - Angle to rotate by
|
|
768
768
|
* @param {Color} [additiveColor] - Additive color to be applied if any
|
|
769
769
|
* @param {boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering?
|
|
770
770
|
* @param {boolean} [screenSpace=drawScreenSpace] - Are pos and size in screen space?
|
|
@@ -1106,9 +1106,9 @@ function drawEllipse(pos, size=vec2(1), color=WHITE, angle=0, lineWidth=0, lineC
|
|
|
1106
1106
|
|
|
1107
1107
|
/** Draw colored circle using passed in point
|
|
1108
1108
|
* @param {Vector2} pos
|
|
1109
|
-
* @param {number} [size
|
|
1109
|
+
* @param {number} [size] - Diameter
|
|
1110
1110
|
* @param {Color} [color=WHITE]
|
|
1111
|
-
* @param {number} [lineWidth
|
|
1111
|
+
* @param {number} [lineWidth]
|
|
1112
1112
|
* @param {Color} [lineColor=BLACK]
|
|
1113
1113
|
* @param {boolean} [useWebGL=glEnable]
|
|
1114
1114
|
* @param {boolean} [screenSpace=drawScreenSpace]
|
|
@@ -1203,7 +1203,7 @@ function drawEllipseGradient(pos, size=vec2(1), colorInner=WHITE, colorOuter=CLE
|
|
|
1203
1203
|
* - If drawing mostly textured sprites, bake the gradient into a texture and use drawTile instead
|
|
1204
1204
|
* - Stacking gradients at the exact same position may show a faint vertical artifact
|
|
1205
1205
|
* @param {Vector2} pos
|
|
1206
|
-
* @param {number} [size
|
|
1206
|
+
* @param {number} [size] - Diameter
|
|
1207
1207
|
* @param {Color} [colorInner=WHITE]
|
|
1208
1208
|
* @param {Color} [colorOuter=CLEAR_WHITE]
|
|
1209
1209
|
* @param {boolean} [useWebGL=glEnable]
|
|
@@ -1268,7 +1268,7 @@ function drawCanvas2D(pos, size, angle=0, mirror=false, drawFunction, screenSpac
|
|
|
1268
1268
|
* @param {Color} [color=WHITE]
|
|
1269
1269
|
* @param {number} [lineWidth]
|
|
1270
1270
|
* @param {Color} [lineColor=BLACK]
|
|
1271
|
-
* @param {'left'|'center'|'right'} [textAlign
|
|
1271
|
+
* @param {'left'|'center'|'right'} [textAlign]
|
|
1272
1272
|
* @param {string} [font=fontDefault]
|
|
1273
1273
|
* @param {string} [fontStyle]
|
|
1274
1274
|
* @param {number} [maxWidth]
|