littlejsengine 1.13.4 → 1.14.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/README.md +4 -3
- package/dist/littlejs.d.ts +395 -249
- package/dist/littlejs.esm.js +1550 -754
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +1528 -744
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +1504 -720
- package/examples/box2d/game.js +4 -4
- package/examples/box2d/gameObjects.js +1 -1
- package/examples/breakout/game.js +30 -25
- package/examples/breakoutTutorial/README.md +1 -1
- package/examples/breakoutTutorial/game.js +1 -1
- package/examples/electron/build.js +1 -1
- package/examples/electron/index.html +2 -2
- package/examples/empty/game.js +1 -1
- package/examples/htmlMenu/index.html +7 -7
- package/examples/index.html +208 -97
- package/examples/platformer/gameEffects.js +20 -25
- package/examples/platformer/gameLevel.js +6 -1
- package/examples/shorts/base.html +1 -1
- package/examples/shorts/flappyGame.js +2 -1
- package/examples/shorts/helloWorld.js +1 -1
- package/examples/shorts/music.js +106 -0
- package/examples/shorts/parallax.js +71 -0
- package/examples/shorts/piano.js +7 -8
- package/examples/shorts/postProcess.js +25 -8
- package/examples/shorts/shapes.js +12 -18
- package/examples/shorts/song.mp3 +0 -0
- package/examples/shorts/uiSystem.js +15 -8
- package/examples/starter/index.html +2 -2
- package/examples/stress/index.html +14 -7
- package/examples/style.css +14 -4
- package/examples/typescript/build.js +1 -1
- package/examples/uiSystem/game.js +11 -11
- package/package.json +1 -1
- package/plugins/box2d.js +12 -10
- package/plugins/drawUtilities.js +5 -5
- package/plugins/newgrounds.js +6 -6
- package/plugins/pluginExport.js +1 -1
- package/plugins/uiSystem.js +103 -79
- package/plugins/zzfxm.js +10 -10
- package/reference.md +94 -56
- package/src/engine.js +28 -24
- package/src/engineAudio.js +284 -109
- package/src/engineBuild.js +11 -11
- package/src/engineDebug.js +29 -29
- package/src/engineDraw.js +285 -112
- package/src/engineExport.js +28 -16
- package/src/engineInput.js +57 -67
- package/src/engineMedals.js +25 -25
- package/src/engineObject.js +28 -25
- package/src/engineParticles.js +59 -59
- package/src/engineRelease.js +1 -1
- package/src/engineSettings.js +20 -13
- package/src/engineTileLayer.js +34 -35
- package/src/engineUtilities.js +66 -59
- package/src/engineWebGL.js +466 -66
- /package/examples/shorts/{playSound.js → sound.js} +0 -0
package/src/engineUtilities.js
CHANGED
|
@@ -75,7 +75,19 @@ function lerp(valueA, valueB, percent)
|
|
|
75
75
|
if (valueA >= 0 && valueA <= 1 && ((valueB < 0 || valueB > 1) && (percent < 0 || percent > 1)))
|
|
76
76
|
console.warn('lerp() parameter order changed! use lerp(start, end, p)');
|
|
77
77
|
return valueA + clamp(percent) * (valueB-valueA);
|
|
78
|
-
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Gets percent between percentA and percentB and linearly interpolates between lerpA and lerpB
|
|
81
|
+
* A shortcut for lerp(lerpA, lerpB, percent(value, percentA, percentB))
|
|
82
|
+
* @param {number} value
|
|
83
|
+
* @param {number} percentA
|
|
84
|
+
* @param {number} percentB
|
|
85
|
+
* @param {number} lerpA
|
|
86
|
+
* @param {number} lerpB
|
|
87
|
+
* @return {number}
|
|
88
|
+
* @memberof Utilities */
|
|
89
|
+
function percentLerp(value, percentA, percentB, lerpA, lerpB)
|
|
90
|
+
{ return lerp(lerpA, lerpB, percent(value, percentA, percentB)); }
|
|
79
91
|
|
|
80
92
|
/** Returns signed wrapped distance between the two values passed in
|
|
81
93
|
* @param {number} valueA
|
|
@@ -127,7 +139,7 @@ function smoothStep(percent) { return percent * percent * (3 - 2 * percent); }
|
|
|
127
139
|
* @memberof Utilities */
|
|
128
140
|
function isPowerOfTwo(value) { return !(value & (value - 1)); }
|
|
129
141
|
|
|
130
|
-
/** Returns the nearest power of two not less
|
|
142
|
+
/** Returns the nearest power of two not less than the value
|
|
131
143
|
* @param {number} value
|
|
132
144
|
* @return {number}
|
|
133
145
|
* @memberof Utilities */
|
|
@@ -142,8 +154,8 @@ function nearestPowerOfTwo(value) { return 2**Math.ceil(Math.log2(value)); }
|
|
|
142
154
|
* @return {boolean} - True if overlapping
|
|
143
155
|
* @memberof Utilities */
|
|
144
156
|
function isOverlapping(posA, sizeA, posB, sizeB=vec2())
|
|
145
|
-
{
|
|
146
|
-
return abs(posA.x - posB.x)*2 < sizeA.x + sizeB.x
|
|
157
|
+
{
|
|
158
|
+
return abs(posA.x - posB.x)*2 < sizeA.x + sizeB.x
|
|
147
159
|
&& abs(posA.y - posB.y)*2 < sizeA.y + sizeB.y;
|
|
148
160
|
}
|
|
149
161
|
|
|
@@ -198,7 +210,7 @@ function isIntersecting(start, end, pos, size)
|
|
|
198
210
|
function wave(frequency=1, amplitude=1, t=time, offset=0)
|
|
199
211
|
{ return amplitude/2 * (1 - Math.cos(offset + t*frequency*2*PI)); }
|
|
200
212
|
|
|
201
|
-
/** Formats seconds to mm:ss style for display purposes
|
|
213
|
+
/** Formats seconds to mm:ss style for display purposes
|
|
202
214
|
* @param {number} t - time in seconds
|
|
203
215
|
* @return {string}
|
|
204
216
|
* @memberof Utilities */
|
|
@@ -214,13 +226,12 @@ async function fetchJSON(url)
|
|
|
214
226
|
return response.json();
|
|
215
227
|
}
|
|
216
228
|
|
|
217
|
-
/**
|
|
229
|
+
/**
|
|
218
230
|
* Check if object is a valid number, not NaN or undefined, but it may be infinite
|
|
219
231
|
* @param {any} n
|
|
220
232
|
* @return {boolean}
|
|
221
|
-
* @memberof Utilities
|
|
222
|
-
|
|
223
|
-
function isNumber(n) { return typeof n == 'number' && !isNaN(n); }
|
|
233
|
+
* @memberof Utilities */
|
|
234
|
+
function isNumber(n) { return typeof n === 'number' && !isNaN(n); }
|
|
224
235
|
|
|
225
236
|
///////////////////////////////////////////////////////////////////////////////
|
|
226
237
|
|
|
@@ -275,13 +286,13 @@ function randInCircle(radius=1, minRadius=0)
|
|
|
275
286
|
* @memberof Random */
|
|
276
287
|
function randColor(colorA=new Color, colorB=new Color(0,0,0,1), linear=false)
|
|
277
288
|
{
|
|
278
|
-
return linear ? colorA.lerp(colorB, rand()) :
|
|
289
|
+
return linear ? colorA.lerp(colorB, rand()) :
|
|
279
290
|
new Color(rand(colorA.r,colorB.r), rand(colorA.g,colorB.g), rand(colorA.b,colorB.b), rand(colorA.a,colorB.a));
|
|
280
291
|
}
|
|
281
292
|
|
|
282
293
|
///////////////////////////////////////////////////////////////////////////////
|
|
283
294
|
|
|
284
|
-
/**
|
|
295
|
+
/**
|
|
285
296
|
* Seeded random number generator
|
|
286
297
|
* - Can be used to create a deterministic random number sequence
|
|
287
298
|
* @example
|
|
@@ -308,8 +319,8 @@ class RandomGenerator
|
|
|
308
319
|
float(valueA=1, valueB=0)
|
|
309
320
|
{
|
|
310
321
|
// xorshift algorithm
|
|
311
|
-
this.seed ^= this.seed << 13;
|
|
312
|
-
this.seed ^= this.seed >>> 17;
|
|
322
|
+
this.seed ^= this.seed << 13;
|
|
323
|
+
this.seed ^= this.seed >>> 17;
|
|
313
324
|
this.seed ^= this.seed << 5;
|
|
314
325
|
return valueB + (valueA - valueB) * ((this.seed >>> 0) / 2**32);
|
|
315
326
|
}
|
|
@@ -358,28 +369,26 @@ class RandomGenerator
|
|
|
358
369
|
* let a = vec2(0, 1); // vector with coordinates (0, 1)
|
|
359
370
|
* a = vec2(5); // set a to (5, 5)
|
|
360
371
|
* b = vec2(); // set b to (0, 0)
|
|
361
|
-
* @memberof Utilities
|
|
362
|
-
*/
|
|
372
|
+
* @memberof Utilities */
|
|
363
373
|
function vec2(x=0, y) { return new Vector2(x, y === undefined ? x : y); }
|
|
364
374
|
|
|
365
|
-
/**
|
|
375
|
+
/**
|
|
366
376
|
* Check if object is a valid Vector2
|
|
367
377
|
* @param {any} v
|
|
368
378
|
* @return {boolean}
|
|
369
|
-
* @memberof Utilities
|
|
370
|
-
|
|
371
|
-
function isVector2(v) { return v instanceof Vector2; }
|
|
379
|
+
* @memberof Utilities */
|
|
380
|
+
function isVector2(v) { return v instanceof Vector2 && v.isValid(); }
|
|
372
381
|
|
|
373
382
|
// vector2 asserts
|
|
374
|
-
function ASSERT_VECTOR2_VALID(v) { ASSERT(isVector2(v)
|
|
383
|
+
function ASSERT_VECTOR2_VALID(v) { ASSERT(isVector2(v), 'Vector2 is invalid.', v); }
|
|
375
384
|
function ASSERT_NUMBER_VALID(n) { ASSERT(isNumber(n), 'Number is invalid.', n); }
|
|
376
385
|
function ASSERT_VECTOR2_NORMAL(v)
|
|
377
386
|
{
|
|
378
387
|
ASSERT_VECTOR2_VALID(v);
|
|
379
|
-
ASSERT(abs(v.lengthSquared()-1) < .01, 'Vector2 is not normal.', v);
|
|
388
|
+
ASSERT(abs(v.lengthSquared()-1) < .01, 'Vector2 is not normal.', v);
|
|
380
389
|
}
|
|
381
390
|
|
|
382
|
-
/**
|
|
391
|
+
/**
|
|
383
392
|
* 2D Vector object with vector math library
|
|
384
393
|
* - Functions do not change this so they can be chained together
|
|
385
394
|
* @example
|
|
@@ -503,7 +512,7 @@ class Vector2
|
|
|
503
512
|
* @param {number} [angle]
|
|
504
513
|
* @param {number} [length]
|
|
505
514
|
* @return {Vector2} */
|
|
506
|
-
setAngle(angle=0, length=1)
|
|
515
|
+
setAngle(angle=0, length=1)
|
|
507
516
|
{
|
|
508
517
|
ASSERT_NUMBER_VALID(angle);
|
|
509
518
|
ASSERT_NUMBER_VALID(length);
|
|
@@ -518,7 +527,7 @@ class Vector2
|
|
|
518
527
|
rotate(angle)
|
|
519
528
|
{
|
|
520
529
|
ASSERT_NUMBER_VALID(angle);
|
|
521
|
-
const c = Math.cos(-angle), s = Math.sin(-angle);
|
|
530
|
+
const c = Math.cos(-angle), s = Math.sin(-angle);
|
|
522
531
|
return new Vector2(this.x*c - this.y*s, this.x*s + this.y*c);
|
|
523
532
|
}
|
|
524
533
|
|
|
@@ -530,9 +539,9 @@ class Vector2
|
|
|
530
539
|
ASSERT_NUMBER_VALID(direction);
|
|
531
540
|
ASSERT_NUMBER_VALID(length);
|
|
532
541
|
direction = mod(direction, 4);
|
|
533
|
-
ASSERT(direction
|
|
542
|
+
ASSERT(direction===0 || direction===1 || direction===2 || direction===3,
|
|
534
543
|
'Vector2.setDirection() direction must be an integer between 0 and 3.');
|
|
535
|
-
return vec2(direction%2 ? direction-1 ? -length : length : 0,
|
|
544
|
+
return vec2(direction%2 ? direction-1 ? -length : length : 0,
|
|
536
545
|
direction%2 ? 0 : direction ? -length : length);
|
|
537
546
|
}
|
|
538
547
|
|
|
@@ -584,7 +593,7 @@ class Vector2
|
|
|
584
593
|
/** Returns this vector expressed as a string
|
|
585
594
|
* @param {number} digits - precision to display
|
|
586
595
|
* @return {string} */
|
|
587
|
-
toString(digits=3)
|
|
596
|
+
toString(digits=3)
|
|
588
597
|
{
|
|
589
598
|
ASSERT_NUMBER_VALID(digits);
|
|
590
599
|
if (debug)
|
|
@@ -603,7 +612,7 @@ class Vector2
|
|
|
603
612
|
|
|
604
613
|
///////////////////////////////////////////////////////////////////////////////
|
|
605
614
|
|
|
606
|
-
/**
|
|
615
|
+
/**
|
|
607
616
|
* Create a color object with RGBA values, white by default
|
|
608
617
|
* @param {number} [r=1] - red
|
|
609
618
|
* @param {number} [g=1] - green
|
|
@@ -614,29 +623,27 @@ class Vector2
|
|
|
614
623
|
*/
|
|
615
624
|
function rgb(r, g, b, a) { return new Color(r, g, b, a); }
|
|
616
625
|
|
|
617
|
-
/**
|
|
626
|
+
/**
|
|
618
627
|
* Create a color object with HSLA values, white by default
|
|
619
628
|
* @param {number} [h=0] - hue
|
|
620
629
|
* @param {number} [s=0] - saturation
|
|
621
630
|
* @param {number} [l=1] - lightness
|
|
622
631
|
* @param {number} [a=1] - alpha
|
|
623
632
|
* @return {Color}
|
|
624
|
-
* @memberof Utilities
|
|
625
|
-
*/
|
|
633
|
+
* @memberof Utilities */
|
|
626
634
|
function hsl(h, s, l, a) { return new Color().setHSLA(h, s, l, a); }
|
|
627
635
|
|
|
628
|
-
/**
|
|
636
|
+
/**
|
|
629
637
|
* Check if object is a valid Color
|
|
630
638
|
* @param {any} c
|
|
631
639
|
* @return {boolean}
|
|
632
|
-
* @memberof Utilities
|
|
633
|
-
|
|
634
|
-
function isColor(c) { return c instanceof Color; }
|
|
640
|
+
* @memberof Utilities */
|
|
641
|
+
function isColor(c) { return c instanceof Color && c.isValid(); }
|
|
635
642
|
|
|
636
643
|
// color asserts
|
|
637
|
-
function ASSERT_COLOR_VALID(c) { ASSERT(isColor(c)
|
|
644
|
+
function ASSERT_COLOR_VALID(c) { ASSERT(isColor(c), 'Color is invalid.', c); }
|
|
638
645
|
|
|
639
|
-
/**
|
|
646
|
+
/**
|
|
640
647
|
* Color object (red, green, blue, alpha) with some helpful functions
|
|
641
648
|
* @example
|
|
642
649
|
* let a = new Color; // white
|
|
@@ -708,7 +715,7 @@ class Color
|
|
|
708
715
|
* @param {number} scale
|
|
709
716
|
* @param {number} [alphaScale=scale]
|
|
710
717
|
* @return {Color} */
|
|
711
|
-
scale(scale, alphaScale=scale)
|
|
718
|
+
scale(scale, alphaScale=scale)
|
|
712
719
|
{ return new Color(this.r*scale, this.g*scale, this.b*scale, this.a*alphaScale); }
|
|
713
720
|
|
|
714
721
|
/** Returns a copy of this color clamped to the valid range between 0 and 1
|
|
@@ -725,9 +732,9 @@ class Color
|
|
|
725
732
|
ASSERT_NUMBER_VALID(percent);
|
|
726
733
|
const p = clamp(percent);
|
|
727
734
|
return new Color(
|
|
728
|
-
c.r*p + this.r*(1-p),
|
|
729
|
-
c.g*p + this.g*(1-p),
|
|
730
|
-
c.b*p + this.b*(1-p),
|
|
735
|
+
c.r*p + this.r*(1-p),
|
|
736
|
+
c.g*p + this.g*(1-p),
|
|
737
|
+
c.b*p + this.b*(1-p),
|
|
731
738
|
c.a*p + this.a*(1-p));
|
|
732
739
|
}
|
|
733
740
|
|
|
@@ -767,15 +774,15 @@ class Color
|
|
|
767
774
|
const minC = min(r, g, b);
|
|
768
775
|
const l = (maxC + minC) / 2;
|
|
769
776
|
let h = 0, s = 0;
|
|
770
|
-
if (maxC
|
|
777
|
+
if (maxC !== minC)
|
|
771
778
|
{
|
|
772
779
|
let d = maxC - minC;
|
|
773
780
|
s = l > .5 ? d / (2 - maxC - minC) : d / (maxC + minC);
|
|
774
|
-
if (r
|
|
781
|
+
if (r === maxC)
|
|
775
782
|
h = (g - b) / d + (g < b ? 6 : 0);
|
|
776
|
-
else if (g
|
|
783
|
+
else if (g === maxC)
|
|
777
784
|
h = (b - r) / d + 2;
|
|
778
|
-
else if (b
|
|
785
|
+
else if (b === maxC)
|
|
779
786
|
h = (r - g) / d + 4;
|
|
780
787
|
}
|
|
781
788
|
return [h / 6, s, l, a];
|
|
@@ -785,7 +792,7 @@ class Color
|
|
|
785
792
|
* @param {number} [amount]
|
|
786
793
|
* @param {number} [alphaAmount]
|
|
787
794
|
* @return {Color} */
|
|
788
|
-
mutate(amount=.05, alphaAmount=0)
|
|
795
|
+
mutate(amount=.05, alphaAmount=0)
|
|
789
796
|
{
|
|
790
797
|
ASSERT_NUMBER_VALID(amount);
|
|
791
798
|
ASSERT_NUMBER_VALID(alphaAmount);
|
|
@@ -801,47 +808,47 @@ class Color
|
|
|
801
808
|
/** Returns this color expressed as a hex color code
|
|
802
809
|
* @param {boolean} [useAlpha] - if alpha should be included in result
|
|
803
810
|
* @return {string} */
|
|
804
|
-
toString(useAlpha = true)
|
|
811
|
+
toString(useAlpha = true)
|
|
805
812
|
{
|
|
806
|
-
ASSERT(typeof useAlpha
|
|
813
|
+
ASSERT(typeof useAlpha === 'boolean', 'Use alpha boolean is invalid.', useAlpha);
|
|
807
814
|
if (debug && !this.isValid())
|
|
808
815
|
return `#000`;
|
|
809
816
|
const toHex = (c)=> ((c=clamp(c)*255|0)<16 ? '0' : '') + c.toString(16);
|
|
810
817
|
return '#' + toHex(this.r) + toHex(this.g) + toHex(this.b) + (useAlpha ? toHex(this.a) : '');
|
|
811
818
|
}
|
|
812
|
-
|
|
819
|
+
|
|
813
820
|
/** Set this color from a hex code
|
|
814
821
|
* @param {string} hex - html hex code
|
|
815
822
|
* @return {Color} */
|
|
816
823
|
setHex(hex)
|
|
817
824
|
{
|
|
818
|
-
ASSERT(typeof hex
|
|
825
|
+
ASSERT(typeof hex === 'string' && hex[0] === '#', 'Color hex code must be a string starting with #');
|
|
819
826
|
ASSERT([4,5,7,9].includes(hex.length), 'Invalid hex');
|
|
820
827
|
|
|
821
828
|
if (hex.length < 6)
|
|
822
829
|
{
|
|
823
830
|
const fromHex = (c)=> clamp(parseInt(hex[c],16)/15);
|
|
824
831
|
this.r = fromHex(1);
|
|
825
|
-
this.g = fromHex(2)
|
|
832
|
+
this.g = fromHex(2);
|
|
826
833
|
this.b = fromHex(3);
|
|
827
|
-
this.a = hex.length
|
|
834
|
+
this.a = hex.length === 5 ? fromHex(4) : 1;
|
|
828
835
|
}
|
|
829
836
|
else
|
|
830
837
|
{
|
|
831
838
|
const fromHex = (c)=> clamp(parseInt(hex.slice(c,c+2),16)/255);
|
|
832
839
|
this.r = fromHex(1);
|
|
833
|
-
this.g = fromHex(3)
|
|
840
|
+
this.g = fromHex(3);
|
|
834
841
|
this.b = fromHex(5);
|
|
835
|
-
this.a = hex.length
|
|
842
|
+
this.a = hex.length === 9 ? fromHex(7) : 1;
|
|
836
843
|
}
|
|
837
844
|
|
|
838
845
|
ASSERT_COLOR_VALID(this);
|
|
839
846
|
return this;
|
|
840
847
|
}
|
|
841
|
-
|
|
848
|
+
|
|
842
849
|
/** Returns this color expressed as 32 bit RGBA value
|
|
843
850
|
* @return {number} */
|
|
844
|
-
rgbaInt()
|
|
851
|
+
rgbaInt()
|
|
845
852
|
{
|
|
846
853
|
const r = clamp(this.r)*255|0;
|
|
847
854
|
const g = clamp(this.g)*255<<8;
|
|
@@ -862,7 +869,7 @@ class Color
|
|
|
862
869
|
/** Color - White #ffffff
|
|
863
870
|
* @type {Color}
|
|
864
871
|
* @memberof Utilities */
|
|
865
|
-
const WHITE = rgb();
|
|
872
|
+
const WHITE = rgb();
|
|
866
873
|
|
|
867
874
|
/** Color - Clear White #ffffff with 0 alpha
|
|
868
875
|
* @type {Color}
|
|
@@ -977,11 +984,11 @@ class Timer
|
|
|
977
984
|
/** Get percentage elapsed based on time it was set to, returns 0 if not set
|
|
978
985
|
* @return {number} */
|
|
979
986
|
getPercent() { return this.isSet()? 1-percent(this.time - time, 0, this.setTime) : 0; }
|
|
980
|
-
|
|
987
|
+
|
|
981
988
|
/** Returns this timer expressed as a string
|
|
982
989
|
* @return {string} */
|
|
983
990
|
toString() { if (debug) { return this.isSet() ? Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ) : 'unset'; }}
|
|
984
|
-
|
|
991
|
+
|
|
985
992
|
/** Get how long since elapsed, returns 0 if not set (returns negative if currently active)
|
|
986
993
|
* @return {number} */
|
|
987
994
|
valueOf() { return this.get(); }
|