littlejsengine 1.4.0 → 1.4.5

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 (41) hide show
  1. package/README.md +30 -9
  2. package/build.bat +1 -1
  3. package/buildSetup.bat +2 -2
  4. package/engine/engine.all.js +244 -161
  5. package/engine/engine.all.min.js +1 -1
  6. package/engine/engine.all.module.js +4812 -0
  7. package/engine/engine.all.release.js +228 -138
  8. package/engine/engine.all.release.module.js +4457 -0
  9. package/engine/engine.js +12 -8
  10. package/engine/engineBuild.bat +1 -1
  11. package/engine/engineBuildModule.mjs +14 -0
  12. package/engine/engineDebug.js +16 -23
  13. package/engine/engineDraw.js +13 -13
  14. package/engine/engineExportModule.js +333 -0
  15. package/engine/engineInput.js +8 -7
  16. package/engine/engineMedals.js +10 -6
  17. package/engine/engineObject.js +4 -4
  18. package/engine/engineParticles.js +45 -21
  19. package/engine/engineTileLayer.js +1 -1
  20. package/engine/engineUtilities.js +21 -25
  21. package/engine/engineWebGL.js +114 -54
  22. package/engine/index.d.ts +41 -30
  23. package/examples/breakout/game.js +63 -11
  24. package/examples/breakout/gameObjects.js +14 -12
  25. package/examples/breakout/index.html +3 -3
  26. package/examples/empty/game.js +35 -0
  27. package/examples/empty/index.html +9 -0
  28. package/examples/empty/tiles.png +0 -0
  29. package/examples/module/game.js +122 -0
  30. package/examples/module/index.html +9 -0
  31. package/examples/module/tiles.png +0 -0
  32. package/examples/particles/index.html +14 -14
  33. package/examples/particles/tiles.png +0 -0
  34. package/examples/platformer/gameObjects.js +5 -5
  35. package/examples/platformer/gamePlayer.js +7 -5
  36. package/examples/platformer/index.html +6 -6
  37. package/examples/puzzle/index.html +2 -2
  38. package/examples/stress/index.html +2 -2
  39. package/game.js +9 -11
  40. package/index.html +13 -13
  41. package/package.json +36 -25
package/engine/engine.js CHANGED
@@ -22,7 +22,7 @@
22
22
  const engineName = 'LittleJS';
23
23
 
24
24
  /** Version of engine */
25
- const engineVersion = '1.4.0';
25
+ const engineVersion = '1.4.5';
26
26
 
27
27
  /** Frames per second to update objects
28
28
  * @default */
@@ -57,8 +57,7 @@ let frameTimeLastMS = 0, frameTimeBufferMS = 0, tileImageSize, tileImageFixBleed
57
57
  let averageFPS, drawCount;
58
58
 
59
59
  // css text used for elements created by engine
60
- const styleBody = 'margin:0;overflow:hidden;background:#000' +
61
- ';touch-action:none;user-select:none;-webkit-user-select:none;-moz-user-select:none';
60
+ const styleBody = 'margin:0;overflow:hidden;background:#000';
62
61
  const styleCanvas = 'position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)';
63
62
 
64
63
  ///////////////////////////////////////////////////////////////////////////////
@@ -88,7 +87,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
88
87
 
89
88
  // init stuff and start engine
90
89
  debugInit();
91
- glInit();
90
+ glEnable && glInit();
92
91
 
93
92
  // create overlay canvas for hud to appear above gl canvas
94
93
  document.body.appendChild(overlayCanvas = document.createElement('canvas'));
@@ -108,10 +107,14 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
108
107
  frameTimeLastMS = frameTimeMS;
109
108
  if (debug || showWatermark)
110
109
  averageFPS = lerp(.05, averageFPS || 0, 1e3/(frameTimeDeltaMS||1));
110
+ const debugSpeedUp = debug && keyIsDown(107); // +
111
+ const debugSpeedDown = debug && keyIsDown(109); // -
111
112
  if (debug)
112
- frameTimeDeltaMS *= keyIsDown(107) ? 5 : keyIsDown(109) ? .2 : 1; // +/- to speed/slow time
113
+ frameTimeDeltaMS *= debugSpeedUp ? 5 : debugSpeedDown ? .2 : 1; // +/- to speed/slow time
113
114
  timeReal += frameTimeDeltaMS / 1e3;
114
- frameTimeBufferMS = min(frameTimeBufferMS + !paused * frameTimeDeltaMS, 50); // clamp incase of slow framerate
115
+ frameTimeBufferMS += !paused * frameTimeDeltaMS;
116
+ if (!debugSpeedUp)
117
+ frameTimeBufferMS = min(frameTimeBufferMS, 50); // clamp incase of slow framerate
115
118
 
116
119
  if (canvasFixedSize.x)
117
120
  {
@@ -184,10 +187,11 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
184
187
  for (const o of engineObjects)
185
188
  o.destroyed || o.render();
186
189
  gameRenderPost();
190
+ glRenderPostProcess();
187
191
  medalsRender();
188
192
  touchGamepadRender();
189
193
  debugRender();
190
- glCopyToContext(mainContext);
194
+ glEnable && glCopyToContext(mainContext);
191
195
 
192
196
  if (showWatermark)
193
197
  {
@@ -222,7 +226,7 @@ function enginePreRender()
222
226
  mainContext.imageSmoothingEnabled = !cavasPixelated;
223
227
 
224
228
  // setup gl rendering if enabled
225
- glPreRender(mainCanvas.width, mainCanvas.height, cameraPos.x, cameraPos.y, cameraScale);
229
+ glEnable && glPreRender(mainCanvas.width, mainCanvas.height, cameraPos.x, cameraPos.y, cameraScale);
226
230
  }
227
231
 
228
232
  ///////////////////////////////////////////////////////////////////////////////
@@ -79,7 +79,7 @@ copy engine.all.release.js %OUTPUT_FILENAME%
79
79
 
80
80
  rem check code with closure
81
81
  move %OUTPUT_FILENAME% %OUTPUT_FILENAME%.temp
82
- call npx google-closure-compiler --js=%OUTPUT_FILENAME%.temp --js_output_file=%OUTPUT_FILENAME% --language_out=ECMASCRIPT_2019 --warning_level=VERBOSE --jscomp_off=*
82
+ call npx google-closure-compiler --js=%OUTPUT_FILENAME%.temp --js_output_file=%OUTPUT_FILENAME% --language_out=ECMASCRIPT_2021 --warning_level=VERBOSE --jscomp_off=*
83
83
  del %OUTPUT_FILENAME%.temp
84
84
  if %ERRORLEVEL% NEQ 0 (
85
85
  pause
@@ -0,0 +1,14 @@
1
+ import fs from 'fs'; // node
2
+
3
+ const files = [
4
+ { engine: './engine/engine.all.js', output: './engine/engine.all.module.js' },
5
+ { engine: './engine/engine.all.release.js', output: './engine/engine.all.release.module.js' },
6
+ ];
7
+
8
+ const footerFile = fs.readFileSync('./engine/engineExportModule.js');
9
+
10
+ files.forEach(({ engine, output }) => {
11
+ const engineFile = fs.readFileSync(engine);
12
+ const file = [engineFile, footerFile].join('\n');
13
+ fs.writeFileSync(output, file);
14
+ });
@@ -233,55 +233,49 @@ const debugRender = ()=>
233
233
 
234
234
  if (debugOverlay)
235
235
  {
236
+ const saveContext = mainContext;
237
+ mainContext = overlayContext;
238
+
236
239
  // mouse pick
237
240
  let bestDistance = Infinity, bestObject;
238
241
  for (const o of engineObjects)
239
242
  {
240
243
  if (o.canvas || o.destroyed)
241
- continue; // skip tile layers
242
-
243
- const size = o.size.copy();
244
- if (!size.x || !size.y)
244
+ continue;
245
+ if (!o.size.x || !o.size.y)
245
246
  continue;
246
247
 
247
248
  const distance = mousePos.distanceSquared(o.pos);
248
249
  if (distance < bestDistance)
249
250
  {
250
251
  bestDistance = distance;
251
- bestObject = o
252
+ bestObject = o;
252
253
  }
253
254
 
254
255
  // show object info
255
- const color = new Color(
256
- o.collideTiles?1:0,
257
- o.collideSolidObjects?1:0,
258
- o.isSolid?1:0,
259
- o.parent ? .2 : .5);
260
- size.x = max(size.x, .2);
261
- size.y = max(size.y, .2);
262
- drawRect(o.pos, size, color);
263
- drawRect(o.pos, size.scale(.8), o.parent ? new Color(1,1,1,.5) : new Color(0,0,0,.8));
264
- o.parent && drawLine(o.pos, o.parent.pos, .1, new Color(0,0,1,.5));
256
+ const size = vec2(max(o.size.x, .2), max(o.size.y, .2));
257
+ const color1 = new Color(!!o.collideTiles, !!o.collideSolidObjects, !!o.isSolid, o.parent?.2:.5);
258
+ const color2 = o.parent ? new Color(1,1,1,.5) : new Color(0,0,0,.8);
259
+ drawRect(o.pos, size, color1, o.angle, 0);
260
+ drawRect(o.pos, size.scale(.8), color2, o.angle, 0);
261
+ o.parent && drawLine(o.pos, o.parent.pos, .1, new Color(0,0,1,.5), 0);
265
262
  }
266
263
 
267
264
  if (bestObject)
268
265
  {
269
- const saveContext = mainContext;
270
- mainContext = overlayContext
271
266
  const raycastHitPos = tileCollisionRaycast(bestObject.pos, mousePos);
272
267
  raycastHitPos && drawRect(raycastHitPos.floor().add(vec2(.5)), vec2(1), new Color(0,1,1,.3));
273
- drawRect(mousePos.floor().add(vec2(.5)), vec2(1), new Color(0,0,1,.5));
274
- drawLine(mousePos, bestObject.pos, .1, !raycastHitPos ? new Color(0,1,0,.5) : new Color(1,0,0,.5));
268
+ drawRect(mousePos.floor().add(vec2(.5)), vec2(1), new Color(0,0,1,.5), 0, 0);
269
+ drawLine(mousePos, bestObject.pos, .1, raycastHitPos ? new Color(1,0,0,.5) : new Color(0,1,0,.5), 0);
275
270
 
276
271
  const debugText = 'mouse pos = ' + mousePos +
277
272
  '\nmouse collision = ' + getTileCollisionData(mousePos) +
278
273
  '\n\n--- object info ---\n' +
279
274
  bestObject.toString();
280
- drawTextScreen(debugText, mousePosScreen, 24, new Color, .05, undefined, undefined, 'monospace');
281
- mainContext = saveContext;
275
+ drawTextScreen(debugText, mousePosScreen, 24, new Color, .05, 0, 0, 'monospace');
282
276
  }
283
277
 
284
- glCopyToContext(mainContext);
278
+ glCopyToContext(mainContext = saveContext);
285
279
  }
286
280
 
287
281
  {
@@ -294,7 +288,6 @@ const debugRender = ()=>
294
288
 
295
289
  // create canvas transform from world space to screen space
296
290
  const pos = worldToScreen(p.pos);
297
-
298
291
  overlayContext.translate(pos.x|0, pos.y|0);
299
292
  overlayContext.rotate(p.angle);
300
293
  overlayContext.fillStyle = overlayContext.strokeStyle = p.color;
@@ -233,21 +233,21 @@ function setBlendMode(additive, useWebGL=glEnable)
233
233
  * @param {Color} [lineColor=new Color(0,0,0)]
234
234
  * @param {String} [textAlign='center']
235
235
  * @memberof Draw */
236
- function drawTextScreen(text, pos, size=1, color=new Color, lineWidth=0, lineColor=new Color(0,0,0), textAlign='center', font=fontDefault)
236
+ function drawTextScreen(text, pos, size=1, color=new Color, lineWidth=0, lineColor=new Color(0,0,0), textAlign='center', font=fontDefault, context=overlayContext)
237
237
  {
238
- overlayContext.fillStyle = color;
239
- overlayContext.lineWidth = lineWidth;
240
- overlayContext.strokeStyle = lineColor;
241
- overlayContext.textAlign = textAlign;
242
- overlayContext.font = size + 'px '+ font;
243
- overlayContext.textBaseline = 'middle';
244
- overlayContext.lineJoin = 'round';
238
+ context.fillStyle = color;
239
+ context.lineWidth = lineWidth;
240
+ context.strokeStyle = lineColor;
241
+ context.textAlign = textAlign;
242
+ context.font = size + 'px '+ font;
243
+ context.textBaseline = 'middle';
244
+ context.lineJoin = 'round';
245
245
 
246
246
  pos = pos.copy();
247
247
  (text+'').split('\n').forEach(line=>
248
248
  {
249
- lineWidth && overlayContext.strokeText(line, pos.x, pos.y);
250
- overlayContext.fillText(line, pos.x, pos.y);
249
+ lineWidth && context.strokeText(line, pos.x, pos.y);
250
+ context.fillText(line, pos.x, pos.y);
251
251
  pos.y += size;
252
252
  });
253
253
  }
@@ -264,7 +264,7 @@ function drawTextScreen(text, pos, size=1, color=new Color, lineWidth=0, lineCol
264
264
  * @memberof Draw */
265
265
  function drawText(text, pos, size=1, color, lineWidth, lineColor, textAlign, font)
266
266
  {
267
- drawTextScreen(text, worldToScreen(pos), size*cameraScale, color, lineWidth*cameraScale, lineColor, textAlign, font);
267
+ drawTextScreen(text, worldToScreen(pos), size*cameraScale, color, lineWidth*cameraScale, lineColor, textAlign, font, mainContext);
268
268
  }
269
269
 
270
270
  ///////////////////////////////////////////////////////////////////////////////
@@ -287,7 +287,7 @@ let engineFontImage;
287
287
  class FontImage
288
288
  {
289
289
  /** Create an image font
290
- * @param {Image} [image] - The image the font is stored in, if undefined the default font is used
290
+ * @param {HTMLImageElement} [image] - The image the font is stored in, if undefined the default font is used
291
291
  * @param {Vector2} [tileSize=vec2(8)] - The size of the font source tiles
292
292
  * @param {Vector2} [paddingSize=vec2(0,1)] - How much extra space to add between characters
293
293
  * @param {Number} [startTileIndex=0] - Tile index in image where font starts
@@ -385,4 +385,4 @@ function toggleFullscreen()
385
385
  else if (document.body.mozRequestFullScreen)
386
386
  document.body.mozRequestFullScreen();
387
387
  }
388
- }
388
+ }
@@ -0,0 +1,333 @@
1
+ // This file contains exports neessary when LittleJS is used as a module
2
+
3
+ // setters for all variables that devs will need to modify
4
+ const setCameraPos = (v)=> cameraPos = v;
5
+ const setCameraScale = (v)=> cameraScale = v;
6
+ const setRandSeed = (v)=> randSeed = v;
7
+ const setCanvasMaxSize = (v)=> canvasMaxSize = v;
8
+ const setCanvasFixedSize = (v)=> canvasFixedSize = v;
9
+ const setCavasPixelated = (v)=> cavasPixelated = v;
10
+ const setFontDefault = (v)=> fontDefault = v;
11
+ const setTileSizeDefault = (v)=> tileSizeDefault = v;
12
+ const setTileFixBleedScale = (v)=> tileFixBleedScale = v;
13
+ const setObjectDefaultSize = (v)=> objectDefaultSize = v;
14
+ const setEnablePhysicsSolver = (v)=> enablePhysicsSolver = v;
15
+ const setObjectDefaultMass = (v)=> objectDefaultMass = v;
16
+ const setObjectDefaultDamping = (v)=> objectDefaultDamping = v;
17
+ const setObjectDefaultAngleDamping = (v)=> objectDefaultAngleDamping = v;
18
+ const setObjectDefaultElasticity = (v)=> objectDefaultElasticity = v;
19
+ const setObjectDefaultFriction = (v)=> objectDefaultFriction = v;
20
+ const setObjectMaxSpeed = (v)=> objectMaxSpeed = v;
21
+ const setGravity = (v)=> gravity = v;
22
+ const setParticleEmitRateScale = (v)=> particleEmitRateScale = v;
23
+ const setGlEnable = (v)=> glEnable = v;
24
+ const setGlOverlay = (v)=> glOverlay = v;
25
+ const setGamepadsEnable = (v)=> gamepadsEnable = v;
26
+ const setGamepadDirectionEmulateStick = (v)=> gamepadDirectionEmulateStick = v;
27
+ const setInputWASDEmulateDirection = (v)=> inputWASDEmulateDirection = v;
28
+ const setTouchGamepadEnable = (v)=> touchGamepadEnable = v;
29
+ const setTouchGamepadAnalog = (v)=> touchGamepadAnalog = v;
30
+ const setTouchGamepadSize = (v)=> touchGamepadSize = v;
31
+ const setTouchGamepadAlpha = (v)=> touchGamepadAlpha = v;
32
+ const setVibrateEnable = (v)=> vibrateEnable = v;
33
+ const setSoundVolume = (v)=> soundVolume = v;
34
+ const setSoundEnable = (v)=> soundEnable = v;
35
+ const setSoundDefaultRange = (v)=> soundDefaultRange = v;
36
+ const setSoundDefaultTaper = (v)=> soundDefaultTaper = v;
37
+ const setMedalDisplayTime = (v)=> medalDisplayTime = v;
38
+ const setMedalDisplaySlideTime = (v)=> medalDisplaySlideTime = v;
39
+ const setMedalDisplayWidth = (v)=> medalDisplayWidth = v;
40
+ const setMedalDisplayHeight = (v)=> medalDisplayHeight = v;
41
+ const setMedalDisplayIconSize = (v)=> medalDisplayIconSize = v;
42
+ const setMedalsPreventUnlock = (v)=> medalsPreventUnlock = v;
43
+ const setDebugPointSize = (v)=> debugPointSize = v;
44
+ const setShowWatermark = (v)=> showWatermark = v;
45
+ const setGodMode = (v)=> godMode = v;
46
+
47
+ // This is a full list of everything in engine.all
48
+ export {
49
+ // Custom methods
50
+ setCameraPos,
51
+ setCameraScale,
52
+ setRandSeed,
53
+ setCanvasMaxSize,
54
+ setCanvasFixedSize,
55
+ setCavasPixelated,
56
+ setFontDefault,
57
+ setTileSizeDefault,
58
+ setTileFixBleedScale,
59
+ setObjectDefaultSize,
60
+ setEnablePhysicsSolver,
61
+ setObjectDefaultMass,
62
+ setObjectDefaultDamping,
63
+ setObjectDefaultAngleDamping,
64
+ setObjectDefaultElasticity,
65
+ setObjectDefaultFriction,
66
+ setObjectMaxSpeed,
67
+ setGravity,
68
+ setParticleEmitRateScale,
69
+ setGlEnable,
70
+ setGlOverlay,
71
+ setGamepadsEnable,
72
+ setGamepadDirectionEmulateStick,
73
+ setInputWASDEmulateDirection,
74
+ setTouchGamepadEnable,
75
+ setTouchGamepadAnalog,
76
+ setTouchGamepadSize,
77
+ setTouchGamepadAlpha,
78
+ setVibrateEnable,
79
+ setSoundVolume,
80
+ setSoundEnable,
81
+ setSoundDefaultRange,
82
+ setSoundDefaultTaper,
83
+ setMedalDisplayTime,
84
+ setMedalDisplaySlideTime,
85
+ setMedalDisplayWidth,
86
+ setMedalDisplayHeight,
87
+ setMedalDisplayIconSize,
88
+ setMedalsPreventUnlock,
89
+ setDebugPointSize,
90
+ setShowWatermark,
91
+ setGodMode,
92
+
93
+ // Settings
94
+ canvasMaxSize,
95
+ canvasFixedSize,
96
+ cavasPixelated,
97
+ fontDefault,
98
+ tileSizeDefault,
99
+ tileFixBleedScale,
100
+ objectDefaultSize,
101
+ enablePhysicsSolver,
102
+ objectDefaultMass,
103
+ objectDefaultDamping,
104
+ objectDefaultAngleDamping,
105
+ objectDefaultElasticity,
106
+ objectDefaultFriction,
107
+ objectMaxSpeed,
108
+ gravity,
109
+ particleEmitRateScale,
110
+ cameraPos,
111
+ cameraScale,
112
+ glEnable,
113
+ glOverlay,
114
+ gamepadsEnable,
115
+ gamepadDirectionEmulateStick,
116
+ inputWASDEmulateDirection,
117
+ touchGamepadEnable,
118
+ touchGamepadAnalog,
119
+ touchGamepadSize,
120
+ touchGamepadAlpha,
121
+ vibrateEnable,
122
+ soundVolume,
123
+ soundEnable,
124
+ soundDefaultRange,
125
+ soundDefaultTaper,
126
+ medalDisplayTime,
127
+ medalDisplaySlideTime,
128
+ medalDisplayWidth,
129
+ medalDisplayHeight,
130
+ medalDisplayIconSize,
131
+
132
+ // Globals
133
+ debug,
134
+ debugPointSize,
135
+ showWatermark,
136
+ godMode,
137
+ // Debug
138
+ //debugPrimitives,
139
+ //debugOverlay,
140
+ //debugPhysics,
141
+ //debugRaycast,
142
+ //debugParticles,
143
+ //debugGamepads,
144
+ //debugMedals,
145
+ //debugTakeScreenshot,
146
+ //downloadLink,
147
+ //ASSERT,
148
+ debugRect,
149
+ debugCircle,
150
+ debugPoint,
151
+ debugLine,
152
+ debugAABB,
153
+ debugText,
154
+ debugClear,
155
+ debugSaveCanvas,
156
+ //debugInit,
157
+ //debugUpdate,
158
+ //debugRender,
159
+
160
+ // Utilities
161
+ PI,
162
+ abs,
163
+ min,
164
+ max,
165
+ sign,
166
+ mod,
167
+ clamp,
168
+ percent,
169
+ lerp,
170
+ smoothStep,
171
+ nearestPowerOfTwo,
172
+ isOverlapping,
173
+ wave,
174
+ formatTime,
175
+ // Random
176
+ rand,
177
+ randInt,
178
+ randSign,
179
+ randInCircle,
180
+ randVector,
181
+ randColor,
182
+ randSeed,
183
+ randSeeded,
184
+
185
+ // More utilities
186
+ vec2,
187
+ Vector2,
188
+ colorRGBA,
189
+ colorHSLA,
190
+ Color,
191
+ Timer,
192
+
193
+ // Base
194
+ EngineObject,
195
+
196
+ // Draw
197
+ tileImage,
198
+ mainCanvas,
199
+ mainContext,
200
+ overlayCanvas,
201
+ overlayContext,
202
+ mainCanvasSize,
203
+ screenToWorld,
204
+ worldToScreen,
205
+ drawTile,
206
+ drawRect,
207
+ drawTileScreenSpace,
208
+ drawRectScreenSpace,
209
+ drawLine,
210
+ drawCanvas2D,
211
+ setBlendMode,
212
+ drawTextScreen,
213
+ drawText,
214
+ engineFontImage,
215
+ FontImage,
216
+ isFullscreen,
217
+ toggleFullscreen,
218
+
219
+ // Input
220
+ keyIsDown,
221
+ keyWasPressed,
222
+ keyWasReleased,
223
+ clearInput,
224
+ mouseIsDown,
225
+ mouseWasPressed,
226
+ mouseWasReleased,
227
+ mousePos,
228
+ mousePosScreen,
229
+ mouseWheel,
230
+ isUsingGamepad,
231
+ preventDefaultInput,
232
+ gamepadIsDown,
233
+ gamepadWasPressed,
234
+ gamepadWasReleased,
235
+ gamepadStick,
236
+ //inputData,
237
+ //inputUpdate,
238
+ //inputUpdatePost,
239
+ // onkeydown,
240
+ // onkeyup,
241
+ //remapKeyCode,
242
+ // onmousedown,
243
+ // onmouseup,
244
+ // onmousemove,
245
+ // onwheel,
246
+ // oncontextmenu,
247
+ mouseToScreen,
248
+ //stickData,
249
+ gamepadsUpdate,
250
+ vibrate,
251
+ vibrateStop,
252
+ isTouchDevice,
253
+ //touchGamepadTimer,
254
+ touchGamepadCreate,
255
+ touchGamepadRender,
256
+
257
+ // Audio
258
+ Sound,
259
+ Music,
260
+ playAudioFile,
261
+ speak,
262
+ speakStop,
263
+ getNoteFrequency,
264
+ audioContext,
265
+ playSamples,
266
+ zzfx,
267
+ //zzfxR,
268
+ //zzfxG,
269
+ //zzfxM,
270
+
271
+ // Tiles
272
+ tileCollision,
273
+ tileCollisionSize,
274
+ initTileCollision,
275
+ setTileCollisionData,
276
+ getTileCollisionData,
277
+ tileCollisionTest,
278
+ tileCollisionRaycast,
279
+ TileLayerData,
280
+ TileLayer,
281
+
282
+ // Particles
283
+ ParticleEmitter,
284
+ Particle,
285
+
286
+ // Medals
287
+ medals,
288
+ medalsPreventUnlock,
289
+ medalsInit,
290
+ newgroundsInit,
291
+ Medal,
292
+ //medalsRender,
293
+ Newgrounds,
294
+ //CryptoJS,
295
+
296
+ // WebGL
297
+ glCanvas,
298
+ glContext,
299
+ //glInit,
300
+ glSetBlendMode,
301
+ glSetTexture,
302
+ glCompileShader,
303
+ glCreateProgram,
304
+ glCreateTexture,
305
+ //glPreRender,
306
+ //glFlush,
307
+ //glCopyToContext,
308
+ //glDraw,
309
+ glInitPostProcess,
310
+ //glRenderPostProcess,
311
+
312
+ // Engine
313
+ engineName,
314
+ engineVersion,
315
+ frameRate,
316
+ timeDelta,
317
+ engineObjects,
318
+ //engineObjectsCollide,
319
+ frame,
320
+ time,
321
+ timeReal,
322
+ paused,
323
+ //frameTimeLastMS,
324
+ //averageFPS,
325
+ //drawCount,
326
+ //styleBody,
327
+ //styleCanvas,
328
+ engineInit,
329
+ //enginePreRender,
330
+ //engineObjectsUpdate,
331
+ engineObjectsDestroy,
332
+ engineObjectsCallback,
333
+ };
@@ -112,7 +112,7 @@ let inputData = [[]];
112
112
  function inputUpdate()
113
113
  {
114
114
  // clear input when lost focus (prevent stuck keys)
115
- document.hasFocus() || clearInput();
115
+ isTouchDevice || document.hasFocus() || clearInput();
116
116
 
117
117
  // update mouse world space position
118
118
  mousePos = screenToWorld(mousePosScreen);
@@ -187,7 +187,7 @@ function gamepadsUpdate()
187
187
  }
188
188
  }
189
189
 
190
- if (!gamepadsEnable || !navigator.getGamepads || !document.hasFocus() && !debug)
190
+ if (!gamepadsEnable || !navigator || !navigator.getGamepads || !document.hasFocus() && !debug)
191
191
  return;
192
192
 
193
193
  // poll gamepads
@@ -236,7 +236,7 @@ function gamepadsUpdate()
236
236
  /** Pulse the vibration hardware if it exists
237
237
  * @param {Number} [pattern=100] - a single value in miliseconds or vibration interval array
238
238
  * @memberof Input */
239
- const vibrate = (pattern)=> vibrateEnable && Navigator.vibrate && Navigator.vibrate(pattern);
239
+ const vibrate = (pattern)=> vibrateEnable && navigator && navigator.vibrate && navigator.vibrate(pattern);
240
240
 
241
241
  /** Cancel any ongoing vibration
242
242
  * @memberof Input */
@@ -254,7 +254,7 @@ const isTouchDevice = window.ontouchstart !== undefined;
254
254
  if (isTouchDevice)
255
255
  {
256
256
  // handle all touch events the same way
257
- let wasTouching, hadTouchInput;
257
+ let wasTouching, hadTouch;
258
258
  ontouchstart = ontouchmove = ontouchend = (e)=>
259
259
  {
260
260
  e.button = 0; // all touches are left click
@@ -263,7 +263,8 @@ if (isTouchDevice)
263
263
  const touching = e.touches.length;
264
264
  if (touching)
265
265
  {
266
- hadTouchInput || zzfx(0, hadTouchInput=1) ; // fix mobile audio, force it to play a sound the first time
266
+ // fix mobile audio, force it to play a sound on first touch
267
+ hadTouch || zzfx(0, hadTouch=1);
267
268
 
268
269
  // set event pos and pass it along
269
270
  e.x = e.touches[0].clientX;
@@ -276,8 +277,8 @@ if (isTouchDevice)
276
277
  // set was touching
277
278
  wasTouching = touching;
278
279
 
279
- // prevent normal mouse events from being called
280
- return !e.cancelable;
280
+ // must return true so the document will get focus
281
+ return true;
281
282
  }
282
283
  }
283
284
 
@@ -16,11 +16,6 @@ const medals = [];
16
16
  * @memberof Medals */
17
17
  let medalsPreventUnlock;
18
18
 
19
- /** This can used to enable Newgrounds functionality
20
- * @type {Newgrounds}
21
- * @memberof Medals */
22
- let newgrounds;
23
-
24
19
  // Engine internal variables not exposed to documentation
25
20
  let medalsDisplayQueue = [], medalsSaveName, medalsDisplayTimeLast;
26
21
 
@@ -35,7 +30,7 @@ function medalsInit(saveName)
35
30
  {
36
31
  // check if medals are unlocked
37
32
  medalsSaveName = saveName;
38
- debugMedals || medals.forEach(medal=> localStorage[medal.storageKey()]);
33
+ debugMedals || medals.forEach(medal=> medal.unlocked = (localStorage[medal.storageKey()] | 0));
39
34
  }
40
35
 
41
36
  /**
@@ -168,6 +163,15 @@ function medalsRender()
168
163
 
169
164
  ///////////////////////////////////////////////////////////////////////////////
170
165
 
166
+ // global Newgrounds object
167
+ let newgrounds;
168
+
169
+ /** This can used to enable Newgrounds functionality
170
+ * @param {Number} app_id - The newgrounds App ID
171
+ * @param {String} [cipher] - The encryption Key (AES-128/Base64)
172
+ * @memberof Medals */
173
+ function newgroundsInit(app_id, cipher) { newgrounds = new Newgrounds(app_id, cipher); }
174
+
171
175
  /**
172
176
  * Newgrounds API wrapper object
173
177
  * @example
@@ -296,7 +296,7 @@ class EngineObject
296
296
  * @return {Boolean} - true if the raycast should hit */
297
297
  collideWithTileRaycast(tileData, pos) { return tileData > 0; }
298
298
 
299
- /** Called to check if a tile raycast hit
299
+ /** Called to check if a object collision should be resolved
300
300
  * @param {EngineObject} object - the object to test against
301
301
  * @return {Boolean} - true if the collision should be resolved
302
302
  */
@@ -341,10 +341,10 @@ class EngineObject
341
341
  }
342
342
 
343
343
  /** Set how this object collides
344
- * @param {boolean} [collideSolidObjects=0] - Does it collide with solid objects
345
- * @param {boolean} [isSolid=0] - Does it collide with and block other objects (expensive in large numbers)
344
+ * @param {boolean} [collideSolidObjects=1] - Does it collide with solid objects
345
+ * @param {boolean} [isSolid=1] - Does it collide with and block other objects (expensive in large numbers)
346
346
  * @param {boolean} [collideTiles=1] - Does it collide with the tile collision */
347
- setCollision(collideSolidObjects=0, isSolid=0, collideTiles=1)
347
+ setCollision(collideSolidObjects=1, isSolid=1, collideTiles=1)
348
348
  {
349
349
  ASSERT(collideSolidObjects || !isSolid); // solid objects must be set to collide
350
350