littlejsengine 1.15.9 → 1.16.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 (54) hide show
  1. package/dist/littlejs.d.ts +154 -158
  2. package/dist/littlejs.esm.js +573 -570
  3. package/dist/littlejs.esm.min.js +1 -1
  4. package/dist/littlejs.js +553 -553
  5. package/dist/littlejs.min.js +1 -1
  6. package/dist/littlejs.release.js +392 -396
  7. package/examples/box2d/game.js +1 -1
  8. package/examples/box2d/gameObjects.js +5 -5
  9. package/examples/breakout/game.js +3 -3
  10. package/examples/electron/game.js +1 -2
  11. package/examples/electron/index.html +2 -2
  12. package/examples/htmlMenu/game.js +0 -1
  13. package/examples/index.html +1 -1
  14. package/examples/logo.png +0 -0
  15. package/examples/logo2.png +0 -0
  16. package/examples/module/game.js +1 -2
  17. package/examples/particles/index.html +1 -1
  18. package/examples/platformer/game.js +4 -4
  19. package/examples/platformer/gameEffects.js +1 -1
  20. package/examples/puzzle/game.js +2 -2
  21. package/examples/shorts/base.html +4 -3
  22. package/examples/shorts/box2dPool.js +2 -2
  23. package/examples/shorts/empty.js +1 -1
  24. package/examples/shorts/{systemFont.js → fontImage.js} +3 -3
  25. package/examples/shorts/fps.js +1 -1
  26. package/examples/shorts/helloWorld.js +2 -2
  27. package/examples/shorts/nineSlice.js +2 -2
  28. package/examples/shorts/slidingPuzzle.js +1 -1
  29. package/examples/starter/game.js +1 -2
  30. package/examples/starter/index.html +3 -2
  31. package/examples/stress/index.html +1 -1
  32. package/examples/typescript/game.js +1 -2
  33. package/examples/typescript/game.ts +1 -2
  34. package/package.json +1 -1
  35. package/plugins/box2d.js +8 -8
  36. package/plugins/drawUtilities.js +6 -6
  37. package/plugins/postProcess.js +13 -20
  38. package/plugins/uiSystem.js +16 -4
  39. package/reference.md +9 -11
  40. package/src/engine.js +40 -54
  41. package/src/engineAudio.js +5 -7
  42. package/src/engineBuild.js +1 -0
  43. package/src/engineDebug.js +163 -161
  44. package/src/engineDraw.js +108 -130
  45. package/src/engineExport.js +20 -17
  46. package/src/engineInput.js +4 -7
  47. package/src/engineMath.js +1201 -0
  48. package/src/engineMedals.js +7 -7
  49. package/src/engineObject.js +5 -4
  50. package/src/engineRelease.js +2 -4
  51. package/src/engineSettings.js +22 -32
  52. package/src/engineTileLayer.js +9 -10
  53. package/src/engineUtilities.js +34 -1187
  54. package/src/engineWebGL.js +13 -15
package/reference.md CHANGED
@@ -145,7 +145,6 @@ drawCanvas2D(pos, size, angle=0, mirror, drawFunction, screenSpace, context)
145
145
 
146
146
  // Text functions
147
147
  drawText(text, pos, size=1, color=WHITE, lineWidth=0, lineColor=BLACK)
148
- drawTextOverlay(text, pos, size=1, color=WHITE, lineWidth=0, lineColor=BLACK)
149
148
  drawTextScreen(text, pos, size=1, color=WHITE, lineWidth=0, lineColor=BLACK)
150
149
 
151
150
  // Utility drawing functions
@@ -173,7 +172,6 @@ TextureInfo.glTexture // WebGL texture
173
172
  FontImage(image, tileSize=(8,8), paddingSize=(0,1)) // Create an image font
174
173
  FontImage.drawText(text, pos, scale, center) // Draw text in world space
175
174
  FontImage.drawTextScreen(text, pos, scale, center) // Draw text in screen space
176
- FontImage.drawTextOverlay(text, pos, scale, center) // Draw text to overlay canvas
177
175
 
178
176
  // Camera settings
179
177
  cameraPos = (0,0) // Position of camera in world space
@@ -193,8 +191,8 @@ showSplashScreen = false // Show the LittleJS splash screen on startup
193
191
  glEnable = true // Enable fast WebGL rendering
194
192
 
195
193
  // Tile sheet settings
196
- tileSizeDefault = (16,16) // Default size of tiles in pixels
197
- tileFixBleedScale = .3 // How much smaller to draw tiles to prevent bleeding
194
+ tileDefaultSize = (16,16) // Default size of tiles in pixels
195
+ tileDefaultBleed = .3 // How much smaller to draw tiles to prevent bleeding
198
196
  ```
199
197
 
200
198
  ## LittleJS Audio System
@@ -430,18 +428,18 @@ debugCircle(pos, size, color='#fff', time=0, fill) // Draw debug circle
430
428
  debugPoint(pos, color, time, angle) // Draw debug point
431
429
  debugLine(posA, posB, color, width=.1, time) // Draw debug line
432
430
  debugText(text, pos, size=1, color='#fff', time=0, angle=0) // Draw debug text
433
- debugAABB(pA, sA, pB, sB, color) // Draw a debug axis aligned box
434
- debugClear() // Clear all debug primitives
435
- debugSaveCanvas(canvas, filename) // Save canvas to a file
436
- debugSaveText(text, filename) // Save text to a file
437
- debugSaveDataURL(dataURL, filename) // Save url to a file
431
+ debugAABB(pA, sA, pB, sB, color) // Draw a debug axis aligned box
432
+ debugClear() // Clear all debug primitives
433
+ saveCanvas(canvas, filename) // Save canvas to a file
434
+ saveText(text, filename) // Save text to a file
435
+ saveDataURL(dataURL, filename) // Save url to a file
438
436
 
439
437
  // Debug settings
440
438
  debug // Is debug enabled?
441
439
  debugPointSize = .5 // Size to render debug points by default
442
440
  debugKey = 'Escape' // Key code used to toggle debug mode
443
- debugOverlay // True if the debug overlay is active
444
- showWatermark // True if watermark with FPS should be show
441
+ debugOverlay // Is the debug overlay is active?
442
+ debugWatermark // Should watermark with FPS appear in debug mode?
445
443
  ```
446
444
 
447
445
  [LittleJS Engine](https://github.com/KilledByAPixel/LittleJS) Copyright 2021 Frank Force
package/src/engine.js CHANGED
@@ -30,7 +30,7 @@ const engineName = 'LittleJS';
30
30
  * @type {string}
31
31
  * @default
32
32
  * @memberof Engine */
33
- const engineVersion = '1.15.9';
33
+ const engineVersion = '1.16.2';
34
34
 
35
35
  /** Frames per second to update
36
36
  * @type {number}
@@ -177,8 +177,7 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
177
177
  mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
178
178
 
179
179
  // disable smoothing for pixel art
180
- overlayContext.imageSmoothingEnabled =
181
- mainContext.imageSmoothingEnabled = !tilesPixelated;
180
+ mainContext.imageSmoothingEnabled = !tilesPixelated;
182
181
 
183
182
  // setup gl rendering if enabled
184
183
  glPreRender();
@@ -190,7 +189,7 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
190
189
  // update time keeping
191
190
  let frameTimeDeltaMS = frameTimeMS - frameTimeLastMS;
192
191
  frameTimeLastMS = frameTimeMS;
193
- if (debug || showWatermark)
192
+ if (debug || debugWatermark)
194
193
  averageFPS = lerp(averageFPS, 1e3/(frameTimeDeltaMS||1), .05);
195
194
  const debugSpeedUp = debug && keyIsDown('Equal'); // +
196
195
  const debugSpeedDown = debug && keyIsDown('Minus'); // -
@@ -218,6 +217,8 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
218
217
  debugUpdate();
219
218
  gameUpdatePost();
220
219
  inputUpdatePost();
220
+ if (debugVideoCaptureIsActive())
221
+ renderFrame();
221
222
  }
222
223
  else
223
224
  {
@@ -268,33 +269,20 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
268
269
  if (!wasUpdated)
269
270
  updateCanvas();
270
271
 
271
- // render sort then render while removing destroyed objects
272
+ // render the game and objects
272
273
  enginePreRender();
273
274
  gameRender();
274
275
  engineObjects.sort((a,b)=> a.renderOrder - b.renderOrder);
275
276
  for (const o of engineObjects)
276
277
  o.destroyed || o.render();
278
+
279
+ // post rendering
277
280
  gameRenderPost();
278
281
  pluginList.forEach(plugin=>plugin.render?.());
279
282
  inputRender();
280
283
  debugRender();
281
284
  glFlush();
282
- debugVideoCaptureUpdate();
283
-
284
- if (showWatermark && !debugVideoCaptureIsActive())
285
- {
286
- // update fps display
287
- overlayContext.textAlign = 'right';
288
- overlayContext.textBaseline = 'top';
289
- overlayContext.font = '1em monospace';
290
- overlayContext.fillStyle = '#000';
291
- const text = engineName + ' ' + 'v' + engineVersion + ' / '
292
- + drawCount + ' / ' + engineObjects.length + ' / ' + averageFPS.toFixed(1)
293
- + (glEnable ? ' GL' : ' 2D') ;
294
- overlayContext.fillText(text, mainCanvas.width-3, 3);
295
- overlayContext.fillStyle = '#fff';
296
- overlayContext.fillText(text, mainCanvas.width-2, 2);
297
- }
285
+ debugRenderPost();
298
286
  drawCount = 0;
299
287
  }
300
288
  }
@@ -313,8 +301,8 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
313
301
  const fixedAspect = canvasFixedSize.x / canvasFixedSize.y;
314
302
  const w = innerAspect < fixedAspect ? '100%' : '';
315
303
  const h = innerAspect < fixedAspect ? '' : '100%';
316
- overlayCanvas.style.width = mainCanvas.style.width = w;
317
- overlayCanvas.style.height = mainCanvas.style.height = h;
304
+ mainCanvas.style.width = w;
305
+ mainCanvas.style.height = h;
318
306
  if (glCanvas)
319
307
  {
320
308
  glCanvas.style.width = w;
@@ -329,6 +317,7 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
329
317
 
330
318
  // responsive aspect ratio with native resolution
331
319
  const innerAspect = innerWidth / innerHeight;
320
+ ASSERT(canvasMinAspect <= canvasMaxAspect);
332
321
  if (canvasMaxAspect && innerAspect > canvasMaxAspect)
333
322
  {
334
323
  // full height
@@ -343,12 +332,12 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
343
332
  }
344
333
  }
345
334
 
346
- // clear main and overlay canvas and set size
347
- overlayCanvas.width = mainCanvas.width = mainCanvasSize.x;
348
- overlayCanvas.height = mainCanvas.height = mainCanvasSize.y;
335
+ // clear main canvas and set size
336
+ mainCanvas.width = mainCanvasSize.x;
337
+ mainCanvas.height = mainCanvasSize.y;
349
338
 
350
339
  // apply the clear color to main canvas
351
- if (canvasClearColor.a > 0)
340
+ if (canvasClearColor.a > 0 && !glEnable)
352
341
  {
353
342
  mainContext.fillStyle = canvasClearColor.toString();
354
343
  mainContext.fillRect(0, 0, mainCanvasSize.x, mainCanvasSize.y);
@@ -356,19 +345,15 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
356
345
  }
357
346
 
358
347
  // set default line join and cap
359
- const lineJoin = 'round', lineCap = 'round';
360
- mainContext.lineJoin = overlayContext.lineJoin = lineJoin;
361
- mainContext.lineCap = overlayContext.lineCap = lineCap;
348
+ mainContext.lineJoin = 'round';
349
+ mainContext.lineCap = 'round';
362
350
  }
351
+
352
+ // skip setup if headless
353
+ if (headlessMode) return startEngine();
363
354
 
364
- // wait for gameInit to load
365
- async function startEngine()
366
- {
367
- await gameInit();
368
- engineUpdate();
369
- }
370
- if (headlessMode)
371
- return startEngine();
355
+ // setup webgl
356
+ glInit(rootElement);
372
357
 
373
358
  // setup html
374
359
  const styleRoot =
@@ -380,36 +365,30 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
380
365
  'touch-action:none;' + // prevent mobile pinch to resize
381
366
  '-webkit-touch-callout:none'; // compatibility for ios
382
367
  rootElement.style.cssText = styleRoot;
383
- drawCanvas = mainCanvas = document.createElement('canvas');
384
- rootElement.appendChild(mainCanvas);
368
+ mainCanvas = rootElement.appendChild(document.createElement('canvas'));
385
369
  drawContext = mainContext = mainCanvas.getContext('2d');
386
370
 
387
371
  // init stuff and start engine
388
372
  inputInit();
389
373
  audioInit();
390
374
  debugInit();
391
- glInit();
392
-
393
- // create overlay canvas for hud to appear above gl canvas
394
- overlayCanvas = document.createElement('canvas')
395
- rootElement.appendChild(overlayCanvas);
396
- overlayContext = overlayCanvas.getContext('2d');
397
375
 
398
376
  // setup canvases
399
377
  // transform way is still more reliable then flexbox or grid
400
378
  const styleCanvas = 'position:absolute;'+ // allow canvases to overlap
401
379
  'top:50%;left:50%;transform:translate(-50%,-50%)'; // center on screen
402
- mainCanvas.style.cssText = overlayCanvas.style.cssText = styleCanvas;
380
+ mainCanvas.style.cssText = styleCanvas;
403
381
  if (glCanvas)
404
382
  glCanvas.style.cssText = styleCanvas;
405
383
  setCanvasPixelated(canvasPixelated);
406
- setOverlayCanvasPixelated(overlayCanvasPixelated);
407
384
  updateCanvas();
408
385
  glPreRender();
409
386
 
410
- // create offscreen canvas for image processing
411
- workCanvas = new OffscreenCanvas(256, 256);
412
- workContext = workCanvas.getContext('2d', { willReadFrequently: true });
387
+ // create offscreen canvases for image processing
388
+ workCanvas = new OffscreenCanvas(64, 64);
389
+ workContext = workCanvas.getContext('2d');
390
+ workReadCanvas = new OffscreenCanvas(64, 64);
391
+ workReadContext = workReadCanvas.getContext('2d', { willReadFrequently: true });
413
392
 
414
393
  // create promises for loading images
415
394
  const promises = imageSources.map((src, textureIndex)=>
@@ -461,13 +440,20 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
461
440
  await Promise.all(promises);
462
441
  return startEngine();
463
442
 
443
+ async function startEngine()
444
+ {
445
+ // wait for gameInit to load
446
+ await gameInit();
447
+ engineUpdate();
448
+ }
449
+
464
450
  ///////////////////////////////////////////////////////////////////////////
465
451
  // LittleJS Splash Screen
466
452
  function drawEngineSplashScreen(t)
467
453
  {
468
- const x = overlayContext;
469
- const w = overlayCanvas.width = innerWidth;
470
- const h = overlayCanvas.height = innerHeight;
454
+ const x = mainContext;
455
+ const w = mainCanvas.width = innerWidth;
456
+ const h = mainCanvas.height = innerHeight;
471
457
 
472
458
  {
473
459
  // background
@@ -178,12 +178,12 @@ class Sound
178
178
  ///////////////////////////////////////////////////////////////////////////////
179
179
 
180
180
  /**
181
- * Sound Wave Object - Stores a wave sound for later use and can be played positionally
182
- * - this can be used to play wave, mp3, and ogg files
181
+ * Sound Wave Object - Loads and stores an audio file for later use
182
+ * - this can be used to load and play wave, mp3, and ogg files
183
183
  * @extends Sound
184
184
  * @memberof Audio
185
185
  * @example
186
- * // create a sound
186
+ * // load an audio asset file
187
187
  * const sound_example = new SoundWave('sound.mp3');
188
188
  *
189
189
  * // play the sound
@@ -383,8 +383,7 @@ class SoundInstance
383
383
  /** Pause this sound instance */
384
384
  pause()
385
385
  {
386
- if (this.isPaused())
387
- return;
386
+ if (this.isPaused()) return;
388
387
 
389
388
  // save current time and stop sound
390
389
  this.pausedTime = this.getCurrentTime();
@@ -396,8 +395,7 @@ class SoundInstance
396
395
  /** Unpauses this sound instance */
397
396
  resume()
398
397
  {
399
- if (!this.isPaused())
400
- return;
398
+ if (!this.isPaused()) return;
401
399
 
402
400
  // restart sound from paused time
403
401
  this.start(this.pausedTime);
@@ -16,6 +16,7 @@ const SOURCE_FOLDER = 'src';
16
16
  const PLUGIN_FOLDER = 'plugins';
17
17
  const engineSourceFiles =
18
18
  [
19
+ `${SOURCE_FOLDER}/engineMath.js`,
19
20
  `${SOURCE_FOLDER}/engineUtilities.js`,
20
21
  `${SOURCE_FOLDER}/engineSettings.js`,
21
22
  `${SOURCE_FOLDER}/engineObject.js`,