littlejsengine 1.17.15 â 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 +28 -9
- package/dist/littlejs.esm.js +111 -44
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +107 -43
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +104 -40
- 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/shorts/music.js +1 -1
- package/examples/shorts/musicPlayer.js +3 -3
- package/examples/shorts/sequencer.js +1 -1
- package/examples/shorts/timers.js +1 -1
- package/examples/shorts/uiSystem.js +5 -5
- package/examples/starter/index.html +2 -2
- package/examples/stress/index.html +1 -1
- package/examples/uiSystem/game.js +6 -6
- package/package.json +1 -1
- package/plugins/box2d.js +18 -7
- package/plugins/pluginExport.js +1 -1
- package/plugins/uiSystem.js +15 -15
- package/src/engine.js +23 -6
- package/src/engineBuild.mjs +1 -1
- package/src/engineDebug.js +3 -3
- package/src/engineDraw.js +1 -0
- package/src/engineExport.js +3 -0
- package/src/engineInput.js +19 -8
- package/src/engineMath.js +1 -1
- package/src/engineObject.js +3 -3
- package/src/engineSettings.js +24 -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
|
|
@@ -500,6 +506,11 @@ declare module "littlejsengine" {
|
|
|
500
506
|
* @default
|
|
501
507
|
* @memberof Settings */
|
|
502
508
|
export let touchGamepadAlpha: number;
|
|
509
|
+
/** How long to display the touch gamepad on screen in seconds, set to 0 to always display
|
|
510
|
+
* @type {number}
|
|
511
|
+
* @default
|
|
512
|
+
* @memberof Settings */
|
|
513
|
+
export let touchGamepadDisplayTime: number;
|
|
503
514
|
/** Allow vibration hardware if it exists
|
|
504
515
|
* @type {boolean}
|
|
505
516
|
* @default
|
|
@@ -587,6 +598,11 @@ declare module "littlejsengine" {
|
|
|
587
598
|
* @param {boolean} pixelated
|
|
588
599
|
* @memberof Settings */
|
|
589
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;
|
|
590
606
|
/** Set default font used for text rendering
|
|
591
607
|
* @param {string} font
|
|
592
608
|
* @memberof Settings */
|
|
@@ -3304,7 +3320,7 @@ declare module "littlejsengine" {
|
|
|
3304
3320
|
* - Buttons
|
|
3305
3321
|
* - Checkboxes
|
|
3306
3322
|
* - Images
|
|
3307
|
-
* -
|
|
3323
|
+
* - Sliders
|
|
3308
3324
|
* - Video
|
|
3309
3325
|
* @namespace UISystem
|
|
3310
3326
|
*/
|
|
@@ -3719,18 +3735,18 @@ declare module "littlejsengine" {
|
|
|
3719
3735
|
* @param {Color} [color=uiSystem.defaultButtonColor]
|
|
3720
3736
|
*/
|
|
3721
3737
|
constructor(pos?: Vector2, size?: Vector2, checked?: boolean, text?: string, color?: Color);
|
|
3722
|
-
/** @property {boolean} - Current percentage value of this
|
|
3738
|
+
/** @property {boolean} - Current percentage value of this slider 0-1 */
|
|
3723
3739
|
checked: boolean;
|
|
3724
3740
|
text: string;
|
|
3725
3741
|
click(): void;
|
|
3726
3742
|
}
|
|
3727
3743
|
/**
|
|
3728
|
-
*
|
|
3744
|
+
* UISlider - A UI object that acts as a slider or scrollbar
|
|
3729
3745
|
* @extends UIObject
|
|
3730
3746
|
* @memberof UISystem
|
|
3731
3747
|
*/
|
|
3732
|
-
export class
|
|
3733
|
-
/** Create a
|
|
3748
|
+
export class UISlider extends UIObject {
|
|
3749
|
+
/** Create a UISlider object
|
|
3734
3750
|
* @param {Vector2} [pos]
|
|
3735
3751
|
* @param {Vector2} [size]
|
|
3736
3752
|
* @param {number} [value]
|
|
@@ -3739,9 +3755,9 @@ declare module "littlejsengine" {
|
|
|
3739
3755
|
* @param {Color} [handleColor=WHITE]
|
|
3740
3756
|
*/
|
|
3741
3757
|
constructor(pos?: Vector2, size?: Vector2, value?: number, text?: string, color?: Color, handleColor?: Color);
|
|
3742
|
-
/** @property {number} - Current percentage value of this
|
|
3758
|
+
/** @property {number} - Current percentage value of this slider 0-1 */
|
|
3743
3759
|
value: number;
|
|
3744
|
-
/** @property {Color} - Color for the handle part of the
|
|
3760
|
+
/** @property {Color} - Color for the handle part of the slider */
|
|
3745
3761
|
handleColor: Color;
|
|
3746
3762
|
/** @property {boolean} - Should it fill up like a progress bar? */
|
|
3747
3763
|
fillMode: boolean;
|
|
@@ -3921,9 +3937,12 @@ declare module "littlejsengine" {
|
|
|
3921
3937
|
/** checks if a box2d object is null
|
|
3922
3938
|
* @param {Object} o */
|
|
3923
3939
|
isNull(o: any): boolean;
|
|
3924
|
-
/** casts a box2d object to
|
|
3940
|
+
/** casts a box2d object to a shape type
|
|
3941
|
+
* @param {Object} o */
|
|
3942
|
+
castShapeObject(o: any): any;
|
|
3943
|
+
/** casts a box2d object to a joint type
|
|
3925
3944
|
* @param {Object} o */
|
|
3926
|
-
|
|
3945
|
+
castJointObject(o: any): any;
|
|
3927
3946
|
}
|
|
3928
3947
|
/**
|
|
3929
3948
|
* Box2D Object - extend with your own custom physics objects
|
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.
|
|
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()
|
|
@@ -961,8 +980,6 @@ function debugUpdate()
|
|
|
961
980
|
debugOverlay = !debugOverlay;
|
|
962
981
|
if (debugOverlay)
|
|
963
982
|
{
|
|
964
|
-
if (keyWasPressed('Digit0'))
|
|
965
|
-
debugWatermark = !debugWatermark;
|
|
966
983
|
if (keyWasPressed('Digit1'))
|
|
967
984
|
debugPhysics = !debugPhysics, debugParticles = false;
|
|
968
985
|
if (keyWasPressed('Digit2'))
|
|
@@ -1250,7 +1267,7 @@ function debugRenderPost()
|
|
|
1250
1267
|
return;
|
|
1251
1268
|
}
|
|
1252
1269
|
|
|
1253
|
-
if (!debugWatermark) return;
|
|
1270
|
+
if (!debugWatermark && !debugOverlay) return;
|
|
1254
1271
|
|
|
1255
1272
|
// update fps display
|
|
1256
1273
|
mainContext.textAlign = 'right';
|
|
@@ -1734,7 +1751,7 @@ function lineTest(posStart, posEnd, testFunction, normal)
|
|
|
1734
1751
|
// get ray direction and length
|
|
1735
1752
|
const dx = posEnd.x - posStart.x;
|
|
1736
1753
|
const dy = posEnd.y - posStart.y;
|
|
1737
|
-
const totalLength =
|
|
1754
|
+
const totalLength = (dx*dx + dy*dy)**.5;
|
|
1738
1755
|
if (!totalLength) return;
|
|
1739
1756
|
|
|
1740
1757
|
// current integer cell we are in
|
|
@@ -2838,6 +2855,13 @@ let canvasPixelated = false;
|
|
|
2838
2855
|
* @memberof Settings */
|
|
2839
2856
|
let tilesPixelated = true;
|
|
2840
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
|
+
|
|
2841
2865
|
/** Default font used for text rendering
|
|
2842
2866
|
* @type {string}
|
|
2843
2867
|
* @default
|
|
@@ -3016,6 +3040,12 @@ let touchGamepadSize = 99;
|
|
|
3016
3040
|
* @memberof Settings */
|
|
3017
3041
|
let touchGamepadAlpha = .3;
|
|
3018
3042
|
|
|
3043
|
+
/** How long to display the touch gamepad on screen in seconds, set to 0 to always display
|
|
3044
|
+
* @type {number}
|
|
3045
|
+
* @default
|
|
3046
|
+
* @memberof Settings */
|
|
3047
|
+
let touchGamepadDisplayTime = 3;
|
|
3048
|
+
|
|
3019
3049
|
/** Allow vibration hardware if it exists
|
|
3020
3050
|
* @type {boolean}
|
|
3021
3051
|
* @default
|
|
@@ -3144,6 +3174,12 @@ function setCanvasPixelated(pixelated)
|
|
|
3144
3174
|
* @memberof Settings */
|
|
3145
3175
|
function setTilesPixelated(pixelated) { tilesPixelated = pixelated; }
|
|
3146
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
|
+
|
|
3147
3183
|
/** Set default font used for text rendering
|
|
3148
3184
|
* @param {string} font
|
|
3149
3185
|
* @memberof Settings */
|
|
@@ -3290,6 +3326,11 @@ function setTouchGamepadSize(size) { touchGamepadSize = size; }
|
|
|
3290
3326
|
* @memberof Settings */
|
|
3291
3327
|
function setTouchGamepadAlpha(alpha) { touchGamepadAlpha = alpha; }
|
|
3292
3328
|
|
|
3329
|
+
/** Set how long to display the touch gamepad on screen in seconds, set to 0 to always display
|
|
3330
|
+
* @param {number} time
|
|
3331
|
+
* @memberof Settings */
|
|
3332
|
+
function setTouchGamepadDisplayTime(time) { touchGamepadDisplayTime = time; }
|
|
3333
|
+
|
|
3293
3334
|
/** Set to allow vibration hardware if it exists
|
|
3294
3335
|
* @param {boolean} enable
|
|
3295
3336
|
* @memberof Settings */
|
|
@@ -3561,10 +3602,10 @@ class EngineObject
|
|
|
3561
3602
|
// if already was touching, try to push away
|
|
3562
3603
|
const deltaPos = oldPos.subtract(o.pos);
|
|
3563
3604
|
const length = deltaPos.length();
|
|
3564
|
-
const pushAwayAccel = .001;
|
|
3565
|
-
const velocity = length < .
|
|
3605
|
+
const pushAwayAccel = .001;
|
|
3606
|
+
const velocity = length < .001 ? vec2(0,1) : deltaPos.scale(pushAwayAccel/length);
|
|
3566
3607
|
this.velocity = this.velocity.add(velocity);
|
|
3567
|
-
if (o.mass) // push away if not fixed
|
|
3608
|
+
if (o.mass) // push away other object if not fixed
|
|
3568
3609
|
o.velocity = o.velocity.subtract(velocity);
|
|
3569
3610
|
|
|
3570
3611
|
debugPhysics && debugOverlap(this.pos, this.size, o.pos, o.size, '#f00');
|
|
@@ -3993,6 +4034,7 @@ function tile(index=new Vector2, size=tileDefaultSize, texture=0, padding=tileDe
|
|
|
3993
4034
|
const textureInfo = typeof texture === 'number' ?
|
|
3994
4035
|
textureInfos[texture] : texture;
|
|
3995
4036
|
ASSERT(textureInfo instanceof TextureInfo, 'tile texture is not loaded');
|
|
4037
|
+
ASSERT(textureInfo.size.x > 0, 'tile texture is not loaded');
|
|
3996
4038
|
|
|
3997
4039
|
// get the position of the tile
|
|
3998
4040
|
const sizePaddedX = size.x + padding*2;
|
|
@@ -5355,7 +5397,7 @@ function inputInit()
|
|
|
5355
5397
|
document.addEventListener('mouseup', onMouseUp);
|
|
5356
5398
|
document.addEventListener('mousemove', onMouseMove);
|
|
5357
5399
|
document.addEventListener('mouseleave', onMouseLeave);
|
|
5358
|
-
document.addEventListener('wheel', onMouseWheel);
|
|
5400
|
+
document.addEventListener('wheel', onMouseWheel, { passive: false });
|
|
5359
5401
|
document.addEventListener('contextmenu', onContextMenu);
|
|
5360
5402
|
document.addEventListener('blur', onBlur);
|
|
5361
5403
|
|
|
@@ -5374,7 +5416,7 @@ function inputInit()
|
|
|
5374
5416
|
}
|
|
5375
5417
|
|
|
5376
5418
|
// try to prevent default browser handling of input
|
|
5377
|
-
if (!inputPreventDefault || !
|
|
5419
|
+
if (!inputPreventDefault || !e.cancelable || !document.hasFocus()) return;
|
|
5378
5420
|
|
|
5379
5421
|
// don't break browser shortcuts
|
|
5380
5422
|
if (e.ctrlKey || e.metaKey || e.altKey) return;
|
|
@@ -5433,7 +5475,7 @@ function inputInit()
|
|
|
5433
5475
|
mousePosScreen = mouseEventToScreen(vec2(e.x,e.y));
|
|
5434
5476
|
mouseDeltaScreen = mouseDeltaScreen.add(mousePosScreen.subtract(mousePosScreenLast));
|
|
5435
5477
|
|
|
5436
|
-
if (inputPreventDefault &&
|
|
5478
|
+
if (inputPreventDefault && e.cancelable && document.hasFocus())
|
|
5437
5479
|
e.preventDefault();
|
|
5438
5480
|
}
|
|
5439
5481
|
function onMouseUp(e)
|
|
@@ -5455,7 +5497,12 @@ function inputInit()
|
|
|
5455
5497
|
mouseDeltaScreen = mouseDeltaScreen.add(movement);
|
|
5456
5498
|
}
|
|
5457
5499
|
function onMouseLeave() { mouseInWindow = false; } // mouse moved off window
|
|
5458
|
-
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
|
+
}
|
|
5459
5506
|
function onContextMenu(e) { e.preventDefault(); } // prevent right click menu
|
|
5460
5507
|
function onBlur() { inputClear(); } // reset input when focus is lost
|
|
5461
5508
|
|
|
@@ -5505,7 +5552,7 @@ function inputInit()
|
|
|
5505
5552
|
wasTouching = touching;
|
|
5506
5553
|
|
|
5507
5554
|
// prevent default handling like copy, magnifier lens, and scrolling
|
|
5508
|
-
if (inputPreventDefault &&
|
|
5555
|
+
if (inputPreventDefault && e.cancelable && document.hasFocus())
|
|
5509
5556
|
e.preventDefault();
|
|
5510
5557
|
|
|
5511
5558
|
// must return true so the document will get focus
|
|
@@ -5663,7 +5710,13 @@ function inputUpdate()
|
|
|
5663
5710
|
}
|
|
5664
5711
|
|
|
5665
5712
|
// return if gamepads are disabled or not supported
|
|
5666
|
-
|
|
5713
|
+
try {
|
|
5714
|
+
// protect against getGamepads disallowed security error
|
|
5715
|
+
if (!gamepadsEnable || !navigator?.getGamepads)
|
|
5716
|
+
return;
|
|
5717
|
+
} catch(e) {
|
|
5718
|
+
return;
|
|
5719
|
+
}
|
|
5667
5720
|
|
|
5668
5721
|
// only poll gamepads when focused or in debug mode
|
|
5669
5722
|
if (!debug && !document.hasFocus()) return;
|
|
@@ -5761,10 +5814,10 @@ function inputRender()
|
|
|
5761
5814
|
function touchGamepadRender()
|
|
5762
5815
|
{
|
|
5763
5816
|
if (!touchInputEnable || !isTouchDevice || headlessMode) return;
|
|
5764
|
-
if (!touchGamepadEnable || !touchGamepadTimer.isSet()) return;
|
|
5817
|
+
if (!touchGamepadEnable || !touchGamepadTimer.isSet() && touchGamepadDisplayTime) return;
|
|
5765
5818
|
|
|
5766
5819
|
// fade off when not touching or paused
|
|
5767
|
-
const alpha = percent(touchGamepadTimer.get(),
|
|
5820
|
+
const alpha = touchGamepadDisplayTime ? percent(touchGamepadTimer.get(), touchGamepadDisplayTime+1, touchGamepadDisplayTime) : 1;
|
|
5768
5821
|
if (!alpha || paused) return;
|
|
5769
5822
|
|
|
5770
5823
|
// setup the canvas
|
|
@@ -9335,7 +9388,7 @@ function zzfxM(instruments, patterns, sequence, BPM = 125)
|
|
|
9335
9388
|
* - Buttons
|
|
9336
9389
|
* - Checkboxes
|
|
9337
9390
|
* - Images
|
|
9338
|
-
* -
|
|
9391
|
+
* - Sliders
|
|
9339
9392
|
* - Video
|
|
9340
9393
|
* @namespace UISystem
|
|
9341
9394
|
*/
|
|
@@ -10532,7 +10585,7 @@ class UICheckbox extends UIObject
|
|
|
10532
10585
|
ASSERT(isString(text), 'ui checkbox must be a string');
|
|
10533
10586
|
ASSERT(isColor(color), 'ui checkbox color must be a color');
|
|
10534
10587
|
|
|
10535
|
-
/** @property {boolean} - Current percentage value of this
|
|
10588
|
+
/** @property {boolean} - Current percentage value of this slider 0-1 */
|
|
10536
10589
|
this.checked = checked;
|
|
10537
10590
|
// set properties
|
|
10538
10591
|
this.text = text;
|
|
@@ -10567,13 +10620,13 @@ class UICheckbox extends UIObject
|
|
|
10567
10620
|
|
|
10568
10621
|
///////////////////////////////////////////////////////////////////////////////
|
|
10569
10622
|
/**
|
|
10570
|
-
*
|
|
10623
|
+
* UISlider - A UI object that acts as a slider or scrollbar
|
|
10571
10624
|
* @extends UIObject
|
|
10572
10625
|
* @memberof UISystem
|
|
10573
10626
|
*/
|
|
10574
|
-
class
|
|
10627
|
+
class UISlider extends UIObject
|
|
10575
10628
|
{
|
|
10576
|
-
/** Create a
|
|
10629
|
+
/** Create a UISlider object
|
|
10577
10630
|
* @param {Vector2} [pos]
|
|
10578
10631
|
* @param {Vector2} [size]
|
|
10579
10632
|
* @param {number} [value]
|
|
@@ -10585,14 +10638,14 @@ class UIScrollbar extends UIObject
|
|
|
10585
10638
|
{
|
|
10586
10639
|
super(pos, size);
|
|
10587
10640
|
|
|
10588
|
-
ASSERT(isNumber(value), 'ui
|
|
10589
|
-
ASSERT(isString(text), 'ui
|
|
10590
|
-
ASSERT(isColor(color), 'ui
|
|
10591
|
-
ASSERT(isColor(handleColor), 'ui
|
|
10641
|
+
ASSERT(isNumber(value), 'ui slider value must be a number');
|
|
10642
|
+
ASSERT(isString(text), 'ui slider must be a string');
|
|
10643
|
+
ASSERT(isColor(color), 'ui slider color must be a color');
|
|
10644
|
+
ASSERT(isColor(handleColor), 'ui slider handleColor must be a color');
|
|
10592
10645
|
|
|
10593
|
-
/** @property {number} - Current percentage value of this
|
|
10646
|
+
/** @property {number} - Current percentage value of this slider 0-1 */
|
|
10594
10647
|
this.value = value;
|
|
10595
|
-
/** @property {Color} - Color for the handle part of the
|
|
10648
|
+
/** @property {Color} - Color for the handle part of the slider */
|
|
10596
10649
|
this.handleColor = handleColor.copy();
|
|
10597
10650
|
/** @property {boolean} - Should it fill up like a progress bar? */
|
|
10598
10651
|
this.fillMode = false;
|
|
@@ -10611,7 +10664,7 @@ class UIScrollbar extends UIObject
|
|
|
10611
10664
|
const oldValue = this.value;
|
|
10612
10665
|
if (this.isActiveObject())
|
|
10613
10666
|
{
|
|
10614
|
-
// handle horizontal or vertical
|
|
10667
|
+
// handle horizontal or vertical slider
|
|
10615
10668
|
const isHorizontal = this.size.x > this.size.y;
|
|
10616
10669
|
const handleSize = isHorizontal ? this.size.y : this.size.x;
|
|
10617
10670
|
const barSize = isHorizontal ? this.size.x : this.size.y;
|
|
@@ -10639,7 +10692,7 @@ class UIScrollbar extends UIObject
|
|
|
10639
10692
|
{
|
|
10640
10693
|
super.render();
|
|
10641
10694
|
|
|
10642
|
-
// handle horizontal or vertical
|
|
10695
|
+
// handle horizontal or vertical slider
|
|
10643
10696
|
const isHorizontal = this.size.x > this.size.y;
|
|
10644
10697
|
const barWidth = isHorizontal ? this.size.x : this.size.y;
|
|
10645
10698
|
const handleWidth = isHorizontal ? this.size.y : this.size.x;
|
|
@@ -10657,7 +10710,7 @@ class UIScrollbar extends UIObject
|
|
|
10657
10710
|
}
|
|
10658
10711
|
else
|
|
10659
10712
|
{
|
|
10660
|
-
// draw the
|
|
10713
|
+
// draw the slider handle
|
|
10661
10714
|
const value = clamp(isHorizontal ? this.value : 1 - this.value);
|
|
10662
10715
|
const p = (barWidth - handleWidth) * (value - .5);
|
|
10663
10716
|
const pos = this.pos.add(isHorizontal ? vec2(p, 0) : vec2(0, p));
|
|
@@ -10666,7 +10719,7 @@ class UIScrollbar extends UIObject
|
|
|
10666
10719
|
uiSystem.drawRect(pos, drawSize, color, this.lineWidth, this.lineColor, this.cornerRadius, this.gradientColor);
|
|
10667
10720
|
}
|
|
10668
10721
|
|
|
10669
|
-
// draw the text scaled to fit on the
|
|
10722
|
+
// draw the text scaled to fit on the slider
|
|
10670
10723
|
const textSize = this.getTextSize();
|
|
10671
10724
|
uiSystem.drawText(this.text, this.pos, textSize,
|
|
10672
10725
|
this.textColor, this.textLineWidth, this.textLineColor, this.align, this.font, this.fontStyle, true, this.textShadow);
|
|
@@ -10941,7 +10994,7 @@ class Box2dObject extends EngineObject
|
|
|
10941
10994
|
// draw non-edge fixtures
|
|
10942
10995
|
this.getFixtureList().forEach((fixture)=>
|
|
10943
10996
|
{
|
|
10944
|
-
const shape = box2d.
|
|
10997
|
+
const shape = box2d.castShapeObject(fixture.GetShape());
|
|
10945
10998
|
if (shape.GetType() !== box2d.instance.b2Shape.e_edge)
|
|
10946
10999
|
{
|
|
10947
11000
|
box2d.drawFixture(fixture, this.pos, this.angle, color, lineColor, lineWidth, useWebGL, context);
|
|
@@ -11581,7 +11634,7 @@ class Box2dJoint
|
|
|
11581
11634
|
constructor(jointDef)
|
|
11582
11635
|
{
|
|
11583
11636
|
/** @property {Object} - The Box2d joint */
|
|
11584
|
-
this.box2dJoint = box2d.
|
|
11637
|
+
this.box2dJoint = box2d.castJointObject(box2d.world.CreateJoint(jointDef));
|
|
11585
11638
|
}
|
|
11586
11639
|
|
|
11587
11640
|
/** Destroy this joint */
|
|
@@ -11866,7 +11919,7 @@ class Box2dRevoluteJoint extends Box2dJoint
|
|
|
11866
11919
|
|
|
11867
11920
|
/** Enable/disable the joint limit
|
|
11868
11921
|
* @param {boolean} [enable] */
|
|
11869
|
-
enableLimit(enable=true) { return this.box2dJoint.
|
|
11922
|
+
enableLimit(enable=true) { return this.box2dJoint.EnableLimit(enable); }
|
|
11870
11923
|
|
|
11871
11924
|
/** Get the lower joint limit
|
|
11872
11925
|
* @return {number} */
|
|
@@ -12024,7 +12077,7 @@ class Box2dPrismaticJoint extends Box2dJoint
|
|
|
12024
12077
|
|
|
12025
12078
|
/** Enable/disable the joint limit
|
|
12026
12079
|
* @param {boolean} [enable] */
|
|
12027
|
-
enableLimit(enable=true) { return this.box2dJoint.
|
|
12080
|
+
enableLimit(enable=true) { return this.box2dJoint.EnableLimit(enable); }
|
|
12028
12081
|
|
|
12029
12082
|
/** Get the lower joint limit
|
|
12030
12083
|
* @return {number} */
|
|
@@ -12638,7 +12691,7 @@ class Box2dPlugin
|
|
|
12638
12691
|
* @param {CanvasRenderingContext2D} [context] */
|
|
12639
12692
|
drawFixture(fixture, pos, angle, color=WHITE, lineColor=BLACK, lineWidth=.1, useWebgl, context)
|
|
12640
12693
|
{
|
|
12641
|
-
const shape = box2d.
|
|
12694
|
+
const shape = box2d.castShapeObject(fixture.GetShape());
|
|
12642
12695
|
switch (shape.GetType())
|
|
12643
12696
|
{
|
|
12644
12697
|
case box2d.instance.b2Shape.e_polygon:
|
|
@@ -12696,9 +12749,9 @@ class Box2dPlugin
|
|
|
12696
12749
|
* @param {Object} o */
|
|
12697
12750
|
isNull(o) { return !box2d.instance.getPointer(o); }
|
|
12698
12751
|
|
|
12699
|
-
/** casts a box2d object to
|
|
12752
|
+
/** casts a box2d object to a shape type
|
|
12700
12753
|
* @param {Object} o */
|
|
12701
|
-
|
|
12754
|
+
castShapeObject(o)
|
|
12702
12755
|
{
|
|
12703
12756
|
switch (o.GetType())
|
|
12704
12757
|
{
|
|
@@ -12710,6 +12763,17 @@ class Box2dPlugin
|
|
|
12710
12763
|
return box2d.instance.castObject(o, box2d.instance.b2PolygonShape);
|
|
12711
12764
|
case box2d.instance.b2Shape.e_chain:
|
|
12712
12765
|
return box2d.instance.castObject(o, box2d.instance.b2ChainShape);
|
|
12766
|
+
}
|
|
12767
|
+
|
|
12768
|
+
ASSERT(false, 'Unknown box2d object type');
|
|
12769
|
+
}
|
|
12770
|
+
|
|
12771
|
+
/** casts a box2d object to a joint type
|
|
12772
|
+
* @param {Object} o */
|
|
12773
|
+
castJointObject(o)
|
|
12774
|
+
{
|
|
12775
|
+
switch (o.GetType())
|
|
12776
|
+
{
|
|
12713
12777
|
case box2d.instance.e_revoluteJoint:
|
|
12714
12778
|
return box2d.instance.castObject(o, box2d.instance.b2RevoluteJoint);
|
|
12715
12779
|
case box2d.instance.e_prismaticJoint:
|
|
@@ -13040,6 +13104,7 @@ export
|
|
|
13040
13104
|
canvasFixedSize,
|
|
13041
13105
|
canvasPixelated,
|
|
13042
13106
|
tilesPixelated,
|
|
13107
|
+
canvasPixelRatio,
|
|
13043
13108
|
fontDefault,
|
|
13044
13109
|
showSplashScreen,
|
|
13045
13110
|
headlessMode,
|
|
@@ -13064,6 +13129,7 @@ export
|
|
|
13064
13129
|
touchGamepadAnalog,
|
|
13065
13130
|
touchGamepadSize,
|
|
13066
13131
|
touchGamepadAlpha,
|
|
13132
|
+
touchGamepadDisplayTime,
|
|
13067
13133
|
vibrateEnable,
|
|
13068
13134
|
soundEnable,
|
|
13069
13135
|
soundVolume,
|
|
@@ -13085,6 +13151,7 @@ export
|
|
|
13085
13151
|
setCanvasFixedSize,
|
|
13086
13152
|
setCanvasPixelated,
|
|
13087
13153
|
setTilesPixelated,
|
|
13154
|
+
setCanvasPixelRatio,
|
|
13088
13155
|
setFontDefault,
|
|
13089
13156
|
setShowSplashScreen,
|
|
13090
13157
|
setHeadlessMode,
|
|
@@ -13360,7 +13427,7 @@ export
|
|
|
13360
13427
|
UITile,
|
|
13361
13428
|
UIButton,
|
|
13362
13429
|
UICheckbox,
|
|
13363
|
-
|
|
13430
|
+
UISlider,
|
|
13364
13431
|
UIVideo,
|
|
13365
13432
|
|
|
13366
13433
|
// Box2D Physics
|