littlejsengine 1.0.14 → 1.1.8

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 (99) hide show
  1. package/build.bat +5 -1
  2. package/docs/Audio.html +2268 -0
  3. package/docs/Color.html +2989 -0
  4. package/docs/Debug.html +2933 -0
  5. package/docs/Draw.html +4092 -0
  6. package/docs/EngineObject.html +4458 -0
  7. package/docs/Input.html +2482 -0
  8. package/docs/Medal.html +1007 -0
  9. package/docs/Medals.html +628 -0
  10. package/docs/Music.html +584 -0
  11. package/docs/Newgrounds.html +1399 -0
  12. package/docs/Particle.html +4535 -0
  13. package/docs/ParticleEmitter.html +7770 -0
  14. package/docs/Random.html +1774 -0
  15. package/docs/Settings.html +2679 -0
  16. package/docs/Sound.html +1249 -0
  17. package/docs/TileCollision.html +1409 -0
  18. package/docs/TileLayer.html +6948 -0
  19. package/docs/TileLayerData.html +1052 -0
  20. package/docs/Timer.html +1183 -0
  21. package/docs/Utilities.html +3281 -0
  22. package/docs/Vector2.html +4207 -0
  23. package/docs/WebGL.html +2327 -0
  24. package/docs/engine.js.html +429 -0
  25. package/docs/engineAudio.js.html +609 -0
  26. package/docs/engineDebug.js.html +725 -0
  27. package/docs/engineDraw.js.html +419 -0
  28. package/docs/engineInput.js.html +401 -0
  29. package/docs/engineMedals.js.html +461 -0
  30. package/docs/engineObject.js.html +518 -0
  31. package/docs/engineParticles.js.html +441 -0
  32. package/docs/engineSettings.js.html +349 -0
  33. package/docs/engineTileLayer.js.html +513 -0
  34. package/docs/engineUtilities.js.html +647 -0
  35. package/docs/engineWebGL.js.html +522 -0
  36. package/docs/fonts/MavenPro-Regular.ttf +0 -0
  37. package/docs/fonts/Montserrat-Regular.ttf +0 -0
  38. package/docs/fonts/Muli-Black.ttf +0 -0
  39. package/docs/fonts/OFL-hind.txt +93 -0
  40. package/docs/fonts/OFL-montserrat.txt +93 -0
  41. package/docs/global.html +1691 -0
  42. package/docs/index.css +6 -0
  43. package/docs/index.html +247 -0
  44. package/docs/scripts/fix-code-block.js +53 -0
  45. package/docs/scripts/fix-navbar.js +25 -0
  46. package/docs/scripts/linenumber.js +25 -0
  47. package/docs/scripts/misc.js +217 -0
  48. package/docs/scripts/resize.js +85 -0
  49. package/docs/scripts/search.js +83 -0
  50. package/docs/scripts/third-party/Apache-License-2.0.txt +202 -0
  51. package/docs/scripts/third-party/fuse.js +9 -0
  52. package/docs/scripts/third-party/lang-css.js +2 -0
  53. package/docs/scripts/third-party/prettify.js +28 -0
  54. package/docs/static/favicon.png +0 -0
  55. package/docs/static/index.css +4 -0
  56. package/docs/styles/clean-jsdoc-theme-base.css +393 -0
  57. package/docs/styles/clean-jsdoc-theme-dark.css +324 -0
  58. package/docs/styles/clean-jsdoc-theme-light.css +319 -0
  59. package/docs/styles/reset.css +346 -0
  60. package/docs/styles/third-party/ionicons.min.css +11 -0
  61. package/docs/styles/third-party/prettify-jsdoc.css +111 -0
  62. package/docs/styles/third-party/prettify-tomorrow.css +5 -0
  63. package/engine/engine.all.js +1997 -744
  64. package/engine/engine.all.min.js +1 -1
  65. package/engine/engine.all.release.js +1743 -569
  66. package/engine/engine.js +107 -39
  67. package/engine/engineAudio.js +152 -34
  68. package/engine/{build.bat → engineBuild.bat} +10 -10
  69. package/engine/{buildSetup.bat → engineBuildSetup.bat} +0 -0
  70. package/engine/engineDebug.js +105 -32
  71. package/engine/engineDraw.js +137 -32
  72. package/engine/engineInput.js +111 -37
  73. package/engine/{engineMedal.js → engineMedals.js} +129 -56
  74. package/engine/engineObject.js +117 -67
  75. package/engine/engineParticles.js +282 -0
  76. package/engine/engineRelease.js +3 -9
  77. package/engine/engineSettings.js +190 -0
  78. package/engine/engineTileLayer.js +147 -44
  79. package/engine/engineUtilities.js +488 -0
  80. package/engine/engineWebGL.js +113 -74
  81. package/examples/breakout/game.js +1 -1
  82. package/examples/breakout/gameObjects.js +3 -3
  83. package/examples/breakout/index.html +3 -3
  84. package/examples/platformer/game.js +5 -7
  85. package/examples/platformer/gameEffects.js +7 -7
  86. package/examples/platformer/gameLevel.js +2 -2
  87. package/examples/platformer/gameObjects.js +4 -5
  88. package/examples/platformer/gamePlayer.js +3 -3
  89. package/examples/platformer/index.html +6 -6
  90. package/examples/puzzle/game.js +1 -2
  91. package/examples/puzzle/index.html +2 -2
  92. package/examples/stress/index.html +2 -8
  93. package/game.js +5 -11
  94. package/index.html +13 -13
  95. package/package.json +4 -4
  96. package/tiles.png +0 -0
  97. package/engine/engineConfig.js +0 -64
  98. package/engine/engineParticle.js +0 -199
  99. package/engine/engineUtil.js +0 -147
@@ -1,69 +1,137 @@
1
- /*
2
- LittleJS - The Tiny JavaScript Game Engine That Can
3
- MIT License - Copyright 2019 Frank Force
4
- */
5
- /*
6
- LittleJS Debug System
7
-
8
- Debug Features
9
- - debug overlay with mouse pick
10
- - debug primitive rendering
11
- - save screenshots
12
- */
1
+ /**
2
+ * LittleJS Debug System
3
+ * <br> - Debug overlay with mouse pick
4
+ * <br> - Debug primitive rendering
5
+ * <br> - Save screenshots to disk
6
+ * @namespace Debug
7
+ */
13
8
 
14
9
  'use strict';
15
10
 
11
+ /** True if debug is enabled
12
+ * @default
13
+ * @memberof Debug */
16
14
  const debug = 1;
15
+
16
+ /** True if asserts are enaled
17
+ * @default
18
+ * @memberof Debug */
17
19
  const enableAsserts = 1;
20
+
21
+ /** Size to render debug points by default
22
+ * @default
23
+ * @memberof Debug */
18
24
  const debugPointSize = .5;
19
25
 
26
+ /** True if watermark with FPS should be down
27
+ * @default
28
+ * @memberof Debug */
20
29
  let showWatermark = 1;
30
+
31
+ /** True if god mode is enabled, handle this however you want
32
+ * @default
33
+ * @memberof Debug */
21
34
  let godMode = 0;
22
- let debugPrimitives = [];
23
- let debugOverlay = 0;
24
- let debugPhysics = 0;
25
- let debugRaycast = 0;
26
- let debugParticles = 0;
27
- let debugGamepads = 0;
28
- let debugMedals = 0;
29
- let debugCanvas = -1;
30
- let debugTakeScreenshot;
31
- let downloadLink;
32
-
33
- // debug helper functions
35
+
36
+ // Engine internal variables not exposed to documentation
37
+ let debugPrimitives = [], debugOverlay = 0, debugPhysics = 0, debugRaycast = 0,
38
+ debugParticles = 0, debugGamepads = 0, debugMedals = 0, debugTakeScreenshot, downloadLink;
39
+
40
+ ///////////////////////////////////////////////////////////////////////////////
41
+ // Debug helper functions
42
+
43
+ /** Asserts if the experssion is false, does not do anything in release builds
44
+ * @param {Boolean} assertion
45
+ * @param {Object} output
46
+ * @memberof Debug */
34
47
  const ASSERT = enableAsserts ? (...assert)=> console.assert(...assert) : ()=>{};
35
- const debugRect = (pos, size=vec2(0), color='#fff', time=0, angle=0, fill=0)=>
48
+
49
+ /** Draw a debug rectangle in world space
50
+ * @param {Vector2} pos
51
+ * @param {Vector2} [size=new Vector2()]
52
+ * @param {String} [color='#fff']
53
+ * @param {Number} [time=0]
54
+ * @param {Number} [angle=0]
55
+ * @param {Boolean} [fill=0]
56
+ * @memberof Debug */
57
+ const debugRect = (pos, size=vec2(), color='#fff', time=0, angle=0, fill=0)=>
36
58
  {
37
59
  ASSERT(typeof color == 'string'); // pass in regular html strings as colors
38
60
  debugPrimitives.push({pos, size:vec2(size), color, time:new Timer(time), angle, fill});
39
61
  }
62
+
63
+ /** Draw a debug circle in world space
64
+ * @param {Vector2} pos
65
+ * @param {Number} [radius=0]
66
+ * @param {String} [color='#fff']
67
+ * @param {Number} [time=0]
68
+ * @param {Boolean} [fill=0]
69
+ * @memberof Debug */
40
70
  const debugCircle = (pos, radius=0, color='#fff', time=0, fill=0)=>
41
71
  {
42
72
  ASSERT(typeof color == 'string'); // pass in regular html strings as colors
43
73
  debugPrimitives.push({pos, size:radius, color, time:new Timer(time), angle:0, fill});
44
74
  }
75
+
76
+ /** Draw a debug point in world space
77
+ * @param {Vector2} pos
78
+ * @param {String} [color='#fff']
79
+ * @param {Number} [time=0]
80
+ * @param {Number} [angle=0]
81
+ * @memberof Debug */
45
82
  const debugPoint = (pos, color, time, angle)=> debugRect(pos, 0, color, time, angle);
83
+
84
+ /** Draw a debug line in world space
85
+ * @param {Vector2} posA
86
+ * @param {Vector2} posB
87
+ * @param {String} [color='#fff']
88
+ * @param {Number} [thickness=.1]
89
+ * @param {Number} [time=0]
90
+ * @memberof Debug */
46
91
  const debugLine = (posA, posB, color, thickness=.1, time)=>
47
92
  {
48
93
  const halfDelta = vec2((posB.x - posA.x)/2, (posB.y - posA.y)/2);
49
94
  const size = vec2(thickness, halfDelta.length()*2);
50
95
  debugRect(posA.add(halfDelta), size, color, time, halfDelta.angle(), 1);
51
96
  }
52
- const debugAABB = (pA, pB, sA, sB, color)=>
97
+
98
+ /** Draw a debug axis aligned bounding box in world space
99
+ * @param {Vector2} posA
100
+ * @param {Vector2} sizeA
101
+ * @param {Vector2} posB
102
+ * @param {Vector2} sizeB
103
+ * @param {String} [color='#fff']
104
+ * @memberof Debug */
105
+ const debugAABB = (pA, sA, pB, sB, color)=>
53
106
  {
54
107
  const minPos = vec2(min(pA.x - sA.x/2, pB.x - sB.x/2), min(pA.y - sA.y/2, pB.y - sB.y/2));
55
108
  const maxPos = vec2(max(pA.x + sA.x/2, pB.x + sB.x/2), max(pA.y + sA.y/2, pB.y + sB.y/2));
56
109
  debugRect(minPos.lerp(maxPos,.5), maxPos.subtract(minPos), color);
57
110
  }
58
- const debugText = (text='', pos, size=1, color='#fff', time=0, angle=0, font='monospace')=>
111
+
112
+ /** Draw a debug axis aligned bounding box in world space
113
+ * @param {String} text
114
+ * @param {Vector2} pos
115
+ * @param {Number} [size=1]
116
+ * @param {String} [color='#fff']
117
+ * @param {Number} [time=0]
118
+ * @param {Number} [angle=0]
119
+ * @param {String} [font='monospace']
120
+ * @memberof Debug */
121
+ const debugText = (text, pos, size=1, color='#fff', time=0, angle=0, font='monospace')=>
59
122
  {
60
123
  ASSERT(typeof color == 'string'); // pass in regular html strings as colors
61
124
  debugPrimitives.push({text, pos, size, color, time:new Timer(time), angle, font});
62
125
  }
63
126
 
127
+ /** Clear all debug primitives in the list
128
+ * @memberof Debug */
64
129
  const debugClear = ()=> debugPrimitives = [];
65
130
 
66
- // save a canvas to disk
131
+ /** Save a canvas to disk
132
+ * @param {HTMLCanvasElement} canvas
133
+ * @param {String} [filename]
134
+ * @memberof Debug */
67
135
  const debugSaveCanvas = (canvas, filename = engineName + '.png') =>
68
136
  {
69
137
  downloadLink.download = 'screenshot.png';
@@ -72,7 +140,7 @@ const debugSaveCanvas = (canvas, filename = engineName + '.png') =>
72
140
  }
73
141
 
74
142
  ///////////////////////////////////////////////////////////////////////////////
75
- // engine debug function (called automatically)
143
+ // Engine debug function (called automatically)
76
144
 
77
145
  const debugInit = ()=>
78
146
  {
@@ -112,6 +180,11 @@ const debugRender = ()=>
112
180
 
113
181
  if (debugTakeScreenshot)
114
182
  {
183
+ // composite canvas
184
+ glCopyToContext(mainContext, 1);
185
+ mainContext.drawImage(overlayCanvas, 0, 0);
186
+ overlayCanvas.width |= 0;
187
+
115
188
  debugSaveCanvas(mainCanvas);
116
189
  debugTakeScreenshot = 0;
117
190
  }
@@ -189,8 +262,8 @@ const debugRender = ()=>
189
262
  const saveContext = mainContext;
190
263
  mainContext = overlayContext
191
264
  const raycastHitPos = tileCollisionRaycast(bestObject.pos, mousePos);
192
- raycastHitPos && drawRect(raycastHitPos.int().add(vec2(.5)), vec2(1), new Color(0,1,1,.3));
193
- drawRect(mousePos.int().add(vec2(.5)), vec2(1), new Color(0,0,1,.5));
265
+ raycastHitPos && drawRect(raycastHitPos.floor().add(vec2(.5)), vec2(1), new Color(0,1,1,.3));
266
+ drawRect(mousePos.floor().add(vec2(.5)), vec2(1), new Color(0,0,1,.5));
194
267
  drawLine(mousePos, bestObject.pos, .1, !raycastHitPos ? new Color(0,1,0,.5) : new Color(1,0,0,.5));
195
268
 
196
269
  let pos = mousePos.copy(), height = vec2(0,.5);
@@ -304,7 +377,7 @@ const debugRender = ()=>
304
377
  }
305
378
 
306
379
  ///////////////////////////////////////////////////////////////////////////////
307
- // particle system editor
380
+ // particle system editor (work in progress)
308
381
  let debugParticleEditor = 0, debugParticleSystem, debugParticleSystemDiv, particleSystemCode;
309
382
 
310
383
  const debugToggleParticleEditor = ()=>
@@ -1,28 +1,78 @@
1
- /*
2
- LittleJS Drawing System
3
-
4
- - Super fast tile sheet rendering
5
- - Utility functions for webgl
6
- */
1
+ /**
2
+ * LittleJS Drawing System
3
+ * <br> - Hybrid with both Canvas2D and WebGL available
4
+ * <br> - Super fast tile sheet rendering with WebGL
5
+ * <br> - Can apply rotation, mirror, color and additive color
6
+ * <br> - Many useful utility functions
7
+ * @namespace Draw
8
+ */
7
9
 
8
10
  'use strict';
9
11
 
10
- // convert between screen and world coordinates
12
+ /** Tile sheet for batch rendering system
13
+ * @type {Image}
14
+ * @memberof Draw */
15
+ const tileImage = new Image();
16
+
17
+ /** The primary 2D canvas visible to the user
18
+ * @type {HTMLCanvasElement}
19
+ * @memberof Draw */
20
+ let mainCanvas;
21
+
22
+ /** 2d context for mainCanvas
23
+ * @type {CanvasRenderingContext2D}
24
+ * @memberof Draw */
25
+ let mainContext;
26
+
27
+ /** A canvas that appears on top of everything the same size as mainCanvas
28
+ * @type {HTMLCanvasElement}
29
+ * @memberof Draw */
30
+ let overlayCanvas;
31
+
32
+ /** 2d context for overlayCanvas
33
+ * @type {CanvasRenderingContext2D}
34
+ * @memberof Draw */
35
+ let overlayContext;
36
+
37
+ /** The size of the main canvas (and other secondary canvases)
38
+ * @type {Vector2}
39
+ * @memberof Draw */
40
+ let mainCanvasSize = vec2();
41
+
42
+ /** Convert from screen to world space coordinates
43
+ * @param {Vector2} screenPos
44
+ * @return {Vector2}
45
+ * @memberof Draw */
11
46
  const screenToWorld = (screenPos)=>
12
47
  screenPos.add(vec2(.5)).subtract(mainCanvasSize.scale(.5)).multiply(vec2(1/cameraScale,-1/cameraScale)).add(cameraPos);
48
+
49
+ /** Convert from world to screen space coordinates
50
+ * @param {Vector2} worldPos
51
+ * @return {Vector2}
52
+ * @memberof Draw */
13
53
  const worldToScreen = (worldPos)=>
14
54
  worldPos.subtract(cameraPos).multiply(vec2(cameraScale,-cameraScale)).add(mainCanvasSize.scale(.5)).subtract(vec2(.5));
15
55
 
16
- // draw textured tile centered on pos
17
- function drawTile(pos, size=vec2(1), tileIndex=-1, tileSize=defaultTileSize, color=new Color, angle=0, mirror,
18
- additiveColor=new Color(0,0,0,0))
56
+ /** Draw textured tile centered in world space, with color applied if using WebGL
57
+ * @param {Vector2} pos - Center of the tile in world space
58
+ * @param {Vector2} [size=new Vector2(1,1)] - Size of the tile in world space, width and height
59
+ * @param {Number} [tileIndex=-1] - Tile index to use, negative is untextured
60
+ * @param {Vector2} [tileSize=tileSizeDefault] - Tile size in source pixels
61
+ * @param {Color} [color=new Color(1,1,1)] - Color to modulate with
62
+ * @param {Number} [angle=0] - Angle to rotate by
63
+ * @param {Boolean} [mirror=0] - If true image is flipped along the Y axis
64
+ * @param {Color} [additiveColor=new Color(0,0,0,0)] - Additive color to be applied
65
+ * @param {Boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering
66
+ * @memberof Draw */
67
+ function drawTile(pos, size=vec2(1), tileIndex=-1, tileSize=tileSizeDefault, color=new Color, angle=0, mirror,
68
+ additiveColor=new Color(0,0,0,0), useWebGL=glEnable)
19
69
  {
20
70
  showWatermark && ++drawCount;
21
- if (glEnable)
71
+ if (glEnable && useWebGL)
22
72
  {
23
- if (tileIndex < 0)
73
+ if (tileIndex < 0 || !tileImage.width)
24
74
  {
25
- // if negative tile index, force untextured
75
+ // if negative tile index or image not found, force untextured
26
76
  glDraw(pos.x, pos.y, size.x, size.y, angle, 0, 0, 0, 0, 0, color.rgbaInt());
27
77
  }
28
78
  else
@@ -69,33 +119,68 @@ function drawTile(pos, size=vec2(1), tileIndex=-1, tileSize=defaultTileSize, col
69
119
  }
70
120
  }
71
121
 
72
- // draw a colored untextured rect centered on pos
73
- function drawRect(pos, size, color, angle)
122
+ /** Draw colored rect centered on pos
123
+ * @param {Vector2} pos
124
+ * @param {Vector2} [size=new Vector2(1,1)]
125
+ * @param {Color} [color=new Color(1,1,1)]
126
+ * @param {Number} [angle=0]
127
+ * @param {Boolean} [useWebGL=glEnable]
128
+ * @memberof Draw */
129
+ function drawRect(pos, size, color, angle, useWebGL)
74
130
  {
75
- drawTile(pos, size, -1, defaultTileSize, color, angle);
131
+ drawTile(pos, size, -1, tileSizeDefault, color, angle, 0, 0, useWebGL);
76
132
  }
77
133
 
78
- // draw textured tile centered on pos in screen space
79
- function drawTileScreenSpace(pos, size=vec2(1), tileIndex, tileSize, color, angle, mirror, additiveColor)
134
+ /** Draw textured tile centered on pos in screen space
135
+ * @param {Vector2} pos - Center of the tile
136
+ * @param {Vector2} [size=new Vector2(1,1)] - Size of the tile
137
+ * @param {Number} [tileIndex=-1] - Tile index to use, negative is untextured
138
+ * @param {Vector2} [tileSize=tileSizeDefault] - Tile size in source pixels
139
+ * @param {Color} [color=new Color]
140
+ * @param {Number} [angle=0]
141
+ * @param {Boolean} [mirror=0]
142
+ * @param {Color} [additiveColor=new Color(0,0,0,0)]
143
+ * @param {Boolean} [useWebGL=glEnable]
144
+ * @memberof Draw */
145
+ function drawTileScreenSpace(pos, size=vec2(1), tileIndex, tileSize, color, angle, mirror, additiveColor, useWebGL)
80
146
  {
81
- drawTile(screenToWorld(pos), size.scale(1/cameraScale), tileIndex, tileSize, color, angle, mirror, additiveColor);
147
+ drawTile(screenToWorld(pos), size.scale(1/cameraScale), tileIndex, tileSize, color, angle, mirror, additiveColor, useWebGL);
82
148
  }
83
149
 
84
- // draw a colored untextured rect in screen space
85
- function drawRectScreenSpace(pos, size, color, angle)
150
+ /** Draw colored rectangle in screen space
151
+ * @param {Vector2} pos
152
+ * @param {Vector2} [size=new Vector2(1,1)]
153
+ * @param {Color} [color=new Color(1,1,1)]
154
+ * @param {Number} [angle=0]
155
+ * @param {Boolean} [useWebGL=glEnable]
156
+ * @memberof Draw */
157
+ function drawRectScreenSpace(pos, size, color, angle, useWebGL)
86
158
  {
87
- drawTileScreenSpace(pos, size, -1, defaultTileSize, color, angle);
159
+ drawTileSrceenSpace(pos, size, -1, tileSizeDefault, color, angle, 0, 0, useWebGL);
88
160
  }
89
161
 
90
- // draw a colored line between two points
91
- function drawLine(posA, posB, thickness=.1, color)
162
+ /** Draw colored line between two points
163
+ * @param {Vector2} posA
164
+ * @param {Vector2} posB
165
+ * @param {Number} [thickness=.1]
166
+ * @param {Color} [color=new Color(1,1,1)]
167
+ * @param {Boolean} [useWebGL=glEnable]
168
+ * @memberof Draw */
169
+ function drawLine(posA, posB, thickness=.1, color, useWebGL)
92
170
  {
93
171
  const halfDelta = vec2((posB.x - posA.x)/2, (posB.y - posA.y)/2);
94
172
  const size = vec2(thickness, halfDelta.length()*2);
95
- drawRect(posA.add(halfDelta), size, color, halfDelta.angle());
173
+ drawRect(posA.add(halfDelta), size, color, halfDelta.angle(), 0, 0, useWebGL);
96
174
  }
97
175
 
98
- // draw directly to the 2d canvas in world space (bipass webgl)
176
+ /** Draw directly to a 2d canvas context in world space
177
+ * @param {Vector2} pos
178
+ * @param {Vector2} size
179
+ * @param {Number} angle
180
+ * @param {Boolean} mirror
181
+ * @param {Function} drawFunction
182
+ * @param {CanvasRenderingContext2D} [context=mainContext]
183
+ * @memberof Draw */
99
184
  function drawCanvas2D(pos, size, angle, mirror, drawFunction, context = mainContext)
100
185
  {
101
186
  // create canvas transform from world space to screen space
@@ -109,8 +194,16 @@ function drawCanvas2D(pos, size, angle, mirror, drawFunction, context = mainCont
109
194
  context.restore();
110
195
  }
111
196
 
112
- // draw text on overlay canvas in world space
113
- function drawText(text, pos, size=1, color=new Color, lineWidth=0, lineColor=new Color(0,0,0), textAlign='center', font=defaultFont)
197
+ /** Draw text on overlay canvas in world space
198
+ * @param {String} text
199
+ * @param {Vector2} pos
200
+ * @param {Number} [size=1]
201
+ * @param {Color} [color=new Color(1,1,1)]
202
+ * @param {Number} [lineWidth=0]
203
+ * @param {Color} [lineColor=new Color(0,0,0)]
204
+ * @param {String} [textAlign='center']
205
+ * @memberof Draw */
206
+ function drawText(text, pos, size=1, color=new Color, lineWidth=0, lineColor=new Color(0,0,0), textAlign='center', font=fontDefault)
114
207
  {
115
208
  pos = worldToScreen(pos);
116
209
  overlayContext.font = size*cameraScale + 'px '+ font;
@@ -126,16 +219,28 @@ function drawText(text, pos, size=1, color=new Color, lineWidth=0, lineColor=new
126
219
  overlayContext.fillText(text, pos.x, pos.y);
127
220
  }
128
221
 
129
- // enable additive or regular blend mode
130
- function setBlendMode(additive)
222
+ /** Enable normal or additive blend mode
223
+ * @param {Boolean} [additive=0]
224
+ * @param {Boolean} [useWebGL=glEnable]
225
+ * @memberof Draw */
226
+ function setBlendMode(additive, useWebGL=glEnable)
131
227
  {
132
- glEnable ? glSetBlendMode(additive) : mainContext.globalCompositeOperation = additive ? 'lighter' : 'source-over';
228
+ if (glEnable && useWebGL)
229
+ glSetBlendMode(additive);
230
+ else
231
+ mainContext.globalCompositeOperation = additive ? 'lighter' : 'source-over';
133
232
  }
134
233
 
135
234
  ///////////////////////////////////////////////////////////////////////////////
136
- // fullscreen mode
235
+ // Fullscreen mode
137
236
 
237
+ /** Returns true if fullscreen mode is active
238
+ * @return {Boolean}
239
+ * @memberof Draw */
138
240
  const isFullscreen =()=> document.fullscreenElement;
241
+
242
+ /** Toggle fullsceen mode
243
+ * @memberof Draw */
139
244
  function toggleFullscreen()
140
245
  {
141
246
  if (isFullscreen())
@@ -1,36 +1,104 @@
1
- /*
2
- LittleJS Input System
3
- - Tracks key down, pressed, and released
4
- - Also tracks mouse buttons, position, and wheel
5
- - Supports multiple gamepads
6
- */
1
+ /**
2
+ * LittleJS Input System
3
+ * <br> - Tracks key down, pressed, and released
4
+ * <br> - Also tracks mouse buttons, position, and wheel
5
+ * <br> - Supports multiple gamepads
6
+ * @namespace Input
7
+ */
7
8
 
8
9
  'use strict';
9
10
 
10
- // input for all devices including keyboard, mouse, and gamepad
11
- let hadInput = 0;
12
- const keyIsDown = (key, device=0)=> inputData[device] && inputData[device][key] & 1 ? 1 : 0;
13
- const keyWasPressed = (key, device=0)=> inputData[device] && inputData[device][key] & 2 ? 1 : 0;
11
+ /** Returns true if device key is down
12
+ * @param {Number} key
13
+ * @param {Number} [device=0]
14
+ * @return {Boolean}
15
+ * @memberof Input */
16
+ const keyIsDown = (key, device=0)=> inputData[device] && inputData[device][key] & 1 ? 1 : 0;
17
+
18
+ /** Returns true if device key was pressed this frame
19
+ * @param {Number} key
20
+ * @param {Number} [device=0]
21
+ * @return {Boolean}
22
+ * @memberof Input */
23
+ const keyWasPressed = (key, device=0)=> inputData[device] && inputData[device][key] & 2 ? 1 : 0;
24
+
25
+ /** Returns true if device key was released this frame
26
+ * @param {Number} key
27
+ * @param {Number} [device=0]
28
+ * @return {Boolean}
29
+ * @memberof Input */
14
30
  const keyWasReleased = (key, device=0)=> inputData[device] && inputData[device][key] & 4 ? 1 : 0;
15
- const clearInput = ()=> inputData[0] = [];
16
31
 
17
- // mouse input
18
- const mouseIsDown = keyIsDown;
19
- const mouseWasPressed = keyWasPressed;
32
+ /** Clears all input
33
+ * @memberof Input */
34
+ const clearInput = ()=> inputData[0] = [];
35
+
36
+ /** Returns true if mouse button is down
37
+ * @param {Number} button
38
+ * @return {Boolean}
39
+ * @memberof Input */
40
+ const mouseIsDown = keyIsDown;
41
+
42
+ /** Returns true if mouse button was pressed
43
+ * @param {Number} button
44
+ * @return {Boolean}
45
+ * @memberof Input */
46
+ const mouseWasPressed = keyWasPressed;
47
+
48
+ /** Returns true if mouse button was released
49
+ * @param {Number} button
50
+ * @return {Boolean}
51
+ * @memberof Input */
20
52
  const mouseWasReleased = keyWasReleased;
21
- let mousePos = vec2();
22
- let mousePosScreen = vec2();
23
- let mouseWheel = 0;
24
-
25
- // gamepad input
26
- let usingGamepad = 0;
27
- const gamepadIsDown = (button, gamepad=0)=> keyIsDown (button, gamepad+1);
28
- const gamepadWasPressed = (button, gamepad=0)=> keyWasPressed (button, gamepad+1);
53
+
54
+ /** Mouse pos in world space
55
+ * @type {Vector2}
56
+ * @memberof Input */
57
+ let mousePos = vec2();
58
+
59
+ /** Mouse pos in screen space
60
+ * @type {Vector2}
61
+ * @memberof Input */
62
+ let mousePosScreen = vec2();
63
+
64
+ /** Mouse wheel delta this frame
65
+ * @memberof Input */
66
+ let mouseWheel = 0;
67
+
68
+ /** Returns true if user is using gamepad (has more recently pressed a gamepad button)
69
+ * @memberof Input */
70
+ let isUsingGamepad = 0;
71
+
72
+ /** Returns true if gamepad button is down
73
+ * @param {Number} button
74
+ * @param {Number} [gamepad=0]
75
+ * @return {Boolean}
76
+ * @memberof Input */
77
+ const gamepadIsDown = (button, gamepad=0)=> keyIsDown(button, gamepad+1);
78
+
79
+ /** Returns true if gamepad button was pressed
80
+ * @param {Number} button
81
+ * @param {Number} [gamepad=0]
82
+ * @return {Boolean}
83
+ * @memberof Input */
84
+ const gamepadWasPressed = (button, gamepad=0)=> keyWasPressed(button, gamepad+1);
85
+
86
+ /** Returns true if gamepad button was released
87
+ * @param {Number} button
88
+ * @param {Number} [gamepad=0]
89
+ * @return {Boolean}
90
+ * @memberof Input */
29
91
  const gamepadWasReleased = (button, gamepad=0)=> keyWasReleased(button, gamepad+1);
30
- const gamepadStick = (stick, gamepad=0)=> stickData[gamepad] ? stickData[gamepad][stick] || vec2() : vec2();
92
+
93
+ /** Returns gamepad stick value
94
+ * @param {Number} stick
95
+ * @param {Number} [gamepad=0]
96
+ * @return {Vector2}
97
+ * @memberof Input */
98
+ const gamepadStick = (stick, gamepad=0)=> stickData[gamepad] ? stickData[gamepad][stick] || vec2() : vec2();
31
99
 
32
100
  ///////////////////////////////////////////////////////////////////////////////
33
- // input update called by engine
101
+ // Input update called by engine
34
102
 
35
103
  const inputData = [[]];
36
104
 
@@ -56,23 +124,25 @@ function inputUpdatePost()
56
124
  }
57
125
 
58
126
  ///////////////////////////////////////////////////////////////////////////////
59
- // keyboard event handlers
127
+ // Keyboard event handlers
128
+
60
129
  onkeydown = e=>
61
130
  {
62
131
  if (debug && e.target != document.body) return;
63
- e.repeat || (inputData[usingGamepad = 0][remapKeyCode(e.keyCode)] = 3);
64
- hadInput = 1;
132
+ e.repeat || (inputData[isUsingGamepad = 0][remapKeyCode(e.keyCode)] = 3);
133
+ debug || e.preventDefault();
65
134
  }
66
135
  onkeyup = e=>
67
136
  {
68
137
  if (debug && e.target != document.body) return;
69
138
  inputData[0][remapKeyCode(e.keyCode)] = 4;
70
139
  }
71
- const remapKeyCode = c=> copyWASDToDpad ? c==87?38 : c==83?40 : c==65?37 : c==68?39 : c : c;
140
+ const remapKeyCode = c=> inputWASDEmulateDirection ? c==87?38 : c==83?40 : c==65?37 : c==68?39 : c : c;
72
141
 
73
142
  ///////////////////////////////////////////////////////////////////////////////
74
- // mouse event handlers
75
- onmousedown = e=> (inputData[usingGamepad = 0][e.button] = 3, hadInput = 1, onmousemove(e));
143
+ // Mouse event handlers
144
+
145
+ onmousedown = e=> {inputData[isUsingGamepad = 0][e.button] = 3; onmousemove(e); e.button && e.preventDefault();}
76
146
  onmouseup = e=> inputData[0][e.button] = inputData[0][e.button] & 2 | 4;
77
147
  onmousemove = e=>
78
148
  {
@@ -86,7 +156,7 @@ onwheel = e=> e.ctrlKey || (mouseWheel = sign(e.deltaY));
86
156
  oncontextmenu = e=> !1; // prevent right click menu
87
157
 
88
158
  ///////////////////////////////////////////////////////////////////////////////
89
- // gamepad input
159
+ // Gamepad input
90
160
 
91
161
  const stickData = [];
92
162
  function gamepadsUpdate()
@@ -120,10 +190,10 @@ function gamepadsUpdate()
120
190
  {
121
191
  const button = gamepad.buttons[j];
122
192
  data[j] = button.pressed ? 1 + 2*!gamepadIsDown(j,i) : 4*gamepadIsDown(j,i);
123
- usingGamepad |= !i && button.pressed;
193
+ isUsingGamepad |= !i && button.pressed;
124
194
  }
125
195
 
126
- if (copyGamepadDirectionToStick)
196
+ if (gamepadDirectionEmulateStick)
127
197
  {
128
198
  // copy dpad to left analog stick when pressed
129
199
  const dpad = vec2(gamepadIsDown(15,i) - gamepadIsDown(14,i), gamepadIsDown(12,i) - gamepadIsDown(13,i));
@@ -135,12 +205,16 @@ function gamepadsUpdate()
135
205
  }
136
206
 
137
207
  ///////////////////////////////////////////////////////////////////////////////
138
- // touch input
139
- const isTouchDevice = touchInputEnable && window.ontouchstart !== undefined;
208
+ // Touch input
209
+
210
+ /** True if a touch device has been detected
211
+ * @const {boolean}
212
+ * @memberof Input */
213
+ const isTouchDevice = inputTouchEnable && window.ontouchstart !== undefined;
140
214
  if (isTouchDevice)
141
215
  {
142
216
  // handle all touch events the same way
143
- let wasTouching;
217
+ let wasTouching, hadTouchInput;
144
218
  ontouchstart = ontouchmove = ontouchend = e=>
145
219
  {
146
220
  e.button = 0; // all touches are left click
@@ -149,7 +223,7 @@ if (isTouchDevice)
149
223
  const touching = e.touches.length;
150
224
  if (touching)
151
225
  {
152
- hadInput || zzfx(0) ; // fix mobile audio, force it to play a sound the first time
226
+ hadTouchInput || zzfx(0, hadTouchInput=1) ; // fix mobile audio, force it to play a sound the first time
153
227
 
154
228
  // set event pos and pass it along
155
229
  e.x = e.touches[0].clientX;