littlejsengine 1.11.8 → 1.11.10

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 (39) hide show
  1. package/README.md +3 -3
  2. package/dist/littlejs.d.ts +496 -493
  3. package/dist/littlejs.esm.js +533 -522
  4. package/dist/littlejs.esm.min.js +1 -1
  5. package/dist/littlejs.js +531 -520
  6. package/dist/littlejs.min.js +1 -1
  7. package/dist/littlejs.release.js +487 -479
  8. package/examples/index.html +8 -2
  9. package/examples/module/game.js +2 -2
  10. package/examples/shorts/base.html +1 -1
  11. package/examples/starter/game.js +8 -1
  12. package/examples/typescript/build/dist/littlejs.esm.js +4834 -0
  13. package/examples/typescript/build/examples/typescript/build.js +24 -0
  14. package/examples/typescript/build/examples/typescript/game.js +102 -0
  15. package/examples/typescript/build.bat +5 -0
  16. package/examples/typescript/build.js +33 -0
  17. package/examples/typescript/game.js +102 -0
  18. package/examples/typescript/game.ts +134 -0
  19. package/examples/typescript/index.html +10 -0
  20. package/examples/typescript/tiles.png +0 -0
  21. package/examples/typescript/tsconfig.json +8 -0
  22. package/package.json +1 -1
  23. package/plugins/newgrounds.js +38 -34
  24. package/plugins/postProcess.js +18 -4
  25. package/plugins/uiSystem.js +196 -30
  26. package/reference.md +3 -3
  27. package/src/engine.js +21 -20
  28. package/src/engineAudio.js +59 -59
  29. package/src/engineDebug.js +44 -41
  30. package/src/engineDraw.js +58 -58
  31. package/src/engineExport.js +2 -2
  32. package/src/engineInput.js +30 -30
  33. package/src/engineMedals.js +1 -1
  34. package/src/engineObject.js +42 -37
  35. package/src/engineParticles.js +10 -10
  36. package/src/engineSettings.js +74 -72
  37. package/src/engineTileLayer.js +21 -21
  38. package/src/engineUtilities.js +168 -168
  39. 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,34 +730,34 @@ 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
744
747
  this.seed ^= this.seed << 13;
745
748
  this.seed ^= this.seed >>> 17;
746
749
  this.seed ^= this.seed << 5;
747
- return valueB + (valueA - valueB) * abs(this.seed % 1e8) / 1e8;
750
+ return valueB + (valueA - valueB) * ((this.seed >>> 0) / 2**32);
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,20 +929,20 @@ 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));
933
936
  return this.x*v.y - this.y*v.x;
934
937
  }
935
938
 
936
- /** Returns the angle of this vector, up is angle 0
937
- * @return {Number} */
939
+ /** Returns the clockwise angle of this vector, up is angle 0
940
+ * @return {number} */
938
941
  angle() { return Math.atan2(this.x, this.y); }
939
942
 
940
- /** Sets this vector with angle and length passed in
941
- * @param {Number} [angle]
942
- * @param {Number} [length]
943
+ /** Sets this vector with clockwise angle and length passed in
944
+ * @param {number} [angle]
945
+ * @param {number} [length]
943
946
  * @return {Vector2} */
944
947
  setAngle(angle=0, length=1)
945
948
  {
@@ -948,18 +951,18 @@ class Vector2
948
951
  return this;
949
952
  }
950
953
 
951
- /** Returns copy of this vector rotated by the angle passed in
952
- * @param {Number} angle
954
+ /** Returns copy of this vector rotated by the clockwise angle passed in
955
+ * @param {number} angle
953
956
  * @return {Vector2} */
954
957
  rotate(angle)
955
958
  {
956
- const c = Math.cos(angle), s = Math.sin(angle);
957
- return new Vector2(this.x*c + this.y*s, this.x*s + this.y*c);
959
+ const c = Math.cos(-angle), s = Math.sin(-angle);
960
+ return new Vector2(this.x*c - this.y*s, this.x*s + this.y*c);
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)
@@ -1289,57 +1292,57 @@ class Color
1289
1292
  ///////////////////////////////////////////////////////////////////////////////
1290
1293
  // default colors
1291
1294
 
1292
- /** Color - White
1295
+ /** Color - White #ffffff
1293
1296
  * @type {Color}
1294
1297
  * @memberof Utilities */
1295
- const WHITE = rgb();
1298
+ const WHITE = rgb();
1296
1299
 
1297
- /** Color - Black
1300
+ /** Color - Black #000000
1298
1301
  * @type {Color}
1299
1302
  * @memberof Utilities */
1300
1303
  const BLACK = rgb(0,0,0);
1301
1304
 
1302
- /** Color - Gray
1305
+ /** Color - Gray #808080
1303
1306
  * @type {Color}
1304
1307
  * @memberof Utilities */
1305
1308
  const GRAY = rgb(.5,.5,.5);
1306
1309
 
1307
- /** Color - Red
1310
+ /** Color - Red #ff0000
1308
1311
  * @type {Color}
1309
1312
  * @memberof Utilities */
1310
1313
  const RED = rgb(1,0,0);
1311
1314
 
1312
- /** Color - Orange
1315
+ /** Color - Orange #ff8000
1313
1316
  * @type {Color}
1314
1317
  * @memberof Utilities */
1315
1318
  const ORANGE = rgb(1,.5,0);
1316
1319
 
1317
- /** Color - Yellow
1320
+ /** Color - Yellow #ffff00
1318
1321
  * @type {Color}
1319
1322
  * @memberof Utilities */
1320
1323
  const YELLOW = rgb(1,1,0);
1321
1324
 
1322
- /** Color - Green
1325
+ /** Color - Green #00ff00
1323
1326
  * @type {Color}
1324
1327
  * @memberof Utilities */
1325
1328
  const GREEN = rgb(0,1,0);
1326
1329
 
1327
- /** Color - Cyan
1330
+ /** Color - Cyan #00ffff
1328
1331
  * @type {Color}
1329
1332
  * @memberof Utilities */
1330
1333
  const CYAN = rgb(0,1,1);
1331
1334
 
1332
- /** Color - Blue
1335
+ /** Color - Blue #0000ff
1333
1336
  * @type {Color}
1334
1337
  * @memberof Utilities */
1335
1338
  const BLUE = rgb(0,0,1);
1336
1339
 
1337
- /** Color - Purple
1340
+ /** Color - Purple #8000ff
1338
1341
  * @type {Color}
1339
1342
  * @memberof Utilities */
1340
1343
  const PURPLE = rgb(.5,0,1);
1341
1344
 
1342
- /** Color - Magenta
1345
+ /** Color - Magenta #ff00ff
1343
1346
  * @type {Color}
1344
1347
  * @memberof Utilities */
1345
1348
  const MAGENTA = rgb(1,0,1);
@@ -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,33 @@ 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
+ * @type {boolean}
1464
1469
  * @default
1465
1470
  * @memberof Settings */
1466
1471
  let headlessMode = false;
@@ -1469,13 +1474,13 @@ let headlessMode = false;
1469
1474
  // WebGL settings
1470
1475
 
1471
1476
  /** Enable webgl rendering, webgl can be disabled and removed from build (with some features disabled)
1472
- * @type {Boolean}
1477
+ * @type {boolean}
1473
1478
  * @default
1474
1479
  * @memberof Settings */
1475
1480
  let glEnable = true;
1476
1481
 
1477
1482
  /** Fixes slow rendering in some browsers by not compositing the WebGL canvas
1478
- * @type {Boolean}
1483
+ * @type {boolean}
1479
1484
  * @default
1480
1485
  * @memberof Settings */
1481
1486
  let glOverlay = true;
@@ -1490,7 +1495,7 @@ let glOverlay = true;
1490
1495
  let tileSizeDefault = vec2(16);
1491
1496
 
1492
1497
  /** How many pixels smaller to draw tiles to prevent bleeding from neighbors
1493
- * @type {Number}
1498
+ * @type {number}
1494
1499
  * @default
1495
1500
  * @memberof Settings */
1496
1501
  let tileFixBleedScale = 0;
@@ -1499,55 +1504,55 @@ let tileFixBleedScale = 0;
1499
1504
  // Object settings
1500
1505
 
1501
1506
  /** Enable physics solver for collisions between objects
1502
- * @type {Boolean}
1507
+ * @type {boolean}
1503
1508
  * @default
1504
1509
  * @memberof Settings */
1505
1510
  let enablePhysicsSolver = true;
1506
1511
 
1507
1512
  /** Default object mass for collision calculations (how heavy objects are)
1508
- * @type {Number}
1513
+ * @type {number}
1509
1514
  * @default
1510
1515
  * @memberof Settings */
1511
1516
  let objectDefaultMass = 1;
1512
1517
 
1513
1518
  /** How much to slow velocity by each frame (0-1)
1514
- * @type {Number}
1519
+ * @type {number}
1515
1520
  * @default
1516
1521
  * @memberof Settings */
1517
1522
  let objectDefaultDamping = 1;
1518
1523
 
1519
1524
  /** How much to slow angular velocity each frame (0-1)
1520
- * @type {Number}
1525
+ * @type {number}
1521
1526
  * @default
1522
1527
  * @memberof Settings */
1523
1528
  let objectDefaultAngleDamping = 1;
1524
1529
 
1525
1530
  /** How much to bounce when a collision occurs (0-1)
1526
- * @type {Number}
1531
+ * @type {number}
1527
1532
  * @default
1528
1533
  * @memberof Settings */
1529
1534
  let objectDefaultElasticity = 0;
1530
1535
 
1531
1536
  /** How much to slow when touching (0-1)
1532
- * @type {Number}
1537
+ * @type {number}
1533
1538
  * @default
1534
1539
  * @memberof Settings */
1535
1540
  let objectDefaultFriction = .8;
1536
1541
 
1537
1542
  /** Clamp max speed to avoid fast objects missing collisions
1538
- * @type {Number}
1543
+ * @type {number}
1539
1544
  * @default
1540
1545
  * @memberof Settings */
1541
1546
  let objectMaxSpeed = 1;
1542
1547
 
1543
1548
  /** How much gravity to apply to objects along the Y axis, negative is down
1544
- * @type {Number}
1549
+ * @type {number}
1545
1550
  * @default
1546
1551
  * @memberof Settings */
1547
1552
  let gravity = 0;
1548
1553
 
1549
1554
  /** Scales emit rate of particles, useful for low graphics mode (0 disables particle emitters)
1550
- * @type {Number}
1555
+ * @type {number}
1551
1556
  * @default
1552
1557
  * @memberof Settings */
1553
1558
  let particleEmitRateScale = 1;
@@ -1556,26 +1561,26 @@ let particleEmitRateScale = 1;
1556
1561
  // Input settings
1557
1562
 
1558
1563
  /** Should gamepads be allowed
1559
- * @type {Boolean}
1564
+ * @type {boolean}
1560
1565
  * @default
1561
1566
  * @memberof Settings */
1562
1567
  let gamepadsEnable = true;
1563
1568
 
1564
1569
  /** If true, the dpad input is also routed to the left analog stick (for better accessability)
1565
- * @type {Boolean}
1570
+ * @type {boolean}
1566
1571
  * @default
1567
1572
  * @memberof Settings */
1568
1573
  let gamepadDirectionEmulateStick = true;
1569
1574
 
1570
1575
  /** If true the WASD keys are also routed to the direction keys (for better accessability)
1571
- * @type {Boolean}
1576
+ * @type {boolean}
1572
1577
  * @default
1573
1578
  * @memberof Settings */
1574
1579
  let inputWASDEmulateDirection = true;
1575
1580
 
1576
1581
  /** True if touch input is enabled for mobile devices
1577
1582
  * - Touch events will be routed to mouse events
1578
- * @type {Boolean}
1583
+ * @type {boolean}
1579
1584
  * @default
1580
1585
  * @memberof Settings */
1581
1586
  let touchInputEnable = true;
@@ -1583,31 +1588,31 @@ let touchInputEnable = true;
1583
1588
  /** True if touch gamepad should appear on mobile devices
1584
1589
  * - Supports left analog stick, 4 face buttons and start button (button 9)
1585
1590
  * - Must be set by end of gameInit to be activated
1586
- * @type {Boolean}
1591
+ * @type {boolean}
1587
1592
  * @default
1588
1593
  * @memberof Settings */
1589
1594
  let touchGamepadEnable = false;
1590
1595
 
1591
1596
  /** True if touch gamepad should be analog stick or false to use if 8 way dpad
1592
- * @type {Boolean}
1597
+ * @type {boolean}
1593
1598
  * @default
1594
1599
  * @memberof Settings */
1595
1600
  let touchGamepadAnalog = true;
1596
1601
 
1597
1602
  /** Size of virtual gamepad for touch devices in pixels
1598
- * @type {Number}
1603
+ * @type {number}
1599
1604
  * @default
1600
1605
  * @memberof Settings */
1601
1606
  let touchGamepadSize = 99;
1602
1607
 
1603
1608
  /** Transparency of touch gamepad overlay
1604
- * @type {Number}
1609
+ * @type {number}
1605
1610
  * @default
1606
1611
  * @memberof Settings */
1607
1612
  let touchGamepadAlpha = .3;
1608
1613
 
1609
1614
  /** Allow vibration hardware if it exists
1610
- * @type {Boolean}
1615
+ * @type {boolean}
1611
1616
  * @default
1612
1617
  * @memberof Settings */
1613
1618
  let vibrateEnable = true;
@@ -1616,25 +1621,25 @@ let vibrateEnable = true;
1616
1621
  // Audio settings
1617
1622
 
1618
1623
  /** All audio code can be disabled and removed from build
1619
- * @type {Boolean}
1624
+ * @type {boolean}
1620
1625
  * @default
1621
1626
  * @memberof Settings */
1622
1627
  let soundEnable = true;
1623
1628
 
1624
1629
  /** Volume scale to apply to all sound, music and speech
1625
- * @type {Number}
1630
+ * @type {number}
1626
1631
  * @default
1627
1632
  * @memberof Settings */
1628
1633
  let soundVolume = .3;
1629
1634
 
1630
1635
  /** Default range where sound no longer plays
1631
- * @type {Number}
1636
+ * @type {number}
1632
1637
  * @default
1633
1638
  * @memberof Settings */
1634
1639
  let soundDefaultRange = 40;
1635
1640
 
1636
1641
  /** Default range percent to start tapering off sound (0-1)
1637
- * @type {Number}
1642
+ * @type {number}
1638
1643
  * @default
1639
1644
  * @memberof Settings */
1640
1645
  let soundDefaultTaper = .7;
@@ -1643,13 +1648,13 @@ let soundDefaultTaper = .7;
1643
1648
  // Medals settings
1644
1649
 
1645
1650
  /** How long to show medals for in seconds
1646
- * @type {Number}
1651
+ * @type {number}
1647
1652
  * @default
1648
1653
  * @memberof Settings */
1649
1654
  let medalDisplayTime = 5;
1650
1655
 
1651
1656
  /** How quickly to slide on/off medals in seconds
1652
- * @type {Number}
1657
+ * @type {number}
1653
1658
  * @default
1654
1659
  * @memberof Settings */
1655
1660
  let medalDisplaySlideTime = .5;
@@ -1661,13 +1666,13 @@ let medalDisplaySlideTime = .5;
1661
1666
  let medalDisplaySize = vec2(640, 80);
1662
1667
 
1663
1668
  /** Size of icon in medal display
1664
- * @type {Number}
1669
+ * @type {number}
1665
1670
  * @default
1666
1671
  * @memberof Settings */
1667
1672
  let medalDisplayIconSize = 50;
1668
1673
 
1669
1674
  /** Set to stop medals from being unlockable (like if cheats are enabled)
1670
- * @type {Boolean}
1675
+ * @type {boolean}
1671
1676
  * @default
1672
1677
  * @memberof Settings */
1673
1678
  let medalsPreventUnlock = false;
@@ -1681,7 +1686,7 @@ let medalsPreventUnlock = false;
1681
1686
  function setCameraPos(pos) { cameraPos = pos; }
1682
1687
 
1683
1688
  /** Set scale of camera in world space
1684
- * @param {Number} scale
1689
+ * @param {number} scale
1685
1690
  * @memberof Settings */
1686
1691
  function setCameraScale(scale) { cameraScale = scale; }
1687
1692
 
@@ -1696,37 +1701,37 @@ function setCanvasMaxSize(size) { canvasMaxSize = size; }
1696
1701
  function setCanvasFixedSize(size) { canvasFixedSize = size; }
1697
1702
 
1698
1703
  /** Use nearest neighbor scaling algorithm for canvas for more pixelated look
1699
- * @param {Boolean} pixelated
1704
+ * @param {boolean} pixelated
1700
1705
  * @memberof Settings */
1701
1706
  function setCanvasPixelated(pixelated) { canvasPixelated = pixelated; }
1702
1707
 
1703
1708
  /** Disables texture filtering for crisper pixel art
1704
- * @param {Boolean} pixelated
1709
+ * @param {boolean} pixelated
1705
1710
  * @memberof Settings */
1706
1711
  function setTilesPixelated(pixelated) { tilesPixelated = pixelated; }
1707
1712
 
1708
1713
  /** Set default font used for text rendering
1709
- * @param {String} font
1714
+ * @param {string} font
1710
1715
  * @memberof Settings */
1711
1716
  function setFontDefault(font) { fontDefault = font; }
1712
1717
 
1713
1718
  /** Set if the LittleJS splash screen be shown on startup
1714
- * @param {Boolean} show
1719
+ * @param {boolean} show
1715
1720
  * @memberof Settings */
1716
1721
  function setShowSplashScreen(show) { showSplashScreen = show; }
1717
1722
 
1718
1723
  /** Set to disable rendering, audio, and input for servers
1719
- * @param {Boolean} headless
1724
+ * @param {boolean} headless
1720
1725
  * @memberof Settings */
1721
1726
  function setHeadlessMode(headless) { headlessMode = headless; }
1722
1727
 
1723
1728
  /** Set if webgl rendering is enabled
1724
- * @param {Boolean} enable
1729
+ * @param {boolean} enable
1725
1730
  * @memberof Settings */
1726
1731
  function setGlEnable(enable) { glEnable = enable; }
1727
1732
 
1728
1733
  /** Set to not composite the WebGL canvas
1729
- * @param {Boolean} overlay
1734
+ * @param {boolean} overlay
1730
1735
  * @memberof Settings */
1731
1736
  function setGlOverlay(overlay) { glOverlay = overlay; }
1732
1737
 
@@ -1736,107 +1741,107 @@ function setGlOverlay(overlay) { glOverlay = overlay; }
1736
1741
  function setTileSizeDefault(size) { tileSizeDefault = size; }
1737
1742
 
1738
1743
  /** Set to prevent tile bleeding from neighbors in pixels
1739
- * @param {Number} scale
1744
+ * @param {number} scale
1740
1745
  * @memberof Settings */
1741
1746
  function setTileFixBleedScale(scale) { tileFixBleedScale = scale; }
1742
1747
 
1743
1748
  /** Set if collisions between objects are enabled
1744
- * @param {Boolean} enable
1749
+ * @param {boolean} enable
1745
1750
  * @memberof Settings */
1746
1751
  function setEnablePhysicsSolver(enable) { enablePhysicsSolver = enable; }
1747
1752
 
1748
1753
  /** Set default object mass for collision calculations
1749
- * @param {Number} mass
1754
+ * @param {number} mass
1750
1755
  * @memberof Settings */
1751
1756
  function setObjectDefaultMass(mass) { objectDefaultMass = mass; }
1752
1757
 
1753
1758
  /** Set how much to slow velocity by each frame
1754
- * @param {Number} damp
1759
+ * @param {number} damp
1755
1760
  * @memberof Settings */
1756
1761
  function setObjectDefaultDamping(damp) { objectDefaultDamping = damp; }
1757
1762
 
1758
1763
  /** Set how much to slow angular velocity each frame
1759
- * @param {Number} damp
1764
+ * @param {number} damp
1760
1765
  * @memberof Settings */
1761
1766
  function setObjectDefaultAngleDamping(damp) { objectDefaultAngleDamping = damp; }
1762
1767
 
1763
1768
  /** Set how much to bounce when a collision occur
1764
- * @param {Number} elasticity
1769
+ * @param {number} elasticity
1765
1770
  * @memberof Settings */
1766
1771
  function setObjectDefaultElasticity(elasticity) { objectDefaultElasticity = elasticity; }
1767
1772
 
1768
1773
  /** Set how much to slow when touching
1769
- * @param {Number} friction
1774
+ * @param {number} friction
1770
1775
  * @memberof Settings */
1771
1776
  function setObjectDefaultFriction(friction) { objectDefaultFriction = friction; }
1772
1777
 
1773
1778
  /** Set max speed to avoid fast objects missing collisions
1774
- * @param {Number} speed
1779
+ * @param {number} speed
1775
1780
  * @memberof Settings */
1776
1781
  function setObjectMaxSpeed(speed) { objectMaxSpeed = speed; }
1777
1782
 
1778
1783
  /** Set how much gravity to apply to objects along the Y axis
1779
- * @param {Number} newGravity
1784
+ * @param {number} newGravity
1780
1785
  * @memberof Settings */
1781
1786
  function setGravity(newGravity) { gravity = newGravity; }
1782
1787
 
1783
1788
  /** Set to scales emit rate of particles
1784
- * @param {Number} scale
1789
+ * @param {number} scale
1785
1790
  * @memberof Settings */
1786
1791
  function setParticleEmitRateScale(scale) { particleEmitRateScale = scale; }
1787
1792
 
1788
1793
  /** Set if gamepads are enabled
1789
- * @param {Boolean} enable
1794
+ * @param {boolean} enable
1790
1795
  * @memberof Settings */
1791
1796
  function setGamepadsEnable(enable) { gamepadsEnable = enable; }
1792
1797
 
1793
1798
  /** Set if the dpad input is also routed to the left analog stick
1794
- * @param {Boolean} enable
1799
+ * @param {boolean} enable
1795
1800
  * @memberof Settings */
1796
1801
  function setGamepadDirectionEmulateStick(enable) { gamepadDirectionEmulateStick = enable; }
1797
1802
 
1798
1803
  /** Set if true the WASD keys are also routed to the direction keys
1799
- * @param {Boolean} enable
1804
+ * @param {boolean} enable
1800
1805
  * @memberof Settings */
1801
1806
  function setInputWASDEmulateDirection(enable) { inputWASDEmulateDirection = enable; }
1802
1807
 
1803
1808
  /** Set if touch input is allowed
1804
- * @param {Boolean} enable
1809
+ * @param {boolean} enable
1805
1810
  * @memberof Settings */
1806
1811
  function setTouchInputEnable(enable) { touchInputEnable = enable; }
1807
1812
 
1808
1813
  /** Set if touch gamepad should appear on mobile devices
1809
- * @param {Boolean} enable
1814
+ * @param {boolean} enable
1810
1815
  * @memberof Settings */
1811
1816
  function setTouchGamepadEnable(enable) { touchGamepadEnable = enable; }
1812
1817
 
1813
1818
  /** Set if touch gamepad should be analog stick or 8 way dpad
1814
- * @param {Boolean} analog
1819
+ * @param {boolean} analog
1815
1820
  * @memberof Settings */
1816
1821
  function setTouchGamepadAnalog(analog) { touchGamepadAnalog = analog; }
1817
1822
 
1818
1823
  /** Set size of virtual gamepad for touch devices in pixels
1819
- * @param {Number} size
1824
+ * @param {number} size
1820
1825
  * @memberof Settings */
1821
1826
  function setTouchGamepadSize(size) { touchGamepadSize = size; }
1822
1827
 
1823
1828
  /** Set transparency of touch gamepad overlay
1824
- * @param {Number} alpha
1829
+ * @param {number} alpha
1825
1830
  * @memberof Settings */
1826
1831
  function setTouchGamepadAlpha(alpha) { touchGamepadAlpha = alpha; }
1827
1832
 
1828
1833
  /** Set to allow vibration hardware if it exists
1829
- * @param {Boolean} enable
1834
+ * @param {boolean} enable
1830
1835
  * @memberof Settings */
1831
1836
  function setVibrateEnable(enable) { vibrateEnable = enable; }
1832
1837
 
1833
1838
  /** Set to disable all audio code
1834
- * @param {Boolean} enable
1839
+ * @param {boolean} enable
1835
1840
  * @memberof Settings */
1836
1841
  function setSoundEnable(enable) { soundEnable = enable; }
1837
1842
 
1838
1843
  /** Set volume scale to apply to all sound, music and speech
1839
- * @param {Number} volume
1844
+ * @param {number} volume
1840
1845
  * @memberof Settings */
1841
1846
  function setSoundVolume(volume)
1842
1847
  {
@@ -1846,22 +1851,22 @@ function setSoundVolume(volume)
1846
1851
  }
1847
1852
 
1848
1853
  /** Set default range where sound no longer plays
1849
- * @param {Number} range
1854
+ * @param {number} range
1850
1855
  * @memberof Settings */
1851
1856
  function setSoundDefaultRange(range) { soundDefaultRange = range; }
1852
1857
 
1853
1858
  /** Set default range percent to start tapering off sound
1854
- * @param {Number} taper
1859
+ * @param {number} taper
1855
1860
  * @memberof Settings */
1856
1861
  function setSoundDefaultTaper(taper) { soundDefaultTaper = taper; }
1857
1862
 
1858
1863
  /** Set how long to show medals for in seconds
1859
- * @param {Number} time
1864
+ * @param {number} time
1860
1865
  * @memberof Settings */
1861
1866
  function setMedalDisplayTime(time) { medalDisplayTime = time; }
1862
1867
 
1863
1868
  /** Set how quickly to slide on/off medals in seconds
1864
- * @param {Number} time
1869
+ * @param {number} time
1865
1870
  * @memberof Settings */
1866
1871
  function setMedalDisplaySlideTime(time) { medalDisplaySlideTime = time; }
1867
1872
 
@@ -1871,22 +1876,22 @@ function setMedalDisplaySlideTime(time) { medalDisplaySlideTime = time; }
1871
1876
  function setMedalDisplaySize(size) { medalDisplaySize = size; }
1872
1877
 
1873
1878
  /** Set size of icon in medal display
1874
- * @param {Number} size
1879
+ * @param {number} size
1875
1880
  * @memberof Settings */
1876
1881
  function setMedalDisplayIconSize(size) { medalDisplayIconSize = size; }
1877
1882
 
1878
1883
  /** Set to stop medals from being unlockable
1879
- * @param {Boolean} preventUnlock
1884
+ * @param {boolean} preventUnlock
1880
1885
  * @memberof Settings */
1881
1886
  function setMedalsPreventUnlock(preventUnlock) { medalsPreventUnlock = preventUnlock; }
1882
1887
 
1883
1888
  /** Set if watermark with FPS should be shown
1884
- * @param {Boolean} show
1889
+ * @param {boolean} show
1885
1890
  * @memberof Debug */
1886
1891
  function setShowWatermark(show) { showWatermark = show; }
1887
1892
 
1888
1893
  /** Set key code used to toggle debug mode, Esc by default
1889
- * @param {String} key
1894
+ * @param {string} key
1890
1895
  * @memberof Debug */
1891
1896
  function setDebugKey(key) { debugKey = key; }
1892
1897
  /**
@@ -1926,9 +1931,9 @@ class EngineObject
1926
1931
  * @param {Vector2} [pos=(0,0)] - World space position of the object
1927
1932
  * @param {Vector2} [size=(1,1)] - World space size of the object
1928
1933
  * @param {TileInfo} [tileInfo] - Tile info to render object (undefined is untextured)
1929
- * @param {Number} [angle] - Angle the object is rotated by
1934
+ * @param {number} [angle] - Angle the object is rotated by
1930
1935
  * @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
1936
+ * @param {number} [renderOrder] - Objects sorted by renderOrder before being rendered
1932
1937
  */
1933
1938
  constructor(pos=vec2(), size=vec2(1), tileInfo, angle=0, color=new Color, renderOrder=0)
1934
1939
  {
@@ -1944,57 +1949,59 @@ class EngineObject
1944
1949
  this.drawSize = undefined;
1945
1950
  /** @property {TileInfo} - Tile info to render object (undefined is untextured) */
1946
1951
  this.tileInfo = tileInfo;
1947
- /** @property {Number} - Angle to rotate the object */
1952
+ /** @property {number} - Angle to rotate the object */
1948
1953
  this.angle = angle;
1949
1954
  /** @property {Color} - Color to apply when rendered */
1950
1955
  this.color = color;
1951
1956
  /** @property {Color} - Additive color to apply when rendered */
1952
1957
  this.additiveColor = undefined;
1953
- /** @property {Boolean} - Should it flip along y axis when rendered */
1958
+ /** @property {boolean} - Should it flip along y axis when rendered */
1954
1959
  this.mirror = false;
1955
1960
 
1956
1961
  // physical properties
1957
- /** @property {Number} [mass=objectDefaultMass] - How heavy the object is, static if 0 */
1962
+ /** @property {number} [mass=objectDefaultMass] - How heavy the object is, static if 0 */
1958
1963
  this.mass = objectDefaultMass;
1959
- /** @property {Number} [damping=objectDefaultDamping] - How much to slow down velocity each frame (0-1) */
1964
+ /** @property {number} [damping=objectDefaultDamping] - How much to slow down velocity each frame (0-1) */
1960
1965
  this.damping = objectDefaultDamping;
1961
- /** @property {Number} [angleDamping=objectDefaultAngleDamping] - How much to slow down rotation each frame (0-1) */
1966
+ /** @property {number} [angleDamping=objectDefaultAngleDamping] - How much to slow down rotation each frame (0-1) */
1962
1967
  this.angleDamping = objectDefaultAngleDamping;
1963
- /** @property {Number} [elasticity=objectDefaultElasticity] - How bouncy the object is when colliding (0-1) */
1968
+ /** @property {number} [elasticity=objectDefaultElasticity] - How bouncy the object is when colliding (0-1) */
1964
1969
  this.elasticity = objectDefaultElasticity;
1965
- /** @property {Number} [friction=objectDefaultFriction] - How much friction to apply when sliding (0-1) */
1970
+ /** @property {number} [friction=objectDefaultFriction] - How much friction to apply when sliding (0-1) */
1966
1971
  this.friction = objectDefaultFriction;
1967
- /** @property {Number} - How much to scale gravity by for this object */
1972
+ /** @property {number} - How much to scale gravity by for this object */
1968
1973
  this.gravityScale = 1;
1969
- /** @property {Number} - Objects are sorted by render order */
1974
+ /** @property {number} - Objects are sorted by render order */
1970
1975
  this.renderOrder = renderOrder;
1971
1976
  /** @property {Vector2} - Velocity of the object */
1972
1977
  this.velocity = vec2();
1973
- /** @property {Number} - Angular velocity of the object */
1978
+ /** @property {number} - Angular velocity of the object */
1974
1979
  this.angleVelocity = 0;
1975
- /** @property {Number} - Track when object was created */
1980
+ /** @property {number} - Track when object was created */
1976
1981
  this.spawnTime = time;
1977
- /** @property {Array} - List of children of this object */
1982
+ /** @property {Array<EngineObject>} - List of children of this object */
1978
1983
  this.children = [];
1979
- /** @property {Boolean} - Limit object speed using linear or circular math */
1984
+ /** @property {boolean} - Limit object speed using linear or circular math */
1980
1985
  this.clampSpeedLinear = true;
1986
+ /** @property {EngineObject} - Object we are standing on, if any */
1987
+ this.groundObject = undefined;
1981
1988
 
1982
1989
  // parent child system
1983
1990
  /** @property {EngineObject} - Parent of object if in local space */
1984
1991
  this.parent = undefined;
1985
1992
  /** @property {Vector2} - Local position if child */
1986
1993
  this.localPos = vec2();
1987
- /** @property {Number} - Local angle if child */
1994
+ /** @property {number} - Local angle if child */
1988
1995
  this.localAngle = 0;
1989
1996
 
1990
1997
  // collision flags
1991
- /** @property {Boolean} - Object collides with the tile collision */
1998
+ /** @property {boolean} - Object collides with the tile collision */
1992
1999
  this.collideTiles = false;
1993
- /** @property {Boolean} - Object collides with solid objects */
2000
+ /** @property {boolean} - Object collides with solid objects */
1994
2001
  this.collideSolidObjects = false;
1995
- /** @property {Boolean} - Object collides with and blocks other objects */
2002
+ /** @property {boolean} - Object collides with and blocks other objects */
1996
2003
  this.isSolid = false;
1997
- /** @property {Boolean} - Object collides with raycasts */
2004
+ /** @property {boolean} - Object collides with raycasts */
1998
2005
  this.collideRaycast = false;
1999
2006
 
2000
2007
  // add to list of objects
@@ -2009,7 +2016,7 @@ class EngineObject
2009
2016
  {
2010
2017
  // copy parent pos/angle
2011
2018
  const mirror = parent.getMirrorSign();
2012
- this.pos = this.localPos.multiply(vec2(mirror,1)).rotate(-parent.angle).add(parent.pos);
2019
+ this.pos = this.localPos.multiply(vec2(mirror,1)).rotate(parent.angle).add(parent.pos);
2013
2020
  this.angle = mirror*this.localAngle + parent.angle;
2014
2021
  }
2015
2022
 
@@ -2064,7 +2071,7 @@ class EngineObject
2064
2071
  // apply friction in local space of ground object
2065
2072
  const groundSpeed = this.groundObject.velocity ? this.groundObject.velocity.x : 0;
2066
2073
  this.velocity.x = groundSpeed + (this.velocity.x - groundSpeed) * this.friction;
2067
- this.groundObject = 0;
2074
+ this.groundObject = undefined;
2068
2075
  //debugOverlay && debugPhysics && debugPoint(this.pos.subtract(vec2(0,this.size.y/2)), '#0f0');
2069
2076
  }
2070
2077
 
@@ -2181,18 +2188,21 @@ class EngineObject
2181
2188
  // bounce velocity
2182
2189
  this.velocity.y *= -this.elasticity;
2183
2190
 
2184
- // set if landed on ground
2185
- if (this.groundObject = wasMovingDown)
2191
+ if (wasMovingDown)
2186
2192
  {
2187
2193
  // adjust position to slightly above nearest tile boundary
2188
2194
  // this prevents gap between object and ground
2189
2195
  const epsilon = .0001;
2190
2196
  this.pos.y = (oldPos.y-this.size.y/2|0)+this.size.y/2+epsilon;
2197
+
2198
+ // set ground object to self for tile collision
2199
+ this.groundObject = this;
2191
2200
  }
2192
2201
  else
2193
2202
  {
2194
2203
  // move to previous position
2195
2204
  this.pos.y = oldPos.y;
2205
+ this.groundObject = undefined;
2196
2206
  }
2197
2207
  }
2198
2208
  if (isBlockedX)
@@ -2237,26 +2247,26 @@ class EngineObject
2237
2247
 
2238
2248
  /** Convert from local space to world space for a vector (rotation only)
2239
2249
  * @param {Vector2} vec - local space vector */
2240
- localToWorldVector(vec) { return vec.rotate(-this.angle); }
2250
+ localToWorldVector(vec) { return vec.rotate(this.angle); }
2241
2251
 
2242
2252
  /** Convert from world space to local space for a vector (rotation only)
2243
2253
  * @param {Vector2} vec - world space vector */
2244
- worldToLocalVector(vec) { return vec.rotate(this.angle); }
2254
+ worldToLocalVector(vec) { return vec.rotate(-this.angle); }
2245
2255
 
2246
2256
  /** Called to check if a tile collision should be resolved
2247
- * @param {Number} tileData - the value of the tile at the position
2257
+ * @param {number} tileData - the value of the tile at the position
2248
2258
  * @param {Vector2} pos - tile where the collision occurred
2249
- * @return {Boolean} - true if the collision should be resolved */
2259
+ * @return {boolean} - true if the collision should be resolved */
2250
2260
  collideWithTile(tileData, pos) { return tileData > 0; }
2251
2261
 
2252
2262
  /** Called to check if a object collision should be resolved
2253
2263
  * @param {EngineObject} object - the object to test against
2254
- * @return {Boolean} - true if the collision should be resolved
2264
+ * @return {boolean} - true if the collision should be resolved
2255
2265
  */
2256
2266
  collideWithObject(object) { return true; }
2257
2267
 
2258
2268
  /** How long since the object was created
2259
- * @return {Number} */
2269
+ * @return {number} */
2260
2270
  getAliveTime() { return time - this.spawnTime; }
2261
2271
 
2262
2272
  /** Apply acceleration to this object (adjust velocity, not affected by mass)
@@ -2268,13 +2278,13 @@ class EngineObject
2268
2278
  applyForce(force) { this.applyAcceleration(force.scale(1/this.mass)); }
2269
2279
 
2270
2280
  /** Get the direction of the mirror
2271
- * @return {Number} -1 if this.mirror is true, or 1 if not mirrored */
2281
+ * @return {number} -1 if this.mirror is true, or 1 if not mirrored */
2272
2282
  getMirrorSign() { return this.mirror ? -1 : 1; }
2273
2283
 
2274
2284
  /** Attaches a child to this with a given local transform
2275
2285
  * @param {EngineObject} child
2276
2286
  * @param {Vector2} [localPos=(0,0)]
2277
- * @param {Number} [localAngle] */
2287
+ * @param {number} [localAngle] */
2278
2288
  addChild(child, localPos=vec2(), localAngle=0)
2279
2289
  {
2280
2290
  ASSERT(!child.parent && !this.children.includes(child));
@@ -2294,10 +2304,10 @@ class EngineObject
2294
2304
  }
2295
2305
 
2296
2306
  /** 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? */
2307
+ * @param {boolean} [collideSolidObjects] - Does it collide with solid objects?
2308
+ * @param {boolean} [isSolid] - Does it collide with and block other objects? (expensive in large numbers)
2309
+ * @param {boolean} [collideTiles] - Does it collide with the tile collision?
2310
+ * @param {boolean} [collideRaycast] - Does it collide with raycasts? */
2301
2311
  setCollision(collideSolidObjects=true, isSolid=true, collideTiles=true, collideRaycast=true)
2302
2312
  {
2303
2313
  ASSERT(collideSolidObjects || !isSolid, 'solid objects must be set to collide');
@@ -2309,7 +2319,7 @@ class EngineObject
2309
2319
  }
2310
2320
 
2311
2321
  /** Returns string containing info about this object for debugging
2312
- * @return {String} */
2322
+ * @return {string} */
2313
2323
  toString()
2314
2324
  {
2315
2325
  if (debug)
@@ -2407,10 +2417,10 @@ let drawCount;
2407
2417
  * Create a tile info object using a grid based system
2408
2418
  * - This can take vecs or floats for easier use and conversion
2409
2419
  * - 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
2420
+ * @param {Vector2|number} [pos=0] - Index of tile in sheet
2421
+ * @param {Vector2|number} [size=tileSizeDefault] - Size of tile in pixels
2422
+ * @param {number} [textureIndex] - Texture index to use
2423
+ * @param {number} [padding] - How many pixels padding around tiles
2414
2424
  * @return {TileInfo}
2415
2425
  * @example
2416
2426
  * tile(2) // a tile at index 2 using the default tile size of 16
@@ -2454,8 +2464,8 @@ class TileInfo
2454
2464
  /** Create a tile info object
2455
2465
  * @param {Vector2} [pos=(0,0)] - Top left corner of tile in pixels
2456
2466
  * @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
2467
+ * @param {number} [textureIndex] - Texture index to use
2468
+ * @param {number} [padding] - How many pixels padding around tiles
2459
2469
  */
2460
2470
  constructor(pos=vec2(), size=tileSizeDefault, textureIndex=0, padding=0)
2461
2471
  {
@@ -2463,9 +2473,9 @@ class TileInfo
2463
2473
  this.pos = pos.copy();
2464
2474
  /** @property {Vector2} - Size of tile in pixels */
2465
2475
  this.size = size.copy();
2466
- /** @property {Number} - Texture index to use */
2476
+ /** @property {number} - Texture index to use */
2467
2477
  this.textureIndex = textureIndex;
2468
- /** @property {Number} - How many pixels padding around tiles */
2478
+ /** @property {number} - How many pixels padding around tiles */
2469
2479
  this.padding = padding;
2470
2480
  }
2471
2481
 
@@ -2477,7 +2487,7 @@ class TileInfo
2477
2487
  { return new TileInfo(this.pos.add(offset), this.size, this.textureIndex); }
2478
2488
 
2479
2489
  /** Returns a copy of this tile offset by a number of animation frames
2480
- * @param {Number} frame - Offset to apply in animation frames
2490
+ * @param {number} frame - Offset to apply in animation frames
2481
2491
  * @return {TileInfo}
2482
2492
  */
2483
2493
  frame(frame)
@@ -2549,11 +2559,11 @@ function getCameraSize() { return mainCanvasSize.scale(1/cameraScale); }
2549
2559
  * @param {Vector2} [size=(1,1)] - Size of the tile in world space
2550
2560
  * @param {TileInfo}[tileInfo] - Tile info to use, untextured if undefined
2551
2561
  * @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
2562
+ * @param {number} [angle] - Angle to rotate by
2563
+ * @param {boolean} [mirror] - If true image is flipped along the Y axis
2554
2564
  * @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
2565
+ * @param {boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering
2566
+ * @param {boolean} [screenSpace=false] - If true the pos and size are in screen space
2557
2567
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context] - Canvas 2D context to draw to
2558
2568
  * @memberof Draw */
2559
2569
  function drawTile(pos, size=vec2(1), tileInfo, color=new Color,
@@ -2628,9 +2638,9 @@ function drawTile(pos, size=vec2(1), tileInfo, color=new Color,
2628
2638
  * @param {Vector2} pos
2629
2639
  * @param {Vector2} [size=(1,1)]
2630
2640
  * @param {Color} [color=(1,1,1,1)]
2631
- * @param {Number} [angle]
2632
- * @param {Boolean} [useWebGL=glEnable]
2633
- * @param {Boolean} [screenSpace=false]
2641
+ * @param {number} [angle]
2642
+ * @param {boolean} [useWebGL=glEnable]
2643
+ * @param {boolean} [screenSpace=false]
2634
2644
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
2635
2645
  * @memberof Draw */
2636
2646
  function drawRect(pos, size, color, angle, useWebGL, screenSpace, context)
@@ -2641,10 +2651,10 @@ function drawRect(pos, size, color, angle, useWebGL, screenSpace, context)
2641
2651
  /** Draw colored line between two points
2642
2652
  * @param {Vector2} posA
2643
2653
  * @param {Vector2} posB
2644
- * @param {Number} [thickness]
2654
+ * @param {number} [thickness]
2645
2655
  * @param {Color} [color=(1,1,1,1)]
2646
- * @param {Boolean} [useWebGL=glEnable]
2647
- * @param {Boolean} [screenSpace=false]
2656
+ * @param {boolean} [useWebGL=glEnable]
2657
+ * @param {boolean} [screenSpace=false]
2648
2658
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
2649
2659
  * @memberof Draw */
2650
2660
  function drawLine(posA, posB, thickness=.1, color, useWebGL, screenSpace, context)
@@ -2655,11 +2665,11 @@ function drawLine(posA, posB, thickness=.1, color, useWebGL, screenSpace, contex
2655
2665
  }
2656
2666
 
2657
2667
  /** Draw colored polygon using passed in points
2658
- * @param {Array} points - Array of Vector2 points
2668
+ * @param {Array<Vector2>} points - Array of Vector2 points
2659
2669
  * @param {Color} [color=(1,1,1,1)]
2660
- * @param {Number} [lineWidth=0]
2670
+ * @param {number} [lineWidth=0]
2661
2671
  * @param {Color} [lineColor=(0,0,0,1)]
2662
- * @param {Boolean} [screenSpace=false]
2672
+ * @param {boolean} [screenSpace=false]
2663
2673
  * @param {CanvasRenderingContext2D} [context=mainContext]
2664
2674
  * @memberof Draw */
2665
2675
  function drawPoly(points, color=new Color, lineWidth=0, lineColor=new Color(0,0,0), screenSpace, context=mainContext)
@@ -2681,13 +2691,13 @@ function drawPoly(points, color=new Color, lineWidth=0, lineColor=new Color(0,0,
2681
2691
 
2682
2692
  /** Draw colored ellipse using passed in point
2683
2693
  * @param {Vector2} pos
2684
- * @param {Number} [width=1]
2685
- * @param {Number} [height=1]
2686
- * @param {Number} [angle=0]
2694
+ * @param {number} [width=1]
2695
+ * @param {number} [height=1]
2696
+ * @param {number} [angle=0]
2687
2697
  * @param {Color} [color=(1,1,1,1)]
2688
- * @param {Number} [lineWidth=0]
2698
+ * @param {number} [lineWidth=0]
2689
2699
  * @param {Color} [lineColor=(0,0,0,1)]
2690
- * @param {Boolean} [screenSpace=false]
2700
+ * @param {boolean} [screenSpace=false]
2691
2701
  * @param {CanvasRenderingContext2D} [context=mainContext]
2692
2702
  * @memberof Draw */
2693
2703
  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 +2724,11 @@ function drawEllipse(pos, width=1, height=1, angle=0, color=new Color, lineWidth
2714
2724
 
2715
2725
  /** Draw colored circle using passed in point
2716
2726
  * @param {Vector2} pos
2717
- * @param {Number} [radius=1]
2727
+ * @param {number} [radius=1]
2718
2728
  * @param {Color} [color=(1,1,1,1)]
2719
- * @param {Number} [lineWidth=0]
2729
+ * @param {number} [lineWidth=0]
2720
2730
  * @param {Color} [lineColor=(0,0,0,1)]
2721
- * @param {Boolean} [screenSpace=false]
2731
+ * @param {boolean} [screenSpace=false]
2722
2732
  * @param {CanvasRenderingContext2D} [context=mainContext]
2723
2733
  * @memberof Draw */
2724
2734
  function drawCircle(pos, radius=1, color=new Color, lineWidth=0, lineColor=new Color(0,0,0), screenSpace, context=mainContext)
@@ -2727,10 +2737,10 @@ function drawCircle(pos, radius=1, color=new Color, lineWidth=0, lineColor=new C
2727
2737
  /** Draw directly to a 2d canvas context in world space
2728
2738
  * @param {Vector2} pos
2729
2739
  * @param {Vector2} size
2730
- * @param {Number} angle
2731
- * @param {Boolean} mirror
2740
+ * @param {number} angle
2741
+ * @param {boolean} mirror
2732
2742
  * @param {Function} drawFunction
2733
- * @param {Boolean} [screenSpace=false]
2743
+ * @param {boolean} [screenSpace=false]
2734
2744
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=mainContext]
2735
2745
  * @memberof Draw */
2736
2746
  function drawCanvas2D(pos, size, angle, mirror, drawFunction, screenSpace, context=mainContext)
@@ -2751,15 +2761,15 @@ function drawCanvas2D(pos, size, angle, mirror, drawFunction, screenSpace, conte
2751
2761
 
2752
2762
  /** Draw text on main canvas in world space
2753
2763
  * Automatically splits new lines into rows
2754
- * @param {String} text
2764
+ * @param {string} text
2755
2765
  * @param {Vector2} pos
2756
- * @param {Number} [size]
2766
+ * @param {number} [size]
2757
2767
  * @param {Color} [color=(1,1,1,1)]
2758
- * @param {Number} [lineWidth]
2768
+ * @param {number} [lineWidth]
2759
2769
  * @param {Color} [lineColor=(0,0,0,1)]
2760
2770
  * @param {CanvasTextAlign} [textAlign='center']
2761
- * @param {String} [font=fontDefault]
2762
- * @param {Number} [maxWidth]
2771
+ * @param {string} [font=fontDefault]
2772
+ * @param {number} [maxWidth]
2763
2773
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=mainContext]
2764
2774
  * @memberof Draw */
2765
2775
  function drawText(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, font, maxWidth, context=mainContext)
@@ -2769,15 +2779,15 @@ function drawText(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, f
2769
2779
 
2770
2780
  /** Draw text on overlay canvas in world space
2771
2781
  * Automatically splits new lines into rows
2772
- * @param {String} text
2782
+ * @param {string} text
2773
2783
  * @param {Vector2} pos
2774
- * @param {Number} [size]
2784
+ * @param {number} [size]
2775
2785
  * @param {Color} [color=(1,1,1,1)]
2776
- * @param {Number} [lineWidth]
2786
+ * @param {number} [lineWidth]
2777
2787
  * @param {Color} [lineColor=(0,0,0,1)]
2778
2788
  * @param {CanvasTextAlign} [textAlign='center']
2779
- * @param {String} [font=fontDefault]
2780
- * @param {Number} [maxWidth]
2789
+ * @param {string} [font=fontDefault]
2790
+ * @param {number} [maxWidth]
2781
2791
  * @memberof Draw */
2782
2792
  function drawTextOverlay(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, font, maxWidth)
2783
2793
  {
@@ -2786,15 +2796,15 @@ function drawTextOverlay(text, pos, size=1, color, lineWidth=0, lineColor, textA
2786
2796
 
2787
2797
  /** Draw text on overlay canvas in screen space
2788
2798
  * Automatically splits new lines into rows
2789
- * @param {String} text
2799
+ * @param {string} text
2790
2800
  * @param {Vector2} pos
2791
- * @param {Number} [size]
2801
+ * @param {number} [size]
2792
2802
  * @param {Color} [color=(1,1,1,1)]
2793
- * @param {Number} [lineWidth]
2803
+ * @param {number} [lineWidth]
2794
2804
  * @param {Color} [lineColor=(0,0,0,1)]
2795
2805
  * @param {CanvasTextAlign} [textAlign]
2796
- * @param {String} [font=fontDefault]
2797
- * @param {Number} [maxWidth]
2806
+ * @param {string} [font=fontDefault]
2807
+ * @param {number} [maxWidth]
2798
2808
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=overlayContext]
2799
2809
  * @memberof Draw */
2800
2810
  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 +2830,8 @@ function drawTextScreen(text, pos, size=1, color=new Color, lineWidth=0, lineCol
2820
2830
  }
2821
2831
 
2822
2832
  /** Enable normal or additive blend mode
2823
- * @param {Boolean} [additive]
2824
- * @param {Boolean} [useWebGL=glEnable]
2833
+ * @param {boolean} [additive]
2834
+ * @param {boolean} [useWebGL=glEnable]
2825
2835
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=mainContext]
2826
2836
  * @memberof Draw */
2827
2837
  function setBlendMode(additive, useWebGL=glEnable, context)
@@ -2888,10 +2898,10 @@ class FontImage
2888
2898
  }
2889
2899
 
2890
2900
  /** Draw text in world space using the image font
2891
- * @param {String} text
2901
+ * @param {string} text
2892
2902
  * @param {Vector2} pos
2893
- * @param {Number} [scale=.25]
2894
- * @param {Boolean} [center]
2903
+ * @param {number} [scale=.25]
2904
+ * @param {boolean} [center]
2895
2905
  */
2896
2906
  drawText(text, pos, scale=1, center)
2897
2907
  {
@@ -2899,10 +2909,10 @@ class FontImage
2899
2909
  }
2900
2910
 
2901
2911
  /** Draw text in screen space using the image font
2902
- * @param {String} text
2912
+ * @param {string} text
2903
2913
  * @param {Vector2} pos
2904
- * @param {Number} [scale]
2905
- * @param {Boolean} [center]
2914
+ * @param {number} [scale]
2915
+ * @param {boolean} [center]
2906
2916
  */
2907
2917
  drawTextScreen(text, pos, scale=4, center)
2908
2918
  {
@@ -2940,7 +2950,7 @@ class FontImage
2940
2950
  // Display functions
2941
2951
 
2942
2952
  /** Returns true if fullscreen mode is active
2943
- * @return {Boolean}
2953
+ * @return {boolean}
2944
2954
  * @memberof Draw */
2945
2955
  function isFullscreen() { return !!document.fullscreenElement; }
2946
2956
 
@@ -2959,7 +2969,7 @@ function toggleFullscreen()
2959
2969
  }
2960
2970
 
2961
2971
  /** Set the cursor style
2962
- * @param {String} cursorStyle - CSS cursor style (auto, none, crosshair, etc)
2972
+ * @param {string} cursorStyle - CSS cursor style (auto, none, crosshair, etc)
2963
2973
  * @memberof Draw */
2964
2974
  function setCursor(cursorStyle = 'auto')
2965
2975
  {
@@ -2979,9 +2989,9 @@ function setCursor(cursorStyle = 'auto')
2979
2989
 
2980
2990
 
2981
2991
  /** Returns true if device key is down
2982
- * @param {String|Number} key
2983
- * @param {Number} [device]
2984
- * @return {Boolean}
2992
+ * @param {string|number} key
2993
+ * @param {number} [device]
2994
+ * @return {boolean}
2985
2995
  * @memberof Input */
2986
2996
  function keyIsDown(key, device=0)
2987
2997
  {
@@ -2990,9 +3000,9 @@ function keyIsDown(key, device=0)
2990
3000
  }
2991
3001
 
2992
3002
  /** Returns true if device key was pressed this frame
2993
- * @param {String|Number} key
2994
- * @param {Number} [device]
2995
- * @return {Boolean}
3003
+ * @param {string|number} key
3004
+ * @param {number} [device]
3005
+ * @return {boolean}
2996
3006
  * @memberof Input */
2997
3007
  function keyWasPressed(key, device=0)
2998
3008
  {
@@ -3001,9 +3011,9 @@ function keyWasPressed(key, device=0)
3001
3011
  }
3002
3012
 
3003
3013
  /** Returns true if device key was released this frame
3004
- * @param {String|Number} key
3005
- * @param {Number} [device]
3006
- * @return {Boolean}
3014
+ * @param {string|number} key
3015
+ * @param {number} [device]
3016
+ * @return {boolean}
3007
3017
  * @memberof Input */
3008
3018
  function keyWasReleased(key, device=0)
3009
3019
  {
@@ -3026,22 +3036,22 @@ function clearInput() { inputData = [[]]; touchGamepadButtons = []; }
3026
3036
 
3027
3037
  /** Returns true if mouse button is down
3028
3038
  * @function
3029
- * @param {Number} button
3030
- * @return {Boolean}
3039
+ * @param {number} button
3040
+ * @return {boolean}
3031
3041
  * @memberof Input */
3032
3042
  const mouseIsDown = keyIsDown;
3033
3043
 
3034
3044
  /** Returns true if mouse button was pressed
3035
3045
  * @function
3036
- * @param {Number} button
3037
- * @return {Boolean}
3046
+ * @param {number} button
3047
+ * @return {boolean}
3038
3048
  * @memberof Input */
3039
3049
  const mouseWasPressed = keyWasPressed;
3040
3050
 
3041
3051
  /** Returns true if mouse button was released
3042
3052
  * @function
3043
- * @param {Number} button
3044
- * @return {Boolean}
3053
+ * @param {number} button
3054
+ * @return {boolean}
3045
3055
  * @memberof Input */
3046
3056
  const mouseWasReleased = keyWasReleased;
3047
3057
 
@@ -3056,47 +3066,47 @@ let mousePos = vec2();
3056
3066
  let mousePosScreen = vec2();
3057
3067
 
3058
3068
  /** Mouse wheel delta this frame
3059
- * @type {Number}
3069
+ * @type {number}
3060
3070
  * @memberof Input */
3061
3071
  let mouseWheel = 0;
3062
3072
 
3063
3073
  /** Returns true if user is using gamepad (has more recently pressed a gamepad button)
3064
- * @type {Boolean}
3074
+ * @type {boolean}
3065
3075
  * @memberof Input */
3066
3076
  let isUsingGamepad = false;
3067
3077
 
3068
3078
  /** Prevents input continuing to the default browser handling (false by default)
3069
- * @type {Boolean}
3079
+ * @type {boolean}
3070
3080
  * @memberof Input */
3071
3081
  let preventDefaultInput = false;
3072
3082
 
3073
3083
  /** Returns true if gamepad button is down
3074
- * @param {Number} button
3075
- * @param {Number} [gamepad]
3076
- * @return {Boolean}
3084
+ * @param {number} button
3085
+ * @param {number} [gamepad]
3086
+ * @return {boolean}
3077
3087
  * @memberof Input */
3078
3088
  function gamepadIsDown(button, gamepad=0)
3079
3089
  { return keyIsDown(button, gamepad+1); }
3080
3090
 
3081
3091
  /** Returns true if gamepad button was pressed
3082
- * @param {Number} button
3083
- * @param {Number} [gamepad]
3084
- * @return {Boolean}
3092
+ * @param {number} button
3093
+ * @param {number} [gamepad]
3094
+ * @return {boolean}
3085
3095
  * @memberof Input */
3086
3096
  function gamepadWasPressed(button, gamepad=0)
3087
3097
  { return keyWasPressed(button, gamepad+1); }
3088
3098
 
3089
3099
  /** Returns true if gamepad button was released
3090
- * @param {Number} button
3091
- * @param {Number} [gamepad]
3092
- * @return {Boolean}
3100
+ * @param {number} button
3101
+ * @param {number} [gamepad]
3102
+ * @return {boolean}
3093
3103
  * @memberof Input */
3094
3104
  function gamepadWasReleased(button, gamepad=0)
3095
3105
  { return keyWasReleased(button, gamepad+1); }
3096
3106
 
3097
3107
  /** Returns gamepad stick value
3098
- * @param {Number} stick
3099
- * @param {Number} [gamepad]
3108
+ * @param {number} stick
3109
+ * @param {number} [gamepad]
3100
3110
  * @return {Vector2}
3101
3111
  * @memberof Input */
3102
3112
  function gamepadStick(stick, gamepad=0)
@@ -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); }
@@ -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
@@ -5002,7 +5012,7 @@ let glCanvas;
5002
5012
  let glContext;
5003
5013
 
5004
5014
  /** Should webgl be setup with anti-aliasing? must be set before calling engineInit
5005
- * @type {Boolean}
5015
+ * @type {boolean}
5006
5016
  * @memberof WebGL */
5007
5017
  let glAntialias = true;
5008
5018
 
@@ -5225,7 +5235,7 @@ function glFlush()
5225
5235
 
5226
5236
  /** Draw any sprites still in the buffer and copy to main canvas
5227
5237
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} context
5228
- * @param {Boolean} [forceDraw]
5238
+ * @param {boolean} [forceDraw]
5229
5239
  * @memberof WebGL */
5230
5240
  function glCopyToContext(context, forceDraw=false)
5231
5241
  {
@@ -5239,7 +5249,7 @@ function glCopyToContext(context, forceDraw=false)
5239
5249
  }
5240
5250
 
5241
5251
  /** Set anti-aliasing for webgl canvas
5242
- * @param {Boolean} [antialias]
5252
+ * @param {boolean} [antialias]
5243
5253
  * @memberof WebGL */
5244
5254
  function glSetAntialias(antialias=true)
5245
5255
  {
@@ -5304,61 +5314,62 @@ function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba, rgbaAdd
5304
5314
 
5305
5315
 
5306
5316
  /** Name of engine
5307
- * @type {String}
5317
+ * @type {string}
5308
5318
  * @default
5309
5319
  * @memberof Engine */
5310
5320
  const engineName = 'LittleJS';
5311
5321
 
5312
5322
  /** Version of engine
5313
- * @type {String}
5323
+ * @type {string}
5314
5324
  * @default
5315
5325
  * @memberof Engine */
5316
- const engineVersion = '1.11.8';
5326
+ const engineVersion = '1.11.10';
5317
5327
 
5318
5328
  /** Frames per second to update
5319
- * @type {Number}
5329
+ * @type {number}
5320
5330
  * @default
5321
5331
  * @memberof Engine */
5322
5332
  const frameRate = 60;
5323
5333
 
5324
5334
  /** How many seconds each frame lasts, engine uses a fixed time step
5325
- * @type {Number}
5335
+ * @type {number}
5326
5336
  * @default 1/60
5327
5337
  * @memberof Engine */
5328
5338
  const timeDelta = 1/frameRate;
5329
5339
 
5330
5340
  /** Array containing all engine objects
5331
- * @type {Array}
5341
+ * @type {Array<EngineObject>}
5332
5342
  * @memberof Engine */
5333
5343
  let engineObjects = [];
5334
5344
 
5335
5345
  /** Array with only objects set to collide with other objects this frame (for optimization)
5336
- * @type {Array}
5346
+ * @type {Array<EngineObject>}
5337
5347
  * @memberof Engine */
5338
5348
  let engineObjectsCollide = [];
5339
5349
 
5340
5350
  /** Current update frame, used to calculate time
5341
- * @type {Number}
5351
+ * @type {number}
5342
5352
  * @memberof Engine */
5343
5353
  let frame = 0;
5344
5354
 
5345
5355
  /** Current engine time since start in seconds
5346
- * @type {Number}
5356
+ * @type {number}
5347
5357
  * @memberof Engine */
5348
5358
  let time = 0;
5349
5359
 
5350
5360
  /** Actual clock time since start in seconds (not affected by pause or frame rate clamping)
5351
- * @type {Number}
5361
+ * @type {number}
5352
5362
  * @memberof Engine */
5353
5363
  let timeReal = 0;
5354
5364
 
5355
5365
  /** Is the game paused? Causes time and objects to not be updated
5356
- * @type {Boolean}
5366
+ * @type {boolean}
5357
5367
  * @default false
5358
5368
  * @memberof Engine */
5359
5369
  let paused = false;
5370
+
5360
5371
  /** Set if game is paused
5361
- * @param {Boolean} isPaused
5372
+ * @param {boolean} isPaused
5362
5373
  * @memberof Engine */
5363
5374
  function setPaused(isPaused) { paused = isPaused; }
5364
5375
 
@@ -5391,7 +5402,7 @@ function engineAddPlugin(updateFunction, renderFunction)
5391
5402
  * @param {Function} gameUpdatePost - Called after physics and objects are updated, even when paused
5392
5403
  * @param {Function} gameRender - Called before objects are rendered, for drawing the background
5393
5404
  * @param {Function} gameRenderPost - Called after objects are rendered, useful for drawing UI
5394
- * @param {Array} [imageSources=[]] - List of images to load
5405
+ * @param {Array<string>} [imageSources=[]] - List of images to load
5395
5406
  * @param {HTMLElement} [rootElement] - Root element to attach to, the document body by default
5396
5407
  * @memberof Engine */
5397
5408
  function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, imageSources=[], rootElement=document.body)
@@ -5687,9 +5698,9 @@ function engineObjectsDestroy()
5687
5698
 
5688
5699
  /** Collects all object within a given area
5689
5700
  * @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
5701
+ * @param {Vector2|number} [size] - Radius of circle if float, rectangle size if Vector2
5702
+ * @param {Array<EngineObject>} [objects=engineObjects] - List of objects to check
5703
+ * @return {Array<EngineObject>} - List of collected objects
5693
5704
  * @memberof Engine */
5694
5705
  function engineObjectsCollect(pos, size, objects=engineObjects)
5695
5706
  {
@@ -5715,9 +5726,9 @@ function engineObjectsCollect(pos, size, objects=engineObjects)
5715
5726
 
5716
5727
  /** Triggers a callback for each object within a given area
5717
5728
  * @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
5729
+ * @param {Vector2|number} [size] - Radius of circle if float, rectangle size if Vector2
5719
5730
  * @param {Function} [callbackFunction] - Calls this function on every object that passes the test
5720
- * @param {Array} [objects=engineObjects] - List of objects to check
5731
+ * @param {Array<EngineObject>} [objects=engineObjects] - List of objects to check
5721
5732
  * @memberof Engine */
5722
5733
  function engineObjectsCallback(pos, size, callbackFunction, objects=engineObjects)
5723
5734
  { engineObjectsCollect(pos, size, objects).forEach(o => callbackFunction(o)); }
@@ -5725,8 +5736,8 @@ function engineObjectsCallback(pos, size, callbackFunction, objects=engineObject
5725
5736
  /** Return a list of objects intersecting a ray
5726
5737
  * @param {Vector2} start
5727
5738
  * @param {Vector2} end
5728
- * @param {Array} [objects=engineObjects] - List of objects to check
5729
- * @return {Array} - List of objects hit
5739
+ * @param {Array<EngineObject>} [objects=engineObjects] - List of objects to check
5740
+ * @return {Array<EngineObject>} - List of objects hit
5730
5741
  * @memberof Engine */
5731
5742
  function engineObjectsRaycast(start, end, objects=engineObjects)
5732
5743
  {
@@ -5917,8 +5928,8 @@ function drawEngineSplashScreen(t)
5917
5928
  * - Export engine as a module
5918
5929
  */
5919
5930
 
5920
- export {
5921
-
5931
+ export
5932
+ {
5922
5933
  // Engine
5923
5934
  engineName,
5924
5935
  engineVersion,