littlejsengine 1.18.0 → 1.18.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.
- package/.claude/settings.local.json +7 -0
- package/.github/workflows/test.yml +17 -0
- package/AI.md +10 -0
- package/CLAUDE.md +1 -0
- package/README.md +15 -6
- package/dist/littlejs.d.ts +47 -7
- package/dist/littlejs.esm.js +97 -30
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +91 -28
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +89 -28
- package/examples/box2d/game.js +2 -2
- package/examples/box2d/gameObjects.js +74 -0
- package/examples/box2d/scenes.js +7 -0
- package/examples/shorts/base.html +1 -1
- package/examples/starter/index.html +2 -2
- package/examples/stress/index.html +1 -1
- package/package.json +3 -2
- package/src/engine.js +23 -6
- package/src/engineBuild.mjs +1 -1
- package/src/engineDebug.js +2 -0
- package/src/engineDraw.js +1 -0
- package/src/engineExport.js +6 -2
- package/src/engineInput.js +34 -10
- package/src/engineMath.js +1 -1
- package/src/engineObject.js +4 -3
- package/src/engineSettings.js +26 -8
- package/test/math.test.mjs +774 -0
- package/test/setup.mjs +22 -0
- package/test/smoke.test.mjs +258 -0
- package/test/util.test.mjs +80 -0
package/src/engineInput.js
CHANGED
|
@@ -321,7 +321,7 @@ function inputInit()
|
|
|
321
321
|
document.addEventListener('mouseup', onMouseUp);
|
|
322
322
|
document.addEventListener('mousemove', onMouseMove);
|
|
323
323
|
document.addEventListener('mouseleave', onMouseLeave);
|
|
324
|
-
document.addEventListener('wheel', onMouseWheel);
|
|
324
|
+
document.addEventListener('wheel', onMouseWheel, { passive: false });
|
|
325
325
|
document.addEventListener('contextmenu', onContextMenu);
|
|
326
326
|
document.addEventListener('blur', onBlur);
|
|
327
327
|
|
|
@@ -340,7 +340,7 @@ function inputInit()
|
|
|
340
340
|
}
|
|
341
341
|
|
|
342
342
|
// try to prevent default browser handling of input
|
|
343
|
-
if (!inputPreventDefault || !
|
|
343
|
+
if (!inputPreventDefault || !e.cancelable || !document.hasFocus()) return;
|
|
344
344
|
|
|
345
345
|
// don't break browser shortcuts
|
|
346
346
|
if (e.ctrlKey || e.metaKey || e.altKey) return;
|
|
@@ -399,7 +399,7 @@ function inputInit()
|
|
|
399
399
|
mousePosScreen = mouseEventToScreen(vec2(e.x,e.y));
|
|
400
400
|
mouseDeltaScreen = mouseDeltaScreen.add(mousePosScreen.subtract(mousePosScreenLast));
|
|
401
401
|
|
|
402
|
-
if (inputPreventDefault &&
|
|
402
|
+
if (inputPreventDefault && e.cancelable && document.hasFocus())
|
|
403
403
|
e.preventDefault();
|
|
404
404
|
}
|
|
405
405
|
function onMouseUp(e)
|
|
@@ -421,7 +421,12 @@ function inputInit()
|
|
|
421
421
|
mouseDeltaScreen = mouseDeltaScreen.add(movement);
|
|
422
422
|
}
|
|
423
423
|
function onMouseLeave() { mouseInWindow = false; } // mouse moved off window
|
|
424
|
-
function onMouseWheel(e)
|
|
424
|
+
function onMouseWheel(e)
|
|
425
|
+
{
|
|
426
|
+
mouseWheel = e.ctrlKey ? 0 : sign(e.deltaY);
|
|
427
|
+
if (inputPreventDefault && e.cancelable && document.hasFocus())
|
|
428
|
+
e.preventDefault(); // prevent page scrolling
|
|
429
|
+
}
|
|
425
430
|
function onContextMenu(e) { e.preventDefault(); } // prevent right click menu
|
|
426
431
|
function onBlur() { inputClear(); } // reset input when focus is lost
|
|
427
432
|
|
|
@@ -471,7 +476,7 @@ function inputInit()
|
|
|
471
476
|
wasTouching = touching;
|
|
472
477
|
|
|
473
478
|
// prevent default handling like copy, magnifier lens, and scrolling
|
|
474
|
-
if (inputPreventDefault &&
|
|
479
|
+
if (inputPreventDefault && e.cancelable && document.hasFocus())
|
|
475
480
|
e.preventDefault();
|
|
476
481
|
|
|
477
482
|
// must return true so the document will get focus
|
|
@@ -492,7 +497,7 @@ function inputInit()
|
|
|
492
497
|
if (touching)
|
|
493
498
|
{
|
|
494
499
|
touchGamepadTimer.set();
|
|
495
|
-
if (
|
|
500
|
+
if (touchGamepadCenterButtonSize && !wasTouching && paused)
|
|
496
501
|
{
|
|
497
502
|
// touch anywhere to press start when paused
|
|
498
503
|
touchGamepadButtons[9] = 1;
|
|
@@ -517,6 +522,7 @@ function inputInit()
|
|
|
517
522
|
// virtual analog stick
|
|
518
523
|
const delta = touchPos.subtract(stickCenter);
|
|
519
524
|
touchGamepadSticks[0] = delta.scale(2/touchGamepadSize).clampLength();
|
|
525
|
+
touchGamepadButtons[10] = 1; // also press a button when touching stick
|
|
520
526
|
}
|
|
521
527
|
else if (buttonCenter.distance(touchPos) < touchGamepadSize)
|
|
522
528
|
{
|
|
@@ -525,6 +531,7 @@ function inputInit()
|
|
|
525
531
|
// virtual right analog stick
|
|
526
532
|
const delta = touchPos.subtract(buttonCenter);
|
|
527
533
|
touchGamepadSticks[1] = delta.scale(2/touchGamepadSize).clampLength();
|
|
534
|
+
touchGamepadButtons[11] = 1; // also press a button when touching right stick
|
|
528
535
|
}
|
|
529
536
|
// virtual face buttons
|
|
530
537
|
let button = buttonCenter.subtract(touchPos).direction();
|
|
@@ -541,8 +548,7 @@ function inputInit()
|
|
|
541
548
|
if (button < touchGamepadButtonCount)
|
|
542
549
|
touchGamepadButtons[button] = 1;
|
|
543
550
|
}
|
|
544
|
-
else if (
|
|
545
|
-
startCenter.distance(touchPos) < touchGamepadSize)
|
|
551
|
+
else if (startCenter.distance(touchPos) < touchGamepadCenterButtonSize)
|
|
546
552
|
{
|
|
547
553
|
// virtual start button in center
|
|
548
554
|
touchGamepadButtons[9] = 1;
|
|
@@ -591,6 +597,18 @@ function inputUpdate()
|
|
|
591
597
|
// update touch gamepad if enabled
|
|
592
598
|
if (touchGamepadEnable && isTouchDevice)
|
|
593
599
|
{
|
|
600
|
+
if (debugGamepads)
|
|
601
|
+
{
|
|
602
|
+
const stickCenter = vec2(touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
|
|
603
|
+
const buttonCenter = touchGamepadButtonCenter();
|
|
604
|
+
const startCenter = mainCanvasSize.scale(.5);
|
|
605
|
+
|
|
606
|
+
debugCircle(stickCenter, 2*touchGamepadSize, 'cyan', 0, false, true);
|
|
607
|
+
debugCircle(buttonCenter, 2*touchGamepadSize, 'cyan', 0, false, true);
|
|
608
|
+
if (touchGamepadCenterButtonSize)
|
|
609
|
+
debugCircle(startCenter, 2*touchGamepadCenterButtonSize, 'cyan', 0, false, true);
|
|
610
|
+
}
|
|
611
|
+
|
|
594
612
|
if (!touchGamepadTimer.isSet()) return;
|
|
595
613
|
|
|
596
614
|
// read virtual analog stick
|
|
@@ -618,7 +636,7 @@ function inputUpdate()
|
|
|
618
636
|
|
|
619
637
|
// read virtual gamepad buttons
|
|
620
638
|
const data = inputData[1] ?? (inputData[1] = []);
|
|
621
|
-
for (let i=
|
|
639
|
+
for (let i=12; i--;)
|
|
622
640
|
{
|
|
623
641
|
const wasDown = gamepadIsDown(i,0);
|
|
624
642
|
data[i] = touchGamepadButtons[i] ? wasDown ? 1 : 3 : wasDown ? 4 : 0;
|
|
@@ -629,7 +647,13 @@ function inputUpdate()
|
|
|
629
647
|
}
|
|
630
648
|
|
|
631
649
|
// return if gamepads are disabled or not supported
|
|
632
|
-
|
|
650
|
+
try {
|
|
651
|
+
// protect against getGamepads disallowed security error
|
|
652
|
+
if (!gamepadsEnable || !navigator?.getGamepads)
|
|
653
|
+
return;
|
|
654
|
+
} catch(e) {
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
633
657
|
|
|
634
658
|
// only poll gamepads when focused or in debug mode
|
|
635
659
|
if (!debug && !document.hasFocus()) return;
|
package/src/engineMath.js
CHANGED
|
@@ -327,7 +327,7 @@ function lineTest(posStart, posEnd, testFunction, normal)
|
|
|
327
327
|
// get ray direction and length
|
|
328
328
|
const dx = posEnd.x - posStart.x;
|
|
329
329
|
const dy = posEnd.y - posStart.y;
|
|
330
|
-
const totalLength =
|
|
330
|
+
const totalLength = (dx*dx + dy*dy)**.5;
|
|
331
331
|
if (!totalLength) return;
|
|
332
332
|
|
|
333
333
|
// current integer cell we are in
|
package/src/engineObject.js
CHANGED
|
@@ -212,10 +212,10 @@ class EngineObject
|
|
|
212
212
|
// if already was touching, try to push away
|
|
213
213
|
const deltaPos = oldPos.subtract(o.pos);
|
|
214
214
|
const length = deltaPos.length();
|
|
215
|
-
const pushAwayAccel = .001;
|
|
216
|
-
const velocity = length < .
|
|
215
|
+
const pushAwayAccel = .001;
|
|
216
|
+
const velocity = length < .001 ? vec2(0,1) : deltaPos.scale(pushAwayAccel/length);
|
|
217
217
|
this.velocity = this.velocity.add(velocity);
|
|
218
|
-
if (o.mass) // push away if not fixed
|
|
218
|
+
if (o.mass) // push away other object if not fixed
|
|
219
219
|
o.velocity = o.velocity.subtract(velocity);
|
|
220
220
|
|
|
221
221
|
debugPhysics && debugOverlap(this.pos, this.size, o.pos, o.size, '#f00');
|
|
@@ -452,6 +452,7 @@ class EngineObject
|
|
|
452
452
|
child.parent = this;
|
|
453
453
|
child.localPos = localPos.copy();
|
|
454
454
|
child.localAngle = localAngle;
|
|
455
|
+
child.updateTransforms();
|
|
455
456
|
return child;
|
|
456
457
|
}
|
|
457
458
|
|
package/src/engineSettings.js
CHANGED
|
@@ -82,6 +82,13 @@ let canvasPixelated = false;
|
|
|
82
82
|
* @memberof Settings */
|
|
83
83
|
let tilesPixelated = true;
|
|
84
84
|
|
|
85
|
+
/** Scale factor applied to the canvas backing store for native-resolution rendering.
|
|
86
|
+
* Pass 1 for no scaling, a number for an explicit ratio, or undefined to track devicePixelRatio each frame.
|
|
87
|
+
* @type {number|undefined}
|
|
88
|
+
* @default
|
|
89
|
+
* @memberof Settings */
|
|
90
|
+
let canvasPixelRatio = 1;
|
|
91
|
+
|
|
85
92
|
/** Default font used for text rendering
|
|
86
93
|
* @type {string}
|
|
87
94
|
* @default
|
|
@@ -223,18 +230,22 @@ let touchInputEnable = true;
|
|
|
223
230
|
|
|
224
231
|
/** True if touch gamepad should appear on mobile devices
|
|
225
232
|
* - Supports left analog stick, 4 face buttons and start button (button 9)
|
|
233
|
+
* - setTouchGamepadButtonCount(1) to use face buttons as right analog stick
|
|
234
|
+
* - Analog stick buttons 10 and 11 are also activated when virtual sticks are touched
|
|
235
|
+
|
|
226
236
|
* @type {boolean}
|
|
227
237
|
* @default
|
|
228
238
|
* @memberof Settings */
|
|
229
239
|
let touchGamepadEnable = false;
|
|
230
240
|
|
|
231
241
|
/** True if touch gamepad should have start button in the center
|
|
242
|
+
* - Prevents activating if overlappng with virtual stick or buttons if they are enabled
|
|
232
243
|
* - When the game is paused, any touch will press the button
|
|
233
|
-
* -
|
|
234
|
-
* @type {
|
|
244
|
+
* - Set size to enable the center button
|
|
245
|
+
* @type {number}
|
|
235
246
|
* @default
|
|
236
247
|
* @memberof Settings */
|
|
237
|
-
let
|
|
248
|
+
let touchGamepadCenterButtonSize = 300;
|
|
238
249
|
|
|
239
250
|
/** Number of buttons on touch gamepad (0-4), if 1 also acts as right analog stick
|
|
240
251
|
* @type {number}
|
|
@@ -252,7 +263,7 @@ let touchGamepadAnalog = true;
|
|
|
252
263
|
* @type {number}
|
|
253
264
|
* @default
|
|
254
265
|
* @memberof Settings */
|
|
255
|
-
let touchGamepadSize =
|
|
266
|
+
let touchGamepadSize = 100;
|
|
256
267
|
|
|
257
268
|
/** Transparency of touch gamepad overlay
|
|
258
269
|
* @type {number}
|
|
@@ -394,6 +405,12 @@ function setCanvasPixelated(pixelated)
|
|
|
394
405
|
* @memberof Settings */
|
|
395
406
|
function setTilesPixelated(pixelated) { tilesPixelated = pixelated; }
|
|
396
407
|
|
|
408
|
+
/** Set the canvas pixel ratio.
|
|
409
|
+
* Pass a number for an explicit ratio, or call with no argument to track devicePixelRatio each frame.
|
|
410
|
+
* @param {number} [pixelRatio]
|
|
411
|
+
* @memberof Settings */
|
|
412
|
+
function setCanvasPixelRatio(pixelRatio) { canvasPixelRatio = pixelRatio; }
|
|
413
|
+
|
|
397
414
|
/** Set default font used for text rendering
|
|
398
415
|
* @param {string} font
|
|
399
416
|
* @memberof Settings */
|
|
@@ -514,11 +531,12 @@ function setTouchInputEnable(enable) { touchInputEnable = enable; }
|
|
|
514
531
|
* @memberof Settings */
|
|
515
532
|
function setTouchGamepadEnable(enable) { touchGamepadEnable = enable; }
|
|
516
533
|
|
|
517
|
-
/**
|
|
518
|
-
* -
|
|
519
|
-
*
|
|
534
|
+
/** Set if touch gamepad should have start button in the center
|
|
535
|
+
* - Set size to enable the center button
|
|
536
|
+
* - When the game is paused, any touch will press the button
|
|
537
|
+
* @param {number} size
|
|
520
538
|
* @memberof Settings */
|
|
521
|
-
function
|
|
539
|
+
function setTouchGamepadCenterButtonSize(size) { touchGamepadCenterButtonSize = size; }
|
|
522
540
|
|
|
523
541
|
/** Set number of buttons on touch gamepad (0-4), if 1 also acts as right analog stick
|
|
524
542
|
* @param {number} count
|