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/CLAUDE.md +1 -0
- package/README.md +13 -4
- package/dist/littlejs.d.ts +11 -0
- package/dist/littlejs.esm.js +62 -16
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +60 -16
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +58 -16
- 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 +1 -1
- 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 +2 -0
- package/src/engineInput.js +17 -6
- package/src/engineMath.js +1 -1
- package/src/engineObject.js +3 -3
- package/src/engineSettings.js +13 -0
package/CLAUDE.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
See @AI.md for instructions.
|
package/README.md
CHANGED
|
@@ -18,6 +18,10 @@ LittleJS is a fast, lightweight, and fully open source HTML5 game engine designe
|
|
|
18
18
|
Its small footprint is packed with a comprehensive feature set including rendering, physics, particles, sound, and input handling.
|
|
19
19
|
The code is very clean and well documented with many examples to get you started quickly.
|
|
20
20
|
|
|
21
|
+
### đ Join the LittleJS Game Jam
|
|
22
|
+
|
|
23
|
+
*The Third Annual LittleJS Game Jam will take place From Oct 2 to Nov 2! Unleash your creativity and develop amazing games using the LittleJS game engine. đšī¸đŽ [Sign up today and get more info about the jam on itch.io!](https://itch.io/jam/littlejs-jam)*
|
|
24
|
+
|
|
21
25
|
<div align='center'>
|
|
22
26
|
|
|
23
27
|
## [Demos](https://killedbyapixel.github.io/LittleJS/examples) | [Docs](https://killedbyapixel.github.io/LittleJS/docs) | [Trailer](https://youtu.be/chuBzGjv7Ms) | [Discord](https://discord.gg/zb7hcGkyZe) | [FAQ](https://github.com/KilledByAPixel/LittleJS/blob/main/FAQ.md)
|
|
@@ -30,14 +34,15 @@ The code is very clean and well documented with many examples to get you started
|
|
|
30
34
|
|
|
31
35
|
### ⨠Graphics
|
|
32
36
|
|
|
33
|
-
-
|
|
37
|
+
- Blazing fast WebGL2 + Canvas2D hybrid rendering system
|
|
34
38
|
- Apply [Shadertoy](https://www.shadertoy.com) style shaders for post-processing effects
|
|
35
39
|
- Robust particle effect system and [effect design tool](https://killedbyapixel.github.io/LittleJS/examples/particles/)
|
|
36
40
|
|
|
37
41
|
### đ Audio
|
|
38
42
|
|
|
39
43
|
- Sound and music with mp3, ogg, or wave files
|
|
40
|
-
- Use [ZzFX](https://killedbyapixel.github.io/ZzFX/) sound
|
|
44
|
+
- Use [ZzFX](https://killedbyapixel.github.io/ZzFX/) sound generator to play sounds without asset files
|
|
45
|
+
- Spatial audio stereo panning
|
|
41
46
|
|
|
42
47
|
### đŽ Input
|
|
43
48
|
|
|
@@ -53,13 +58,14 @@ The code is very clean and well documented with many examples to get you started
|
|
|
53
58
|
### đ Flexibility
|
|
54
59
|
|
|
55
60
|
- Compatible with all modern web browsers and mobile devices
|
|
56
|
-
- TypeScript and Module support with example projects for both
|
|
61
|
+
- Full TypeScript and Module support with example projects for both
|
|
57
62
|
- Great for size coding competitions like [Js13kGames](https://js13kgames.com/)
|
|
58
63
|
- Open Source and [MIT licensed](https://github.com/KilledByAPixel/LittleJS/blob/main/LICENSE)
|
|
59
64
|
|
|
60
65
|
### đ ī¸ Developer Tools
|
|
61
66
|
|
|
62
67
|
- Live example browser with code editor
|
|
68
|
+
- Import level editor data from [Tiled](https://github.com/mapeditor/tiled) or other JSON
|
|
63
69
|
- Debug overlay and primitive rendering system
|
|
64
70
|
- Medal tracking system with [Newgrounds](https://www.newgrounds.com/) support
|
|
65
71
|
- Node.js build system
|
|
@@ -74,6 +80,8 @@ To get started download the latest LittleJS package from GitHub or install via n
|
|
|
74
80
|
- [LittleJS Quick Reference Sheet](https://github.com/KilledByAPixel/LittleJS/blob/main/reference.md) - A reference sheet to help you get started.
|
|
75
81
|
- [Little JS FAQ](https://github.com/KilledByAPixel/LittleJS/blob/main/FAQ.md) - Answers to common questions about LittleJS.
|
|
76
82
|
- [JS13k Branch](https://github.com/KilledByAPixel/LittleJS/tree/js13k) - For size coding events like JS13k there is a special branch that builds to a 7KB zip.
|
|
83
|
+
- [LittleJS GPT AI](https://chatgpt.com/g/g-67c7c080b5bc81919736bc8815836be6-make-games-with-littlejs) - Use AI to make games without writing any code!
|
|
84
|
+
- [LittleJS AI Info](https://github.com/KilledByAPixel/LittleJS-AI) - Experiments, games, and templates to improve LittleJS + AI workflows.
|
|
77
85
|
|
|
78
86
|
## Examples
|
|
79
87
|
|
|
@@ -82,7 +90,7 @@ LittleJS comes with a several demos both for learning and using as starter proje
|
|
|
82
90
|
- [Example Browser](https://killedbyapixel.github.io/LittleJS/examples/) - Live example browser with all examples
|
|
83
91
|
- [Breakout](https://killedbyapixel.github.io/LittleJS/examples/breakout/) - Block breaking game with post-processing effects
|
|
84
92
|
- [Puzzle Game](https://killedbyapixel.github.io/LittleJS/examples/puzzle/) - Match 3 puzzle game with HD rendering and high score tracking
|
|
85
|
-
- [Platformer](https://killedbyapixel.github.io/LittleJS/examples/platformer/) - Platformer/shooter that loads level data
|
|
93
|
+
- [Platformer](https://killedbyapixel.github.io/LittleJS/examples/platformer/) - Platformer/shooter demo that loads level data
|
|
86
94
|
- [Box2D Demo](https://killedbyapixel.github.io/LittleJS/examples/box2d/) - Box2D plugin demonstration and testbed
|
|
87
95
|
- [Stress Test](https://killedbyapixel.github.io/LittleJS/examples/stress/) - Sprite rendering benchmark and music system demo
|
|
88
96
|
- [Particle System Designer](https://killedbyapixel.github.io/LittleJS/examples/particles/) - Particle system editor and visualizer
|
|
@@ -117,6 +125,7 @@ Here are a few of the many amazing games created with LittleJS...
|
|
|
117
125
|
- [Bug&Bee](https://itch.io/jam/littlejs-game-jam-2025/results) - Low fi shoot em up with co-op gameplay. LittleJS Jam 1st place! by [eoinmcg](https://eoinmcg.itch.io/)
|
|
118
126
|
- [Little Platformer](https://psemo.itch.io/little-platformer) - Platformer with many mechanics. LittleJS Jam 2st place! by [PSEMO](https://psemo.itch.io/), [Solita666](https://itch.io/profile/solita666), [GabrielRG](https://gabrielrg.itch.io/), [Nate](https://natesassoon.itch.io/)
|
|
119
127
|
- [Rogue Pong](https://itch.io/jam/littlejs-game-jam-2025/rate/4004165) - Roguelike crossed with classic pong gameplay. LittleJS Jam 3rd place! by [webdevbrian](https://webdevbrian.itch.io/)
|
|
128
|
+
- [Orbitswarm](https://focaccai.itch.io/orbitswarm) - Fast paced space strategy game. by [Focaccai](https://www.focaccai.com/)
|
|
120
129
|
- [LittleJS Jam 2024 Results](https://itch.io/jam/littlejs-jam-2024/results) - All the games from the first LittleJS Game Jam.
|
|
121
130
|
- [LittleJS Jam 2025 Results](https://itch.io/jam/littlejs-game-jam-2025/results) - All the games from the second LittleJS Game Jam.
|
|
122
131
|
|
package/dist/littlejs.d.ts
CHANGED
|
@@ -377,6 +377,12 @@ declare module "littlejsengine" {
|
|
|
377
377
|
* @default
|
|
378
378
|
* @memberof Settings */
|
|
379
379
|
export let tilesPixelated: boolean;
|
|
380
|
+
/** Scale factor applied to the canvas backing store for native-resolution rendering.
|
|
381
|
+
* Pass 1 for no scaling, a number for an explicit ratio, or undefined to track devicePixelRatio each frame.
|
|
382
|
+
* @type {number|undefined}
|
|
383
|
+
* @default
|
|
384
|
+
* @memberof Settings */
|
|
385
|
+
export let canvasPixelRatio: number | undefined;
|
|
380
386
|
/** Default font used for text rendering
|
|
381
387
|
* @type {string}
|
|
382
388
|
* @default
|
|
@@ -592,6 +598,11 @@ declare module "littlejsengine" {
|
|
|
592
598
|
* @param {boolean} pixelated
|
|
593
599
|
* @memberof Settings */
|
|
594
600
|
export function setTilesPixelated(pixelated: boolean): void;
|
|
601
|
+
/** Set the canvas pixel ratio.
|
|
602
|
+
* Pass a number for an explicit ratio, or call with no argument to track devicePixelRatio each frame.
|
|
603
|
+
* @param {number} [pixelRatio]
|
|
604
|
+
* @memberof Settings */
|
|
605
|
+
export function setCanvasPixelRatio(pixelRatio?: number): void;
|
|
595
606
|
/** Set default font used for text rendering
|
|
596
607
|
* @param {string} font
|
|
597
608
|
* @memberof Settings */
|
package/dist/littlejs.esm.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.
|
|
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(
|
|
323
|
-
mainCanvasSize.y = min(
|
|
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 =
|
|
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
|
|
560
|
-
const
|
|
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 =
|
|
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;
|
|
3574
|
-
const velocity = 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 || !
|
|
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 &&
|
|
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)
|
|
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 &&
|
|
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
|
-
|
|
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;
|
|
@@ -13060,6 +13104,7 @@ export
|
|
|
13060
13104
|
canvasFixedSize,
|
|
13061
13105
|
canvasPixelated,
|
|
13062
13106
|
tilesPixelated,
|
|
13107
|
+
canvasPixelRatio,
|
|
13063
13108
|
fontDefault,
|
|
13064
13109
|
showSplashScreen,
|
|
13065
13110
|
headlessMode,
|
|
@@ -13106,6 +13151,7 @@ export
|
|
|
13106
13151
|
setCanvasFixedSize,
|
|
13107
13152
|
setCanvasPixelated,
|
|
13108
13153
|
setTilesPixelated,
|
|
13154
|
+
setCanvasPixelRatio,
|
|
13109
13155
|
setFontDefault,
|
|
13110
13156
|
setShowSplashScreen,
|
|
13111
13157
|
setHeadlessMode,
|