littlejsengine 1.11.9 → 1.11.13

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 (44) hide show
  1. package/README.md +3 -3
  2. package/dist/littlejs.d.ts +485 -492
  3. package/dist/littlejs.esm.js +548 -529
  4. package/dist/littlejs.esm.min.js +1 -1
  5. package/dist/littlejs.js +546 -525
  6. package/dist/littlejs.min.js +1 -1
  7. package/dist/littlejs.release.js +502 -484
  8. package/examples/htmlMenu/game.js +11 -1
  9. package/examples/htmlMenu/index.html +1 -10
  10. package/examples/module/game.js +2 -2
  11. package/examples/shorts/base.html +1 -1
  12. package/examples/starter/build/index.html +2 -0
  13. package/examples/starter/build/index.js +1 -0
  14. package/examples/starter/build/tiles.png +0 -0
  15. package/examples/starter/build.js +13 -3
  16. package/examples/starter/game.js +8 -1
  17. package/examples/starter/game.zip +0 -0
  18. package/examples/typescript/build/dist/littlejs.esm.js +4834 -0
  19. package/examples/typescript/build/examples/typescript/build.js +24 -0
  20. package/examples/typescript/build/examples/typescript/game.js +102 -0
  21. package/examples/typescript/build.bat +5 -0
  22. package/examples/typescript/build.js +33 -0
  23. package/examples/typescript/game.js +102 -0
  24. package/examples/typescript/game.ts +134 -0
  25. package/examples/typescript/index.html +10 -0
  26. package/examples/typescript/tiles.png +0 -0
  27. package/examples/typescript/tsconfig.json +8 -0
  28. package/package.json +1 -1
  29. package/plugins/newgrounds.js +44 -35
  30. package/plugins/postProcess.js +18 -4
  31. package/plugins/uiSystem.js +196 -30
  32. package/src/engine.js +21 -20
  33. package/src/engineAudio.js +59 -59
  34. package/src/engineDebug.js +44 -41
  35. package/src/engineDraw.js +58 -58
  36. package/src/engineExport.js +2 -4
  37. package/src/engineInput.js +40 -35
  38. package/src/engineMedals.js +21 -11
  39. package/src/engineObject.js +42 -35
  40. package/src/engineParticles.js +10 -10
  41. package/src/engineSettings.js +77 -82
  42. package/src/engineTileLayer.js +21 -21
  43. package/src/engineUtilities.js +150 -150
  44. package/src/engineWebGL.js +3 -3
@@ -16,37 +16,37 @@
16
16
 
17
17
 
18
18
  /** True if debug is enabled
19
- * @type {Boolean}
19
+ * @type {boolean}
20
20
  * @default
21
21
  * @memberof Debug */
22
22
  const debug = true;
23
23
 
24
24
  /** True if asserts are enabled
25
- * @type {Boolean}
25
+ * @type {boolean}
26
26
  * @default
27
27
  * @memberof Debug */
28
28
  const enableAsserts = true;
29
29
 
30
30
  /** Size to render debug points by default
31
- * @type {Number}
31
+ * @type {number}
32
32
  * @default
33
33
  * @memberof Debug */
34
34
  const debugPointSize = .5;
35
35
 
36
36
  /** True if watermark with FPS should be shown, false in release builds
37
- * @type {Boolean}
37
+ * @type {boolean}
38
38
  * @default
39
39
  * @memberof Debug */
40
40
  let showWatermark = true;
41
41
 
42
42
  /** Key code used to toggle debug mode, Esc by default
43
- * @type {String}
43
+ * @type {string}
44
44
  * @default
45
45
  * @memberof Debug */
46
46
  let debugKey = 'Escape';
47
47
 
48
48
  /** True if the debug overlay is active, always false in release builds
49
- * @type {Boolean}
49
+ * @type {boolean}
50
50
  * @default
51
51
  * @memberof Debug */
52
52
  let debugOverlay = false;
@@ -58,7 +58,7 @@ let debugPrimitives = [], debugPhysics = false, debugRaycast = false, debugParti
58
58
  // Debug helper functions
59
59
 
60
60
  /** Asserts if the expression is false, does not do anything in release builds
61
- * @param {Boolean} assert
61
+ * @param {boolean} assert
62
62
  * @param {Object} [output]
63
63
  * @memberof Debug */
64
64
  function ASSERT(assert, output)
@@ -70,10 +70,10 @@ function ASSERT(assert, output)
70
70
  /** Draw a debug rectangle in world space
71
71
  * @param {Vector2} pos
72
72
  * @param {Vector2} [size=Vector2()]
73
- * @param {String} [color]
74
- * @param {Number} [time]
75
- * @param {Number} [angle]
76
- * @param {Boolean} [fill]
73
+ * @param {string} [color]
74
+ * @param {number} [time]
75
+ * @param {number} [angle]
76
+ * @param {boolean} [fill]
77
77
  * @memberof Debug */
78
78
  function debugRect(pos, size=vec2(), color='#fff', time=0, angle=0, fill=false)
79
79
  {
@@ -83,11 +83,11 @@ function debugRect(pos, size=vec2(), color='#fff', time=0, angle=0, fill=false)
83
83
 
84
84
  /** Draw a debug poly in world space
85
85
  * @param {Vector2} pos
86
- * @param {Array} points
87
- * @param {String} [color]
88
- * @param {Number} [time]
89
- * @param {Number} [angle]
90
- * @param {Boolean} [fill]
86
+ * @param {Array<Vector2>} points
87
+ * @param {string} [color]
88
+ * @param {number} [time]
89
+ * @param {number} [angle]
90
+ * @param {boolean} [fill]
91
91
  * @memberof Debug */
92
92
  function debugPoly(pos, points, color='#fff', time=0, angle=0, fill=false)
93
93
  {
@@ -97,10 +97,10 @@ function debugPoly(pos, points, color='#fff', time=0, angle=0, fill=false)
97
97
 
98
98
  /** Draw a debug circle in world space
99
99
  * @param {Vector2} pos
100
- * @param {Number} [radius]
101
- * @param {String} [color]
102
- * @param {Number} [time]
103
- * @param {Boolean} [fill]
100
+ * @param {number} [radius]
101
+ * @param {string} [color]
102
+ * @param {number} [time]
103
+ * @param {boolean} [fill]
104
104
  * @memberof Debug */
105
105
  function debugCircle(pos, radius=0, color='#fff', time=0, fill=false)
106
106
  {
@@ -110,9 +110,9 @@ function debugCircle(pos, radius=0, color='#fff', time=0, fill=false)
110
110
 
111
111
  /** Draw a debug point in world space
112
112
  * @param {Vector2} pos
113
- * @param {String} [color]
114
- * @param {Number} [time]
115
- * @param {Number} [angle]
113
+ * @param {string} [color]
114
+ * @param {number} [time]
115
+ * @param {number} [angle]
116
116
  * @memberof Debug */
117
117
  function debugPoint(pos, color, time, angle)
118
118
  {
@@ -123,9 +123,9 @@ function debugPoint(pos, color, time, angle)
123
123
  /** Draw a debug line in world space
124
124
  * @param {Vector2} posA
125
125
  * @param {Vector2} posB
126
- * @param {String} [color]
127
- * @param {Number} [thickness]
128
- * @param {Number} [time]
126
+ * @param {string} [color]
127
+ * @param {number} [thickness]
128
+ * @param {number} [time]
129
129
  * @memberof Debug */
130
130
  function debugLine(posA, posB, color, thickness=.1, time)
131
131
  {
@@ -139,7 +139,7 @@ function debugLine(posA, posB, color, thickness=.1, time)
139
139
  * @param {Vector2} sA - size A
140
140
  * @param {Vector2} pB - position B
141
141
  * @param {Vector2} sB - size B
142
- * @param {String} [color]
142
+ * @param {string} [color]
143
143
  * @memberof Debug */
144
144
  function debugOverlap(pA, sA, pB, sB, color)
145
145
  {
@@ -149,13 +149,13 @@ function debugOverlap(pA, sA, pB, sB, color)
149
149
  }
150
150
 
151
151
  /** Draw a debug axis aligned bounding box in world space
152
- * @param {String} text
152
+ * @param {string} text
153
153
  * @param {Vector2} pos
154
- * @param {Number} [size]
155
- * @param {String} [color]
156
- * @param {Number} [time]
157
- * @param {Number} [angle]
158
- * @param {String} [font]
154
+ * @param {number} [size]
155
+ * @param {string} [color]
156
+ * @param {number} [time]
157
+ * @param {number} [angle]
158
+ * @param {string} [font]
159
159
  * @memberof Debug */
160
160
  function debugText(text, pos, size=1, color='#fff', time=0, angle=0, font='monospace')
161
161
  {
@@ -173,23 +173,23 @@ function debugScreenshot() { debugTakeScreenshot = 1; }
173
173
 
174
174
  /** Save a canvas to disk
175
175
  * @param {HTMLCanvasElement} canvas
176
- * @param {String} [filename]
177
- * @param {String} [type]
176
+ * @param {string} [filename]
177
+ * @param {string} [type]
178
178
  * @memberof Debug */
179
179
  function debugSaveCanvas(canvas, filename='screenshot', type='image/png')
180
180
  { debugSaveDataURL(canvas.toDataURL(type), filename); }
181
181
 
182
182
  /** Save a text file to disk
183
- * @param {String} text
184
- * @param {String} [filename]
185
- * @param {String} [type]
183
+ * @param {string} text
184
+ * @param {string} [filename]
185
+ * @param {string} [type]
186
186
  * @memberof Debug */
187
187
  function debugSaveText(text, filename='text', type='text/plain')
188
188
  { debugSaveDataURL(URL.createObjectURL(new Blob([text], {'type':type})), filename); }
189
189
 
190
190
  /** Save a data url to disk
191
- * @param {String} dataURL
192
- * @param {String} filename
191
+ * @param {string} dataURL
192
+ * @param {string} filename
193
193
  * @memberof Debug */
194
194
  function debugSaveDataURL(dataURL, filename)
195
195
  {
@@ -309,9 +309,12 @@ function debugRender()
309
309
  let bestDistance = Infinity;
310
310
  for (const o of engineObjects)
311
311
  {
312
- if (o.canvas || o.destroyed)
312
+ if (o.destroyed)
313
313
  continue;
314
314
 
315
+ if (o instanceof TileLayer)
316
+ continue; // prevent tile layers from being picked
317
+
315
318
  o.renderDebugInfo();
316
319
  if (!o.size.x || !o.size.y)
317
320
  continue;
@@ -483,112 +486,112 @@ function debugRender()
483
486
 
484
487
 
485
488
  /** A shortcut to get Math.PI
486
- * @type {Number}
489
+ * @type {number}
487
490
  * @default Math.PI
488
491
  * @memberof Utilities */
489
492
  const PI = Math.PI;
490
493
 
491
494
  /** Returns absolute value of value passed in
492
- * @param {Number} value
493
- * @return {Number}
495
+ * @param {number} value
496
+ * @return {number}
494
497
  * @memberof Utilities */
495
498
  function abs(value) { return Math.abs(value); }
496
499
 
497
500
  /** Returns lowest of two values passed in
498
- * @param {Number} valueA
499
- * @param {Number} valueB
500
- * @return {Number}
501
+ * @param {number} valueA
502
+ * @param {number} valueB
503
+ * @return {number}
501
504
  * @memberof Utilities */
502
505
  function min(valueA, valueB) { return Math.min(valueA, valueB); }
503
506
 
504
507
  /** Returns highest of two values passed in
505
- * @param {Number} valueA
506
- * @param {Number} valueB
507
- * @return {Number}
508
+ * @param {number} valueA
509
+ * @param {number} valueB
510
+ * @return {number}
508
511
  * @memberof Utilities */
509
512
  function max(valueA, valueB) { return Math.max(valueA, valueB); }
510
513
 
511
514
  /** Returns the sign of value passed in
512
- * @param {Number} value
513
- * @return {Number}
515
+ * @param {number} value
516
+ * @return {number}
514
517
  * @memberof Utilities */
515
518
  function sign(value) { return Math.sign(value); }
516
519
 
517
520
  /** Returns first parm modulo the second param, but adjusted so negative numbers work as expected
518
- * @param {Number} dividend
519
- * @param {Number} [divisor]
520
- * @return {Number}
521
+ * @param {number} dividend
522
+ * @param {number} [divisor]
523
+ * @return {number}
521
524
  * @memberof Utilities */
522
525
  function mod(dividend, divisor=1) { return ((dividend % divisor) + divisor) % divisor; }
523
526
 
524
527
  /** Clamps the value between max and min
525
- * @param {Number} value
526
- * @param {Number} [min]
527
- * @param {Number} [max]
528
- * @return {Number}
528
+ * @param {number} value
529
+ * @param {number} [min]
530
+ * @param {number} [max]
531
+ * @return {number}
529
532
  * @memberof Utilities */
530
533
  function clamp(value, min=0, max=1) { return value < min ? min : value > max ? max : value; }
531
534
 
532
535
  /** Returns what percentage the value is between valueA and valueB
533
- * @param {Number} value
534
- * @param {Number} valueA
535
- * @param {Number} valueB
536
- * @return {Number}
536
+ * @param {number} value
537
+ * @param {number} valueA
538
+ * @param {number} valueB
539
+ * @return {number}
537
540
  * @memberof Utilities */
538
541
  function percent(value, valueA, valueB)
539
542
  { return (valueB-=valueA) ? clamp((value-valueA)/valueB) : 0; }
540
543
 
541
544
  /** Linearly interpolates between values passed in using percent
542
- * @param {Number} percent
543
- * @param {Number} valueA
544
- * @param {Number} valueB
545
- * @return {Number}
545
+ * @param {number} percent
546
+ * @param {number} valueA
547
+ * @param {number} valueB
548
+ * @return {number}
546
549
  * @memberof Utilities */
547
550
  function lerp(percent, valueA, valueB) { return valueA + clamp(percent) * (valueB-valueA); }
548
551
 
549
552
  /** Returns signed wrapped distance between the two values passed in
550
- * @param {Number} valueA
551
- * @param {Number} valueB
552
- * @param {Number} [wrapSize]
553
- * @returns {Number}
553
+ * @param {number} valueA
554
+ * @param {number} valueB
555
+ * @param {number} [wrapSize]
556
+ * @returns {number}
554
557
  * @memberof Utilities */
555
558
  function distanceWrap(valueA, valueB, wrapSize=1)
556
559
  { const d = (valueA - valueB) % wrapSize; return d*2 % wrapSize - d; }
557
560
 
558
561
  /** Linearly interpolates between values passed in with wrapping
559
- * @param {Number} percent
560
- * @param {Number} valueA
561
- * @param {Number} valueB
562
- * @param {Number} [wrapSize]
563
- * @returns {Number}
562
+ * @param {number} percent
563
+ * @param {number} valueA
564
+ * @param {number} valueB
565
+ * @param {number} [wrapSize]
566
+ * @returns {number}
564
567
  * @memberof Utilities */
565
568
  function lerpWrap(percent, valueA, valueB, wrapSize=1)
566
569
  { return valueB + clamp(percent) * distanceWrap(valueA, valueB, wrapSize); }
567
570
 
568
571
  /** Returns signed wrapped distance between the two angles passed in
569
- * @param {Number} angleA
570
- * @param {Number} angleB
571
- * @returns {Number}
572
+ * @param {number} angleA
573
+ * @param {number} angleB
574
+ * @returns {number}
572
575
  * @memberof Utilities */
573
576
  function distanceAngle(angleA, angleB) { return distanceWrap(angleA, angleB, 2*PI); }
574
577
 
575
578
  /** Linearly interpolates between the angles passed in with wrapping
576
- * @param {Number} percent
577
- * @param {Number} angleA
578
- * @param {Number} angleB
579
- * @returns {Number}
579
+ * @param {number} percent
580
+ * @param {number} angleA
581
+ * @param {number} angleB
582
+ * @returns {number}
580
583
  * @memberof Utilities */
581
584
  function lerpAngle(percent, angleA, angleB) { return lerpWrap(percent, angleA, angleB, 2*PI); }
582
585
 
583
586
  /** Applies smoothstep function to the percentage value
584
- * @param {Number} percent
585
- * @return {Number}
587
+ * @param {number} percent
588
+ * @return {number}
586
589
  * @memberof Utilities */
587
590
  function smoothStep(percent) { return percent * percent * (3 - 2 * percent); }
588
591
 
589
592
  /** Returns the nearest power of two not less then the value
590
- * @param {Number} value
591
- * @return {Number}
593
+ * @param {number} value
594
+ * @return {number}
592
595
  * @memberof Utilities */
593
596
  function nearestPowerOfTwo(value) { return 2**Math.ceil(Math.log2(value)); }
594
597
 
@@ -597,7 +600,7 @@ function nearestPowerOfTwo(value) { return 2**Math.ceil(Math.log2(value)); }
597
600
  * @param {Vector2} sizeA - Size of box A
598
601
  * @param {Vector2} posB - Center of box B
599
602
  * @param {Vector2} [sizeB=(0,0)] - Size of box B, a point if undefined
600
- * @return {Boolean} - True if overlapping
603
+ * @return {boolean} - True if overlapping
601
604
  * @memberof Utilities */
602
605
  function isOverlapping(posA, sizeA, posB, sizeB=vec2())
603
606
  {
@@ -610,7 +613,7 @@ function isOverlapping(posA, sizeA, posB, sizeB=vec2())
610
613
  * @param {Vector2} end - End of raycast
611
614
  * @param {Vector2} pos - Center of box
612
615
  * @param {Vector2} size - Size of box
613
- * @return {Boolean} - True if intersecting
616
+ * @return {boolean} - True if intersecting
614
617
  * @memberof Utilities */
615
618
  function isIntersecting(start, end, pos, size)
616
619
  {
@@ -647,17 +650,17 @@ function isIntersecting(start, end, pos, size)
647
650
  }
648
651
 
649
652
  /** Returns an oscillating wave between 0 and amplitude with frequency of 1 Hz by default
650
- * @param {Number} [frequency] - Frequency of the wave in Hz
651
- * @param {Number} [amplitude] - Amplitude (max height) of the wave
652
- * @param {Number} [t=time] - Value to use for time of the wave
653
- * @return {Number} - Value waving between 0 and amplitude
653
+ * @param {number} [frequency] - Frequency of the wave in Hz
654
+ * @param {number} [amplitude] - Amplitude (max height) of the wave
655
+ * @param {number} [t=time] - Value to use for time of the wave
656
+ * @return {number} - Value waving between 0 and amplitude
654
657
  * @memberof Utilities */
655
658
  function wave(frequency=1, amplitude=1, t=time)
656
659
  { return amplitude/2 * (1 - Math.cos(t*frequency*2*PI)); }
657
660
 
658
661
  /** Formats seconds to mm:ss style for display purposes
659
- * @param {Number} t - time in seconds
660
- * @return {String}
662
+ * @param {number} t - time in seconds
663
+ * @return {string}
661
664
  * @memberof Utilities */
662
665
  function formatTime(t) { return (t/60|0) + ':' + (t%60<10?'0':'') + (t%60|0); }
663
666
 
@@ -667,34 +670,34 @@ function formatTime(t) { return (t/60|0) + ':' + (t%60<10?'0':'') + (t%60|0); }
667
670
  * @namespace Random */
668
671
 
669
672
  /** Returns a random value between the two values passed in
670
- * @param {Number} [valueA]
671
- * @param {Number} [valueB]
672
- * @return {Number}
673
+ * @param {number} [valueA]
674
+ * @param {number} [valueB]
675
+ * @return {number}
673
676
  * @memberof Random */
674
677
  function rand(valueA=1, valueB=0) { return valueB + Math.random() * (valueA-valueB); }
675
678
 
676
679
  /** Returns a floored random value between the two values passed in
677
680
  * The upper bound is exclusive. (If 2 is passed in, result will be 0 or 1)
678
- * @param {Number} valueA
679
- * @param {Number} [valueB]
680
- * @return {Number}
681
+ * @param {number} valueA
682
+ * @param {number} [valueB]
683
+ * @return {number}
681
684
  * @memberof Random */
682
685
  function randInt(valueA, valueB=0) { return Math.floor(rand(valueA,valueB)); }
683
686
 
684
687
  /** Randomly returns either -1 or 1
685
- * @return {Number}
688
+ * @return {number}
686
689
  * @memberof Random */
687
690
  function randSign() { return randInt(2) * 2 - 1; }
688
691
 
689
692
  /** Returns a random Vector2 with the passed in length
690
- * @param {Number} [length]
693
+ * @param {number} [length]
691
694
  * @return {Vector2}
692
695
  * @memberof Random */
693
696
  function randVector(length=1) { return new Vector2().setAngle(rand(2*PI), length); }
694
697
 
695
698
  /** Returns a random Vector2 within a circular shape
696
- * @param {Number} [radius]
697
- * @param {Number} [minRadius]
699
+ * @param {number} [radius]
700
+ * @param {number} [minRadius]
698
701
  * @return {Vector2}
699
702
  * @memberof Random */
700
703
  function randInCircle(radius=1, minRadius=0)
@@ -703,7 +706,7 @@ function randInCircle(radius=1, minRadius=0)
703
706
  /** Returns a random color between the two passed in colors, combine components if linear
704
707
  * @param {Color} [colorA=(1,1,1,1)]
705
708
  * @param {Color} [colorB=(0,0,0,1)]
706
- * @param {Boolean} [linear]
709
+ * @param {boolean} [linear]
707
710
  * @return {Color}
708
711
  * @memberof Random */
709
712
  function randColor(colorA=new Color, colorB=new Color(0,0,0,1), linear=false)
@@ -727,17 +730,17 @@ function randColor(colorA=new Color, colorB=new Color(0,0,0,1), linear=false)
727
730
  class RandomGenerator
728
731
  {
729
732
  /** Create a random number generator with the seed passed in
730
- * @param {Number} seed - Starting seed */
733
+ * @param {number} seed - Starting seed */
731
734
  constructor(seed)
732
735
  {
733
- /** @property {Number} - random seed */
736
+ /** @property {number} - random seed */
734
737
  this.seed = seed;
735
738
  }
736
739
 
737
740
  /** Returns a seeded random value between the two values passed in
738
- * @param {Number} [valueA]
739
- * @param {Number} [valueB]
740
- * @return {Number} */
741
+ * @param {number} [valueA]
742
+ * @param {number} [valueB]
743
+ * @return {number} */
741
744
  float(valueA=1, valueB=0)
742
745
  {
743
746
  // xorshift algorithm
@@ -748,13 +751,13 @@ class RandomGenerator
748
751
  }
749
752
 
750
753
  /** Returns a floored seeded random value the two values passed in
751
- * @param {Number} valueA
752
- * @param {Number} [valueB]
753
- * @return {Number} */
754
+ * @param {number} valueA
755
+ * @param {number} [valueB]
756
+ * @return {number} */
754
757
  int(valueA, valueB=0) { return Math.floor(this.float(valueA, valueB)); }
755
758
 
756
759
  /** Randomly returns either -1 or 1 deterministically
757
- * @return {Number} */
760
+ * @return {number} */
758
761
  sign() { return this.float() > .5 ? 1 : -1; }
759
762
  }
760
763
 
@@ -762,8 +765,8 @@ class RandomGenerator
762
765
 
763
766
  /**
764
767
  * Create a 2d vector, can take another Vector2 to copy, 2 scalars, or 1 scalar
765
- * @param {(Number|Vector2)} [x]
766
- * @param {Number} [y]
768
+ * @param {Vector2|number} [x]
769
+ * @param {number} [y]
767
770
  * @return {Vector2}
768
771
  * @example
769
772
  * let a = vec2(0, 1); // vector with coordinates (0, 1)
@@ -782,7 +785,7 @@ function vec2(x=0, y)
782
785
  /**
783
786
  * Check if object is a valid Vector2
784
787
  * @param {any} v
785
- * @return {Boolean}
788
+ * @return {boolean}
786
789
  * @memberof Utilities
787
790
  */
788
791
  function isVector2(v) { return v instanceof Vector2; }
@@ -799,20 +802,20 @@ function isVector2(v) { return v instanceof Vector2; }
799
802
  class Vector2
800
803
  {
801
804
  /** Create a 2D vector with the x and y passed in, can also be created with vec2()
802
- * @param {Number} [x] - X axis location
803
- * @param {Number} [y] - Y axis location */
805
+ * @param {number} [x] - X axis location
806
+ * @param {number} [y] - Y axis location */
804
807
  constructor(x=0, y=0)
805
808
  {
806
- /** @property {Number} - X axis location */
809
+ /** @property {number} - X axis location */
807
810
  this.x = x;
808
- /** @property {Number} - Y axis location */
811
+ /** @property {number} - Y axis location */
809
812
  this.y = y;
810
813
  ASSERT(this.isValid());
811
814
  }
812
815
 
813
816
  /** Sets values of this vector and returns self
814
- * @param {Number} [x] - X axis location
815
- * @param {Number} [y] - Y axis location
817
+ * @param {number} [x] - X axis location
818
+ * @param {number} [y] - Y axis location
816
819
  * @return {Vector2} */
817
820
  set(x=0, y=0)
818
821
  {
@@ -863,7 +866,7 @@ class Vector2
863
866
  }
864
867
 
865
868
  /** Returns a copy of this vector scaled by the vector passed in
866
- * @param {Number} s - scale
869
+ * @param {number} s - scale
867
870
  * @return {Vector2} */
868
871
  scale(s)
869
872
  {
@@ -872,16 +875,16 @@ class Vector2
872
875
  }
873
876
 
874
877
  /** Returns the length of this vector
875
- * @return {Number} */
878
+ * @return {number} */
876
879
  length() { return this.lengthSquared()**.5; }
877
880
 
878
881
  /** Returns the length of this vector squared
879
- * @return {Number} */
882
+ * @return {number} */
880
883
  lengthSquared() { return this.x**2 + this.y**2; }
881
884
 
882
885
  /** Returns the distance from this vector to vector passed in
883
886
  * @param {Vector2} v - other vector
884
- * @return {Number} */
887
+ * @return {number} */
885
888
  distance(v)
886
889
  {
887
890
  ASSERT(isVector2(v));
@@ -890,7 +893,7 @@ class Vector2
890
893
 
891
894
  /** Returns the distance squared from this vector to vector passed in
892
895
  * @param {Vector2} v - other vector
893
- * @return {Number} */
896
+ * @return {number} */
894
897
  distanceSquared(v)
895
898
  {
896
899
  ASSERT(isVector2(v));
@@ -898,7 +901,7 @@ class Vector2
898
901
  }
899
902
 
900
903
  /** Returns a new vector in same direction as this one with the length passed in
901
- * @param {Number} [length]
904
+ * @param {number} [length]
902
905
  * @return {Vector2} */
903
906
  normalize(length=1)
904
907
  {
@@ -907,7 +910,7 @@ class Vector2
907
910
  }
908
911
 
909
912
  /** Returns a new vector clamped to length passed in
910
- * @param {Number} [length]
913
+ * @param {number} [length]
911
914
  * @return {Vector2} */
912
915
  clampLength(length=1)
913
916
  {
@@ -917,7 +920,7 @@ class Vector2
917
920
 
918
921
  /** Returns the dot product of this and the vector passed in
919
922
  * @param {Vector2} v - other vector
920
- * @return {Number} */
923
+ * @return {number} */
921
924
  dot(v)
922
925
  {
923
926
  ASSERT(isVector2(v));
@@ -926,7 +929,7 @@ class Vector2
926
929
 
927
930
  /** Returns the cross product of this and the vector passed in
928
931
  * @param {Vector2} v - other vector
929
- * @return {Number} */
932
+ * @return {number} */
930
933
  cross(v)
931
934
  {
932
935
  ASSERT(isVector2(v));
@@ -934,12 +937,12 @@ class Vector2
934
937
  }
935
938
 
936
939
  /** Returns the clockwise angle of this vector, up is angle 0
937
- * @return {Number} */
940
+ * @return {number} */
938
941
  angle() { return Math.atan2(this.x, this.y); }
939
942
 
940
943
  /** Sets this vector with clockwise angle and length passed in
941
- * @param {Number} [angle]
942
- * @param {Number} [length]
944
+ * @param {number} [angle]
945
+ * @param {number} [length]
943
946
  * @return {Vector2} */
944
947
  setAngle(angle=0, length=1)
945
948
  {
@@ -949,7 +952,7 @@ class Vector2
949
952
  }
950
953
 
951
954
  /** Returns copy of this vector rotated by the clockwise angle passed in
952
- * @param {Number} angle
955
+ * @param {number} angle
953
956
  * @return {Vector2} */
954
957
  rotate(angle)
955
958
  {
@@ -958,8 +961,8 @@ class Vector2
958
961
  }
959
962
 
960
963
  /** Set the integer direction of this vector, corresponding to multiples of 90 degree rotation (0-3)
961
- * @param {Number} [direction]
962
- * @param {Number} [length] */
964
+ * @param {number} [direction]
965
+ * @param {number} [length] */
963
966
  setDirection(direction, length=1)
964
967
  {
965
968
  direction = mod(direction, 4);
@@ -969,7 +972,7 @@ class Vector2
969
972
  }
970
973
 
971
974
  /** Returns the integer direction of this vector, corresponding to multiples of 90 degree rotation (0-3)
972
- * @return {Number} */
975
+ * @return {number} */
973
976
  direction()
974
977
  { return abs(this.x) > abs(this.y) ? this.x < 0 ? 3 : 1 : this.y < 0 ? 2 : 0; }
975
978
 
@@ -982,12 +985,12 @@ class Vector2
982
985
  floor() { return new Vector2(Math.floor(this.x), Math.floor(this.y)); }
983
986
 
984
987
  /** Returns the area this vector covers as a rectangle
985
- * @return {Number} */
988
+ * @return {number} */
986
989
  area() { return abs(this.x * this.y); }
987
990
 
988
991
  /** Returns a new vector that is p percent between this and the vector passed in
989
992
  * @param {Vector2} v - other vector
990
- * @param {Number} percent
993
+ * @param {number} percent
991
994
  * @return {Vector2} */
992
995
  lerp(v, percent)
993
996
  {
@@ -997,7 +1000,7 @@ class Vector2
997
1000
 
998
1001
  /** Returns true if this vector is within the bounds of an array size passed in
999
1002
  * @param {Vector2} arraySize
1000
- * @return {Boolean} */
1003
+ * @return {boolean} */
1001
1004
  arrayCheck(arraySize)
1002
1005
  {
1003
1006
  ASSERT(isVector2(arraySize));
@@ -1005,8 +1008,8 @@ class Vector2
1005
1008
  }
1006
1009
 
1007
1010
  /** Returns this vector expressed as a string
1008
- * @param {Number} digits - precision to display
1009
- * @return {String} */
1011
+ * @param {number} digits - precision to display
1012
+ * @return {string} */
1010
1013
  toString(digits=3)
1011
1014
  {
1012
1015
  if (debug)
@@ -1014,7 +1017,7 @@ class Vector2
1014
1017
  }
1015
1018
 
1016
1019
  /** Checks if this is a valid vector
1017
- * @return {Boolean} */
1020
+ * @return {boolean} */
1018
1021
  isValid()
1019
1022
  {
1020
1023
  return typeof this.x == 'number' && !isNaN(this.x)
@@ -1026,10 +1029,10 @@ class Vector2
1026
1029
 
1027
1030
  /**
1028
1031
  * Create a color object with RGBA values, white by default
1029
- * @param {Number} [r=1] - red
1030
- * @param {Number} [g=1] - green
1031
- * @param {Number} [b=1] - blue
1032
- * @param {Number} [a=1] - alpha
1032
+ * @param {number} [r=1] - red
1033
+ * @param {number} [g=1] - green
1034
+ * @param {number} [b=1] - blue
1035
+ * @param {number} [a=1] - alpha
1033
1036
  * @return {Color}
1034
1037
  * @memberof Utilities
1035
1038
  */
@@ -1037,10 +1040,10 @@ function rgb(r, g, b, a) { return new Color(r, g, b, a); }
1037
1040
 
1038
1041
  /**
1039
1042
  * Create a color object with HSLA values, white by default
1040
- * @param {Number} [h=0] - hue
1041
- * @param {Number} [s=0] - saturation
1042
- * @param {Number} [l=1] - lightness
1043
- * @param {Number} [a=1] - alpha
1043
+ * @param {number} [h=0] - hue
1044
+ * @param {number} [s=0] - saturation
1045
+ * @param {number} [l=1] - lightness
1046
+ * @param {number} [a=1] - alpha
1044
1047
  * @return {Color}
1045
1048
  * @memberof Utilities
1046
1049
  */
@@ -1049,7 +1052,7 @@ function hsl(h, s, l, a) { return new Color().setHSLA(h, s, l, a); }
1049
1052
  /**
1050
1053
  * Check if object is a valid Color
1051
1054
  * @param {any} c
1052
- * @return {Boolean}
1055
+ * @return {boolean}
1053
1056
  * @memberof Utilities
1054
1057
  */
1055
1058
  function isColor(c) { return c instanceof Color; }
@@ -1066,28 +1069,28 @@ function isColor(c) { return c instanceof Color; }
1066
1069
  class Color
1067
1070
  {
1068
1071
  /** Create a color with the rgba components passed in, white by default
1069
- * @param {Number} [r] - red
1070
- * @param {Number} [g] - green
1071
- * @param {Number} [b] - blue
1072
- * @param {Number} [a] - alpha*/
1072
+ * @param {number} [r] - red
1073
+ * @param {number} [g] - green
1074
+ * @param {number} [b] - blue
1075
+ * @param {number} [a] - alpha*/
1073
1076
  constructor(r=1, g=1, b=1, a=1)
1074
1077
  {
1075
- /** @property {Number} - Red */
1078
+ /** @property {number} - Red */
1076
1079
  this.r = r;
1077
- /** @property {Number} - Green */
1080
+ /** @property {number} - Green */
1078
1081
  this.g = g;
1079
- /** @property {Number} - Blue */
1082
+ /** @property {number} - Blue */
1080
1083
  this.b = b;
1081
- /** @property {Number} - Alpha */
1084
+ /** @property {number} - Alpha */
1082
1085
  this.a = a;
1083
1086
  ASSERT(this.isValid());
1084
1087
  }
1085
1088
 
1086
1089
  /** Sets values of this color and returns self
1087
- * @param {Number} [r] - red
1088
- * @param {Number} [g] - green
1089
- * @param {Number} [b] - blue
1090
- * @param {Number} [a] - alpha
1090
+ * @param {number} [r] - red
1091
+ * @param {number} [g] - green
1092
+ * @param {number} [b] - blue
1093
+ * @param {number} [a] - alpha
1091
1094
  * @return {Color} */
1092
1095
  set(r=1, g=1, b=1, a=1)
1093
1096
  {
@@ -1140,8 +1143,8 @@ class Color
1140
1143
  }
1141
1144
 
1142
1145
  /** Returns a copy of this color scaled by the value passed in, alpha can be scaled separately
1143
- * @param {Number} scale
1144
- * @param {Number} [alphaScale=scale]
1146
+ * @param {number} scale
1147
+ * @param {number} [alphaScale=scale]
1145
1148
  * @return {Color} */
1146
1149
  scale(scale, alphaScale=scale)
1147
1150
  { return new Color(this.r*scale, this.g*scale, this.b*scale, this.a*alphaScale); }
@@ -1152,7 +1155,7 @@ class Color
1152
1155
 
1153
1156
  /** Returns a new color that is p percent between this and the color passed in
1154
1157
  * @param {Color} c - other color
1155
- * @param {Number} percent
1158
+ * @param {number} percent
1156
1159
  * @return {Color} */
1157
1160
  lerp(c, percent)
1158
1161
  {
@@ -1161,10 +1164,10 @@ class Color
1161
1164
  }
1162
1165
 
1163
1166
  /** Sets this color given a hue, saturation, lightness, and alpha
1164
- * @param {Number} [h] - hue
1165
- * @param {Number} [s] - saturation
1166
- * @param {Number} [l] - lightness
1167
- * @param {Number} [a] - alpha
1167
+ * @param {number} [h] - hue
1168
+ * @param {number} [s] - saturation
1169
+ * @param {number} [l] - lightness
1170
+ * @param {number} [a] - alpha
1168
1171
  * @return {Color} */
1169
1172
  setHSLA(h=0, s=0, l=1, a=1)
1170
1173
  {
@@ -1185,7 +1188,7 @@ class Color
1185
1188
  }
1186
1189
 
1187
1190
  /** Returns this color expressed in hsla format
1188
- * @return {Array} */
1191
+ * @return {Array<number>} */
1189
1192
  HSLA()
1190
1193
  {
1191
1194
  const r = clamp(this.r);
@@ -1212,8 +1215,8 @@ class Color
1212
1215
  }
1213
1216
 
1214
1217
  /** Returns a new color that has each component randomly adjusted
1215
- * @param {Number} [amount]
1216
- * @param {Number} [alphaAmount]
1218
+ * @param {number} [amount]
1219
+ * @param {number} [alphaAmount]
1217
1220
  * @return {Color} */
1218
1221
  mutate(amount=.05, alphaAmount=0)
1219
1222
  {
@@ -1227,8 +1230,8 @@ class Color
1227
1230
  }
1228
1231
 
1229
1232
  /** Returns this color expressed as a hex color code
1230
- * @param {Boolean} [useAlpha] - if alpha should be included in result
1231
- * @return {String} */
1233
+ * @param {boolean} [useAlpha] - if alpha should be included in result
1234
+ * @return {string} */
1232
1235
  toString(useAlpha = true)
1233
1236
  {
1234
1237
  const toHex = (c)=> ((c=clamp(c)*255|0)<16 ? '0' : '') + c.toString(16);
@@ -1236,7 +1239,7 @@ class Color
1236
1239
  }
1237
1240
 
1238
1241
  /** Set this color from a hex code
1239
- * @param {String} hex - html hex code
1242
+ * @param {string} hex - html hex code
1240
1243
  * @return {Color} */
1241
1244
  setHex(hex)
1242
1245
  {
@@ -1265,7 +1268,7 @@ class Color
1265
1268
  }
1266
1269
 
1267
1270
  /** Returns this color expressed as 32 bit RGBA value
1268
- * @return {Number} */
1271
+ * @return {number} */
1269
1272
  rgbaInt()
1270
1273
  {
1271
1274
  const r = clamp(this.r)*255|0;
@@ -1276,7 +1279,7 @@ class Color
1276
1279
  }
1277
1280
 
1278
1281
  /** Checks if this is a valid color
1279
- * @return {Boolean} */
1282
+ * @return {boolean} */
1280
1283
  isValid()
1281
1284
  {
1282
1285
  return typeof this.r == 'number' && !isNaN(this.r)
@@ -1358,42 +1361,42 @@ const MAGENTA = rgb(1,0,1);
1358
1361
  class Timer
1359
1362
  {
1360
1363
  /** Create a timer object set time passed in
1361
- * @param {Number} [timeLeft] - How much time left before the timer elapses in seconds */
1364
+ * @param {number} [timeLeft] - How much time left before the timer elapses in seconds */
1362
1365
  constructor(timeLeft) { this.time = timeLeft == undefined ? undefined : time + timeLeft; this.setTime = timeLeft; }
1363
1366
 
1364
1367
  /** Set the timer with seconds passed in
1365
- * @param {Number} [timeLeft] - How much time left before the timer is elapsed in seconds */
1368
+ * @param {number} [timeLeft] - How much time left before the timer is elapsed in seconds */
1366
1369
  set(timeLeft=0) { this.time = time + timeLeft; this.setTime = timeLeft; }
1367
1370
 
1368
1371
  /** Unset the timer */
1369
1372
  unset() { this.time = undefined; }
1370
1373
 
1371
1374
  /** Returns true if set
1372
- * @return {Boolean} */
1375
+ * @return {boolean} */
1373
1376
  isSet() { return this.time != undefined; }
1374
1377
 
1375
1378
  /** Returns true if set and has not elapsed
1376
- * @return {Boolean} */
1379
+ * @return {boolean} */
1377
1380
  active() { return time < this.time; }
1378
1381
 
1379
1382
  /** Returns true if set and elapsed
1380
- * @return {Boolean} */
1383
+ * @return {boolean} */
1381
1384
  elapsed() { return time >= this.time; }
1382
1385
 
1383
1386
  /** Get how long since elapsed, returns 0 if not set (returns negative if currently active)
1384
- * @return {Number} */
1387
+ * @return {number} */
1385
1388
  get() { return this.isSet()? time - this.time : 0; }
1386
1389
 
1387
1390
  /** Get percentage elapsed based on time it was set to, returns 0 if not set
1388
- * @return {Number} */
1391
+ * @return {number} */
1389
1392
  getPercent() { return this.isSet()? 1-percent(this.time - time, 0, this.setTime) : 0; }
1390
1393
 
1391
1394
  /** Returns this timer expressed as a string
1392
- * @return {String} */
1395
+ * @return {string} */
1393
1396
  toString() { if (debug) { return this.isSet() ? Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ) : 'unset'; }}
1394
1397
 
1395
1398
  /** Get how long since elapsed, returns 0 if not set (returns negative if currently active)
1396
- * @return {Number} */
1399
+ * @return {number} */
1397
1400
  valueOf() { return this.get(); }
1398
1401
  }
1399
1402
  /**
@@ -1414,7 +1417,7 @@ class Timer
1414
1417
  let cameraPos = vec2();
1415
1418
 
1416
1419
  /** Scale of camera in world space
1417
- * @type {Number}
1420
+ * @type {number}
1418
1421
  * @default
1419
1422
  * @memberof Settings */
1420
1423
  let cameraScale = 32;
@@ -1436,31 +1439,34 @@ let canvasMaxSize = vec2(1920, 1080);
1436
1439
  let canvasFixedSize = vec2();
1437
1440
 
1438
1441
  /** Use nearest neighbor scaling algorithm for canvas for more pixelated look
1439
- * @type {Boolean}
1442
+ * - Must be set before startup to take effect
1443
+ * - If enabled sets css image-rendering:pixelated
1444
+ * @type {boolean}
1440
1445
  * @default
1441
1446
  * @memberof Settings */
1442
1447
  let canvasPixelated = true;
1443
1448
 
1444
1449
  /** Disables texture filtering for crisper pixel art
1445
- * @type {Boolean}
1450
+ * @type {boolean}
1446
1451
  * @default
1447
1452
  * @memberof Settings */
1448
1453
  let tilesPixelated = true;
1449
1454
 
1450
1455
  /** Default font used for text rendering
1451
- * @type {String}
1456
+ * @type {string}
1452
1457
  * @default
1453
1458
  * @memberof Settings */
1454
1459
  let fontDefault = 'arial';
1455
1460
 
1456
1461
  /** Enable to show the LittleJS splash screen be shown on startup
1457
- * @type {Boolean}
1462
+ * @type {boolean}
1458
1463
  * @default
1459
1464
  * @memberof Settings */
1460
1465
  let showSplashScreen = false;
1461
1466
 
1462
1467
  /** Disables all rendering, audio, and input for servers
1463
- * @type {Boolean}
1468
+ * - Must be set before startup to take effect
1469
+ * @type {boolean}
1464
1470
  * @default
1465
1471
  * @memberof Settings */
1466
1472
  let headlessMode = false;
@@ -1469,13 +1475,15 @@ let headlessMode = false;
1469
1475
  // WebGL settings
1470
1476
 
1471
1477
  /** Enable webgl rendering, webgl can be disabled and removed from build (with some features disabled)
1472
- * @type {Boolean}
1478
+ * - Must be set before startup to take effect
1479
+ * @type {boolean}
1473
1480
  * @default
1474
1481
  * @memberof Settings */
1475
1482
  let glEnable = true;
1476
1483
 
1477
1484
  /** Fixes slow rendering in some browsers by not compositing the WebGL canvas
1478
- * @type {Boolean}
1485
+ * - Must be set before startup to take effect
1486
+ * @type {boolean}
1479
1487
  * @default
1480
1488
  * @memberof Settings */
1481
1489
  let glOverlay = true;
@@ -1490,7 +1498,7 @@ let glOverlay = true;
1490
1498
  let tileSizeDefault = vec2(16);
1491
1499
 
1492
1500
  /** How many pixels smaller to draw tiles to prevent bleeding from neighbors
1493
- * @type {Number}
1501
+ * @type {number}
1494
1502
  * @default
1495
1503
  * @memberof Settings */
1496
1504
  let tileFixBleedScale = 0;
@@ -1499,55 +1507,55 @@ let tileFixBleedScale = 0;
1499
1507
  // Object settings
1500
1508
 
1501
1509
  /** Enable physics solver for collisions between objects
1502
- * @type {Boolean}
1510
+ * @type {boolean}
1503
1511
  * @default
1504
1512
  * @memberof Settings */
1505
1513
  let enablePhysicsSolver = true;
1506
1514
 
1507
1515
  /** Default object mass for collision calculations (how heavy objects are)
1508
- * @type {Number}
1516
+ * @type {number}
1509
1517
  * @default
1510
1518
  * @memberof Settings */
1511
1519
  let objectDefaultMass = 1;
1512
1520
 
1513
1521
  /** How much to slow velocity by each frame (0-1)
1514
- * @type {Number}
1522
+ * @type {number}
1515
1523
  * @default
1516
1524
  * @memberof Settings */
1517
1525
  let objectDefaultDamping = 1;
1518
1526
 
1519
1527
  /** How much to slow angular velocity each frame (0-1)
1520
- * @type {Number}
1528
+ * @type {number}
1521
1529
  * @default
1522
1530
  * @memberof Settings */
1523
1531
  let objectDefaultAngleDamping = 1;
1524
1532
 
1525
1533
  /** How much to bounce when a collision occurs (0-1)
1526
- * @type {Number}
1534
+ * @type {number}
1527
1535
  * @default
1528
1536
  * @memberof Settings */
1529
1537
  let objectDefaultElasticity = 0;
1530
1538
 
1531
1539
  /** How much to slow when touching (0-1)
1532
- * @type {Number}
1540
+ * @type {number}
1533
1541
  * @default
1534
1542
  * @memberof Settings */
1535
1543
  let objectDefaultFriction = .8;
1536
1544
 
1537
1545
  /** Clamp max speed to avoid fast objects missing collisions
1538
- * @type {Number}
1546
+ * @type {number}
1539
1547
  * @default
1540
1548
  * @memberof Settings */
1541
1549
  let objectMaxSpeed = 1;
1542
1550
 
1543
1551
  /** How much gravity to apply to objects along the Y axis, negative is down
1544
- * @type {Number}
1552
+ * @type {number}
1545
1553
  * @default
1546
1554
  * @memberof Settings */
1547
1555
  let gravity = 0;
1548
1556
 
1549
1557
  /** Scales emit rate of particles, useful for low graphics mode (0 disables particle emitters)
1550
- * @type {Number}
1558
+ * @type {number}
1551
1559
  * @default
1552
1560
  * @memberof Settings */
1553
1561
  let particleEmitRateScale = 1;
@@ -1556,58 +1564,59 @@ let particleEmitRateScale = 1;
1556
1564
  // Input settings
1557
1565
 
1558
1566
  /** Should gamepads be allowed
1559
- * @type {Boolean}
1567
+ * @type {boolean}
1560
1568
  * @default
1561
1569
  * @memberof Settings */
1562
1570
  let gamepadsEnable = true;
1563
1571
 
1564
1572
  /** If true, the dpad input is also routed to the left analog stick (for better accessability)
1565
- * @type {Boolean}
1573
+ * @type {boolean}
1566
1574
  * @default
1567
1575
  * @memberof Settings */
1568
1576
  let gamepadDirectionEmulateStick = true;
1569
1577
 
1570
1578
  /** If true the WASD keys are also routed to the direction keys (for better accessability)
1571
- * @type {Boolean}
1579
+ * @type {boolean}
1572
1580
  * @default
1573
1581
  * @memberof Settings */
1574
1582
  let inputWASDEmulateDirection = true;
1575
1583
 
1576
1584
  /** True if touch input is enabled for mobile devices
1577
1585
  * - Touch events will be routed to mouse events
1578
- * @type {Boolean}
1586
+ * - Must be set before startup to take effect
1587
+ * @type {boolean}
1579
1588
  * @default
1580
1589
  * @memberof Settings */
1581
1590
  let touchInputEnable = true;
1582
1591
 
1583
1592
  /** True if touch gamepad should appear on mobile devices
1584
1593
  * - Supports left analog stick, 4 face buttons and start button (button 9)
1585
- * - Must be set by end of gameInit to be activated
1586
- * @type {Boolean}
1594
+ * - Must be set before startup to take effect
1595
+ * @type {boolean}
1587
1596
  * @default
1588
1597
  * @memberof Settings */
1589
1598
  let touchGamepadEnable = false;
1590
1599
 
1591
1600
  /** True if touch gamepad should be analog stick or false to use if 8 way dpad
1592
- * @type {Boolean}
1601
+ * @type {boolean}
1593
1602
  * @default
1594
1603
  * @memberof Settings */
1595
1604
  let touchGamepadAnalog = true;
1596
1605
 
1597
1606
  /** Size of virtual gamepad for touch devices in pixels
1598
- * @type {Number}
1607
+ * @type {number}
1599
1608
  * @default
1600
1609
  * @memberof Settings */
1601
1610
  let touchGamepadSize = 99;
1602
1611
 
1603
1612
  /** Transparency of touch gamepad overlay
1604
- * @type {Number}
1613
+ * @type {number}
1605
1614
  * @default
1606
1615
  * @memberof Settings */
1607
1616
  let touchGamepadAlpha = .3;
1608
1617
 
1609
1618
  /** Allow vibration hardware if it exists
1610
- * @type {Boolean}
1619
+ * @type {boolean}
1611
1620
  * @default
1612
1621
  * @memberof Settings */
1613
1622
  let vibrateEnable = true;
@@ -1616,25 +1625,25 @@ let vibrateEnable = true;
1616
1625
  // Audio settings
1617
1626
 
1618
1627
  /** All audio code can be disabled and removed from build
1619
- * @type {Boolean}
1628
+ * @type {boolean}
1620
1629
  * @default
1621
1630
  * @memberof Settings */
1622
1631
  let soundEnable = true;
1623
1632
 
1624
1633
  /** Volume scale to apply to all sound, music and speech
1625
- * @type {Number}
1634
+ * @type {number}
1626
1635
  * @default
1627
1636
  * @memberof Settings */
1628
1637
  let soundVolume = .3;
1629
1638
 
1630
1639
  /** Default range where sound no longer plays
1631
- * @type {Number}
1640
+ * @type {number}
1632
1641
  * @default
1633
1642
  * @memberof Settings */
1634
1643
  let soundDefaultRange = 40;
1635
1644
 
1636
1645
  /** Default range percent to start tapering off sound (0-1)
1637
- * @type {Number}
1646
+ * @type {number}
1638
1647
  * @default
1639
1648
  * @memberof Settings */
1640
1649
  let soundDefaultTaper = .7;
@@ -1643,13 +1652,13 @@ let soundDefaultTaper = .7;
1643
1652
  // Medals settings
1644
1653
 
1645
1654
  /** How long to show medals for in seconds
1646
- * @type {Number}
1655
+ * @type {number}
1647
1656
  * @default
1648
1657
  * @memberof Settings */
1649
1658
  let medalDisplayTime = 5;
1650
1659
 
1651
1660
  /** How quickly to slide on/off medals in seconds
1652
- * @type {Number}
1661
+ * @type {number}
1653
1662
  * @default
1654
1663
  * @memberof Settings */
1655
1664
  let medalDisplaySlideTime = .5;
@@ -1660,14 +1669,8 @@ let medalDisplaySlideTime = .5;
1660
1669
  * @memberof Settings */
1661
1670
  let medalDisplaySize = vec2(640, 80);
1662
1671
 
1663
- /** Size of icon in medal display
1664
- * @type {Number}
1665
- * @default
1666
- * @memberof Settings */
1667
- let medalDisplayIconSize = 50;
1668
-
1669
1672
  /** Set to stop medals from being unlockable (like if cheats are enabled)
1670
- * @type {Boolean}
1673
+ * @type {boolean}
1671
1674
  * @default
1672
1675
  * @memberof Settings */
1673
1676
  let medalsPreventUnlock = false;
@@ -1681,7 +1684,7 @@ let medalsPreventUnlock = false;
1681
1684
  function setCameraPos(pos) { cameraPos = pos; }
1682
1685
 
1683
1686
  /** Set scale of camera in world space
1684
- * @param {Number} scale
1687
+ * @param {number} scale
1685
1688
  * @memberof Settings */
1686
1689
  function setCameraScale(scale) { cameraScale = scale; }
1687
1690
 
@@ -1696,37 +1699,37 @@ function setCanvasMaxSize(size) { canvasMaxSize = size; }
1696
1699
  function setCanvasFixedSize(size) { canvasFixedSize = size; }
1697
1700
 
1698
1701
  /** Use nearest neighbor scaling algorithm for canvas for more pixelated look
1699
- * @param {Boolean} pixelated
1702
+ * @param {boolean} pixelated
1700
1703
  * @memberof Settings */
1701
1704
  function setCanvasPixelated(pixelated) { canvasPixelated = pixelated; }
1702
1705
 
1703
1706
  /** Disables texture filtering for crisper pixel art
1704
- * @param {Boolean} pixelated
1707
+ * @param {boolean} pixelated
1705
1708
  * @memberof Settings */
1706
1709
  function setTilesPixelated(pixelated) { tilesPixelated = pixelated; }
1707
1710
 
1708
1711
  /** Set default font used for text rendering
1709
- * @param {String} font
1712
+ * @param {string} font
1710
1713
  * @memberof Settings */
1711
1714
  function setFontDefault(font) { fontDefault = font; }
1712
1715
 
1713
1716
  /** Set if the LittleJS splash screen be shown on startup
1714
- * @param {Boolean} show
1717
+ * @param {boolean} show
1715
1718
  * @memberof Settings */
1716
1719
  function setShowSplashScreen(show) { showSplashScreen = show; }
1717
1720
 
1718
1721
  /** Set to disable rendering, audio, and input for servers
1719
- * @param {Boolean} headless
1722
+ * @param {boolean} headless
1720
1723
  * @memberof Settings */
1721
1724
  function setHeadlessMode(headless) { headlessMode = headless; }
1722
1725
 
1723
1726
  /** Set if webgl rendering is enabled
1724
- * @param {Boolean} enable
1727
+ * @param {boolean} enable
1725
1728
  * @memberof Settings */
1726
1729
  function setGlEnable(enable) { glEnable = enable; }
1727
1730
 
1728
1731
  /** Set to not composite the WebGL canvas
1729
- * @param {Boolean} overlay
1732
+ * @param {boolean} overlay
1730
1733
  * @memberof Settings */
1731
1734
  function setGlOverlay(overlay) { glOverlay = overlay; }
1732
1735
 
@@ -1736,107 +1739,107 @@ function setGlOverlay(overlay) { glOverlay = overlay; }
1736
1739
  function setTileSizeDefault(size) { tileSizeDefault = size; }
1737
1740
 
1738
1741
  /** Set to prevent tile bleeding from neighbors in pixels
1739
- * @param {Number} scale
1742
+ * @param {number} scale
1740
1743
  * @memberof Settings */
1741
1744
  function setTileFixBleedScale(scale) { tileFixBleedScale = scale; }
1742
1745
 
1743
1746
  /** Set if collisions between objects are enabled
1744
- * @param {Boolean} enable
1747
+ * @param {boolean} enable
1745
1748
  * @memberof Settings */
1746
1749
  function setEnablePhysicsSolver(enable) { enablePhysicsSolver = enable; }
1747
1750
 
1748
1751
  /** Set default object mass for collision calculations
1749
- * @param {Number} mass
1752
+ * @param {number} mass
1750
1753
  * @memberof Settings */
1751
1754
  function setObjectDefaultMass(mass) { objectDefaultMass = mass; }
1752
1755
 
1753
1756
  /** Set how much to slow velocity by each frame
1754
- * @param {Number} damp
1757
+ * @param {number} damp
1755
1758
  * @memberof Settings */
1756
1759
  function setObjectDefaultDamping(damp) { objectDefaultDamping = damp; }
1757
1760
 
1758
1761
  /** Set how much to slow angular velocity each frame
1759
- * @param {Number} damp
1762
+ * @param {number} damp
1760
1763
  * @memberof Settings */
1761
1764
  function setObjectDefaultAngleDamping(damp) { objectDefaultAngleDamping = damp; }
1762
1765
 
1763
1766
  /** Set how much to bounce when a collision occur
1764
- * @param {Number} elasticity
1767
+ * @param {number} elasticity
1765
1768
  * @memberof Settings */
1766
1769
  function setObjectDefaultElasticity(elasticity) { objectDefaultElasticity = elasticity; }
1767
1770
 
1768
1771
  /** Set how much to slow when touching
1769
- * @param {Number} friction
1772
+ * @param {number} friction
1770
1773
  * @memberof Settings */
1771
1774
  function setObjectDefaultFriction(friction) { objectDefaultFriction = friction; }
1772
1775
 
1773
1776
  /** Set max speed to avoid fast objects missing collisions
1774
- * @param {Number} speed
1777
+ * @param {number} speed
1775
1778
  * @memberof Settings */
1776
1779
  function setObjectMaxSpeed(speed) { objectMaxSpeed = speed; }
1777
1780
 
1778
1781
  /** Set how much gravity to apply to objects along the Y axis
1779
- * @param {Number} newGravity
1782
+ * @param {number} newGravity
1780
1783
  * @memberof Settings */
1781
1784
  function setGravity(newGravity) { gravity = newGravity; }
1782
1785
 
1783
1786
  /** Set to scales emit rate of particles
1784
- * @param {Number} scale
1787
+ * @param {number} scale
1785
1788
  * @memberof Settings */
1786
1789
  function setParticleEmitRateScale(scale) { particleEmitRateScale = scale; }
1787
1790
 
1788
1791
  /** Set if gamepads are enabled
1789
- * @param {Boolean} enable
1792
+ * @param {boolean} enable
1790
1793
  * @memberof Settings */
1791
1794
  function setGamepadsEnable(enable) { gamepadsEnable = enable; }
1792
1795
 
1793
1796
  /** Set if the dpad input is also routed to the left analog stick
1794
- * @param {Boolean} enable
1797
+ * @param {boolean} enable
1795
1798
  * @memberof Settings */
1796
1799
  function setGamepadDirectionEmulateStick(enable) { gamepadDirectionEmulateStick = enable; }
1797
1800
 
1798
1801
  /** Set if true the WASD keys are also routed to the direction keys
1799
- * @param {Boolean} enable
1802
+ * @param {boolean} enable
1800
1803
  * @memberof Settings */
1801
1804
  function setInputWASDEmulateDirection(enable) { inputWASDEmulateDirection = enable; }
1802
1805
 
1803
1806
  /** Set if touch input is allowed
1804
- * @param {Boolean} enable
1807
+ * @param {boolean} enable
1805
1808
  * @memberof Settings */
1806
1809
  function setTouchInputEnable(enable) { touchInputEnable = enable; }
1807
1810
 
1808
1811
  /** Set if touch gamepad should appear on mobile devices
1809
- * @param {Boolean} enable
1812
+ * @param {boolean} enable
1810
1813
  * @memberof Settings */
1811
1814
  function setTouchGamepadEnable(enable) { touchGamepadEnable = enable; }
1812
1815
 
1813
1816
  /** Set if touch gamepad should be analog stick or 8 way dpad
1814
- * @param {Boolean} analog
1817
+ * @param {boolean} analog
1815
1818
  * @memberof Settings */
1816
1819
  function setTouchGamepadAnalog(analog) { touchGamepadAnalog = analog; }
1817
1820
 
1818
1821
  /** Set size of virtual gamepad for touch devices in pixels
1819
- * @param {Number} size
1822
+ * @param {number} size
1820
1823
  * @memberof Settings */
1821
1824
  function setTouchGamepadSize(size) { touchGamepadSize = size; }
1822
1825
 
1823
1826
  /** Set transparency of touch gamepad overlay
1824
- * @param {Number} alpha
1827
+ * @param {number} alpha
1825
1828
  * @memberof Settings */
1826
1829
  function setTouchGamepadAlpha(alpha) { touchGamepadAlpha = alpha; }
1827
1830
 
1828
1831
  /** Set to allow vibration hardware if it exists
1829
- * @param {Boolean} enable
1832
+ * @param {boolean} enable
1830
1833
  * @memberof Settings */
1831
1834
  function setVibrateEnable(enable) { vibrateEnable = enable; }
1832
1835
 
1833
1836
  /** Set to disable all audio code
1834
- * @param {Boolean} enable
1837
+ * @param {boolean} enable
1835
1838
  * @memberof Settings */
1836
1839
  function setSoundEnable(enable) { soundEnable = enable; }
1837
1840
 
1838
1841
  /** Set volume scale to apply to all sound, music and speech
1839
- * @param {Number} volume
1842
+ * @param {number} volume
1840
1843
  * @memberof Settings */
1841
1844
  function setSoundVolume(volume)
1842
1845
  {
@@ -1846,22 +1849,22 @@ function setSoundVolume(volume)
1846
1849
  }
1847
1850
 
1848
1851
  /** Set default range where sound no longer plays
1849
- * @param {Number} range
1852
+ * @param {number} range
1850
1853
  * @memberof Settings */
1851
1854
  function setSoundDefaultRange(range) { soundDefaultRange = range; }
1852
1855
 
1853
1856
  /** Set default range percent to start tapering off sound
1854
- * @param {Number} taper
1857
+ * @param {number} taper
1855
1858
  * @memberof Settings */
1856
1859
  function setSoundDefaultTaper(taper) { soundDefaultTaper = taper; }
1857
1860
 
1858
1861
  /** Set how long to show medals for in seconds
1859
- * @param {Number} time
1862
+ * @param {number} time
1860
1863
  * @memberof Settings */
1861
1864
  function setMedalDisplayTime(time) { medalDisplayTime = time; }
1862
1865
 
1863
1866
  /** Set how quickly to slide on/off medals in seconds
1864
- * @param {Number} time
1867
+ * @param {number} time
1865
1868
  * @memberof Settings */
1866
1869
  function setMedalDisplaySlideTime(time) { medalDisplaySlideTime = time; }
1867
1870
 
@@ -1870,23 +1873,18 @@ function setMedalDisplaySlideTime(time) { medalDisplaySlideTime = time; }
1870
1873
  * @memberof Settings */
1871
1874
  function setMedalDisplaySize(size) { medalDisplaySize = size; }
1872
1875
 
1873
- /** Set size of icon in medal display
1874
- * @param {Number} size
1875
- * @memberof Settings */
1876
- function setMedalDisplayIconSize(size) { medalDisplayIconSize = size; }
1877
-
1878
1876
  /** Set to stop medals from being unlockable
1879
- * @param {Boolean} preventUnlock
1877
+ * @param {boolean} preventUnlock
1880
1878
  * @memberof Settings */
1881
1879
  function setMedalsPreventUnlock(preventUnlock) { medalsPreventUnlock = preventUnlock; }
1882
1880
 
1883
1881
  /** Set if watermark with FPS should be shown
1884
- * @param {Boolean} show
1882
+ * @param {boolean} show
1885
1883
  * @memberof Debug */
1886
1884
  function setShowWatermark(show) { showWatermark = show; }
1887
1885
 
1888
1886
  /** Set key code used to toggle debug mode, Esc by default
1889
- * @param {String} key
1887
+ * @param {string} key
1890
1888
  * @memberof Debug */
1891
1889
  function setDebugKey(key) { debugKey = key; }
1892
1890
  /**
@@ -1926,9 +1924,9 @@ class EngineObject
1926
1924
  * @param {Vector2} [pos=(0,0)] - World space position of the object
1927
1925
  * @param {Vector2} [size=(1,1)] - World space size of the object
1928
1926
  * @param {TileInfo} [tileInfo] - Tile info to render object (undefined is untextured)
1929
- * @param {Number} [angle] - Angle the object is rotated by
1927
+ * @param {number} [angle] - Angle the object is rotated by
1930
1928
  * @param {Color} [color=(1,1,1,1)] - Color to apply to tile when rendered
1931
- * @param {Number} [renderOrder] - Objects sorted by renderOrder before being rendered
1929
+ * @param {number} [renderOrder] - Objects sorted by renderOrder before being rendered
1932
1930
  */
1933
1931
  constructor(pos=vec2(), size=vec2(1), tileInfo, angle=0, color=new Color, renderOrder=0)
1934
1932
  {
@@ -1944,57 +1942,59 @@ class EngineObject
1944
1942
  this.drawSize = undefined;
1945
1943
  /** @property {TileInfo} - Tile info to render object (undefined is untextured) */
1946
1944
  this.tileInfo = tileInfo;
1947
- /** @property {Number} - Angle to rotate the object */
1945
+ /** @property {number} - Angle to rotate the object */
1948
1946
  this.angle = angle;
1949
1947
  /** @property {Color} - Color to apply when rendered */
1950
1948
  this.color = color;
1951
1949
  /** @property {Color} - Additive color to apply when rendered */
1952
1950
  this.additiveColor = undefined;
1953
- /** @property {Boolean} - Should it flip along y axis when rendered */
1951
+ /** @property {boolean} - Should it flip along y axis when rendered */
1954
1952
  this.mirror = false;
1955
1953
 
1956
1954
  // physical properties
1957
- /** @property {Number} [mass=objectDefaultMass] - How heavy the object is, static if 0 */
1955
+ /** @property {number} [mass=objectDefaultMass] - How heavy the object is, static if 0 */
1958
1956
  this.mass = objectDefaultMass;
1959
- /** @property {Number} [damping=objectDefaultDamping] - How much to slow down velocity each frame (0-1) */
1957
+ /** @property {number} [damping=objectDefaultDamping] - How much to slow down velocity each frame (0-1) */
1960
1958
  this.damping = objectDefaultDamping;
1961
- /** @property {Number} [angleDamping=objectDefaultAngleDamping] - How much to slow down rotation each frame (0-1) */
1959
+ /** @property {number} [angleDamping=objectDefaultAngleDamping] - How much to slow down rotation each frame (0-1) */
1962
1960
  this.angleDamping = objectDefaultAngleDamping;
1963
- /** @property {Number} [elasticity=objectDefaultElasticity] - How bouncy the object is when colliding (0-1) */
1961
+ /** @property {number} [elasticity=objectDefaultElasticity] - How bouncy the object is when colliding (0-1) */
1964
1962
  this.elasticity = objectDefaultElasticity;
1965
- /** @property {Number} [friction=objectDefaultFriction] - How much friction to apply when sliding (0-1) */
1963
+ /** @property {number} [friction=objectDefaultFriction] - How much friction to apply when sliding (0-1) */
1966
1964
  this.friction = objectDefaultFriction;
1967
- /** @property {Number} - How much to scale gravity by for this object */
1965
+ /** @property {number} - How much to scale gravity by for this object */
1968
1966
  this.gravityScale = 1;
1969
- /** @property {Number} - Objects are sorted by render order */
1967
+ /** @property {number} - Objects are sorted by render order */
1970
1968
  this.renderOrder = renderOrder;
1971
1969
  /** @property {Vector2} - Velocity of the object */
1972
1970
  this.velocity = vec2();
1973
- /** @property {Number} - Angular velocity of the object */
1971
+ /** @property {number} - Angular velocity of the object */
1974
1972
  this.angleVelocity = 0;
1975
- /** @property {Number} - Track when object was created */
1973
+ /** @property {number} - Track when object was created */
1976
1974
  this.spawnTime = time;
1977
- /** @property {Array} - List of children of this object */
1975
+ /** @property {Array<EngineObject>} - List of children of this object */
1978
1976
  this.children = [];
1979
- /** @property {Boolean} - Limit object speed using linear or circular math */
1977
+ /** @property {boolean} - Limit object speed using linear or circular math */
1980
1978
  this.clampSpeedLinear = true;
1979
+ /** @property {EngineObject} - Object we are standing on, if any */
1980
+ this.groundObject = undefined;
1981
1981
 
1982
1982
  // parent child system
1983
1983
  /** @property {EngineObject} - Parent of object if in local space */
1984
1984
  this.parent = undefined;
1985
1985
  /** @property {Vector2} - Local position if child */
1986
1986
  this.localPos = vec2();
1987
- /** @property {Number} - Local angle if child */
1987
+ /** @property {number} - Local angle if child */
1988
1988
  this.localAngle = 0;
1989
1989
 
1990
1990
  // collision flags
1991
- /** @property {Boolean} - Object collides with the tile collision */
1991
+ /** @property {boolean} - Object collides with the tile collision */
1992
1992
  this.collideTiles = false;
1993
- /** @property {Boolean} - Object collides with solid objects */
1993
+ /** @property {boolean} - Object collides with solid objects */
1994
1994
  this.collideSolidObjects = false;
1995
- /** @property {Boolean} - Object collides with and blocks other objects */
1995
+ /** @property {boolean} - Object collides with and blocks other objects */
1996
1996
  this.isSolid = false;
1997
- /** @property {Boolean} - Object collides with raycasts */
1997
+ /** @property {boolean} - Object collides with raycasts */
1998
1998
  this.collideRaycast = false;
1999
1999
 
2000
2000
  // add to list of objects
@@ -2062,9 +2062,10 @@ class EngineObject
2062
2062
  if (this.groundObject)
2063
2063
  {
2064
2064
  // apply friction in local space of ground object
2065
- const groundSpeed = this.groundObject.velocity ? this.groundObject.velocity.x : 0;
2065
+ const groundSpeed = this.groundObject != this && this.groundObject.velocity ?
2066
+ this.groundObject.velocity.x : 0;
2066
2067
  this.velocity.x = groundSpeed + (this.velocity.x - groundSpeed) * this.friction;
2067
- this.groundObject = 0;
2068
+ this.groundObject = undefined;
2068
2069
  //debugOverlay && debugPhysics && debugPoint(this.pos.subtract(vec2(0,this.size.y/2)), '#0f0');
2069
2070
  }
2070
2071
 
@@ -2181,18 +2182,22 @@ class EngineObject
2181
2182
  // bounce velocity
2182
2183
  this.velocity.y *= -this.elasticity;
2183
2184
 
2184
- // set if landed on ground
2185
- if (this.groundObject = wasMovingDown)
2185
+ if (wasMovingDown)
2186
2186
  {
2187
2187
  // adjust position to slightly above nearest tile boundary
2188
2188
  // this prevents gap between object and ground
2189
2189
  const epsilon = .0001;
2190
2190
  this.pos.y = (oldPos.y-this.size.y/2|0)+this.size.y/2+epsilon;
2191
+
2192
+ // set ground object to self for tile collision
2193
+ // TODO: rework system so tile collision is its own object
2194
+ this.groundObject = this;
2191
2195
  }
2192
2196
  else
2193
2197
  {
2194
2198
  // move to previous position
2195
2199
  this.pos.y = oldPos.y;
2200
+ this.groundObject = undefined;
2196
2201
  }
2197
2202
  }
2198
2203
  if (isBlockedX)
@@ -2244,19 +2249,19 @@ class EngineObject
2244
2249
  worldToLocalVector(vec) { return vec.rotate(-this.angle); }
2245
2250
 
2246
2251
  /** Called to check if a tile collision should be resolved
2247
- * @param {Number} tileData - the value of the tile at the position
2252
+ * @param {number} tileData - the value of the tile at the position
2248
2253
  * @param {Vector2} pos - tile where the collision occurred
2249
- * @return {Boolean} - true if the collision should be resolved */
2254
+ * @return {boolean} - true if the collision should be resolved */
2250
2255
  collideWithTile(tileData, pos) { return tileData > 0; }
2251
2256
 
2252
2257
  /** Called to check if a object collision should be resolved
2253
2258
  * @param {EngineObject} object - the object to test against
2254
- * @return {Boolean} - true if the collision should be resolved
2259
+ * @return {boolean} - true if the collision should be resolved
2255
2260
  */
2256
2261
  collideWithObject(object) { return true; }
2257
2262
 
2258
2263
  /** How long since the object was created
2259
- * @return {Number} */
2264
+ * @return {number} */
2260
2265
  getAliveTime() { return time - this.spawnTime; }
2261
2266
 
2262
2267
  /** Apply acceleration to this object (adjust velocity, not affected by mass)
@@ -2268,13 +2273,13 @@ class EngineObject
2268
2273
  applyForce(force) { this.applyAcceleration(force.scale(1/this.mass)); }
2269
2274
 
2270
2275
  /** Get the direction of the mirror
2271
- * @return {Number} -1 if this.mirror is true, or 1 if not mirrored */
2276
+ * @return {number} -1 if this.mirror is true, or 1 if not mirrored */
2272
2277
  getMirrorSign() { return this.mirror ? -1 : 1; }
2273
2278
 
2274
2279
  /** Attaches a child to this with a given local transform
2275
2280
  * @param {EngineObject} child
2276
2281
  * @param {Vector2} [localPos=(0,0)]
2277
- * @param {Number} [localAngle] */
2282
+ * @param {number} [localAngle] */
2278
2283
  addChild(child, localPos=vec2(), localAngle=0)
2279
2284
  {
2280
2285
  ASSERT(!child.parent && !this.children.includes(child));
@@ -2294,10 +2299,10 @@ class EngineObject
2294
2299
  }
2295
2300
 
2296
2301
  /** Set how this object collides
2297
- * @param {Boolean} [collideSolidObjects] - Does it collide with solid objects?
2298
- * @param {Boolean} [isSolid] - Does it collide with and block other objects? (expensive in large numbers)
2299
- * @param {Boolean} [collideTiles] - Does it collide with the tile collision?
2300
- * @param {Boolean} [collideRaycast] - Does it collide with raycasts? */
2302
+ * @param {boolean} [collideSolidObjects] - Does it collide with solid objects?
2303
+ * @param {boolean} [isSolid] - Does it collide with and block other objects? (expensive in large numbers)
2304
+ * @param {boolean} [collideTiles] - Does it collide with the tile collision?
2305
+ * @param {boolean} [collideRaycast] - Does it collide with raycasts? */
2301
2306
  setCollision(collideSolidObjects=true, isSolid=true, collideTiles=true, collideRaycast=true)
2302
2307
  {
2303
2308
  ASSERT(collideSolidObjects || !isSolid, 'solid objects must be set to collide');
@@ -2309,7 +2314,7 @@ class EngineObject
2309
2314
  }
2310
2315
 
2311
2316
  /** Returns string containing info about this object for debugging
2312
- * @return {String} */
2317
+ * @return {string} */
2313
2318
  toString()
2314
2319
  {
2315
2320
  if (debug)
@@ -2407,10 +2412,10 @@ let drawCount;
2407
2412
  * Create a tile info object using a grid based system
2408
2413
  * - This can take vecs or floats for easier use and conversion
2409
2414
  * - If an index is passed in, the tile size and index will determine the position
2410
- * @param {(Number|Vector2)} [pos=0] - Index of tile in sheet
2411
- * @param {(Number|Vector2)} [size=tileSizeDefault] - Size of tile in pixels
2412
- * @param {Number} [textureIndex] - Texture index to use
2413
- * @param {Number} [padding] - How many pixels padding around tiles
2415
+ * @param {Vector2|number} [pos=0] - Index of tile in sheet
2416
+ * @param {Vector2|number} [size=tileSizeDefault] - Size of tile in pixels
2417
+ * @param {number} [textureIndex] - Texture index to use
2418
+ * @param {number} [padding] - How many pixels padding around tiles
2414
2419
  * @return {TileInfo}
2415
2420
  * @example
2416
2421
  * tile(2) // a tile at index 2 using the default tile size of 16
@@ -2454,8 +2459,8 @@ class TileInfo
2454
2459
  /** Create a tile info object
2455
2460
  * @param {Vector2} [pos=(0,0)] - Top left corner of tile in pixels
2456
2461
  * @param {Vector2} [size=tileSizeDefault] - Size of tile in pixels
2457
- * @param {Number} [textureIndex] - Texture index to use
2458
- * @param {Number} [padding] - How many pixels padding around tiles
2462
+ * @param {number} [textureIndex] - Texture index to use
2463
+ * @param {number} [padding] - How many pixels padding around tiles
2459
2464
  */
2460
2465
  constructor(pos=vec2(), size=tileSizeDefault, textureIndex=0, padding=0)
2461
2466
  {
@@ -2463,9 +2468,9 @@ class TileInfo
2463
2468
  this.pos = pos.copy();
2464
2469
  /** @property {Vector2} - Size of tile in pixels */
2465
2470
  this.size = size.copy();
2466
- /** @property {Number} - Texture index to use */
2471
+ /** @property {number} - Texture index to use */
2467
2472
  this.textureIndex = textureIndex;
2468
- /** @property {Number} - How many pixels padding around tiles */
2473
+ /** @property {number} - How many pixels padding around tiles */
2469
2474
  this.padding = padding;
2470
2475
  }
2471
2476
 
@@ -2477,7 +2482,7 @@ class TileInfo
2477
2482
  { return new TileInfo(this.pos.add(offset), this.size, this.textureIndex); }
2478
2483
 
2479
2484
  /** Returns a copy of this tile offset by a number of animation frames
2480
- * @param {Number} frame - Offset to apply in animation frames
2485
+ * @param {number} frame - Offset to apply in animation frames
2481
2486
  * @return {TileInfo}
2482
2487
  */
2483
2488
  frame(frame)
@@ -2549,11 +2554,11 @@ function getCameraSize() { return mainCanvasSize.scale(1/cameraScale); }
2549
2554
  * @param {Vector2} [size=(1,1)] - Size of the tile in world space
2550
2555
  * @param {TileInfo}[tileInfo] - Tile info to use, untextured if undefined
2551
2556
  * @param {Color} [color=(1,1,1,1)] - Color to modulate with
2552
- * @param {Number} [angle] - Angle to rotate by
2553
- * @param {Boolean} [mirror] - If true image is flipped along the Y axis
2557
+ * @param {number} [angle] - Angle to rotate by
2558
+ * @param {boolean} [mirror] - If true image is flipped along the Y axis
2554
2559
  * @param {Color} [additiveColor=(0,0,0,0)] - Additive color to be applied
2555
- * @param {Boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering
2556
- * @param {Boolean} [screenSpace=false] - If true the pos and size are in screen space
2560
+ * @param {boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering
2561
+ * @param {boolean} [screenSpace=false] - If true the pos and size are in screen space
2557
2562
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context] - Canvas 2D context to draw to
2558
2563
  * @memberof Draw */
2559
2564
  function drawTile(pos, size=vec2(1), tileInfo, color=new Color,
@@ -2628,9 +2633,9 @@ function drawTile(pos, size=vec2(1), tileInfo, color=new Color,
2628
2633
  * @param {Vector2} pos
2629
2634
  * @param {Vector2} [size=(1,1)]
2630
2635
  * @param {Color} [color=(1,1,1,1)]
2631
- * @param {Number} [angle]
2632
- * @param {Boolean} [useWebGL=glEnable]
2633
- * @param {Boolean} [screenSpace=false]
2636
+ * @param {number} [angle]
2637
+ * @param {boolean} [useWebGL=glEnable]
2638
+ * @param {boolean} [screenSpace=false]
2634
2639
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
2635
2640
  * @memberof Draw */
2636
2641
  function drawRect(pos, size, color, angle, useWebGL, screenSpace, context)
@@ -2641,10 +2646,10 @@ function drawRect(pos, size, color, angle, useWebGL, screenSpace, context)
2641
2646
  /** Draw colored line between two points
2642
2647
  * @param {Vector2} posA
2643
2648
  * @param {Vector2} posB
2644
- * @param {Number} [thickness]
2649
+ * @param {number} [thickness]
2645
2650
  * @param {Color} [color=(1,1,1,1)]
2646
- * @param {Boolean} [useWebGL=glEnable]
2647
- * @param {Boolean} [screenSpace=false]
2651
+ * @param {boolean} [useWebGL=glEnable]
2652
+ * @param {boolean} [screenSpace=false]
2648
2653
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
2649
2654
  * @memberof Draw */
2650
2655
  function drawLine(posA, posB, thickness=.1, color, useWebGL, screenSpace, context)
@@ -2655,11 +2660,11 @@ function drawLine(posA, posB, thickness=.1, color, useWebGL, screenSpace, contex
2655
2660
  }
2656
2661
 
2657
2662
  /** Draw colored polygon using passed in points
2658
- * @param {Array} points - Array of Vector2 points
2663
+ * @param {Array<Vector2>} points - Array of Vector2 points
2659
2664
  * @param {Color} [color=(1,1,1,1)]
2660
- * @param {Number} [lineWidth=0]
2665
+ * @param {number} [lineWidth=0]
2661
2666
  * @param {Color} [lineColor=(0,0,0,1)]
2662
- * @param {Boolean} [screenSpace=false]
2667
+ * @param {boolean} [screenSpace=false]
2663
2668
  * @param {CanvasRenderingContext2D} [context=mainContext]
2664
2669
  * @memberof Draw */
2665
2670
  function drawPoly(points, color=new Color, lineWidth=0, lineColor=new Color(0,0,0), screenSpace, context=mainContext)
@@ -2681,13 +2686,13 @@ function drawPoly(points, color=new Color, lineWidth=0, lineColor=new Color(0,0,
2681
2686
 
2682
2687
  /** Draw colored ellipse using passed in point
2683
2688
  * @param {Vector2} pos
2684
- * @param {Number} [width=1]
2685
- * @param {Number} [height=1]
2686
- * @param {Number} [angle=0]
2689
+ * @param {number} [width=1]
2690
+ * @param {number} [height=1]
2691
+ * @param {number} [angle=0]
2687
2692
  * @param {Color} [color=(1,1,1,1)]
2688
- * @param {Number} [lineWidth=0]
2693
+ * @param {number} [lineWidth=0]
2689
2694
  * @param {Color} [lineColor=(0,0,0,1)]
2690
- * @param {Boolean} [screenSpace=false]
2695
+ * @param {boolean} [screenSpace=false]
2691
2696
  * @param {CanvasRenderingContext2D} [context=mainContext]
2692
2697
  * @memberof Draw */
2693
2698
  function drawEllipse(pos, width=1, height=1, angle=0, color=new Color, lineWidth=0, lineColor=new Color(0,0,0), screenSpace, context=mainContext)
@@ -2714,11 +2719,11 @@ function drawEllipse(pos, width=1, height=1, angle=0, color=new Color, lineWidth
2714
2719
 
2715
2720
  /** Draw colored circle using passed in point
2716
2721
  * @param {Vector2} pos
2717
- * @param {Number} [radius=1]
2722
+ * @param {number} [radius=1]
2718
2723
  * @param {Color} [color=(1,1,1,1)]
2719
- * @param {Number} [lineWidth=0]
2724
+ * @param {number} [lineWidth=0]
2720
2725
  * @param {Color} [lineColor=(0,0,0,1)]
2721
- * @param {Boolean} [screenSpace=false]
2726
+ * @param {boolean} [screenSpace=false]
2722
2727
  * @param {CanvasRenderingContext2D} [context=mainContext]
2723
2728
  * @memberof Draw */
2724
2729
  function drawCircle(pos, radius=1, color=new Color, lineWidth=0, lineColor=new Color(0,0,0), screenSpace, context=mainContext)
@@ -2727,10 +2732,10 @@ function drawCircle(pos, radius=1, color=new Color, lineWidth=0, lineColor=new C
2727
2732
  /** Draw directly to a 2d canvas context in world space
2728
2733
  * @param {Vector2} pos
2729
2734
  * @param {Vector2} size
2730
- * @param {Number} angle
2731
- * @param {Boolean} mirror
2735
+ * @param {number} angle
2736
+ * @param {boolean} mirror
2732
2737
  * @param {Function} drawFunction
2733
- * @param {Boolean} [screenSpace=false]
2738
+ * @param {boolean} [screenSpace=false]
2734
2739
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=mainContext]
2735
2740
  * @memberof Draw */
2736
2741
  function drawCanvas2D(pos, size, angle, mirror, drawFunction, screenSpace, context=mainContext)
@@ -2751,15 +2756,15 @@ function drawCanvas2D(pos, size, angle, mirror, drawFunction, screenSpace, conte
2751
2756
 
2752
2757
  /** Draw text on main canvas in world space
2753
2758
  * Automatically splits new lines into rows
2754
- * @param {String} text
2759
+ * @param {string} text
2755
2760
  * @param {Vector2} pos
2756
- * @param {Number} [size]
2761
+ * @param {number} [size]
2757
2762
  * @param {Color} [color=(1,1,1,1)]
2758
- * @param {Number} [lineWidth]
2763
+ * @param {number} [lineWidth]
2759
2764
  * @param {Color} [lineColor=(0,0,0,1)]
2760
2765
  * @param {CanvasTextAlign} [textAlign='center']
2761
- * @param {String} [font=fontDefault]
2762
- * @param {Number} [maxWidth]
2766
+ * @param {string} [font=fontDefault]
2767
+ * @param {number} [maxWidth]
2763
2768
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=mainContext]
2764
2769
  * @memberof Draw */
2765
2770
  function drawText(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, font, maxWidth, context=mainContext)
@@ -2769,15 +2774,15 @@ function drawText(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, f
2769
2774
 
2770
2775
  /** Draw text on overlay canvas in world space
2771
2776
  * Automatically splits new lines into rows
2772
- * @param {String} text
2777
+ * @param {string} text
2773
2778
  * @param {Vector2} pos
2774
- * @param {Number} [size]
2779
+ * @param {number} [size]
2775
2780
  * @param {Color} [color=(1,1,1,1)]
2776
- * @param {Number} [lineWidth]
2781
+ * @param {number} [lineWidth]
2777
2782
  * @param {Color} [lineColor=(0,0,0,1)]
2778
2783
  * @param {CanvasTextAlign} [textAlign='center']
2779
- * @param {String} [font=fontDefault]
2780
- * @param {Number} [maxWidth]
2784
+ * @param {string} [font=fontDefault]
2785
+ * @param {number} [maxWidth]
2781
2786
  * @memberof Draw */
2782
2787
  function drawTextOverlay(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, font, maxWidth)
2783
2788
  {
@@ -2786,15 +2791,15 @@ function drawTextOverlay(text, pos, size=1, color, lineWidth=0, lineColor, textA
2786
2791
 
2787
2792
  /** Draw text on overlay canvas in screen space
2788
2793
  * Automatically splits new lines into rows
2789
- * @param {String} text
2794
+ * @param {string} text
2790
2795
  * @param {Vector2} pos
2791
- * @param {Number} [size]
2796
+ * @param {number} [size]
2792
2797
  * @param {Color} [color=(1,1,1,1)]
2793
- * @param {Number} [lineWidth]
2798
+ * @param {number} [lineWidth]
2794
2799
  * @param {Color} [lineColor=(0,0,0,1)]
2795
2800
  * @param {CanvasTextAlign} [textAlign]
2796
- * @param {String} [font=fontDefault]
2797
- * @param {Number} [maxWidth]
2801
+ * @param {string} [font=fontDefault]
2802
+ * @param {number} [maxWidth]
2798
2803
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=overlayContext]
2799
2804
  * @memberof Draw */
2800
2805
  function drawTextScreen(text, pos, size=1, color=new Color, lineWidth=0, lineColor=new Color(0,0,0), textAlign='center', font=fontDefault, maxWidth=undefined, context=overlayContext)
@@ -2820,8 +2825,8 @@ function drawTextScreen(text, pos, size=1, color=new Color, lineWidth=0, lineCol
2820
2825
  }
2821
2826
 
2822
2827
  /** Enable normal or additive blend mode
2823
- * @param {Boolean} [additive]
2824
- * @param {Boolean} [useWebGL=glEnable]
2828
+ * @param {boolean} [additive]
2829
+ * @param {boolean} [useWebGL=glEnable]
2825
2830
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=mainContext]
2826
2831
  * @memberof Draw */
2827
2832
  function setBlendMode(additive, useWebGL=glEnable, context)
@@ -2888,10 +2893,10 @@ class FontImage
2888
2893
  }
2889
2894
 
2890
2895
  /** Draw text in world space using the image font
2891
- * @param {String} text
2896
+ * @param {string} text
2892
2897
  * @param {Vector2} pos
2893
- * @param {Number} [scale=.25]
2894
- * @param {Boolean} [center]
2898
+ * @param {number} [scale=.25]
2899
+ * @param {boolean} [center]
2895
2900
  */
2896
2901
  drawText(text, pos, scale=1, center)
2897
2902
  {
@@ -2899,10 +2904,10 @@ class FontImage
2899
2904
  }
2900
2905
 
2901
2906
  /** Draw text in screen space using the image font
2902
- * @param {String} text
2907
+ * @param {string} text
2903
2908
  * @param {Vector2} pos
2904
- * @param {Number} [scale]
2905
- * @param {Boolean} [center]
2909
+ * @param {number} [scale]
2910
+ * @param {boolean} [center]
2906
2911
  */
2907
2912
  drawTextScreen(text, pos, scale=4, center)
2908
2913
  {
@@ -2940,7 +2945,7 @@ class FontImage
2940
2945
  // Display functions
2941
2946
 
2942
2947
  /** Returns true if fullscreen mode is active
2943
- * @return {Boolean}
2948
+ * @return {boolean}
2944
2949
  * @memberof Draw */
2945
2950
  function isFullscreen() { return !!document.fullscreenElement; }
2946
2951
 
@@ -2959,7 +2964,7 @@ function toggleFullscreen()
2959
2964
  }
2960
2965
 
2961
2966
  /** Set the cursor style
2962
- * @param {String} cursorStyle - CSS cursor style (auto, none, crosshair, etc)
2967
+ * @param {string} cursorStyle - CSS cursor style (auto, none, crosshair, etc)
2963
2968
  * @memberof Draw */
2964
2969
  function setCursor(cursorStyle = 'auto')
2965
2970
  {
@@ -2979,9 +2984,9 @@ function setCursor(cursorStyle = 'auto')
2979
2984
 
2980
2985
 
2981
2986
  /** Returns true if device key is down
2982
- * @param {String|Number} key
2983
- * @param {Number} [device]
2984
- * @return {Boolean}
2987
+ * @param {string|number} key
2988
+ * @param {number} [device]
2989
+ * @return {boolean}
2985
2990
  * @memberof Input */
2986
2991
  function keyIsDown(key, device=0)
2987
2992
  {
@@ -2990,9 +2995,9 @@ function keyIsDown(key, device=0)
2990
2995
  }
2991
2996
 
2992
2997
  /** Returns true if device key was pressed this frame
2993
- * @param {String|Number} key
2994
- * @param {Number} [device]
2995
- * @return {Boolean}
2998
+ * @param {string|number} key
2999
+ * @param {number} [device]
3000
+ * @return {boolean}
2996
3001
  * @memberof Input */
2997
3002
  function keyWasPressed(key, device=0)
2998
3003
  {
@@ -3001,9 +3006,9 @@ function keyWasPressed(key, device=0)
3001
3006
  }
3002
3007
 
3003
3008
  /** Returns true if device key was released this frame
3004
- * @param {String|Number} key
3005
- * @param {Number} [device]
3006
- * @return {Boolean}
3009
+ * @param {string|number} key
3010
+ * @param {number} [device]
3011
+ * @return {boolean}
3007
3012
  * @memberof Input */
3008
3013
  function keyWasReleased(key, device=0)
3009
3014
  {
@@ -3026,22 +3031,22 @@ function clearInput() { inputData = [[]]; touchGamepadButtons = []; }
3026
3031
 
3027
3032
  /** Returns true if mouse button is down
3028
3033
  * @function
3029
- * @param {Number} button
3030
- * @return {Boolean}
3034
+ * @param {number} button
3035
+ * @return {boolean}
3031
3036
  * @memberof Input */
3032
3037
  const mouseIsDown = keyIsDown;
3033
3038
 
3034
3039
  /** Returns true if mouse button was pressed
3035
3040
  * @function
3036
- * @param {Number} button
3037
- * @return {Boolean}
3041
+ * @param {number} button
3042
+ * @return {boolean}
3038
3043
  * @memberof Input */
3039
3044
  const mouseWasPressed = keyWasPressed;
3040
3045
 
3041
3046
  /** Returns true if mouse button was released
3042
3047
  * @function
3043
- * @param {Number} button
3044
- * @return {Boolean}
3048
+ * @param {number} button
3049
+ * @return {boolean}
3045
3050
  * @memberof Input */
3046
3051
  const mouseWasReleased = keyWasReleased;
3047
3052
 
@@ -3056,47 +3061,53 @@ let mousePos = vec2();
3056
3061
  let mousePosScreen = vec2();
3057
3062
 
3058
3063
  /** Mouse wheel delta this frame
3059
- * @type {Number}
3064
+ * @type {number}
3060
3065
  * @memberof Input */
3061
3066
  let mouseWheel = 0;
3062
3067
 
3063
3068
  /** Returns true if user is using gamepad (has more recently pressed a gamepad button)
3064
- * @type {Boolean}
3069
+ * @type {boolean}
3065
3070
  * @memberof Input */
3066
3071
  let isUsingGamepad = false;
3067
3072
 
3068
- /** Prevents input continuing to the default browser handling (false by default)
3069
- * @type {Boolean}
3073
+ /** Prevents input continuing to the default browser handling (true by default)
3074
+ * @type {boolean}
3075
+ * @memberof Input */
3076
+ let inputPreventDefault = true;
3077
+
3078
+ /** Prevents input continuing to the default browser handling
3079
+ * This is useful to disable for html menus so the browser can handle input normally
3080
+ * @param {boolean} preventDefault
3070
3081
  * @memberof Input */
3071
- let preventDefaultInput = false;
3082
+ function setInputPreventDefault(preventDefault) { inputPreventDefault = preventDefault; }
3072
3083
 
3073
3084
  /** Returns true if gamepad button is down
3074
- * @param {Number} button
3075
- * @param {Number} [gamepad]
3076
- * @return {Boolean}
3085
+ * @param {number} button
3086
+ * @param {number} [gamepad]
3087
+ * @return {boolean}
3077
3088
  * @memberof Input */
3078
3089
  function gamepadIsDown(button, gamepad=0)
3079
3090
  { return keyIsDown(button, gamepad+1); }
3080
3091
 
3081
3092
  /** Returns true if gamepad button was pressed
3082
- * @param {Number} button
3083
- * @param {Number} [gamepad]
3084
- * @return {Boolean}
3093
+ * @param {number} button
3094
+ * @param {number} [gamepad]
3095
+ * @return {boolean}
3085
3096
  * @memberof Input */
3086
3097
  function gamepadWasPressed(button, gamepad=0)
3087
3098
  { return keyWasPressed(button, gamepad+1); }
3088
3099
 
3089
3100
  /** Returns true if gamepad button was released
3090
- * @param {Number} button
3091
- * @param {Number} [gamepad]
3092
- * @return {Boolean}
3101
+ * @param {number} button
3102
+ * @param {number} [gamepad]
3103
+ * @return {boolean}
3093
3104
  * @memberof Input */
3094
3105
  function gamepadWasReleased(button, gamepad=0)
3095
3106
  { return keyWasReleased(button, gamepad+1); }
3096
3107
 
3097
3108
  /** Returns gamepad stick value
3098
- * @param {Number} stick
3099
- * @param {Number} [gamepad]
3109
+ * @param {number} stick
3110
+ * @param {number} [gamepad]
3100
3111
  * @return {Vector2}
3101
3112
  * @memberof Input */
3102
3113
  function gamepadStick(stick, gamepad=0)
@@ -3148,7 +3159,6 @@ function inputInit()
3148
3159
  if (inputWASDEmulateDirection)
3149
3160
  inputData[0][remapKey(e.code)] = 3;
3150
3161
  }
3151
- preventDefaultInput && e.preventDefault();
3152
3162
  }
3153
3163
 
3154
3164
  onkeyup = (e)=>
@@ -3178,7 +3188,7 @@ function inputInit()
3178
3188
  isUsingGamepad = false;
3179
3189
  inputData[0][e.button] = 3;
3180
3190
  mousePosScreen = mouseEventToScreen(e);
3181
- e.button && e.preventDefault();
3191
+ inputPreventDefault && e.button && e.preventDefault();
3182
3192
  }
3183
3193
  onmouseup = (e)=> inputData[0][e.button] = inputData[0][e.button] & 2 | 4;
3184
3194
  onmousemove = (e)=> mousePosScreen = mouseEventToScreen(e);
@@ -3299,7 +3309,7 @@ function gamepadsUpdate()
3299
3309
  ///////////////////////////////////////////////////////////////////////////////
3300
3310
 
3301
3311
  /** Pulse the vibration hardware if it exists
3302
- * @param {Number|Array} [pattern] - single value in ms or vibration interval array
3312
+ * @param {number|Array} [pattern] - single value in ms or vibration interval array
3303
3313
  * @memberof Input */
3304
3314
  function vibrate(pattern=100)
3305
3315
  { vibrateEnable && !headlessMode && navigator && navigator.vibrate && navigator.vibrate(pattern); }
@@ -3362,7 +3372,7 @@ function touchInputInit()
3362
3372
  wasTouching = touching;
3363
3373
 
3364
3374
  // prevent default handling like copy and magnifier lens
3365
- if (document.hasFocus()) // allow document to get focus
3375
+ if (inputPreventDefault && document.hasFocus()) // allow document to get focus
3366
3376
  e.preventDefault();
3367
3377
 
3368
3378
  // must return true so the document will get focus
@@ -3534,20 +3544,20 @@ class Sound
3534
3544
  {
3535
3545
  /** Create a sound object and cache the zzfx samples for later use
3536
3546
  * @param {Array} zzfxSound - Array of zzfx parameters, ex. [.5,.5]
3537
- * @param {Number} [range=soundDefaultRange] - World space max range of sound, will not play if camera is farther away
3538
- * @param {Number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering
3547
+ * @param {number} [range=soundDefaultRange] - World space max range of sound, will not play if camera is farther away
3548
+ * @param {number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering
3539
3549
  */
3540
3550
  constructor(zzfxSound, range=soundDefaultRange, taper=soundDefaultTaper)
3541
3551
  {
3542
3552
  if (!soundEnable || headlessMode) return;
3543
3553
 
3544
- /** @property {Number} - World space max range of sound, will not play if camera is farther away */
3554
+ /** @property {number} - World space max range of sound, will not play if camera is farther away */
3545
3555
  this.range = range;
3546
3556
 
3547
- /** @property {Number} - At what percentage of range should it start tapering off */
3557
+ /** @property {number} - At what percentage of range should it start tapering off */
3548
3558
  this.taper = taper;
3549
3559
 
3550
- /** @property {Number} - How much to randomize frequency each time sound plays */
3560
+ /** @property {number} - How much to randomize frequency each time sound plays */
3551
3561
  this.randomness = 0;
3552
3562
 
3553
3563
  if (zzfxSound)
@@ -3563,10 +3573,10 @@ class Sound
3563
3573
 
3564
3574
  /** Play the sound
3565
3575
  * @param {Vector2} [pos] - World space position to play the sound, sound is not attenuated if null
3566
- * @param {Number} [volume] - How much to scale volume by (in addition to range fade)
3567
- * @param {Number} [pitch] - How much to scale pitch by (also adjusted by this.randomness)
3568
- * @param {Number} [randomnessScale] - How much to scale randomness
3569
- * @param {Boolean} [loop] - Should the sound loop
3576
+ * @param {number} [volume] - How much to scale volume by (in addition to range fade)
3577
+ * @param {number} [pitch] - How much to scale pitch by (also adjusted by this.randomness)
3578
+ * @param {number} [randomnessScale] - How much to scale randomness
3579
+ * @param {boolean} [loop] - Should the sound loop
3570
3580
  * @return {AudioBufferSourceNode} - The audio source node
3571
3581
  */
3572
3582
  play(pos, volume=1, pitch=1, randomnessScale=1, loop=false)
@@ -3601,7 +3611,7 @@ class Sound
3601
3611
  }
3602
3612
 
3603
3613
  /** Set the sound volume of the most recently played instance of this sound
3604
- * @param {Number} [volume] - How much to scale volume by
3614
+ * @param {number} [volume] - How much to scale volume by
3605
3615
  */
3606
3616
  setVolume(volume=1)
3607
3617
  {
@@ -3623,22 +3633,22 @@ class Sound
3623
3633
  getSource() { return this.source; }
3624
3634
 
3625
3635
  /** Play the sound as a note with a semitone offset
3626
- * @param {Number} semitoneOffset - How many semitones to offset pitch
3636
+ * @param {number} semitoneOffset - How many semitones to offset pitch
3627
3637
  * @param {Vector2} [pos] - World space position to play the sound, sound is not attenuated if null
3628
- * @param {Number} [volume=1] - How much to scale volume by (in addition to range fade)
3638
+ * @param {number} [volume=1] - How much to scale volume by (in addition to range fade)
3629
3639
  * @return {AudioBufferSourceNode} - The audio source node
3630
3640
  */
3631
3641
  playNote(semitoneOffset, pos, volume)
3632
3642
  { return this.play(pos, volume, 2**(semitoneOffset/12), 0); }
3633
3643
 
3634
3644
  /** Get how long this sound is in seconds
3635
- * @return {Number} - How long the sound is in seconds (undefined if loading)
3645
+ * @return {number} - How long the sound is in seconds (undefined if loading)
3636
3646
  */
3637
3647
  getDuration()
3638
3648
  { return this.sampleChannels && this.sampleChannels[0].length / this.sampleRate; }
3639
3649
 
3640
3650
  /** Check if sound is loading, for sounds fetched from a url
3641
- * @return {Boolean} - True if sound is loading and not ready to play
3651
+ * @return {boolean} - True if sound is loading and not ready to play
3642
3652
  */
3643
3653
  isLoading() { return !this.sampleChannels; }
3644
3654
  }
@@ -3656,10 +3666,10 @@ class Sound
3656
3666
  class SoundWave extends Sound
3657
3667
  {
3658
3668
  /** Create a sound object and cache the wave file for later use
3659
- * @param {String} filename - Filename of audio file to load
3660
- * @param {Number} [randomness] - How much to randomize frequency each time sound plays
3661
- * @param {Number} [range=soundDefaultRange] - World space max range of sound, will not play if camera is farther away
3662
- * @param {Number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering off
3669
+ * @param {string} filename - Filename of audio file to load
3670
+ * @param {number} [randomness] - How much to randomize frequency each time sound plays
3671
+ * @param {number} [range=soundDefaultRange] - World space max range of sound, will not play if camera is farther away
3672
+ * @param {number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering off
3663
3673
  * @param {Function} [onloadCallback] - callback function to call when sound is loaded
3664
3674
  */
3665
3675
  constructor(filename, randomness=0, range, taper, onloadCallback)
@@ -3682,9 +3692,9 @@ class SoundWave extends Sound
3682
3692
  }
3683
3693
 
3684
3694
  /** Play an mp3, ogg, or wav audio from a local file or url
3685
- * @param {String} filename - Location of sound file to play
3686
- * @param {Number} [volume] - How much to scale volume by
3687
- * @param {Boolean} [loop] - True if the music should loop
3695
+ * @param {string} filename - Location of sound file to play
3696
+ * @param {number} [volume] - How much to scale volume by
3697
+ * @param {boolean} [loop] - True if the music should loop
3688
3698
  * @return {SoundWave} - The sound object for this file
3689
3699
  * @memberof Audio */
3690
3700
  function playAudioFile(filename, volume=1, loop=false)
@@ -3727,7 +3737,7 @@ function playAudioFile(filename, volume=1, loop=false)
3727
3737
  class Music extends Sound
3728
3738
  {
3729
3739
  /** Create a music object and cache the zzfx music samples for later use
3730
- * @param {[Array, Array, Array, Number]} zzfxMusic - Array of zzfx music parameters
3740
+ * @param {[Array, Array, Array, number]} zzfxMusic - Array of zzfx music parameters
3731
3741
  */
3732
3742
  constructor(zzfxMusic)
3733
3743
  {
@@ -3740,8 +3750,8 @@ class Music extends Sound
3740
3750
  }
3741
3751
 
3742
3752
  /** Play the music
3743
- * @param {Number} [volume=1] - How much to scale volume by
3744
- * @param {Boolean} [loop] - True if the music should loop
3753
+ * @param {number} [volume=1] - How much to scale volume by
3754
+ * @param {boolean} [loop] - True if the music should loop
3745
3755
  * @return {AudioBufferSourceNode} - The audio source node
3746
3756
  */
3747
3757
  playMusic(volume, loop=false)
@@ -3749,11 +3759,11 @@ class Music extends Sound
3749
3759
  }
3750
3760
 
3751
3761
  /** Speak text with passed in settings
3752
- * @param {String} text - The text to speak
3753
- * @param {String} [language] - The language/accent to use (examples: en, it, ru, ja, zh)
3754
- * @param {Number} [volume] - How much to scale volume by
3755
- * @param {Number} [rate] - How quickly to speak
3756
- * @param {Number} [pitch] - How much to change the pitch by
3762
+ * @param {string} text - The text to speak
3763
+ * @param {string} [language] - The language/accent to use (examples: en, it, ru, ja, zh)
3764
+ * @param {number} [volume] - How much to scale volume by
3765
+ * @param {number} [rate] - How quickly to speak
3766
+ * @param {number} [pitch] - How much to change the pitch by
3757
3767
  * @return {SpeechSynthesisUtterance} - The utterance that was spoken
3758
3768
  * @memberof Audio */
3759
3769
  function speak(text, language='', volume=1, rate=1, pitch=1)
@@ -3780,9 +3790,9 @@ function speak(text, language='', volume=1, rate=1, pitch=1)
3780
3790
  function speakStop() {speechSynthesis && speechSynthesis.cancel();}
3781
3791
 
3782
3792
  /** Get frequency of a note on a musical scale
3783
- * @param {Number} semitoneOffset - How many semitones away from the root note
3784
- * @param {Number} [rootFrequency=220] - Frequency at semitone offset 0
3785
- * @return {Number} - The frequency of the note
3793
+ * @param {number} semitoneOffset - How many semitones away from the root note
3794
+ * @param {number} [rootFrequency=220] - Frequency at semitone offset 0
3795
+ * @return {number} - The frequency of the note
3786
3796
  * @memberof Audio */
3787
3797
  function getNoteFrequency(semitoneOffset, rootFrequency=220)
3788
3798
  { return rootFrequency * 2**(semitoneOffset/12); }
@@ -3791,11 +3801,11 @@ function getNoteFrequency(semitoneOffset, rootFrequency=220)
3791
3801
 
3792
3802
  /** Play cached audio samples with given settings
3793
3803
  * @param {Array} sampleChannels - Array of arrays of samples to play (for stereo playback)
3794
- * @param {Number} [volume] - How much to scale volume by
3795
- * @param {Number} [rate] - The playback rate to use
3796
- * @param {Number} [pan] - How much to apply stereo panning
3797
- * @param {Boolean} [loop] - True if the sound should loop when it reaches the end
3798
- * @param {Number} [sampleRate=44100] - Sample rate for the sound
3804
+ * @param {number} [volume] - How much to scale volume by
3805
+ * @param {number} [rate] - The playback rate to use
3806
+ * @param {number} [pan] - How much to apply stereo panning
3807
+ * @param {boolean} [loop] - True if the sound should loop when it reaches the end
3808
+ * @param {number} [sampleRate=44100] - Sample rate for the sound
3799
3809
  * @param {GainNode} [gainNode] - Optional gain node for volume control while playing
3800
3810
  * @return {AudioBufferSourceNode} - The audio node of the sound played
3801
3811
  * @memberof Audio */
@@ -3854,27 +3864,27 @@ function zzfx(...zzfxSound) { return playSamples([zzfxG(...zzfxSound)]); }
3854
3864
  const zzfxR = 44100;
3855
3865
 
3856
3866
  /** Generate samples for a ZzFX sound
3857
- * @param {Number} [volume] - Volume scale (percent)
3858
- * @param {Number} [randomness] - How much to randomize frequency (percent Hz)
3859
- * @param {Number} [frequency] - Frequency of sound (Hz)
3860
- * @param {Number} [attack] - Attack time, how fast sound starts (seconds)
3861
- * @param {Number} [sustain] - Sustain time, how long sound holds (seconds)
3862
- * @param {Number} [release] - Release time, how fast sound fades out (seconds)
3863
- * @param {Number} [shape] - Shape of the sound wave
3864
- * @param {Number} [shapeCurve] - Squareness of wave (0=square, 1=normal, 2=pointy)
3865
- * @param {Number} [slide] - How much to slide frequency (kHz/s)
3866
- * @param {Number} [deltaSlide] - How much to change slide (kHz/s/s)
3867
- * @param {Number} [pitchJump] - Frequency of pitch jump (Hz)
3868
- * @param {Number} [pitchJumpTime] - Time of pitch jump (seconds)
3869
- * @param {Number} [repeatTime] - Resets some parameters periodically (seconds)
3870
- * @param {Number} [noise] - How much random noise to add (percent)
3871
- * @param {Number} [modulation] - Frequency of modulation wave, negative flips phase (Hz)
3872
- * @param {Number} [bitCrush] - Resamples at a lower frequency in (samples*100)
3873
- * @param {Number} [delay] - Overlap sound with itself for reverb and flanger effects (seconds)
3874
- * @param {Number} [sustainVolume] - Volume level for sustain (percent)
3875
- * @param {Number} [decay] - Decay time, how long to reach sustain after attack (seconds)
3876
- * @param {Number} [tremolo] - Trembling effect, rate controlled by repeat time (percent)
3877
- * @param {Number} [filter] - Filter cutoff frequency, positive for HPF, negative for LPF (Hz)
3867
+ * @param {number} [volume] - Volume scale (percent)
3868
+ * @param {number} [randomness] - How much to randomize frequency (percent Hz)
3869
+ * @param {number} [frequency] - Frequency of sound (Hz)
3870
+ * @param {number} [attack] - Attack time, how fast sound starts (seconds)
3871
+ * @param {number} [sustain] - Sustain time, how long sound holds (seconds)
3872
+ * @param {number} [release] - Release time, how fast sound fades out (seconds)
3873
+ * @param {number} [shape] - Shape of the sound wave
3874
+ * @param {number} [shapeCurve] - Squareness of wave (0=square, 1=normal, 2=pointy)
3875
+ * @param {number} [slide] - How much to slide frequency (kHz/s)
3876
+ * @param {number} [deltaSlide] - How much to change slide (kHz/s/s)
3877
+ * @param {number} [pitchJump] - Frequency of pitch jump (Hz)
3878
+ * @param {number} [pitchJumpTime] - Time of pitch jump (seconds)
3879
+ * @param {number} [repeatTime] - Resets some parameters periodically (seconds)
3880
+ * @param {number} [noise] - How much random noise to add (percent)
3881
+ * @param {number} [modulation] - Frequency of modulation wave, negative flips phase (Hz)
3882
+ * @param {number} [bitCrush] - Resamples at a lower frequency in (samples*100)
3883
+ * @param {number} [delay] - Overlap sound with itself for reverb and flanger effects (seconds)
3884
+ * @param {number} [sustainVolume] - Volume level for sustain (percent)
3885
+ * @param {number} [decay] - Decay time, how long to reach sustain after attack (seconds)
3886
+ * @param {number} [tremolo] - Trembling effect, rate controlled by repeat time (percent)
3887
+ * @param {number} [filter] - Filter cutoff frequency, positive for HPF, negative for LPF (Hz)
3878
3888
  * @return {Array} - Array of audio samples
3879
3889
  * @memberof Audio
3880
3890
  */
@@ -3980,7 +3990,7 @@ function zzfxG
3980
3990
  * @param {Array} instruments - Array of ZzFX sound parameters
3981
3991
  * @param {Array} patterns - Array of pattern data
3982
3992
  * @param {Array} sequence - Array of pattern indexes
3983
- * @param {Number} [BPM] - Playback speed of the song in BPM
3993
+ * @param {number} [BPM] - Playback speed of the song in BPM
3984
3994
  * @return {Array} - Left and right channel sample data
3985
3995
  * @memberof Audio */
3986
3996
  function zzfxM(instruments, patterns, sequence, BPM = 125)
@@ -4092,7 +4102,7 @@ function zzfxM(instruments, patterns, sequence, BPM = 125)
4092
4102
 
4093
4103
 
4094
4104
  /** The tile collision layer grid, use setTileCollisionData and getTileCollisionData to access
4095
- * @type {Array}
4105
+ * @type {Array<number>}
4096
4106
  * @memberof TileCollision */
4097
4107
  let tileCollision = [];
4098
4108
 
@@ -4114,7 +4124,7 @@ function initTileCollision(size)
4114
4124
 
4115
4125
  /** Set tile collision data for a given cell in the grid
4116
4126
  * @param {Vector2} pos
4117
- * @param {Number} [data]
4127
+ * @param {number} [data]
4118
4128
  * @memberof TileCollision */
4119
4129
  function setTileCollisionData(pos, data=0)
4120
4130
  {
@@ -4123,7 +4133,7 @@ function setTileCollisionData(pos, data=0)
4123
4133
 
4124
4134
  /** Get tile collision data for a given cell in the grid
4125
4135
  * @param {Vector2} pos
4126
- * @return {Number}
4136
+ * @return {number}
4127
4137
  * @memberof TileCollision */
4128
4138
  function getTileCollisionData(pos)
4129
4139
  {
@@ -4134,7 +4144,7 @@ function getTileCollisionData(pos)
4134
4144
  * @param {Vector2} pos
4135
4145
  * @param {Vector2} [size=(0,0)]
4136
4146
  * @param {EngineObject} [object]
4137
- * @return {Boolean}
4147
+ * @return {boolean}
4138
4148
  * @memberof TileCollision */
4139
4149
  function tileCollisionTest(pos, size=vec2(), object)
4140
4150
  {
@@ -4215,17 +4225,17 @@ function tileCollisionRaycast(posStart, posEnd, object)
4215
4225
  class TileLayerData
4216
4226
  {
4217
4227
  /** Create a tile layer data object, one for each tile in a TileLayer
4218
- * @param {Number} [tile] - The tile to use, untextured if undefined
4219
- * @param {Number} [direction] - Integer direction of tile, in 90 degree increments
4220
- * @param {Boolean} [mirror] - If the tile should be mirrored along the x axis
4228
+ * @param {number} [tile] - The tile to use, untextured if undefined
4229
+ * @param {number} [direction] - Integer direction of tile, in 90 degree increments
4230
+ * @param {boolean} [mirror] - If the tile should be mirrored along the x axis
4221
4231
  * @param {Color} [color] - Color of the tile */
4222
4232
  constructor(tile, direction=0, mirror=false, color=new Color)
4223
4233
  {
4224
- /** @property {Number} - The tile to use, untextured if undefined */
4234
+ /** @property {number} - The tile to use, untextured if undefined */
4225
4235
  this.tile = tile;
4226
- /** @property {Number} - Integer direction of tile, in 90 degree increments */
4236
+ /** @property {number} - Integer direction of tile, in 90 degree increments */
4227
4237
  this.direction = direction;
4228
- /** @property {Boolean} - If the tile should be mirrored along the x axis */
4238
+ /** @property {boolean} - If the tile should be mirrored along the x axis */
4229
4239
  this.mirror = mirror;
4230
4240
  /** @property {Color} - Color of the tile */
4231
4241
  this.color = color;
@@ -4254,7 +4264,7 @@ class TileLayer extends EngineObject
4254
4264
  * @param {Vector2} [size=tileCollisionSize] - World space size
4255
4265
  * @param {TileInfo} [tileInfo] - Tile info for layer
4256
4266
  * @param {Vector2} [scale=(1,1)] - How much to scale this layer when rendered
4257
- * @param {Number} [renderOrder] - Objects are sorted by renderOrder
4267
+ * @param {number} [renderOrder] - Objects are sorted by renderOrder
4258
4268
  */
4259
4269
  constructor(position, size=tileCollisionSize, tileInfo=tile(), scale=vec2(1), renderOrder=0)
4260
4270
  {
@@ -4266,7 +4276,7 @@ class TileLayer extends EngineObject
4266
4276
  this.context = this.canvas.getContext('2d');
4267
4277
  /** @property {Vector2} - How much to scale this layer when rendered */
4268
4278
  this.scale = scale;
4269
- /** @property {Boolean} - If true this layer will render to overlay canvas and appear above all objects */
4279
+ /** @property {boolean} - If true this layer will render to overlay canvas and appear above all objects */
4270
4280
  this.isOverlay = false;
4271
4281
 
4272
4282
  // init tile data
@@ -4289,7 +4299,7 @@ class TileLayer extends EngineObject
4289
4299
  /** Set data at a given position in the array
4290
4300
  * @param {Vector2} layerPos - Local position in array
4291
4301
  * @param {TileLayerData} data - Data to set
4292
- * @param {Boolean} [redraw] - Force the tile to redraw if true */
4302
+ * @param {boolean} [redraw] - Force the tile to redraw if true */
4293
4303
  setData(layerPos, data, redraw=false)
4294
4304
  {
4295
4305
  if (layerPos.arrayCheck(this.size))
@@ -4342,7 +4352,7 @@ class TileLayer extends EngineObject
4342
4352
 
4343
4353
  /** Call to start the redraw process
4344
4354
  * - This can be used to manually update small parts of the level
4345
- * @param {Boolean} [clear] - Should it clear the canvas before drawing */
4355
+ * @param {boolean} [clear] - Should it clear the canvas before drawing */
4346
4356
  redrawStart(clear=false)
4347
4357
  {
4348
4358
  // save current render settings
@@ -4386,7 +4396,7 @@ class TileLayer extends EngineObject
4386
4396
  * This can be used to clear out tiles when they are destroyed
4387
4397
  * Tiles can also be redrawn if inside a redrawStart/End block
4388
4398
  * @param {Vector2} layerPos
4389
- * @param {Boolean} [clear] - should the old tile be cleared out
4399
+ * @param {boolean} [clear] - should the old tile be cleared out
4390
4400
  */
4391
4401
  drawTileData(layerPos, clear=true)
4392
4402
  {
@@ -4404,7 +4414,7 @@ class TileLayer extends EngineObject
4404
4414
  {
4405
4415
  ASSERT(mainContext == this.context, 'must call redrawStart() before drawing tiles');
4406
4416
  const pos = layerPos.add(vec2(.5));
4407
- const tileInfo = tile(d.tile, s, this.tileInfo.textureIndex);
4417
+ const tileInfo = tile(d.tile, s, this.tileInfo.textureIndex, this.tileInfo.padding);
4408
4418
  drawTile(pos, vec2(1), tileInfo, d.color, d.direction*PI/2, d.mirror);
4409
4419
  }
4410
4420
  }
@@ -4412,8 +4422,8 @@ class TileLayer extends EngineObject
4412
4422
  /** Draw directly to the 2D canvas in world space (bypass webgl)
4413
4423
  * @param {Vector2} pos
4414
4424
  * @param {Vector2} size
4415
- * @param {Number} angle
4416
- * @param {Boolean} mirror
4425
+ * @param {number} angle
4426
+ * @param {boolean} mirror
4417
4427
  * @param {Function} drawFunction */
4418
4428
  drawCanvas2D(pos, size, angle, mirror, drawFunction)
4419
4429
  {
@@ -4433,8 +4443,8 @@ class TileLayer extends EngineObject
4433
4443
  * @param {Vector2} [size=(1,1)]
4434
4444
  * @param {TileInfo} [tileInfo]
4435
4445
  * @param {Color} [color=(1,1,1,1)]
4436
- * @param {Number} [angle=0]
4437
- * @param {Boolean} [mirror=0] */
4446
+ * @param {number} [angle=0]
4447
+ * @param {boolean} [mirror=0] */
4438
4448
  drawTile(pos, size=vec2(1), tileInfo, color=new Color, angle, mirror)
4439
4449
  {
4440
4450
  this.drawCanvas2D(pos, size, angle, mirror, (context)=>
@@ -4461,7 +4471,7 @@ class TileLayer extends EngineObject
4461
4471
  * @param {Vector2} pos
4462
4472
  * @param {Vector2} [size=(1,1)]
4463
4473
  * @param {Color} [color=(1,1,1,1)]
4464
- * @param {Number} [angle=0] */
4474
+ * @param {number} [angle=0] */
4465
4475
  drawRect(pos, size, color, angle)
4466
4476
  { this.drawTile(pos, size, undefined, color, angle); }
4467
4477
  }
@@ -4513,11 +4523,11 @@ class ParticleEmitter extends EngineObject
4513
4523
  * @param {Number} [particleConeAngle] - Cone for start particle angle
4514
4524
  * @param {Number} [fadeRate] - How quick to fade particles at start/end in percent of life
4515
4525
  * @param {Number} [randomness] - Apply extra randomness percent
4516
- * @param {Boolean} [collideTiles] - Do particles collide against tiles
4517
- * @param {Boolean} [additive] - Should particles use additive blend
4518
- * @param {Boolean} [randomColorLinear] - Should color be randomized linearly or across each component
4526
+ * @param {boolean} [collideTiles] - Do particles collide against tiles
4527
+ * @param {boolean} [additive] - Should particles use additive blend
4528
+ * @param {boolean} [randomColorLinear] - Should color be randomized linearly or across each component
4519
4529
  * @param {Number} [renderOrder] - Render order for particles (additive is above other stuff by default)
4520
- * @param {Boolean} [localSpace] - Should it be in local space of emitter (world space is default)
4530
+ * @param {boolean} [localSpace] - Should it be in local space of emitter (world space is default)
4521
4531
  */
4522
4532
  constructor
4523
4533
  (
@@ -4571,7 +4581,7 @@ class ParticleEmitter extends EngineObject
4571
4581
  this.colorEndA = colorEndA;
4572
4582
  /** @property {Color} - Color at end of life 2, randomized between end colors */
4573
4583
  this.colorEndB = colorEndB;
4574
- /** @property {Boolean} - Should color be randomized linearly or across each component */
4584
+ /** @property {boolean} - Should color be randomized linearly or across each component */
4575
4585
  this.randomColorLinear = randomColorLinear;
4576
4586
 
4577
4587
  // particle settings
@@ -4597,11 +4607,11 @@ class ParticleEmitter extends EngineObject
4597
4607
  this.fadeRate = fadeRate;
4598
4608
  /** @property {Number} - Apply extra randomness percent */
4599
4609
  this.randomness = randomness;
4600
- /** @property {Boolean} - Do particles collide against tiles */
4610
+ /** @property {boolean} - Do particles collide against tiles */
4601
4611
  this.collideTiles = collideTiles;
4602
- /** @property {Boolean} - Should particles use additive blend */
4612
+ /** @property {boolean} - Should particles use additive blend */
4603
4613
  this.additive = additive;
4604
- /** @property {Boolean} - Should it be in local space of emitter */
4614
+ /** @property {boolean} - Should it be in local space of emitter */
4605
4615
  this.localSpace = localSpace;
4606
4616
  /** @property {Number} - If non zero the particle is drawn as a trail, stretched in the direction of velocity */
4607
4617
  this.trailScale = 0;
@@ -4711,7 +4721,7 @@ class Particle extends EngineObject
4711
4721
  * @param {Number} sizeStart - Size at start of life
4712
4722
  * @param {Number} sizeEnd - Size at end of life
4713
4723
  * @param {Number} fadeRate - How quick to fade in/out
4714
- * @param {Boolean} additive - Does it use additive blend mode
4724
+ * @param {boolean} additive - Does it use additive blend mode
4715
4725
  * @param {Number} trailScale - If a trail, how long to make it
4716
4726
  * @param {ParticleEmitter} [localSpaceEmitter] - Parent emitter if local space
4717
4727
  * @param {Function} [destroyCallback] - Callback when particle dies
@@ -4733,7 +4743,7 @@ class Particle extends EngineObject
4733
4743
  this.sizeEndDelta = sizeEnd - sizeStart;
4734
4744
  /** @property {Number} - How quick to fade in/out */
4735
4745
  this.fadeRate = fadeRate;
4736
- /** @property {Boolean} - Is it additive */
4746
+ /** @property {boolean} - Is it additive */
4737
4747
  this.additive = additive;
4738
4748
  /** @property {Number} - If a trail, how long to make it */
4739
4749
  this.trailScale = trailScale;
@@ -4908,7 +4918,7 @@ class Medal
4908
4918
  /** @property {String} - Icon for the medal */
4909
4919
  this.icon = icon;
4910
4920
 
4911
- /** @property {Boolean} - Is the medal unlocked? */
4921
+ /** @property {boolean} - Is the medal unlocked? */
4912
4922
  this.unlocked = false;
4913
4923
 
4914
4924
  // load the source image if provided
@@ -4938,8 +4948,9 @@ class Medal
4938
4948
  {
4939
4949
  const context = overlayContext;
4940
4950
  const width = min(medalDisplaySize.x, mainCanvas.width);
4951
+ const height = medalDisplaySize.y;
4941
4952
  const x = overlayCanvas.width - width;
4942
- const y = -medalDisplaySize.y*hidePercent;
4953
+ const y = -height*hidePercent;
4943
4954
 
4944
4955
  // draw containing rect and clip to that region
4945
4956
  context.save();
@@ -4947,25 +4958,34 @@ class Medal
4947
4958
  context.fillStyle = new Color(.9,.9,.9).toString();
4948
4959
  context.strokeStyle = new Color(0,0,0).toString();
4949
4960
  context.lineWidth = 3;
4950
- context.rect(x, y, width, medalDisplaySize.y);
4961
+ context.rect(x, y, width, height);
4951
4962
  context.fill();
4952
4963
  context.stroke();
4953
4964
  context.clip();
4954
4965
 
4955
- // draw the icon and text
4956
- this.renderIcon(vec2(x+15+medalDisplayIconSize/2, y+medalDisplaySize.y/2));
4957
- const pos = vec2(x+medalDisplayIconSize+30, y+28);
4958
- drawTextScreen(this.name, pos, 38, new Color(0,0,0), 0, undefined, 'left');
4959
- pos.y += 32;
4960
- drawTextScreen(this.description, pos, 24, new Color(0,0,0), 0, undefined, 'left');
4966
+ // draw the icon
4967
+ const gap = vec2(.1, .05).scale(height);
4968
+ const medalDisplayIconSize = height - 2*gap.x;
4969
+ this.renderIcon(vec2(x + gap.x + medalDisplayIconSize/2, y + height/2), medalDisplayIconSize);
4970
+
4971
+ // draw the name
4972
+ const nameSize = height*.5;
4973
+ const descriptionSize = height*.3;
4974
+ const pos = vec2(x + medalDisplayIconSize + 2*gap.x, y + gap.y*2 + nameSize/2);
4975
+ const textWidth = width - medalDisplayIconSize - 3*gap.x;
4976
+ drawTextScreen(this.name, pos, nameSize, new Color(0,0,0), 0, undefined, 'left', undefined, textWidth);
4977
+
4978
+ // draw the description
4979
+ pos.y = y + height - gap.y*2 - descriptionSize/2;
4980
+ drawTextScreen(this.description, pos, descriptionSize, new Color(0,0,0), 0, undefined, 'left', undefined, textWidth);
4961
4981
  context.restore();
4962
4982
  }
4963
4983
 
4964
4984
  /** Render the icon for a medal
4965
4985
  * @param {Vector2} pos - Screen space position
4966
- * @param {Number} [size=medalDisplayIconSize] - Screen space size
4986
+ * @param {Number} size - Screen space size
4967
4987
  */
4968
- renderIcon(pos, size=medalDisplayIconSize)
4988
+ renderIcon(pos, size)
4969
4989
  {
4970
4990
  // draw the image or icon
4971
4991
  if (this.image)
@@ -5002,7 +5022,7 @@ let glCanvas;
5002
5022
  let glContext;
5003
5023
 
5004
5024
  /** Should webgl be setup with anti-aliasing? must be set before calling engineInit
5005
- * @type {Boolean}
5025
+ * @type {boolean}
5006
5026
  * @memberof WebGL */
5007
5027
  let glAntialias = true;
5008
5028
 
@@ -5225,7 +5245,7 @@ function glFlush()
5225
5245
 
5226
5246
  /** Draw any sprites still in the buffer and copy to main canvas
5227
5247
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} context
5228
- * @param {Boolean} [forceDraw]
5248
+ * @param {boolean} [forceDraw]
5229
5249
  * @memberof WebGL */
5230
5250
  function glCopyToContext(context, forceDraw=false)
5231
5251
  {
@@ -5239,7 +5259,7 @@ function glCopyToContext(context, forceDraw=false)
5239
5259
  }
5240
5260
 
5241
5261
  /** Set anti-aliasing for webgl canvas
5242
- * @param {Boolean} [antialias]
5262
+ * @param {boolean} [antialias]
5243
5263
  * @memberof WebGL */
5244
5264
  function glSetAntialias(antialias=true)
5245
5265
  {
@@ -5304,61 +5324,62 @@ function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba, rgbaAdd
5304
5324
 
5305
5325
 
5306
5326
  /** Name of engine
5307
- * @type {String}
5327
+ * @type {string}
5308
5328
  * @default
5309
5329
  * @memberof Engine */
5310
5330
  const engineName = 'LittleJS';
5311
5331
 
5312
5332
  /** Version of engine
5313
- * @type {String}
5333
+ * @type {string}
5314
5334
  * @default
5315
5335
  * @memberof Engine */
5316
- const engineVersion = '1.11.9';
5336
+ const engineVersion = '1.11.13';
5317
5337
 
5318
5338
  /** Frames per second to update
5319
- * @type {Number}
5339
+ * @type {number}
5320
5340
  * @default
5321
5341
  * @memberof Engine */
5322
5342
  const frameRate = 60;
5323
5343
 
5324
5344
  /** How many seconds each frame lasts, engine uses a fixed time step
5325
- * @type {Number}
5345
+ * @type {number}
5326
5346
  * @default 1/60
5327
5347
  * @memberof Engine */
5328
5348
  const timeDelta = 1/frameRate;
5329
5349
 
5330
5350
  /** Array containing all engine objects
5331
- * @type {Array}
5351
+ * @type {Array<EngineObject>}
5332
5352
  * @memberof Engine */
5333
5353
  let engineObjects = [];
5334
5354
 
5335
5355
  /** Array with only objects set to collide with other objects this frame (for optimization)
5336
- * @type {Array}
5356
+ * @type {Array<EngineObject>}
5337
5357
  * @memberof Engine */
5338
5358
  let engineObjectsCollide = [];
5339
5359
 
5340
5360
  /** Current update frame, used to calculate time
5341
- * @type {Number}
5361
+ * @type {number}
5342
5362
  * @memberof Engine */
5343
5363
  let frame = 0;
5344
5364
 
5345
5365
  /** Current engine time since start in seconds
5346
- * @type {Number}
5366
+ * @type {number}
5347
5367
  * @memberof Engine */
5348
5368
  let time = 0;
5349
5369
 
5350
5370
  /** Actual clock time since start in seconds (not affected by pause or frame rate clamping)
5351
- * @type {Number}
5371
+ * @type {number}
5352
5372
  * @memberof Engine */
5353
5373
  let timeReal = 0;
5354
5374
 
5355
5375
  /** Is the game paused? Causes time and objects to not be updated
5356
- * @type {Boolean}
5376
+ * @type {boolean}
5357
5377
  * @default false
5358
5378
  * @memberof Engine */
5359
5379
  let paused = false;
5380
+
5360
5381
  /** Set if game is paused
5361
- * @param {Boolean} isPaused
5382
+ * @param {boolean} isPaused
5362
5383
  * @memberof Engine */
5363
5384
  function setPaused(isPaused) { paused = isPaused; }
5364
5385
 
@@ -5391,7 +5412,7 @@ function engineAddPlugin(updateFunction, renderFunction)
5391
5412
  * @param {Function} gameUpdatePost - Called after physics and objects are updated, even when paused
5392
5413
  * @param {Function} gameRender - Called before objects are rendered, for drawing the background
5393
5414
  * @param {Function} gameRenderPost - Called after objects are rendered, useful for drawing UI
5394
- * @param {Array} [imageSources=[]] - List of images to load
5415
+ * @param {Array<string>} [imageSources=[]] - List of images to load
5395
5416
  * @param {HTMLElement} [rootElement] - Root element to attach to, the document body by default
5396
5417
  * @memberof Engine */
5397
5418
  function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, imageSources=[], rootElement=document.body)
@@ -5687,9 +5708,9 @@ function engineObjectsDestroy()
5687
5708
 
5688
5709
  /** Collects all object within a given area
5689
5710
  * @param {Vector2} [pos] - Center of test area, or undefined for all objects
5690
- * @param {Number|Vector2} [size] - Radius of circle if float, rectangle size if Vector2
5691
- * @param {Array} [objects=engineObjects] - List of objects to check
5692
- * @return {Array} - List of collected objects
5711
+ * @param {Vector2|number} [size] - Radius of circle if float, rectangle size if Vector2
5712
+ * @param {Array<EngineObject>} [objects=engineObjects] - List of objects to check
5713
+ * @return {Array<EngineObject>} - List of collected objects
5693
5714
  * @memberof Engine */
5694
5715
  function engineObjectsCollect(pos, size, objects=engineObjects)
5695
5716
  {
@@ -5715,9 +5736,9 @@ function engineObjectsCollect(pos, size, objects=engineObjects)
5715
5736
 
5716
5737
  /** Triggers a callback for each object within a given area
5717
5738
  * @param {Vector2} [pos] - Center of test area, or undefined for all objects
5718
- * @param {Number|Vector2} [size] - Radius of circle if float, rectangle size if Vector2
5739
+ * @param {Vector2|number} [size] - Radius of circle if float, rectangle size if Vector2
5719
5740
  * @param {Function} [callbackFunction] - Calls this function on every object that passes the test
5720
- * @param {Array} [objects=engineObjects] - List of objects to check
5741
+ * @param {Array<EngineObject>} [objects=engineObjects] - List of objects to check
5721
5742
  * @memberof Engine */
5722
5743
  function engineObjectsCallback(pos, size, callbackFunction, objects=engineObjects)
5723
5744
  { engineObjectsCollect(pos, size, objects).forEach(o => callbackFunction(o)); }
@@ -5725,8 +5746,8 @@ function engineObjectsCallback(pos, size, callbackFunction, objects=engineObject
5725
5746
  /** Return a list of objects intersecting a ray
5726
5747
  * @param {Vector2} start
5727
5748
  * @param {Vector2} end
5728
- * @param {Array} [objects=engineObjects] - List of objects to check
5729
- * @return {Array} - List of objects hit
5749
+ * @param {Array<EngineObject>} [objects=engineObjects] - List of objects to check
5750
+ * @return {Array<EngineObject>} - List of objects hit
5730
5751
  * @memberof Engine */
5731
5752
  function engineObjectsRaycast(start, end, objects=engineObjects)
5732
5753
  {
@@ -5917,8 +5938,8 @@ function drawEngineSplashScreen(t)
5917
5938
  * - Export engine as a module
5918
5939
  */
5919
5940
 
5920
- export {
5921
-
5941
+ export
5942
+ {
5922
5943
  // Engine
5923
5944
  engineName,
5924
5945
  engineVersion,
@@ -5996,7 +6017,6 @@ export {
5996
6017
  medalDisplayTime,
5997
6018
  medalDisplaySlideTime,
5998
6019
  medalDisplaySize,
5999
- medalDisplayIconSize,
6000
6020
 
6001
6021
  // Setters for globals
6002
6022
  setCameraPos,
@@ -6037,7 +6057,6 @@ export {
6037
6057
  setMedalDisplayTime,
6038
6058
  setMedalDisplaySlideTime,
6039
6059
  setMedalDisplaySize,
6040
- setMedalDisplayIconSize,
6041
6060
  setMedalsPreventUnlock,
6042
6061
  setShowWatermark,
6043
6062
  setDebugKey,