littlejsengine 1.18.0 → 1.18.1

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.
package/dist/littlejs.js CHANGED
@@ -35,7 +35,7 @@ const engineName = 'LittleJS';
35
35
  * @type {string}
36
36
  * @default
37
37
  * @memberof Engine */
38
- const engineVersion = '1.18.0';
38
+ const engineVersion = '1.18.1';
39
39
 
40
40
  /** Frames per second to update
41
41
  * @type {number}
@@ -318,12 +318,17 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
318
318
  }
319
319
  else
320
320
  {
321
+ // apply device pixel ratio for crisp rendering
322
+ const dpr = canvasPixelRatio ?? (devicePixelRatio || 1);
323
+ const viewWidth = innerWidth * dpr | 0;
324
+ const viewHeight = innerHeight * dpr | 0;
325
+
321
326
  // get main canvas size based on window size
322
- mainCanvasSize.x = min(innerWidth, canvasMaxSize.x);
323
- mainCanvasSize.y = min(innerHeight, canvasMaxSize.y);
327
+ mainCanvasSize.x = min(viewWidth, canvasMaxSize.x);
328
+ mainCanvasSize.y = min(viewHeight, canvasMaxSize.y);
324
329
 
325
330
  // responsive aspect ratio with native resolution
326
- const innerAspect = innerWidth / innerHeight;
331
+ const innerAspect = viewWidth / viewHeight;
327
332
  ASSERT(canvasMinAspect <= canvasMaxAspect);
328
333
  if (canvasMaxAspect && innerAspect > canvasMaxAspect)
329
334
  {
@@ -337,6 +342,17 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
337
342
  const h = mainCanvasSize.x / canvasMinAspect | 0;
338
343
  mainCanvasSize.y = min(h, canvasMaxSize.y);
339
344
  }
345
+
346
+ // set CSS display size so backing store renders at viewport size
347
+ const cssW = (mainCanvasSize.x / dpr | 0) + 'px';
348
+ const cssH = (mainCanvasSize.y / dpr | 0) + 'px';
349
+ mainCanvas.style.width = cssW;
350
+ mainCanvas.style.height = cssH;
351
+ if (glCanvas)
352
+ {
353
+ glCanvas.style.width = cssW;
354
+ glCanvas.style.height = cssH;
355
+ }
340
356
  }
341
357
 
342
358
  // clear main canvas and set size
@@ -556,8 +572,9 @@ function drawEngineLogo(t)
556
572
 
557
573
  // LittleJS Logo and Splash Screen
558
574
  const x = mainContext;
559
- const w = mainCanvas.width = innerWidth;
560
- const h = mainCanvas.height = innerHeight;
575
+ const dpr = canvasPixelRatio ?? (devicePixelRatio || 1);
576
+ const w = mainCanvas.width = innerWidth * dpr;
577
+ const h = mainCanvas.height = innerHeight * dpr;
561
578
  {
562
579
  // background
563
580
  const p3 = percent(t, 1, .8);
@@ -951,6 +968,8 @@ function debugShowErrors()
951
968
 
952
969
  function debugInit()
953
970
  {
971
+ if (showEngineVersion)
972
+ console.warn("LittleJS DEBUG build loaded. Use the release build for production.");
954
973
  }
955
974
 
956
975
  function debugUpdate()
@@ -1732,7 +1751,7 @@ function lineTest(posStart, posEnd, testFunction, normal)
1732
1751
  // get ray direction and length
1733
1752
  const dx = posEnd.x - posStart.x;
1734
1753
  const dy = posEnd.y - posStart.y;
1735
- const totalLength = hypot(dx, dy);
1754
+ const totalLength = (dx*dx + dy*dy)**.5;
1736
1755
  if (!totalLength) return;
1737
1756
 
1738
1757
  // current integer cell we are in
@@ -2836,6 +2855,13 @@ let canvasPixelated = false;
2836
2855
  * @memberof Settings */
2837
2856
  let tilesPixelated = true;
2838
2857
 
2858
+ /** Scale factor applied to the canvas backing store for native-resolution rendering.
2859
+ * Pass 1 for no scaling, a number for an explicit ratio, or undefined to track devicePixelRatio each frame.
2860
+ * @type {number|undefined}
2861
+ * @default
2862
+ * @memberof Settings */
2863
+ let canvasPixelRatio = 1;
2864
+
2839
2865
  /** Default font used for text rendering
2840
2866
  * @type {string}
2841
2867
  * @default
@@ -3148,6 +3174,12 @@ function setCanvasPixelated(pixelated)
3148
3174
  * @memberof Settings */
3149
3175
  function setTilesPixelated(pixelated) { tilesPixelated = pixelated; }
3150
3176
 
3177
+ /** Set the canvas pixel ratio.
3178
+ * Pass a number for an explicit ratio, or call with no argument to track devicePixelRatio each frame.
3179
+ * @param {number} [pixelRatio]
3180
+ * @memberof Settings */
3181
+ function setCanvasPixelRatio(pixelRatio) { canvasPixelRatio = pixelRatio; }
3182
+
3151
3183
  /** Set default font used for text rendering
3152
3184
  * @param {string} font
3153
3185
  * @memberof Settings */
@@ -3570,10 +3602,10 @@ class EngineObject
3570
3602
  // if already was touching, try to push away
3571
3603
  const deltaPos = oldPos.subtract(o.pos);
3572
3604
  const length = deltaPos.length();
3573
- const pushAwayAccel = .001; // push away if already overlapping
3574
- const velocity = length < .01 ? randVec2(pushAwayAccel) : deltaPos.scale(pushAwayAccel/length);
3605
+ const pushAwayAccel = .001;
3606
+ const velocity = length < .001 ? vec2(0,1) : deltaPos.scale(pushAwayAccel/length);
3575
3607
  this.velocity = this.velocity.add(velocity);
3576
- if (o.mass) // push away if not fixed
3608
+ if (o.mass) // push away other object if not fixed
3577
3609
  o.velocity = o.velocity.subtract(velocity);
3578
3610
 
3579
3611
  debugPhysics && debugOverlap(this.pos, this.size, o.pos, o.size, '#f00');
@@ -4002,6 +4034,7 @@ function tile(index=new Vector2, size=tileDefaultSize, texture=0, padding=tileDe
4002
4034
  const textureInfo = typeof texture === 'number' ?
4003
4035
  textureInfos[texture] : texture;
4004
4036
  ASSERT(textureInfo instanceof TextureInfo, 'tile texture is not loaded');
4037
+ ASSERT(textureInfo.size.x > 0, 'tile texture is not loaded');
4005
4038
 
4006
4039
  // get the position of the tile
4007
4040
  const sizePaddedX = size.x + padding*2;
@@ -5364,7 +5397,7 @@ function inputInit()
5364
5397
  document.addEventListener('mouseup', onMouseUp);
5365
5398
  document.addEventListener('mousemove', onMouseMove);
5366
5399
  document.addEventListener('mouseleave', onMouseLeave);
5367
- document.addEventListener('wheel', onMouseWheel);
5400
+ document.addEventListener('wheel', onMouseWheel, { passive: false });
5368
5401
  document.addEventListener('contextmenu', onContextMenu);
5369
5402
  document.addEventListener('blur', onBlur);
5370
5403
 
@@ -5383,7 +5416,7 @@ function inputInit()
5383
5416
  }
5384
5417
 
5385
5418
  // try to prevent default browser handling of input
5386
- if (!inputPreventDefault || !document.hasFocus() || !e.cancelable) return;
5419
+ if (!inputPreventDefault || !e.cancelable || !document.hasFocus()) return;
5387
5420
 
5388
5421
  // don't break browser shortcuts
5389
5422
  if (e.ctrlKey || e.metaKey || e.altKey) return;
@@ -5442,7 +5475,7 @@ function inputInit()
5442
5475
  mousePosScreen = mouseEventToScreen(vec2(e.x,e.y));
5443
5476
  mouseDeltaScreen = mouseDeltaScreen.add(mousePosScreen.subtract(mousePosScreenLast));
5444
5477
 
5445
- if (inputPreventDefault && document.hasFocus() && e.cancelable)
5478
+ if (inputPreventDefault && e.cancelable && document.hasFocus())
5446
5479
  e.preventDefault();
5447
5480
  }
5448
5481
  function onMouseUp(e)
@@ -5464,7 +5497,12 @@ function inputInit()
5464
5497
  mouseDeltaScreen = mouseDeltaScreen.add(movement);
5465
5498
  }
5466
5499
  function onMouseLeave() { mouseInWindow = false; } // mouse moved off window
5467
- function onMouseWheel(e) { mouseWheel = e.ctrlKey ? 0 : sign(e.deltaY); }
5500
+ function onMouseWheel(e)
5501
+ {
5502
+ mouseWheel = e.ctrlKey ? 0 : sign(e.deltaY);
5503
+ if (inputPreventDefault && e.cancelable && document.hasFocus())
5504
+ e.preventDefault(); // prevent page scrolling
5505
+ }
5468
5506
  function onContextMenu(e) { e.preventDefault(); } // prevent right click menu
5469
5507
  function onBlur() { inputClear(); } // reset input when focus is lost
5470
5508
 
@@ -5514,7 +5552,7 @@ function inputInit()
5514
5552
  wasTouching = touching;
5515
5553
 
5516
5554
  // prevent default handling like copy, magnifier lens, and scrolling
5517
- if (inputPreventDefault && document.hasFocus() && e.cancelable)
5555
+ if (inputPreventDefault && e.cancelable && document.hasFocus())
5518
5556
  e.preventDefault();
5519
5557
 
5520
5558
  // must return true so the document will get focus
@@ -5672,7 +5710,13 @@ function inputUpdate()
5672
5710
  }
5673
5711
 
5674
5712
  // return if gamepads are disabled or not supported
5675
- if (!gamepadsEnable || !navigator || !navigator.getGamepads) return;
5713
+ try {
5714
+ // protect against getGamepads disallowed security error
5715
+ if (!gamepadsEnable || !navigator?.getGamepads)
5716
+ return;
5717
+ } catch(e) {
5718
+ return;
5719
+ }
5676
5720
 
5677
5721
  // only poll gamepads when focused or in debug mode
5678
5722
  if (!debug && !document.hasFocus()) return;