littlejsengine 1.9.0 → 1.9.2

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 (63) hide show
  1. package/README.md +7 -7
  2. package/{build → dist}/littlejs.d.ts +84 -77
  3. package/{build → dist}/littlejs.esm.js +245 -143
  4. package/dist/littlejs.esm.min.js +1 -0
  5. package/{build → dist}/littlejs.js +245 -143
  6. package/dist/littlejs.min.js +1 -0
  7. package/{build → dist}/littlejs.release.js +239 -141
  8. package/examples/breakout/game.js +2 -2
  9. package/examples/breakout/gameObjects.js +3 -3
  10. package/examples/breakout/index.html +3 -3
  11. package/examples/breakoutTutorial/index.html +2 -2
  12. package/examples/electron/build.js +1 -1
  13. package/examples/electron/game.js +49 -38
  14. package/examples/electron/index.html +2 -2
  15. package/examples/electron/tiles.png +0 -0
  16. package/examples/empty/index.html +1 -1
  17. package/examples/js13k/build.js +2 -2
  18. package/examples/js13k/game.js +10 -9
  19. package/examples/js13k/index.html +13 -13
  20. package/examples/js13k/tiles.png +0 -0
  21. package/examples/module/game.js +45 -41
  22. package/examples/module/index.html +1 -1
  23. package/examples/module/tiles.png +0 -0
  24. package/examples/particles/index.html +1 -1
  25. package/examples/platformer/data/gameTileData.tmx +143 -0
  26. package/examples/platformer/data/gameTileData.tsx +4 -0
  27. package/examples/platformer/game.js +0 -1
  28. package/examples/platformer/gameCharacter.js +1 -1
  29. package/examples/platformer/gameEffects.js +42 -110
  30. package/examples/platformer/gameLevel.js +149 -183
  31. package/examples/platformer/gameObjects.js +61 -16
  32. package/examples/platformer/gamePlayer.js +3 -2
  33. package/examples/platformer/gameTileData.js +181 -0
  34. package/examples/platformer/index.html +8 -7
  35. package/examples/platformer/tiles.png +0 -0
  36. package/examples/platformer/tilesLevel.png +0 -0
  37. package/examples/puzzle/game.js +12 -12
  38. package/examples/puzzle/index.html +2 -2
  39. package/examples/starter/build.js +2 -2
  40. package/examples/starter/game.js +6 -6
  41. package/examples/starter/index.html +13 -13
  42. package/examples/starter/tiles.png +0 -0
  43. package/examples/stress/index.html +2 -2
  44. package/examples/typescript/build.bat +4 -1
  45. package/examples/typescript/game.js +34 -31
  46. package/examples/typescript/game.ts +40 -36
  47. package/examples/typescript/index.html +1 -1
  48. package/examples/typescript/tiles.png +0 -0
  49. package/package.json +3 -3
  50. package/src/engine.js +1 -1
  51. package/src/engineAudio.js +4 -10
  52. package/src/engineBuild.js +9 -2
  53. package/src/engineDebug.js +6 -2
  54. package/src/engineDraw.js +27 -27
  55. package/src/engineInput.js +7 -7
  56. package/src/engineMedals.js +2 -2
  57. package/src/engineObject.js +7 -7
  58. package/src/engineParticles.js +9 -9
  59. package/src/engineTileLayer.js +38 -33
  60. package/src/engineUtilities.js +136 -35
  61. package/src/engineWebGL.js +8 -10
  62. package/build/littlejs.esm.min.js +0 -1
  63. package/build/littlejs.min.js +0 -1
@@ -58,9 +58,13 @@ let debugPrimitives = [], debugPhysics = false, debugRaycast = false, debugParti
58
58
 
59
59
  /** Asserts if the experssion is false, does not do anything in release builds
60
60
  * @param {Boolean} assert
61
- * @param {Object} output
61
+ * @param {Object} [output]
62
62
  * @memberof Debug */
63
- function ASSERT(assert, output) { enableAsserts && console.assert(assert, output); }
63
+ function ASSERT(assert, output)
64
+ {
65
+ if (enableAsserts)
66
+ output ? console.assert(assert, output) : console.assert(assert);
67
+ }
64
68
 
65
69
  /** Draw a debug rectangle in world space
66
70
  * @param {Vector2} pos
@@ -534,13 +538,13 @@ function smoothStep(percent) { return percent * percent * (3 - 2 * percent); }
534
538
  function nearestPowerOfTwo(value) { return 2**Math.ceil(Math.log2(value)); }
535
539
 
536
540
  /** Returns true if two axis aligned bounding boxes are overlapping
537
- * @param {Vector2} pointA - Center of box A
538
- * @param {Vector2} sizeA - Size of box A
539
- * @param {Vector2} pointB - Center of box B
540
- * @param {Vector2} sizeB - Size of box B
541
- * @return {Boolean} - True if overlapping
541
+ * @param {Vector2} pointA - Center of box A
542
+ * @param {Vector2} sizeA - Size of box A
543
+ * @param {Vector2} pointB - Center of box B
544
+ * @param {Vector2} [sizeB=(0,0)] - Size of box B, a point if undefined
545
+ * @return {Boolean} - True if overlapping
542
546
  * @memberof Utilities */
543
- function isOverlapping(pointA, sizeA, pointB, sizeB)
547
+ function isOverlapping(pointA, sizeA, pointB, sizeB=vec2())
544
548
  {
545
549
  return abs(pointA.x - pointB.x)*2 < sizeA.x + sizeB.x
546
550
  && abs(pointA.y - pointB.y)*2 < sizeA.y + sizeB.y;
@@ -600,8 +604,8 @@ function randInCircle(radius=1, minRadius=0)
600
604
  { return radius > 0 ? randVector(radius * rand(minRadius / radius, 1)**.5) : new Vector2; }
601
605
 
602
606
  /** Returns a random color between the two passed in colors, combine components if linear
603
- * @param {Color} [colorA=Color()]
604
- * @param {Color} [colorB=Color(0,0,0,1)]
607
+ * @param {Color} [colorA=(1,1,1,1)]
608
+ * @param {Color} [colorB=(0,0,0,1)]
605
609
  * @param {Boolean} [linear]
606
610
  * @return {Color}
607
611
  * @memberof Random */
@@ -672,7 +676,11 @@ class RandomGenerator
672
676
  * @memberof Utilities
673
677
  */
674
678
  function vec2(x=0, y)
675
- { return typeof x === 'number'? new Vector2(x, y == undefined? x : y) : new Vector2(x.x, x.y); }
679
+ {
680
+ return typeof x === 'number' ?
681
+ new Vector2(x, y == undefined? x : y) :
682
+ new Vector2(x.x, x.y);
683
+ }
676
684
 
677
685
  /**
678
686
  * Check if object is a valid Vector2
@@ -680,7 +688,7 @@ function vec2(x=0, y)
680
688
  * @return {Boolean}
681
689
  * @memberof Utilities
682
690
  */
683
- function isVector2(v) { return typeof v === 'object' && typeof v.x === 'number' && typeof v.y === 'number'; }
691
+ function isVector2(v) { return v instanceof Vector2; }
684
692
 
685
693
  /**
686
694
  * 2D Vector object with vector math library
@@ -711,27 +719,47 @@ class Vector2
711
719
  /** Returns a copy of this vector plus the vector passed in
712
720
  * @param {Vector2} v - other vector
713
721
  * @return {Vector2} */
714
- add(v) { ASSERT(isVector2(v)); return new Vector2(this.x + v.x, this.y + v.y); }
722
+ add(v)
723
+ {
724
+ ASSERT(isVector2(v));
725
+ return new Vector2(this.x + v.x, this.y + v.y);
726
+ }
715
727
 
716
728
  /** Returns a copy of this vector minus the vector passed in
717
729
  * @param {Vector2} v - other vector
718
730
  * @return {Vector2} */
719
- subtract(v) { ASSERT(isVector2(v)); return new Vector2(this.x - v.x, this.y - v.y); }
731
+ subtract(v)
732
+ {
733
+ ASSERT(isVector2(v));
734
+ return new Vector2(this.x - v.x, this.y - v.y);
735
+ }
720
736
 
721
737
  /** Returns a copy of this vector times the vector passed in
722
738
  * @param {Vector2} v - other vector
723
739
  * @return {Vector2} */
724
- multiply(v) { ASSERT(isVector2(v)); return new Vector2(this.x * v.x, this.y * v.y); }
740
+ multiply(v)
741
+ {
742
+ ASSERT(isVector2(v));
743
+ return new Vector2(this.x * v.x, this.y * v.y);
744
+ }
725
745
 
726
746
  /** Returns a copy of this vector divided by the vector passed in
727
747
  * @param {Vector2} v - other vector
728
748
  * @return {Vector2} */
729
- divide(v) { ASSERT(isVector2(v)); return new Vector2(this.x / v.x, this.y / v.y); }
749
+ divide(v)
750
+ {
751
+ ASSERT(isVector2(v));
752
+ return new Vector2(this.x / v.x, this.y / v.y);
753
+ }
730
754
 
731
755
  /** Returns a copy of this vector scaled by the vector passed in
732
756
  * @param {Number} s - scale
733
757
  * @return {Vector2} */
734
- scale(s) { ASSERT(!isVector2(s)); return new Vector2(this.x * s, this.y * s); }
758
+ scale(s)
759
+ {
760
+ ASSERT(!isVector2(s));
761
+ return new Vector2(this.x * s, this.y * s);
762
+ }
735
763
 
736
764
  /** Returns the length of this vector
737
765
  * @return {Number} */
@@ -744,32 +772,56 @@ class Vector2
744
772
  /** Returns the distance from this vector to vector passed in
745
773
  * @param {Vector2} v - other vector
746
774
  * @return {Number} */
747
- distance(v) { return this.distanceSquared(v)**.5; }
775
+ distance(v)
776
+ {
777
+ ASSERT(isVector2(v));
778
+ return this.distanceSquared(v)**.5;
779
+ }
748
780
 
749
781
  /** Returns the distance squared from this vector to vector passed in
750
782
  * @param {Vector2} v - other vector
751
783
  * @return {Number} */
752
- distanceSquared(v) { return (this.x - v.x)**2 + (this.y - v.y)**2; }
784
+ distanceSquared(v)
785
+ {
786
+ ASSERT(isVector2(v));
787
+ return (this.x - v.x)**2 + (this.y - v.y)**2;
788
+ }
753
789
 
754
790
  /** Returns a new vector in same direction as this one with the length passed in
755
791
  * @param {Number} [length]
756
792
  * @return {Vector2} */
757
- normalize(length=1) { const l = this.length(); return l ? this.scale(length/l) : new Vector2(0, length); }
793
+ normalize(length=1)
794
+ {
795
+ const l = this.length();
796
+ return l ? this.scale(length/l) : new Vector2(0, length);
797
+ }
758
798
 
759
799
  /** Returns a new vector clamped to length passed in
760
800
  * @param {Number} [length]
761
801
  * @return {Vector2} */
762
- clampLength(length=1) { const l = this.length(); return l > length ? this.scale(length/l) : this; }
802
+ clampLength(length=1)
803
+ {
804
+ const l = this.length();
805
+ return l > length ? this.scale(length/l) : this;
806
+ }
763
807
 
764
808
  /** Returns the dot product of this and the vector passed in
765
809
  * @param {Vector2} v - other vector
766
810
  * @return {Number} */
767
- dot(v) { ASSERT(isVector2(v)); return this.x*v.x + this.y*v.y; }
811
+ dot(v)
812
+ {
813
+ ASSERT(isVector2(v));
814
+ return this.x*v.x + this.y*v.y;
815
+ }
768
816
 
769
817
  /** Returns the cross product of this and the vector passed in
770
818
  * @param {Vector2} v - other vector
771
819
  * @return {Number} */
772
- cross(v) { ASSERT(isVector2(v)); return this.x*v.y - this.y*v.x; }
820
+ cross(v)
821
+ {
822
+ ASSERT(isVector2(v));
823
+ return this.x*v.y - this.y*v.x;
824
+ }
773
825
 
774
826
  /** Returns the angle of this vector, up is angle 0
775
827
  * @return {Number} */
@@ -780,7 +832,11 @@ class Vector2
780
832
  * @param {Number} [length]
781
833
  * @return {Vector2} */
782
834
  setAngle(angle=0, length=1)
783
- { this.x = length*Math.sin(angle); this.y = length*Math.cos(angle); return this; }
835
+ {
836
+ this.x = length*Math.sin(angle);
837
+ this.y = length*Math.cos(angle);
838
+ return this;
839
+ }
784
840
 
785
841
  /** Returns copy of this vector rotated by the angle passed in
786
842
  * @param {Number} angle
@@ -791,9 +847,20 @@ class Vector2
791
847
  return new Vector2(this.x*c - this.y*s, this.x*s + this.y*c);
792
848
  }
793
849
 
850
+ /** Set the integer direction of this vector, corrosponding to multiples of 90 degree rotation (0-3)
851
+ * @param {Number} [direction]
852
+ * @param {Number} [length] */
853
+ setDirection(direction, length=1)
854
+ {
855
+ ASSERT(direction==0 || direction==1 || direction==2 || direction==3);
856
+ return vec2(direction%2 ? direction-1 ? -length : length : 0,
857
+ direction%2 ? 0 : direction ? -length : length);
858
+ }
859
+
794
860
  /** Returns the integer direction of this vector, corrosponding to multiples of 90 degree rotation (0-3)
795
861
  * @return {Number} */
796
- direction() { return abs(this.x) > abs(this.y) ? this.x < 0 ? 3 : 1 : this.y < 0 ? 2 : 0; }
862
+ direction()
863
+ { return abs(this.x) > abs(this.y) ? this.x < 0 ? 3 : 1 : this.y < 0 ? 2 : 0; }
797
864
 
798
865
  /** Returns a copy of this vector that has been inverted
799
866
  * @return {Vector2} */
@@ -812,24 +879,34 @@ class Vector2
812
879
  * @param {Number} percent
813
880
  * @return {Vector2} */
814
881
  lerp(v, percent)
815
- { ASSERT(isVector2(v)); return this.add(v.subtract(this).scale(clamp(percent))); }
882
+ {
883
+ ASSERT(isVector2(v));
884
+ return this.add(v.subtract(this).scale(clamp(percent)));
885
+ }
816
886
 
817
887
  /** Returns true if this vector is within the bounds of an array size passed in
818
888
  * @param {Vector2} arraySize
819
889
  * @return {Boolean} */
820
- arrayCheck(arraySize) { return this.x >= 0 && this.y >= 0 && this.x < arraySize.x && this.y < arraySize.y; }
890
+ arrayCheck(arraySize)
891
+ {
892
+ ASSERT(isVector2(arraySize));
893
+ return this.x >= 0 && this.y >= 0 && this.x < arraySize.x && this.y < arraySize.y;
894
+ }
821
895
 
822
896
  /** Returns this vector expressed as a string
823
897
  * @param {Number} digits - precision to display
824
898
  * @return {String} */
825
899
  toString(digits=3)
826
- { if (debug) { return `(${(this.x<0?'':' ') + this.x.toFixed(digits)},${(this.y<0?'':' ') + this.y.toFixed(digits)} )`; }}
900
+ {
901
+ if (debug)
902
+ return `(${(this.x<0?'':' ') + this.x.toFixed(digits)},${(this.y<0?'':' ') + this.y.toFixed(digits)} )`;
903
+ }
827
904
  }
828
905
 
829
906
  ///////////////////////////////////////////////////////////////////////////////
830
907
 
831
908
  /**
832
- * Create a color object with RGBA values
909
+ * Create a color object with RGBA values, white by default
833
910
  * @param {Number} [r=1] - red
834
911
  * @param {Number} [g=1] - green
835
912
  * @param {Number} [b=1] - blue
@@ -840,7 +917,7 @@ class Vector2
840
917
  function rgb(r, g, b, a) { return new Color(r, g, b, a); }
841
918
 
842
919
  /**
843
- * Create a color object with HSLA values
920
+ * Create a color object with HSLA values, white by default
844
921
  * @param {Number} [h=0] - hue
845
922
  * @param {Number} [s=0] - saturation
846
923
  * @param {Number} [l=1] - lightness
@@ -850,14 +927,22 @@ function rgb(r, g, b, a) { return new Color(r, g, b, a); }
850
927
  */
851
928
  function hsl(h, s, l, a) { return new Color().setHSLA(h, s, l, a); }
852
929
 
930
+ /**
931
+ * Check if object is a valid Color
932
+ * @param {any} c
933
+ * @return {Boolean}
934
+ * @memberof Utilities
935
+ */
936
+ function isColor(c) { return c instanceof Color; }
937
+
853
938
  /**
854
939
  * Color object (red, green, blue, alpha) with some helpful functions
855
940
  * @example
856
941
  * let a = new Color; // white
857
942
  * let b = new Color(1, 0, 0); // red
858
943
  * let c = new Color(0, 0, 0, 0); // transparent black
859
- * let d = RGB(0, 0, 1); // blue using rgb color
860
- * let e = HSL(.3, 1, .5); // green using hsl color
944
+ * let d = rgb(0, 0, 1); // blue using rgb color
945
+ * let e = hsl(.3, 1, .5); // green using hsl color
861
946
  */
862
947
  class Color
863
948
  {
@@ -885,22 +970,38 @@ class Color
885
970
  /** Returns a copy of this color plus the color passed in
886
971
  * @param {Color} c - other color
887
972
  * @return {Color} */
888
- add(c) { return new Color(this.r+c.r, this.g+c.g, this.b+c.b, this.a+c.a); }
973
+ add(c)
974
+ {
975
+ ASSERT(isColor(c));
976
+ return new Color(this.r+c.r, this.g+c.g, this.b+c.b, this.a+c.a);
977
+ }
889
978
 
890
979
  /** Returns a copy of this color minus the color passed in
891
980
  * @param {Color} c - other color
892
981
  * @return {Color} */
893
- subtract(c) { return new Color(this.r-c.r, this.g-c.g, this.b-c.b, this.a-c.a); }
982
+ subtract(c)
983
+ {
984
+ ASSERT(isColor(c));
985
+ return new Color(this.r-c.r, this.g-c.g, this.b-c.b, this.a-c.a);
986
+ }
894
987
 
895
988
  /** Returns a copy of this color times the color passed in
896
989
  * @param {Color} c - other color
897
990
  * @return {Color} */
898
- multiply(c) { return new Color(this.r*c.r, this.g*c.g, this.b*c.b, this.a*c.a); }
991
+ multiply(c)
992
+ {
993
+ ASSERT(isColor(c));
994
+ return new Color(this.r*c.r, this.g*c.g, this.b*c.b, this.a*c.a);
995
+ }
899
996
 
900
997
  /** Returns a copy of this color divided by the color passed in
901
998
  * @param {Color} c - other color
902
999
  * @return {Color} */
903
- divide(c) { return new Color(this.r/c.r, this.g/c.g, this.b/c.b, this.a/c.a); }
1000
+ divide(c)
1001
+ {
1002
+ ASSERT(isColor(c));
1003
+ return new Color(this.r/c.r, this.g/c.g, this.b/c.b, this.a/c.a);
1004
+ }
904
1005
 
905
1006
  /** Returns a copy of this color scaled by the value passed in, alpha can be scaled separately
906
1007
  * @param {Number} scale
@@ -917,7 +1018,11 @@ class Color
917
1018
  * @param {Color} c - other color
918
1019
  * @param {Number} percent
919
1020
  * @return {Color} */
920
- lerp(c, percent) { return this.add(c.subtract(this).scale(clamp(percent))); }
1021
+ lerp(c, percent)
1022
+ {
1023
+ ASSERT(isColor(c));
1024
+ return this.add(c.subtract(this).scale(clamp(percent)));
1025
+ }
921
1026
 
922
1027
  /** Sets this color given a hue, saturation, lightness, and alpha
923
1028
  * @param {Number} [h] - hue
@@ -1557,12 +1662,12 @@ function setDebugKey(key) { debugKey = key; }
1557
1662
  class EngineObject
1558
1663
  {
1559
1664
  /** Create an engine object and adds it to the list of objects
1560
- * @param {Vector2} [pos=Vector2()] - World space position of the object
1561
- * @param {Vector2} [size=Vector2(1,1)] - World space size of the object
1562
- * @param {TileInfo} [tileInfo] - Tile info to render object (undefined is untextured)
1563
- * @param {Number} [angle] - Angle the object is rotated by
1564
- * @param {Color} [color=Color()] - Color to apply to tile when rendered
1565
- * @param {Number} [renderOrder] - Objects sorted by renderOrder before being rendered
1665
+ * @param {Vector2} [pos=(0,0)] - World space position of the object
1666
+ * @param {Vector2} [size=(1,1)] - World space size of the object
1667
+ * @param {TileInfo} [tileInfo] - Tile info to render object (undefined is untextured)
1668
+ * @param {Number} [angle] - Angle the object is rotated by
1669
+ * @param {Color} [color=(1,1,1,1)] - Color to apply to tile when rendered
1670
+ * @param {Number} [renderOrder] - Objects sorted by renderOrder before being rendered
1566
1671
  */
1567
1672
  constructor(pos=vec2(), size=vec2(1), tileInfo, angle=0, color, renderOrder=0)
1568
1673
  {
@@ -1862,7 +1967,7 @@ class EngineObject
1862
1967
 
1863
1968
  /** Attaches a child to this with a given local transform
1864
1969
  * @param {EngineObject} child
1865
- * @param {Vector2} [localPos=Vector2()]
1970
+ * @param {Vector2} [localPos=(0,0)]
1866
1971
  * @param {Number} [localAngle] */
1867
1972
  addChild(child, localPos=vec2(), localAngle=0)
1868
1973
  {
@@ -1979,7 +2084,7 @@ let drawCount;
1979
2084
  * Create a tile info object
1980
2085
  * - This can take vecs or floats for easier use and conversion
1981
2086
  * - If an index is passed in, the tile size and index will determine the position
1982
- * @param {(Number|Vector2)} [pos=Vector2()] - Top left corner of tile in pixels or index
2087
+ * @param {(Number|Vector2)} [pos=(0,0)] - Top left corner of tile in pixels or index
1983
2088
  * @param {(Number|Vector2)} [size=tileSizeDefault] - Size of tile in pixels
1984
2089
  * @param {Number} [textureIndex] - Texture index to use
1985
2090
  * @return {TileInfo}
@@ -2022,7 +2127,7 @@ function tile(pos=vec2(), size=tileSizeDefault, textureIndex=0)
2022
2127
  class TileInfo
2023
2128
  {
2024
2129
  /** Create a tile info object
2025
- * @param {Vector2} [pos=Vector2()] - Top left corner of tile in pixels
2130
+ * @param {Vector2} [pos=(0,0)] - Top left corner of tile in pixels
2026
2131
  * @param {Vector2} [size=tileSizeDefault] - Size of tile in pixels
2027
2132
  * @param {Number} [textureIndex] - Texture index to use
2028
2133
  */
@@ -2099,16 +2204,16 @@ function worldToScreen(worldPos)
2099
2204
  }
2100
2205
 
2101
2206
  /** Draw textured tile centered in world space, with color applied if using WebGL
2102
- * @param {Vector2} pos - Center of the tile in world space
2103
- * @param {Vector2} [size=Vector2(1,1)] - Size of the tile in world space
2104
- * @param {TileInfo}[tileInfo] - Tile info to use, untextured if undefined
2105
- * @param {Color} [color=Color()] - Color to modulate with
2106
- * @param {Number} [angle] - Angle to rotate by
2107
- * @param {Boolean} [mirror] - If true image is flipped along the Y axis
2108
- * @param {Color} [additiveColor=Color(0,0,0,0)] - Additive color to be applied
2109
- * @param {Boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering
2110
- * @param {Boolean} [screenSpace] - If true the pos and size are in screen space
2111
- * @param {CanvasRenderingContext2D} [context] - Canvas 2D context to draw to
2207
+ * @param {Vector2} pos - Center of the tile in world space
2208
+ * @param {Vector2} [size=(1,1)] - Size of the tile in world space
2209
+ * @param {TileInfo}[tileInfo] - Tile info to use, untextured if undefined
2210
+ * @param {Color} [color=(1,1,1,1)] - Color to modulate with
2211
+ * @param {Number} [angle] - Angle to rotate by
2212
+ * @param {Boolean} [mirror] - If true image is flipped along the Y axis
2213
+ * @param {Color} [additiveColor=(0,0,0,0)] - Additive color to be applied
2214
+ * @param {Boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering
2215
+ * @param {Boolean} [screenSpace=false] - If true the pos and size are in screen space
2216
+ * @param {CanvasRenderingContext2D} [context] - Canvas 2D context to draw to
2112
2217
  * @memberof Draw */
2113
2218
  function drawTile(pos, size=vec2(1), tileInfo, color=new Color,
2114
2219
  angle=0, mirror, additiveColor=new Color(0,0,0,0), useWebGL=glEnable, screenSpace, context)
@@ -2176,11 +2281,11 @@ function drawTile(pos, size=vec2(1), tileInfo, color=new Color,
2176
2281
 
2177
2282
  /** Draw colored rect centered on pos
2178
2283
  * @param {Vector2} pos
2179
- * @param {Vector2} [size=Vector2(1,1)]
2180
- * @param {Color} [color=Color()]
2284
+ * @param {Vector2} [size=(1,1)]
2285
+ * @param {Color} [color=(1,1,1,1)]
2181
2286
  * @param {Number} [angle]
2182
2287
  * @param {Boolean} [useWebGL=glEnable]
2183
- * @param {Boolean} [screenSpace]
2288
+ * @param {Boolean} [screenSpace=false]
2184
2289
  * @param {CanvasRenderingContext2D} [context]
2185
2290
  * @memberof Draw */
2186
2291
  function drawRect(pos, size, color, angle, useWebGL, screenSpace, context)
@@ -2190,8 +2295,8 @@ function drawRect(pos, size, color, angle, useWebGL, screenSpace, context)
2190
2295
 
2191
2296
  /** Draw colored polygon using passed in points
2192
2297
  * @param {Array} points - Array of Vector2 points
2193
- * @param {Color} [color=Color()]
2194
- * @param {Boolean} [screenSpace]
2298
+ * @param {Color} [color=(1,1,1,1)]
2299
+ * @param {Boolean} [screenSpace=false]
2195
2300
  * @param {CanvasRenderingContext2D} [context=mainContext]
2196
2301
  * @memberof Draw */
2197
2302
  function drawPoly(points, color=new Color, screenSpace, context=mainContext)
@@ -2207,9 +2312,9 @@ function drawPoly(points, color=new Color, screenSpace, context=mainContext)
2207
2312
  * @param {Vector2} posA
2208
2313
  * @param {Vector2} posB
2209
2314
  * @param {Number} [thickness]
2210
- * @param {Color} [color=Color()]
2315
+ * @param {Color} [color=(1,1,1,1)]
2211
2316
  * @param {Boolean} [useWebGL=glEnable]
2212
- * @param {Boolean} [screenSpace]
2317
+ * @param {Boolean} [screenSpace=false]
2213
2318
  * @param {CanvasRenderingContext2D} [context]
2214
2319
  * @memberof Draw */
2215
2320
  function drawLine(posA, posB, thickness=.1, color, useWebGL, screenSpace, context)
@@ -2225,7 +2330,7 @@ function drawLine(posA, posB, thickness=.1, color, useWebGL, screenSpace, contex
2225
2330
  * @param {Number} angle
2226
2331
  * @param {Boolean} mirror
2227
2332
  * @param {Function} drawFunction
2228
- * @param {Boolean} [screenSpace]
2333
+ * @param {Boolean} [screenSpace=false]
2229
2334
  * @param {CanvasRenderingContext2D} [context=mainContext]
2230
2335
  * @memberof Draw */
2231
2336
  function drawCanvas2D(pos, size, angle, mirror, drawFunction, screenSpace, context=mainContext)
@@ -2267,9 +2372,9 @@ function setBlendMode(additive, useWebGL=glEnable, context)
2267
2372
  * @param {String} text
2268
2373
  * @param {Vector2} pos
2269
2374
  * @param {Number} [size]
2270
- * @param {Color} [color=Color()]
2375
+ * @param {Color} [color=(1,1,1,1)]
2271
2376
  * @param {Number} [lineWidth]
2272
- * @param {Color} [lineColor=Color(0,0,0)]
2377
+ * @param {Color} [lineColor=(0,0,0,1)]
2273
2378
  * @param {CanvasTextAlign} [textAlign='center']
2274
2379
  * @param {String} [font=fontDefault]
2275
2380
  * @param {CanvasRenderingContext2D} [context=overlayContext]
@@ -2284,9 +2389,9 @@ function drawText(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, f
2284
2389
  * @param {String} text
2285
2390
  * @param {Vector2} pos
2286
2391
  * @param {Number} [size]
2287
- * @param {Color} [color=Color()]
2392
+ * @param {Color} [color=(1,1,1,1)]
2288
2393
  * @param {Number} [lineWidth]
2289
- * @param {Color} [lineColor=Color(0,0,0)]
2394
+ * @param {Color} [lineColor=(0,0,0,1)]
2290
2395
  * @param {CanvasTextAlign} [textAlign]
2291
2396
  * @param {String} [font=fontDefault]
2292
2397
  * @param {CanvasRenderingContext2D} [context=overlayContext]
@@ -2329,9 +2434,9 @@ let engineFontImage;
2329
2434
  class FontImage
2330
2435
  {
2331
2436
  /** Create an image font
2332
- * @param {HTMLImageElement} [image] - Image for the font, if undefined default font is used
2333
- * @param {Vector2} [tileSize=Vector2(8)] - Size of the font source tiles
2334
- * @param {Vector2} [paddingSize=Vector2(0,1)] - How much extra space to add between characters
2437
+ * @param {HTMLImageElement} [image] - Image for the font, if undefined default font is used
2438
+ * @param {Vector2} [tileSize=(8,8)] - Size of the font source tiles
2439
+ * @param {Vector2} [paddingSize=(0,1)] - How much extra space to add between characters
2335
2440
  * @param {CanvasRenderingContext2D} [context=overlayContext] - context to draw to
2336
2441
  */
2337
2442
  constructor(image, tileSize=vec2(8), paddingSize=vec2(0,1), context=overlayContext)
@@ -2609,10 +2714,10 @@ function inputUpdatePost()
2609
2714
  ///////////////////////////////////////////////////////////////////////////////
2610
2715
  // Mouse event handlers
2611
2716
 
2612
- onmousedown = (e)=> {isUsingGamepad = false; inputData[0][e.button] = 3; window.onmousemove(e); e.button && e.preventDefault();}
2717
+ onmousedown = (e)=> {isUsingGamepad = false; inputData[0][e.button] = 3; mousePosScreen = mouseToScreen(e); e.button && e.preventDefault();}
2613
2718
  onmouseup = (e)=> inputData[0][e.button] = inputData[0][e.button] & 2 | 4;
2614
2719
  onmousemove = (e)=> mousePosScreen = mouseToScreen(e);
2615
- onwheel = (e)=> e.ctrlKey || (mouseWheel = sign(e.deltaY));
2720
+ onwheel = (e)=> mouseWheel = e.ctrlKey ? 0 : sign(e.deltaY);
2616
2721
  oncontextmenu = (e)=> false; // prevent right click menu
2617
2722
 
2618
2723
  // convert a mouse or touch event position to screen space
@@ -2706,7 +2811,7 @@ function gamepadsUpdate()
2706
2811
  ///////////////////////////////////////////////////////////////////////////////
2707
2812
 
2708
2813
  /** Pulse the vibration hardware if it exists
2709
- * @param {Number} [pattern] - a single value in miliseconds or vibration interval array
2814
+ * @param {Number|Array} [pattern] - single value in ms or vibration interval array
2710
2815
  * @memberof Input */
2711
2816
  function vibrate(pattern=100)
2712
2817
  { vibrateEnable && navigator && navigator.vibrate && navigator.vibrate(pattern); }
@@ -2732,9 +2837,9 @@ if (isTouchDevice)
2732
2837
  // handle all touch events the same way
2733
2838
  ontouchstart = ontouchmove = ontouchend = (e)=>
2734
2839
  {
2735
- // fix stalled audio on mobile
2736
- if (soundEnable)
2737
- audioContext ? audioContext.resume() : zzfx(0);
2840
+ // fix stalled audio requiring user interaction
2841
+ if (soundEnable && audioContext && audioContext.state != 'running')
2842
+ zzfx(0);
2738
2843
 
2739
2844
  // check if touching and pass to mouse events
2740
2845
  const touching = e.touches.length;
@@ -2880,7 +2985,7 @@ function touchGamepadRender()
2880
2985
  const rightCenter = vec2(mainCanvasSize.x-touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
2881
2986
  for (let i=4; i--;)
2882
2987
  {
2883
- const pos = rightCenter.add(vec2().setAngle(i*PI/2, touchGamepadSize/2));
2988
+ const pos = rightCenter.add(vec2().setDirection(i, touchGamepadSize/2));
2884
2989
  overlayContext.fillStyle = touchGamepadButtons[i] ? '#fff' : '#000';
2885
2990
  overlayContext.beginPath();
2886
2991
  overlayContext.arc(pos.x, pos.y, touchGamepadSize/4, 0,9);
@@ -3039,22 +3144,19 @@ class SoundWave extends Sound
3039
3144
  this.randomness = randomness;
3040
3145
 
3041
3146
  if (!soundEnable) return;
3042
- if (!soundDecoderContext)
3043
- soundDecoderContext = new AudioContext;
3044
3147
 
3045
3148
  fetch(filename)
3046
3149
  .then(response => response.arrayBuffer())
3047
- .then(arrayBuffer => soundDecoderContext.decodeAudioData(arrayBuffer))
3150
+ .then(arrayBuffer => audioContext.decodeAudioData(arrayBuffer))
3048
3151
  .then(audioBuffer =>
3049
3152
  {
3050
3153
  this.sampleChannels = [];
3051
3154
  for (let i = audioBuffer.numberOfChannels; i--;)
3052
- this.sampleChannels[i] = audioBuffer.getChannelData(i);
3155
+ this.sampleChannels[i] = Array.from(audioBuffer.getChannelData(i));
3053
3156
  this.sampleRate = audioBuffer.sampleRate;
3054
3157
  });
3055
3158
  }
3056
3159
  }
3057
- let soundDecoderContext; // audio context used only to decode audio files
3058
3160
 
3059
3161
  /**
3060
3162
  * Music Object - Stores a zzfx music track for later use
@@ -3168,8 +3270,9 @@ function getNoteFrequency(semitoneOffset, rootFrequency=220)
3168
3270
  ///////////////////////////////////////////////////////////////////////////////
3169
3271
 
3170
3272
  /** Audio context used by the engine
3273
+ * @type {AudioContext}
3171
3274
  * @memberof Audio */
3172
- let audioContext;
3275
+ let audioContext = new AudioContext;
3173
3276
 
3174
3277
  /** Play cached audio samples with given settings
3175
3278
  * @param {Array} sampleChannels - Array of arrays of samples to play (for stereo playback)
@@ -3184,10 +3287,6 @@ function playSamples(sampleChannels, volume=1, rate=1, pan=0, loop=false, sample
3184
3287
  {
3185
3288
  if (!soundEnable) return;
3186
3289
 
3187
- // create audio context if needed
3188
- if (!audioContext)
3189
- audioContext = new AudioContext;
3190
-
3191
3290
  // prevent sounds from building up if they can't be played
3192
3291
  if (audioContext.state != 'running')
3193
3292
  {
@@ -3513,7 +3612,7 @@ function getTileCollisionData(pos)
3513
3612
 
3514
3613
  /** Check if collision with another object should occur
3515
3614
  * @param {Vector2} pos
3516
- * @param {Vector2} [size=Vector2(1,1)]
3615
+ * @param {Vector2} [size=(1,1)]
3517
3616
  * @param {EngineObject} [object]
3518
3617
  * @return {Boolean}
3519
3618
  * @memberof TileCollision */
@@ -3598,7 +3697,7 @@ class TileLayerData
3598
3697
  * @param {Number} [direction] - Integer direction of tile, in 90 degree increments
3599
3698
  * @param {Boolean} [mirror] - If the tile should be mirrored along the x axis
3600
3699
  * @param {Color} [color] - Color of the tile */
3601
- constructor(tile, direction=0, mirror=false, color=new Color())
3700
+ constructor(tile, direction=0, mirror=false, color=new Color)
3602
3701
  {
3603
3702
  /** @property {Number} - The tile to use, untextured if undefined */
3604
3703
  this.tile = tile;
@@ -3629,11 +3728,11 @@ class TileLayerData
3629
3728
  class TileLayer extends EngineObject
3630
3729
  {
3631
3730
  /** Create a tile layer object
3632
- * @param {Vector2} [position=Vector2()] - World space position
3731
+ * @param {Vector2} [position=(0,0)] - World space position
3633
3732
  * @param {Vector2} [size=tileCollisionSize] - World space size
3634
- * @param {TileInfo} [tileInfo] - Tile info for layer
3635
- * @param {Vector2} [scale=Vector2(1,1)] - How much to scale this layer when rendered
3636
- * @param {Number} [renderOrder] - Objects sorted by renderOrder before being rendered
3733
+ * @param {TileInfo} [tileInfo] - Tile info for layer
3734
+ * @param {Vector2} [scale=(1,1)] - How much to scale this layer when rendered
3735
+ * @param {Number} [renderOrder] - Objects are sorted by renderOrder
3637
3736
  */
3638
3737
  constructor(position, size=tileCollisionSize, tileInfo=tile(), scale=vec2(1), renderOrder=0)
3639
3738
  {
@@ -3694,16 +3793,18 @@ class TileLayer extends EngineObject
3694
3793
  }
3695
3794
 
3696
3795
  /** Draw all the tile data to an offscreen canvas
3697
- * - This may be slow in some browsers
3698
- */
3796
+ * - This may be slow in some browsers but only needs to be done once */
3699
3797
  redraw()
3700
3798
  {
3701
3799
  this.redrawStart(true);
3702
- this.drawAllTileData();
3800
+ for (let x = this.size.x; x--;)
3801
+ for (let y = this.size.y; y--;)
3802
+ this.drawTileData(vec2(x,y), false);
3703
3803
  this.redrawEnd();
3704
3804
  }
3705
3805
 
3706
3806
  /** Call to start the redraw process
3807
+ * - This can be used to manually update small parts of the level
3707
3808
  * @param {Boolean} [clear] - Should it clear the canvas before drawing */
3708
3809
  redrawStart(clear=false)
3709
3810
  {
@@ -3711,17 +3812,19 @@ class TileLayer extends EngineObject
3711
3812
  /** @type {[HTMLCanvasElement, CanvasRenderingContext2D, Vector2, Vector2, number]} */
3712
3813
  this.savedRenderSettings = [mainCanvas, mainContext, mainCanvasSize, cameraPos, cameraScale];
3713
3814
 
3714
- // hack: use normal rendering system to render the tiles
3815
+ // use webgl rendering system to render the tiles if enabled
3816
+ // this works by temporally taking control of the rendering system
3715
3817
  mainCanvas = this.canvas;
3716
3818
  mainContext = this.context;
3819
+ mainCanvasSize = this.size.multiply(this.tileInfo.size);
3717
3820
  cameraPos = this.size.scale(.5);
3718
3821
  cameraScale = this.tileInfo.size.x;
3719
3822
 
3720
3823
  if (clear)
3721
3824
  {
3722
3825
  // clear and set size
3723
- mainCanvas.width = this.size.x * this.tileInfo.size.x;
3724
- mainCanvas.height = this.size.y * this.tileInfo.size.y;
3826
+ mainCanvas.width = mainCanvasSize.x;
3827
+ mainCanvas.height = mainCanvasSize.y;
3725
3828
  }
3726
3829
 
3727
3830
  // begin a new render for the tile canvas
@@ -3739,32 +3842,33 @@ class TileLayer extends EngineObject
3739
3842
  [mainCanvas, mainContext, mainCanvasSize, cameraPos, cameraScale] = this.savedRenderSettings;
3740
3843
  }
3741
3844
 
3742
- /** Draw the tile at a given position
3743
- * @param {Vector2} layerPos */
3744
- drawTileData(layerPos)
3845
+ /** Draw the tile at a given position in the tile grid
3846
+ * This can be used to clear out tiles when they are destroyed
3847
+ * Tiles can also be redrawn if isinde a redrawStart/End block
3848
+ * @param {Vector2} layerPos
3849
+ * @param {Boolean} [clear] - should the old tile be cleared out
3850
+ */
3851
+ drawTileData(layerPos, clear=true)
3745
3852
  {
3746
- // first clear out where the tile was
3747
- const pos = layerPos.floor().add(this.pos).add(vec2(.5));
3748
- this.drawCanvas2D(pos, vec2(1), 0, false, (context)=>context.clearRect(-.5, -.5, 1, 1));
3853
+ // clear out where the tile was, for full opaque tiles this can be skipped
3854
+ const s = this.tileInfo.size;
3855
+ if (clear)
3856
+ {
3857
+ const pos = layerPos.multiply(s);
3858
+ this.context.clearRect(pos.x, this.canvas.height-pos.y, s.x, -s.y);
3859
+ }
3749
3860
 
3750
3861
  // draw the tile if not undefined
3751
3862
  const d = this.getData(layerPos);
3752
3863
  if (d.tile != undefined)
3753
3864
  {
3865
+ const pos = this.pos.add(layerPos).add(vec2(.5));
3754
3866
  ASSERT(mainContext == this.context, 'must call redrawStart() before drawing tiles');
3755
- const tileInfo = tile(d.tile, this.tileInfo.size, this.tileInfo.textureIndex);
3867
+ const tileInfo = tile(d.tile, s, this.tileInfo.textureIndex);
3756
3868
  drawTile(pos, vec2(1), tileInfo, d.color, d.direction*PI/2, d.mirror);
3757
3869
  }
3758
3870
  }
3759
3871
 
3760
- /** Draw all the tiles in this layer */
3761
- drawAllTileData()
3762
- {
3763
- for (let x = this.size.x; x--;)
3764
- for (let y = this.size.y; y--;)
3765
- this.drawTileData(vec2(x,y));
3766
- }
3767
-
3768
3872
  /** Draw directly to the 2D canvas in world space (bipass webgl)
3769
3873
  * @param {Vector2} pos
3770
3874
  * @param {Vector2} size
@@ -3784,11 +3888,11 @@ class TileLayer extends EngineObject
3784
3888
  context.restore();
3785
3889
  }
3786
3890
 
3787
- /** Draw a tile directly onto the layer canvas
3891
+ /** Draw a tile directly onto the layer canvas in world space
3788
3892
  * @param {Vector2} pos
3789
- * @param {Vector2} [size=Vector2(1,1)]
3893
+ * @param {Vector2} [size=(1,1)]
3790
3894
  * @param {TileInfo} [tileInfo]
3791
- * @param {Color} [color=Color()]
3895
+ * @param {Color} [color=(1,1,1,1)]
3792
3896
  * @param {Number} [angle=0]
3793
3897
  * @param {Boolean} [mirror=0] */
3794
3898
  drawTile(pos, size=vec2(1), tileInfo, color=new Color, angle, mirror)
@@ -3813,10 +3917,10 @@ class TileLayer extends EngineObject
3813
3917
  });
3814
3918
  }
3815
3919
 
3816
- /** Draw a rectangle directly onto the layer canvas
3920
+ /** Draw a rectangle directly onto the layer canvas in world space
3817
3921
  * @param {Vector2} pos
3818
- * @param {Vector2} [size=Vector2(1,1)]
3819
- * @param {Color} [color=Color()]
3922
+ * @param {Vector2} [size=(1,1)]
3923
+ * @param {Color} [color=(1,1,1,1)]
3820
3924
  * @param {Number} [angle=0] */
3821
3925
  drawRect(pos, size, color, angle)
3822
3926
  { this.drawTile(pos, size, undefined, color, angle); }
@@ -3833,12 +3937,12 @@ class TileLayer extends EngineObject
3833
3937
  * @example
3834
3938
  * // create a particle emitter
3835
3939
  * let pos = vec2(2,3);
3836
- * let particleEmiter = new ParticleEmitter
3940
+ * let particleEmitter = new ParticleEmitter
3837
3941
  * (
3838
- * pos, 0, 1, 0, 500, PI, // pos, angle, emitSize, emitTime, emitRate, emiteCone
3839
- * tile(0, 16), // tileInfo
3840
- * new Color(1,1,1), new Color(0,0,0), // colorStartA, colorStartB
3841
- * new Color(1,1,1,0), new Color(0,0,0,0), // colorEndA, colorEndB
3942
+ * pos, 0, 1, 0, 500, PI, // pos, angle, emitSize, emitTime, emitRate, emiteCone
3943
+ * tile(0, 16), // tileInfo
3944
+ * rgb(1,1,1), rgb(0,0,0), // colorStartA, colorStartB
3945
+ * rgb(1,1,1,0), rgb(0,0,0,0), // colorEndA, colorEndB
3842
3946
  * 2, .2, .2, .1, .05, // particleTime, sizeStart, sizeEnd, particleSpeed, particleAngleSpeed
3843
3947
  * .99, 1, 1, PI, .05, // damping, angleDamping, gravityScale, particleCone, fadeRate,
3844
3948
  * .5, 1 // randomness, collide, additive, randomColorLinear, renderOrder
@@ -3854,10 +3958,10 @@ class ParticleEmitter extends EngineObject
3854
3958
  * @param {Number} [emitRate] - How many particles per second to spawn, does not emit if 0
3855
3959
  * @param {Number} [emitConeAngle=PI] - Local angle to apply velocity to particles from emitter
3856
3960
  * @param {TileInfo} [tileInfo] - Tile info to render particles (undefined is untextured)
3857
- * @param {Color} [colorStartA=Color()] - Color at start of life 1, randomized between start colors
3858
- * @param {Color} [colorStartB=Color()] - Color at start of life 2, randomized between start colors
3859
- * @param {Color} [colorEndA=Color(1,1,1,0)] - Color at end of life 1, randomized between end colors
3860
- * @param {Color} [colorEndB=Color(1,1,1,0)] - Color at end of life 2, randomized between end colors
3961
+ * @param {Color} [colorStartA=(1,1,1,1)] - Color at start of life 1, randomized between start colors
3962
+ * @param {Color} [colorStartB=(1,1,1,1)] - Color at start of life 2, randomized between start colors
3963
+ * @param {Color} [colorEndA=(1,1,1,0)] - Color at end of life 1, randomized between end colors
3964
+ * @param {Color} [colorEndB=(1,1,1,0)] - Color at end of life 2, randomized between end colors
3861
3965
  * @param {Number} [particleTime] - How long particles live
3862
3966
  * @param {Number} [sizeStart] - How big are particles at start
3863
3967
  * @param {Number} [sizeEnd] - How big are particles at end
@@ -4245,8 +4349,8 @@ class Medal
4245
4349
  // draw containing rect and clip to that region
4246
4350
  context.save();
4247
4351
  context.beginPath();
4248
- context.fillStyle = rgb(.9,.9,.9).toString();
4249
- context.strokeStyle = rgb(0,0,0).toString();
4352
+ context.fillStyle = new Color(.9,.9,.9).toString();
4353
+ context.strokeStyle = new Color(0,0,0).toString();
4250
4354
  context.lineWidth = 3;
4251
4355
  context.rect(x, y, width, medalDisplaySize.y);
4252
4356
  context.fill();
@@ -4695,8 +4799,10 @@ function glCopyToContext(context, forceDraw=false)
4695
4799
  * @memberof WebGL */
4696
4800
  function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba, rgbaAdditive=0)
4697
4801
  {
4802
+ ASSERT(typeof rgba == 'number' && typeof rgbaAdditive == 'number', 'invalid color');
4803
+
4698
4804
  // flush if there is not enough room or if different blend mode
4699
- if (glInstanceCount >= gl_MAX_INSTANCES-1 || glBatchAdditive != glAdditive)
4805
+ if (glInstanceCount >= gl_MAX_INSTANCES || glBatchAdditive != glAdditive)
4700
4806
  glFlush();
4701
4807
 
4702
4808
  let offset = glInstanceCount * gl_INDICIES_PER_INSTANCE;
@@ -4723,7 +4829,7 @@ let glPostShader, glPostArrayBuffer, glPostTexture, glPostIncludeOverlay;
4723
4829
  * @param {String} shaderCode
4724
4830
  * @param {Boolean} includeOverlay
4725
4831
  * @memberof WebGL */
4726
- function glInitPostProcess(shaderCode, includeOverlay)
4832
+ function glInitPostProcess(shaderCode, includeOverlay=false)
4727
4833
  {
4728
4834
  ASSERT(!glPostShader, 'can only have 1 post effects shader');
4729
4835
 
@@ -4759,6 +4865,8 @@ function glInitPostProcess(shaderCode, includeOverlay)
4759
4865
 
4760
4866
  // hide the original 2d canvas
4761
4867
  mainCanvas.style.visibility = 'hidden';
4868
+ if (glPostIncludeOverlay)
4869
+ overlayCanvas.style.visibility = 'hidden';
4762
4870
  }
4763
4871
 
4764
4872
  // Render the post processing shader, called automatically by the engine
@@ -4779,14 +4887,8 @@ function glRenderPostProcess()
4779
4887
  glContext.viewport(0, 0, glCanvas.width = mainCanvas.width, glCanvas.height = mainCanvas.height);
4780
4888
  }
4781
4889
 
4782
- if (glPostIncludeOverlay)
4783
- {
4784
- // copy overlay canvas so it will be included in post processing
4785
- mainContext.drawImage(overlayCanvas, 0, 0);
4786
-
4787
- // clear overlay canvas
4788
- overlayCanvas.width = mainCanvas.width;
4789
- }
4890
+ // copy overlay canvas so it will be included in post processing
4891
+ glPostIncludeOverlay && mainContext.drawImage(overlayCanvas, 0, 0);
4790
4892
 
4791
4893
  // setup shader program to draw one triangle
4792
4894
  glContext.useProgram(glPostShader);
@@ -4880,7 +4982,7 @@ const engineName = 'LittleJS';
4880
4982
  * @type {String}
4881
4983
  * @default
4882
4984
  * @memberof Engine */
4883
- const engineVersion = '1.9.0';
4985
+ const engineVersion = '1.9.2';
4884
4986
 
4885
4987
  /** Frames per second to update objects
4886
4988
  * @type {Number}