littlejsengine 1.14.10 → 1.14.16

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 (76) hide show
  1. package/dist/littlejs.d.ts +264 -120
  2. package/dist/littlejs.esm.js +603 -288
  3. package/dist/littlejs.esm.min.js +1 -1
  4. package/dist/littlejs.js +600 -287
  5. package/dist/littlejs.min.js +1 -1
  6. package/dist/littlejs.release.js +521 -232
  7. package/examples/box2d/gameObjects.js +2 -2
  8. package/examples/breakout/gameObjects.js +2 -2
  9. package/examples/breakoutTutorial/README.md +32 -32
  10. package/examples/breakoutTutorial/game.js +1 -1
  11. package/examples/electron/game.js +3 -3
  12. package/examples/electron/index.html +2 -2
  13. package/examples/electron/package.json +1 -8
  14. package/examples/index.html +59 -51
  15. package/examples/module/game.js +3 -3
  16. package/examples/platformer/gameCharacter.js +6 -2
  17. package/examples/platformer/gameEffects.js +4 -4
  18. package/examples/platformer/gameLevel.js +1 -1
  19. package/examples/platformer/gameObjects.js +11 -9
  20. package/examples/puzzle/game.js +1 -1
  21. package/examples/shorts/animation.js +1 -1
  22. package/examples/shorts/base.html +1 -1
  23. package/examples/shorts/blending.js +8 -14
  24. package/examples/shorts/box2d.js +7 -3
  25. package/examples/shorts/box2dCar.js +2 -1
  26. package/examples/shorts/empty.js +30 -0
  27. package/examples/shorts/helloWorld.js +1 -1
  28. package/examples/shorts/hillGlideGame.js +10 -4
  29. package/examples/shorts/landerGame.js +30 -3
  30. package/examples/shorts/medals.js +4 -4
  31. package/examples/shorts/music.js +29 -55
  32. package/examples/shorts/musicPlayer.js +134 -0
  33. package/examples/shorts/nineSlice.js +34 -15
  34. package/examples/shorts/parallax.js +4 -3
  35. package/examples/shorts/particles.js +16 -16
  36. package/examples/shorts/piano.js +15 -21
  37. package/examples/shorts/pongGame.js +6 -4
  38. package/examples/shorts/raycasting.js +13 -5
  39. package/examples/shorts/sequencer.js +122 -0
  40. package/examples/shorts/shapes.js +7 -4
  41. package/examples/shorts/slidingPuzzle.js +16 -6
  42. package/examples/shorts/sound.js +18 -9
  43. package/examples/shorts/spaceGame.js +12 -8
  44. package/examples/shorts/spriteAtlas.js +7 -7
  45. package/examples/shorts/starfield.js +1 -1
  46. package/examples/shorts/systemFont.js +2 -2
  47. package/examples/shorts/texture.js +2 -2
  48. package/examples/shorts/tileLayer.js +10 -10
  49. package/examples/shorts/tiltedView.js +14 -3
  50. package/examples/shorts/timers.js +10 -0
  51. package/examples/shorts/topDown.js +4 -1
  52. package/examples/shorts/uiSystem.js +8 -5
  53. package/examples/starter/game.js +3 -3
  54. package/examples/starter/index.html +2 -2
  55. package/examples/typescript/game.js +3 -3
  56. package/examples/typescript/game.ts +3 -3
  57. package/examples/uiSystem/game.js +6 -6
  58. package/package.json +4 -2
  59. package/plugins/box2d.js +18 -3
  60. package/plugins/newgrounds.js +11 -9
  61. package/plugins/postProcess.js +5 -2
  62. package/plugins/uiSystem.js +120 -34
  63. package/plugins/zzfxm.js +5 -1
  64. package/reference.md +1 -3
  65. package/src/engine.js +52 -21
  66. package/src/engineAudio.js +31 -14
  67. package/src/engineDebug.js +80 -55
  68. package/src/engineDraw.js +60 -31
  69. package/src/engineExport.js +3 -1
  70. package/src/engineMedals.js +10 -2
  71. package/src/engineObject.js +14 -10
  72. package/src/engineParticles.js +59 -46
  73. package/src/engineRelease.js +1 -0
  74. package/src/engineSettings.js +7 -7
  75. package/src/engineTileLayer.js +49 -18
  76. package/src/engineUtilities.js +79 -34
@@ -217,7 +217,12 @@ function wave(frequency=1, amplitude=1, t=time, offset=0)
217
217
  * @param {number} t - time in seconds
218
218
  * @return {string}
219
219
  * @memberof Utilities */
220
- function formatTime(t) { return (t/60|0) + ':' + (t%60<10?'0':'') + (t%60|0); }
220
+ function formatTime(t)
221
+ {
222
+ const sign = t < 0 ? '-' : '';
223
+ t = abs(t)|0;
224
+ return sign + (t/60|0) + ':' + (t%60<10?'0':'') + t%60;
225
+ }
221
226
 
222
227
  /** Fetches a JSON file from a URL and returns the parsed JSON object. Must be used with await!
223
228
  * @param {string} url - URL of JSON file
@@ -226,6 +231,8 @@ function formatTime(t) { return (t/60|0) + ':' + (t%60<10?'0':'') + (t%60|0); }
226
231
  async function fetchJSON(url)
227
232
  {
228
233
  const response = await fetch(url);
234
+ if (!response.ok)
235
+ throw new Error(`Failed to fetch JSON from ${url}: ${response.status} ${response.statusText}`);
229
236
  return response.json();
230
237
  }
231
238
 
@@ -236,6 +243,13 @@ async function fetchJSON(url)
236
243
  * @memberof Utilities */
237
244
  function isNumber(n) { return typeof n === 'number' && !isNaN(n); }
238
245
 
246
+ /**
247
+ * Check if object is a valid string or can be converted to one
248
+ * @param {any} s
249
+ * @return {boolean}
250
+ * @memberof Utilities */
251
+ function isString(s) { return s !== undefined && s !== null && typeof s.toString() === 'string'; }
252
+
239
253
  ///////////////////////////////////////////////////////////////////////////////
240
254
 
241
255
  /** Random global functions
@@ -298,6 +312,7 @@ function randColor(colorA=new Color, colorB=new Color(0,0,0,1), linear=false)
298
312
  /**
299
313
  * Seeded random number generator
300
314
  * - Can be used to create a deterministic random number sequence
315
+ * @memberof Engine
301
316
  * @example
302
317
  * let r = new RandomGenerator(123); // random number generator with seed 123
303
318
  * let a = r.float(); // random value between 0 and 1
@@ -394,6 +409,7 @@ function ASSERT_VECTOR2_NORMAL(v)
394
409
  /**
395
410
  * 2D Vector object with vector math library
396
411
  * - Functions do not change this so they can be chained together
412
+ * @memberof Engine
397
413
  * @example
398
414
  * let a = new Vector2(2, 3); // vector with coordinates (2, 3)
399
415
  * let b = new Vector2; // vector with coordinates (0, 0)
@@ -534,9 +550,10 @@ class Vector2
534
550
  return new Vector2(this.x*c - this.y*s, this.x*s + this.y*c);
535
551
  }
536
552
 
537
- /** Set the integer direction of this vector, corresponding to multiples of 90 degree rotation (0-3)
553
+ /** Sets this this vector to point in the specified integer direction (0-3), corresponding to multiples of 90 degree rotation
538
554
  * @param {number} [direction]
539
- * @param {number} [length] */
555
+ * @param {number} [length]
556
+ * @return {Vector2} */
540
557
  setDirection(direction, length=1)
541
558
  {
542
559
  ASSERT_NUMBER_VALID(direction);
@@ -544,8 +561,10 @@ class Vector2
544
561
  direction = mod(direction, 4);
545
562
  ASSERT(direction===0 || direction===1 || direction===2 || direction===3,
546
563
  'Vector2.setDirection() direction must be an integer between 0 and 3.');
547
- return vec2(direction%2 ? direction-1 ? -length : length : 0,
548
- direction%2 ? 0 : direction ? -length : length);
564
+
565
+ this.x = direction%2 ? direction-1 ? -length : length : 0;
566
+ this.y = direction%2 ? 0 : direction ? -length : length;
567
+ return this;
549
568
  }
550
569
 
551
570
  /** Returns the integer direction of this vector, corresponding to multiples of 90 degree rotation (0-3)
@@ -553,11 +572,7 @@ class Vector2
553
572
  direction()
554
573
  { return abs(this.x) > abs(this.y) ? this.x < 0 ? 3 : 1 : this.y < 0 ? 2 : 0; }
555
574
 
556
- /** Returns a copy of this vector that has been inverted
557
- * @return {Vector2} */
558
- invert() { return new Vector2(this.y, -this.x); }
559
-
560
- /** Returns a copy of this vector absolute values
575
+ /** Returns a copy of this vector with absolute values
561
576
  * @return {Vector2} */
562
577
  abs() { return new Vector2(abs(this.x), abs(this.y)); }
563
578
 
@@ -599,13 +614,10 @@ class Vector2
599
614
  toString(digits=3)
600
615
  {
601
616
  ASSERT_NUMBER_VALID(digits);
602
- if (debug)
603
- {
604
- if (this.isValid())
605
- return `(${(this.x<0?'':' ') + this.x.toFixed(digits)},${(this.y<0?'':' ') + this.y.toFixed(digits)} )`;
606
- else
607
- return `(${this.x}, ${this.y})`;
608
- }
617
+ if (this.isValid())
618
+ return `(${(this.x<0?'':' ') + this.x.toFixed(digits)},${(this.y<0?'':' ') + this.y.toFixed(digits)} )`;
619
+ else
620
+ return `(${this.x}, ${this.y})`;
609
621
  }
610
622
 
611
623
  /** Checks if this is a valid vector
@@ -648,6 +660,7 @@ function ASSERT_COLOR_VALID(c) { ASSERT(isColor(c), 'Color is invalid.', c); }
648
660
 
649
661
  /**
650
662
  * Color object (red, green, blue, alpha) with some helpful functions
663
+ * @memberof Engine
651
664
  * @example
652
665
  * let a = new Color; // white
653
666
  * let b = new Color(1, 0, 0); // red
@@ -825,7 +838,8 @@ class Color
825
838
  * @return {Color} */
826
839
  setHex(hex)
827
840
  {
828
- ASSERT(typeof hex === 'string' && hex[0] === '#', 'Color hex code must be a string starting with #');
841
+ ASSERT(isString(hex), 'Color hex code must be a string');
842
+ ASSERT(hex[0] === '#', 'Color hex code must start with #');
829
843
  ASSERT([4,5,7,9].includes(hex.length), 'Invalid hex');
830
844
 
831
845
  if (hex.length < 6)
@@ -867,77 +881,78 @@ class Color
867
881
  }
868
882
 
869
883
  ///////////////////////////////////////////////////////////////////////////////
870
- // default colors
884
+ // Default Colors
871
885
 
872
886
  /** Color - White #ffffff
873
887
  * @type {Color}
874
888
  * @memberof Utilities */
875
- const WHITE = rgb();
889
+ const WHITE = protectEngineConstant(rgb());
876
890
 
877
- /** Color - Clear White #ffffff with 0 alpha
891
+ /** Color - Clear White #757474ff with 0 alpha
878
892
  * @type {Color}
879
893
  * @memberof Utilities */
880
- const CLEAR_WHITE = rgb(1,1,1,0);
894
+ const CLEAR_WHITE = protectEngineConstant(rgb(1,1,1,0));
881
895
 
882
896
  /** Color - Black #000000
883
897
  * @type {Color}
884
898
  * @memberof Utilities */
885
- const BLACK = rgb(0,0,0);
899
+ const BLACK = protectEngineConstant(rgb(0,0,0));
886
900
 
887
901
  /** Color - Clear Black #000000 with 0 alpha
888
902
  * @type {Color}
889
903
  * @memberof Utilities */
890
- const CLEAR_BLACK = rgb(0,0,0,0);
904
+ const CLEAR_BLACK = protectEngineConstant(rgb(0,0,0,0));
891
905
 
892
906
  /** Color - Gray #808080
893
907
  * @type {Color}
894
908
  * @memberof Utilities */
895
- const GRAY = rgb(.5,.5,.5);
909
+ const GRAY = protectEngineConstant(rgb(.5,.5,.5));
896
910
 
897
911
  /** Color - Red #ff0000
898
912
  * @type {Color}
899
913
  * @memberof Utilities */
900
- const RED = rgb(1,0,0);
914
+ const RED = protectEngineConstant(rgb(1,0,0));
901
915
 
902
916
  /** Color - Orange #ff8000
903
917
  * @type {Color}
904
918
  * @memberof Utilities */
905
- const ORANGE = rgb(1,.5,0);
919
+ const ORANGE = protectEngineConstant(rgb(1,.5,0));
906
920
 
907
921
  /** Color - Yellow #ffff00
908
922
  * @type {Color}
909
923
  * @memberof Utilities */
910
- const YELLOW = rgb(1,1,0);
924
+ const YELLOW = protectEngineConstant(rgb(1,1,0));
911
925
 
912
926
  /** Color - Green #00ff00
913
927
  * @type {Color}
914
928
  * @memberof Utilities */
915
- const GREEN = rgb(0,1,0);
929
+ const GREEN = protectEngineConstant(rgb(0,1,0));
916
930
 
917
931
  /** Color - Cyan #00ffff
918
932
  * @type {Color}
919
933
  * @memberof Utilities */
920
- const CYAN = rgb(0,1,1);
934
+ const CYAN = protectEngineConstant(rgb(0,1,1));
921
935
 
922
936
  /** Color - Blue #0000ff
923
937
  * @type {Color}
924
938
  * @memberof Utilities */
925
- const BLUE = rgb(0,0,1);
939
+ const BLUE = protectEngineConstant(rgb(0,0,1));
926
940
 
927
941
  /** Color - Purple #8000ff
928
942
  * @type {Color}
929
943
  * @memberof Utilities */
930
- const PURPLE = rgb(.5,0,1);
944
+ const PURPLE = protectEngineConstant(rgb(.5,0,1));
931
945
 
932
946
  /** Color - Magenta #ff00ff
933
947
  * @type {Color}
934
948
  * @memberof Utilities */
935
- const MAGENTA = rgb(1,0,1);
949
+ const MAGENTA = protectEngineConstant(rgb(1,0,1));
936
950
 
937
951
  ///////////////////////////////////////////////////////////////////////////////
938
952
 
939
953
  /**
940
954
  * Timer object tracks how long has passed since it was set
955
+ * @memberof Engine
941
956
  * @example
942
957
  * let a = new Timer; // creates a timer that is not set
943
958
  * a.set(3); // sets the timer to 3 seconds
@@ -994,9 +1009,39 @@ class Timer
994
1009
 
995
1010
  /** Returns this timer expressed as a string
996
1011
  * @return {string} */
997
- toString() { if (debug) { return this.isSet() ? Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ) : 'unset'; }}
1012
+ toString() { return this.isSet() ? Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ) : 'unset'; }
998
1013
 
999
1014
  /** Get how long since elapsed, returns 0 if not set (returns negative if currently active)
1000
1015
  * @return {number} */
1001
1016
  valueOf() { return this.get(); }
1017
+ }
1018
+
1019
+ ///////////////////////////////////////////////////////////////////////////////
1020
+ // Helper functions used by the engine
1021
+
1022
+ // make color constants immutable with debug assertions
1023
+ function protectEngineConstant(obj)
1024
+ {
1025
+ if (debug)
1026
+ {
1027
+ // get properties and store original values
1028
+ const props = Object.keys(obj), values = {};
1029
+ props.forEach(prop => values[prop] = obj[prop]);
1030
+
1031
+ // replace with getters/setters that assert
1032
+ props.forEach(prop =>
1033
+ {
1034
+ Object.defineProperty(obj, prop, {
1035
+ get: () => values[prop],
1036
+ set: (value) =>
1037
+ {
1038
+ ASSERT(false, `Cannot modify engine constant. Attempted to set constant (${obj}) property '${prop}' to '${value}'.`);
1039
+ },
1040
+ enumerable: true
1041
+ });
1042
+ });
1043
+ }
1044
+
1045
+ // freeze the object to prevent adding new properties
1046
+ return Object.freeze(obj);
1002
1047
  }