littlejsengine 1.18.15 → 1.18.18

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/README.md CHANGED
@@ -19,13 +19,13 @@ LittleJS is a fast, lightweight, and fully open source HTML5 game engine designe
19
19
  Its small footprint is packed with a comprehensive feature set including rendering, physics, particles, sound, and input handling.
20
20
  The code is very clean and well documented with many examples to get you started quickly.
21
21
 
22
- ### 🚀 Join the LittleJS Game Jam
22
+ ### 🚀 [Join the LittleJS Game Jam](https://itch.io/jam/littlejs-jam)
23
23
 
24
- *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
+ *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.*
25
25
 
26
26
  <div align='center' markdown='1'>
27
27
 
28
- ## [Demos](https://killedbyapixel.github.io/LittleJS/examples) | [Docs](https://killedbyapixel.github.io/LittleJS/docs) | [Reference](https://github.com/KilledByAPixel/LittleJS/blob/main/REFERENCE.md) | [FAQ](https://github.com/KilledByAPixel/LittleJS/blob/main/FAQ.md) | [Trailer](https://youtu.be/chuBzGjv7Ms) | [Discord](https://discord.gg/zb7hcGkyZe)
28
+ ## [Demos](https://killedbyapixel.github.io/LittleJS/examples) | [Arcade](https://killedbyapixel.github.io/LittleJSArcade) | [Docs](https://killedbyapixel.github.io/LittleJS/docs) | [FAQ](https://github.com/KilledByAPixel/LittleJS/blob/main/FAQ.md) | [Trailer](https://youtu.be/chuBzGjv7Ms) | [Discord](https://discord.gg/zb7hcGkyZe)
29
29
 
30
30
  </div>
31
31
 
@@ -120,6 +120,7 @@ engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost);
120
120
  LittleJS comes with several demos both for learning and using as starter projects to create new games.
121
121
 
122
122
  - [Example Browser](https://killedbyapixel.github.io/LittleJS/examples/) - Live example browser with all examples and editable source
123
+ - [LittleJS Arcade](https://killedbyapixel.github.io/LittleJSArcade/) - Over 50 example games you can use as starter projects
123
124
  - [Short Examples](https://github.com/KilledByAPixel/LittleJS/tree/main/examples/shorts) - 60+ single-file demos showing off individual engine features
124
125
  - [Breakout](https://killedbyapixel.github.io/LittleJS/examples/breakout/) - Block breaking game with post-processing effects
125
126
  - [Puzzle Game](https://killedbyapixel.github.io/LittleJS/examples/puzzle/) - Match 3 puzzle game with HD rendering and high score tracking
@@ -157,7 +158,6 @@ Here are a few of the many amazing games created with LittleJS...
157
158
  - [Tetrimals](https://nixn.itch.io/tetrimals) - A puzzle game mixing Tetris with animals. by [nixn](https://nixn.itch.io/)
158
159
  - [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/)
159
160
  - [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/)
160
- - [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/)
161
161
  - [Alien Escape Pinball](https://focaccai.itch.io/alien-pinball) - Pinball game with physics and aliens. by [Focaccai](https://www.focaccai.com/)
162
162
  - [LittleJS Jam 2024 Results](https://itch.io/jam/littlejs-jam-2024/results) - All the games from the first LittleJS Game Jam.
163
163
  - [LittleJS Jam 2025 Results](https://itch.io/jam/littlejs-game-jam-2025/results) - All the games from the second LittleJS Game Jam.
@@ -390,6 +390,8 @@ declare module "littlejsengine" {
390
390
  * @memberof Settings */
391
391
  export let canvasPixelated: boolean;
392
392
  /** Disables texture filtering for crisper pixel art
393
+ * - Leave true for pixel art so sprites stay sharp when scaled (uses NEAREST filtering)
394
+ * - Set false for smooth/high-resolution art to enable bilinear filtering and mipmaps
393
395
  * @type {boolean}
394
396
  * @default
395
397
  * @memberof Settings */
@@ -510,31 +512,69 @@ declare module "littlejsengine" {
510
512
  * - Supports left analog stick, 4 face buttons and start button (button 9)
511
513
  * - setTouchGamepadButtonCount(1) to use face buttons as right analog stick
512
514
  * - Analog stick buttons 10 and 11 are also activated when virtual sticks are touched
513
-
515
+ * - Rendered as a full-viewport HTML/SVG overlay, so controls may sit outside the game canvas
514
516
  * @type {boolean}
515
517
  * @default
516
518
  * @memberof Settings */
517
519
  export let touchGamepadEnable: boolean;
518
- /** True if touch gamepad should have start button in the center
519
- * - Prevents activating within 2*touchGamepadSize of the virtual stick or face buttons
520
- * (one radius for the visible control + one radius of buffer beyond its edge)
520
+ /** True if touches outside the gamepad controls should still drive mouse/touch input
521
+ * - When false (the default), enabling the touch gamepad suppresses touch-to-mouse input entirely
522
+ * - Set true to also pass touches outside the controls through to the game as mouse/touch input
523
+ * - Touches on the gamepad controls never drive the mouse regardless of this setting
524
+ * @type {boolean}
525
+ * @default
526
+ * @memberof Settings */
527
+ export let touchGamepadPassthrough: boolean;
528
+ /** Size of center button if touch gamepad should have start button in the center
529
+ * - Prevents activating when pressed near virtual stick or face buttons
521
530
  * - When the game is paused, any touch will press the button
522
- * - Set size to enable the center button
531
+ * - Measured in viewport CSS pixels
523
532
  * @type {number}
524
533
  * @default
525
534
  * @memberof Settings */
526
535
  export let touchGamepadCenterButtonSize: number;
527
- /** Number of buttons on touch gamepad (0-4), if 1 also acts as right analog stick
536
+ /** Number of buttons on the right side of the touch gamepad (0-4), using gamepad buttons 0-3
537
+ * - A count of 1 is a single large button (the size of a stick)
538
+ * - Ignored when touchGamepadRightStick is set (the right side is a stick instead)
528
539
  * @type {number}
529
540
  * @default
530
541
  * @memberof Settings */
531
542
  export let touchGamepadButtonCount: number;
543
+ /** True if the touch gamepad should have a left analog stick (or dpad)
544
+ * - When false, the left side is face buttons (touchGamepadLeftButtonCount) or nothing
545
+ * @type {boolean}
546
+ * @default
547
+ * @memberof Settings */
548
+ export let touchGamepadLeftStick: boolean;
549
+ /** Number of buttons on the left side of the touch gamepad (0-4), using gamepad buttons 4-7
550
+ * - Only used when touchGamepadLeftStick is false (otherwise the left side is a stick)
551
+ * - A count of 1 is a single large button (the size of a stick)
552
+ * @type {number}
553
+ * @default
554
+ * @memberof Settings */
555
+ export let touchGamepadLeftButtonCount: number;
556
+ /** True if the touch gamepad right side should be an analog stick (or dpad) instead of face buttons
557
+ * - When set, touchGamepadButtonCount is ignored and the right side is a stick
558
+ * - Uses an analog stick when touchGamepadAnalog is true, otherwise an 8 way dpad
559
+ * @type {boolean}
560
+ * @default
561
+ * @memberof Settings */
562
+ export let touchGamepadRightStick: boolean;
532
563
  /** True if touch gamepad should be analog stick or false to use if 8 way dpad
533
564
  * @type {boolean}
534
565
  * @default
535
566
  * @memberof Settings */
536
567
  export let touchGamepadAnalog: boolean;
537
- /** Size of virtual gamepad for touch devices in pixels
568
+ /** True if touch gamepad directional controls should float to where you press
569
+ * - Only affects analog sticks and dpads, not face buttons
570
+ * - Directional controls re-anchor to where you press within the bottom ~60% of their screen half; the top ~40% passes through to the game
571
+ * - The right side floats only when it acts as the right analog stick (touchGamepadRightStick is set)
572
+ * - A center button (touchGamepadCenterButtonSize) still works since it ignores touches near the sticks
573
+ * @type {boolean}
574
+ * @default
575
+ * @memberof Settings */
576
+ export let touchGamepadFloating: boolean;
577
+ /** Size of virtual gamepad for touch devices in viewport CSS pixels
538
578
  * @type {number}
539
579
  * @default
540
580
  * @memberof Settings */
@@ -549,6 +589,12 @@ declare module "littlejsengine" {
549
589
  * @default
550
590
  * @memberof Settings */
551
591
  export let touchGamepadDisplayTime: number;
592
+ /** Duration in ms to vibrate when a touch gamepad face button or start button is pressed
593
+ * - Set to 0 to disable, also requires vibrateEnable and hardware support (ignored on iOS)
594
+ * @type {number}
595
+ * @default
596
+ * @memberof Settings */
597
+ export let touchGamepadVibration: number;
552
598
  /** Allow vibration hardware if it exists
553
599
  * @type {boolean}
554
600
  * @default
@@ -622,6 +668,7 @@ declare module "littlejsengine" {
622
668
  * @memberof Settings */
623
669
  export function setCanvasPixelated(pixelated: boolean): void;
624
670
  /** Disables texture filtering for crisper pixel art
671
+ * - Leave true for pixel art; set false for smooth/high-resolution art
625
672
  * @param {boolean} pixelated
626
673
  * @memberof Settings */
627
674
  export function setTilesPixelated(pixelated: boolean): void;
@@ -718,20 +765,41 @@ declare module "littlejsengine" {
718
765
  * @param {boolean} enable
719
766
  * @memberof Settings */
720
767
  export function setTouchGamepadEnable(enable: boolean): void;
768
+ /** Set if touches outside the gamepad controls should still drive mouse/touch input
769
+ * @param {boolean} passthrough
770
+ * @memberof Settings */
771
+ export function setTouchGamepadPassthrough(passthrough: boolean): void;
721
772
  /** Set if touch gamepad should have start button in the center
722
773
  * - Set size to enable the center button
723
774
  * - When the game is paused, any touch will press the button
724
775
  * @param {number} size
725
776
  * @memberof Settings */
726
777
  export function setTouchGamepadCenterButtonSize(size: number): void;
727
- /** Set number of buttons on touch gamepad (0-4), if 1 also acts as right analog stick
778
+ /** Set number of buttons on the right side of the touch gamepad (0-4, gamepad buttons 0-3)
728
779
  * @param {number} count
729
780
  * @memberof Settings */
730
781
  export function setTouchGamepadButtonCount(count: number): void;
782
+ /** Set if the touch gamepad should have a left analog stick (or dpad)
783
+ * @param {boolean} enable
784
+ * @memberof Settings */
785
+ export function setTouchGamepadLeftStick(enable: boolean): void;
786
+ /** Set number of buttons on the left side of the touch gamepad (0-4, gamepad buttons 4-7)
787
+ * - Only used when touchGamepadLeftStick is false
788
+ * @param {number} count
789
+ * @memberof Settings */
790
+ export function setTouchGamepadLeftButtonCount(count: number): void;
791
+ /** Set if the touch gamepad right side is an analog stick (or dpad) instead of face buttons
792
+ * @param {boolean} rightStick
793
+ * @memberof Settings */
794
+ export function setTouchGamepadRightStick(rightStick: boolean): void;
731
795
  /** Set if touch gamepad should be analog stick or 8 way dpad
732
796
  * @param {boolean} analog
733
797
  * @memberof Settings */
734
798
  export function setTouchGamepadAnalog(analog: boolean): void;
799
+ /** Set if touch gamepad directional controls should float to where you press
800
+ * @param {boolean} floating
801
+ * @memberof Settings */
802
+ export function setTouchGamepadFloating(floating: boolean): void;
735
803
  /** Set size of virtual gamepad for touch devices in pixels
736
804
  * @param {number} size
737
805
  * @memberof Settings */
@@ -744,6 +812,10 @@ declare module "littlejsengine" {
744
812
  * @param {number} time
745
813
  * @memberof Settings */
746
814
  export function setTouchGamepadDisplayTime(time: number): void;
815
+ /** Set duration in ms to vibrate when a touch gamepad face or start button is pressed (0 disables)
816
+ * @param {number} ms
817
+ * @memberof Settings */
818
+ export function setTouchGamepadVibration(ms: number): void;
747
819
  /** Set to allow vibration hardware if it exists
748
820
  * @param {boolean} enable
749
821
  * @memberof Settings */
@@ -1316,9 +1388,17 @@ declare module "littlejsengine" {
1316
1388
  * @param {Color} c - other color
1317
1389
  * @return {Color} */
1318
1390
  setFrom(c: Color): Color;
1391
+ /** Sets the alpha of this color and returns self
1392
+ * @param {number} [a] - alpha
1393
+ * @return {Color} */
1394
+ setAlpha(a?: number): Color;
1319
1395
  /** Returns a new color that is a copy of this
1320
1396
  * @return {Color} */
1321
1397
  copy(): Color;
1398
+ /** Returns a copy of this color with the alpha set
1399
+ * @param {number} [a] - alpha
1400
+ * @return {Color} */
1401
+ withAlpha(a?: number): Color;
1322
1402
  /** Returns a copy of this color plus the color passed in
1323
1403
  * @param {Color} c - other color
1324
1404
  * @return {Color} */
@@ -1889,7 +1969,10 @@ declare module "littlejsengine" {
1889
1969
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} context
1890
1970
  * @memberof Draw
1891
1971
  */
1892
- /** Draw directly to a 2d canvas context in world space
1972
+ /** Draw directly to a 2d canvas context in world space.
1973
+ * The Y axis is flipped so world-Y-up coordinates render right-side up
1974
+ * (matches the WebGL path). Callers whose drawing depends on Y direction
1975
+ * (e.g. linear gradients) should flip their own Y endpoints accordingly.
1893
1976
  * @param {Vector2} pos
1894
1977
  * @param {Vector2} size
1895
1978
  * @param {number} angle
@@ -1931,11 +2014,10 @@ declare module "littlejsengine" {
1931
2014
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=drawContext]
1932
2015
  * @memberof Draw */
1933
2016
  export function drawTextScreen(text: string | number, pos: Vector2, size: number, color?: Color, lineWidth?: number, lineColor?: Color, textAlign?: CanvasTextAlign, font?: string, fontStyle?: string, maxWidth?: number, angle?: number, context?: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D): void;
1934
- /** Enable normal or additive blend mode
2017
+ /** Enable additive blending
1935
2018
  * @param {boolean} [additive]
1936
- * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
1937
2019
  * @memberof Draw */
1938
- export function setBlendMode(additive?: boolean, context?: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D): void;
2020
+ export function setAdditiveBlendMode(additive?: boolean): void;
1939
2021
  /** Combines LittleJS canvases onto the main canvas
1940
2022
  * This is necessary for things like screenshots and video
1941
2023
  * @memberof Draw */
@@ -2002,6 +2084,19 @@ declare module "littlejsengine" {
2002
2084
  * @return {Vector2}
2003
2085
  * @memberof Draw */
2004
2086
  export function getCameraSize(): Vector2;
2087
+ /** Fit the camera to a rectangle in world space by setting cameraPos and cameraScale
2088
+ * - worldMargin pads the content rectangle in world units, so the gap scales with the content on resize
2089
+ * - screenInset reserves space in screen pixels on each viewport edge (for example a HUD band) and
2090
+ * re-centers the content away from that edge, so the reserved band stays a fixed pixel size on resize
2091
+ * - worldMargin and screenInset may each be a number for all sides, a Vector2 (x=left/right, y=top/bottom),
2092
+ * or an object with any of {top, right, bottom, left}
2093
+ * @param {Vector2} center - Center of the rectangle in world space
2094
+ * @param {Vector2} size - Size of the rectangle in world space
2095
+ * @param {number|Vector2|Object} [worldMargin] - World space padding added around the content rectangle
2096
+ * @param {number|Vector2|Object} [screenInset] - Screen space padding in pixels reserved on each viewport edge
2097
+ * @return {number} - The new camera scale
2098
+ * @memberof Draw */
2099
+ export function cameraFit(center: Vector2, size: Vector2, worldMargin?: number | Vector2 | any, screenInset?: number | Vector2 | any): number;
2005
2100
  /** Check if a box, point, or circle is on screen with a circle test
2006
2101
  * If size is a Vector2, uses the length as diameter
2007
2102
  * This can be used to cull offscreen objects from render or update
@@ -2253,10 +2348,27 @@ declare module "littlejsengine" {
2253
2348
  * @type {boolean}
2254
2349
  * @memberof Input */
2255
2350
  export let mouseInWindow: boolean;
2256
- /** Returns true if user is using gamepad (has more recently pressed a gamepad button)
2351
+ /** True if a gamepad is the most recently used input device.
2352
+ * Equivalent to usingGamepadInput(); derived from lastInputDevice each frame.
2257
2353
  * @type {boolean}
2258
2354
  * @memberof Input */
2259
2355
  export let isUsingGamepad: boolean;
2356
+ /** The most recently used input device: 'mouse' | 'keyboard' | 'gamepad'.
2357
+ * Sticky: it holds its value while every device is idle, so a mouse-follow
2358
+ * control (e.g. paddle = mousePos) won't snap back the instant the stick/keys
2359
+ * are released. With several devices in play at once (e.g. keyboard to move +
2360
+ * mouse to aim) it tracks whichever was touched last each frame, so it may
2361
+ * alternate — that's intended; use it to pick which control drives a shared
2362
+ * action. Updated every frame by inputUpdate().
2363
+ * @type {string}
2364
+ * @memberof Input */
2365
+ export let lastInputDevice: string;
2366
+ /** Screen-pixel mouse movement per frame that counts as "using the mouse"
2367
+ * (so sub-pixel hand jitter doesn't steal focus from the keyboard/gamepad).
2368
+ * @type {number}
2369
+ * @default
2370
+ * @memberof Input */
2371
+ export let inputMouseMoveThreshold: number;
2260
2372
  /** Prevents input continuing to the default browser handling (true by default)
2261
2373
  * @type {boolean}
2262
2374
  * @memberof Input */
@@ -2273,6 +2385,16 @@ declare module "littlejsengine" {
2273
2385
  * @param {boolean} preventDefault
2274
2386
  * @memberof Input */
2275
2387
  export function setInputPreventDefault(preventDefault?: boolean): void;
2388
+ /** Set the screen-pixel mouse movement per frame that counts as using the mouse
2389
+ * @param {number} threshold
2390
+ * @memberof Input */
2391
+ export function setInputMouseMoveThreshold(threshold: number): void;
2392
+ /** @return {boolean} - Is the mouse the most recently used input device? @memberof Input */
2393
+ export function usingMouseInput(): boolean;
2394
+ /** @return {boolean} - Is the keyboard the most recently used input device? @memberof Input */
2395
+ export function usingKeyboardInput(): boolean;
2396
+ /** @return {boolean} - Is a gamepad the most recently used input device? @memberof Input */
2397
+ export function usingGamepadInput(): boolean;
2276
2398
  /** Returns true if gamepad button is down
2277
2399
  * @param {number} button
2278
2400
  * @param {number} [gamepad]
@@ -2424,7 +2546,7 @@ declare module "littlejsengine" {
2424
2546
  * @param {number} [randomnessScale] - How much to scale pitch randomness
2425
2547
  * @param {boolean} [loop] - Should the sound loop?
2426
2548
  * @param {boolean} [paused] - Should the sound start paused
2427
- * @return {SoundInstance} - The audio source node
2549
+ * @return {SoundInstance} - The sound instance, or undefined if sound is disabled, not loaded, or running in headless mode
2428
2550
  */
2429
2551
  play(pos?: Vector2, volume?: number, pitch?: number, randomnessScale?: number, loop?: boolean, paused?: boolean): SoundInstance;
2430
2552
  /** Play a music track that loops by default
@@ -2712,6 +2834,8 @@ declare module "littlejsengine" {
2712
2834
  update(): void;
2713
2835
  /** Render the object, draws a tile by default, automatically called each frame, sorted by renderOrder */
2714
2836
  render(): void;
2837
+ /** Optional hook called during the light system plugin's lightmap pass to draw this object's lightmap contribution. Does nothing by default. */
2838
+ renderLight(): void;
2715
2839
  /** Destroy this object, destroy its children, detach its parent, and mark it for removal
2716
2840
  * @param {boolean} [immediate] - should attached effects be allowed to die off? */
2717
2841
  destroy(immediate?: boolean): void;
@@ -3121,10 +3245,10 @@ declare module "littlejsengine" {
3121
3245
  * @param {number} [particleTime] - How long particles live
3122
3246
  * @param {number} [sizeStart] - How big are particles at start
3123
3247
  * @param {number} [sizeEnd] - How big are particles at end
3124
- * @param {number} [speed] - How fast are particles when spawned
3125
- * @param {number} [angleSpeed] - How fast are particles rotating
3126
- * @param {number} [damping] - How much to dampen particle speed
3127
- * @param {number} [angleDamping] - How much to dampen particle angular speed
3248
+ * @param {number} [speed] - How fast are particles when spawned, in world units per frame (at 60fps, so multiply units/sec by 1/60)
3249
+ * @param {number} [angleSpeed] - How fast are particles rotating, in radians per frame (at 60fps)
3250
+ * @param {number} [damping] - How much to dampen particle speed, per-frame velocity multiplier (1 = no damping, .9 = lose 10% speed each frame)
3251
+ * @param {number} [angleDamping] - How much to dampen particle angular speed, per-frame multiplier (1 = no damping)
3128
3252
  * @param {number} [gravityScale] - How much gravity effect particles
3129
3253
  * @param {number} [particleConeAngle] - Cone for start particle angle
3130
3254
  * @param {number} [fadeRate] - Fraction of life spent fading: half at fade-in (start), half at fade-out (end). e.g. .2 = 10% fade-in, 80% full opacity, 10% fade-out
@@ -3162,9 +3286,9 @@ declare module "littlejsengine" {
3162
3286
  sizeStart: number;
3163
3287
  /** @property {number} - How big are particles at end */
3164
3288
  sizeEnd: number;
3165
- /** @property {number} - How fast are particles when spawned */
3289
+ /** @property {number} - Particle speed when spawned, in world units per frame (at 60fps) */
3166
3290
  speed: number;
3167
- /** @property {number} - How fast are particles rotating */
3291
+ /** @property {number} - Particle angular speed when spawned, in radians per frame (at 60fps) */
3168
3292
  angleSpeed: number;
3169
3293
  /** @property {number} - Cone for start particle angle */
3170
3294
  particleConeAngle: number;
@@ -3298,6 +3422,9 @@ declare module "littlejsengine" {
3298
3422
  * @param {MedalCallbackFunction} callback
3299
3423
  * @memberof Medals */
3300
3424
  export function medalsForEach(callback: MedalCallbackFunction): void;
3425
+ /** Reset all medals to locked and persist the cleared catalog
3426
+ * @memberof Medals */
3427
+ export function medalsReset(): void;
3301
3428
  /** Set how long to show medals for in seconds
3302
3429
  * @param {number} time
3303
3430
  * @memberof Settings */
@@ -3359,7 +3486,6 @@ declare module "littlejsengine" {
3359
3486
  * @param {number} size - Screen space size
3360
3487
  */
3361
3488
  renderIcon(pos: Vector2, size: number): void;
3362
- storageKey(): string;
3363
3489
  }
3364
3490
  /**
3365
3491
  * LittleJS Newgrounds Plugin
@@ -3466,6 +3592,85 @@ declare module "littlejsengine" {
3466
3592
  /** @property {WebGLVertexArrayObject} - Vertex array object */
3467
3593
  vao: any;
3468
3594
  }
3595
+ /**
3596
+ * LittleJS Light System Plugin
3597
+ * - Adds 2D dynamic lighting to the scene
3598
+ * - Lights are first-class EngineObjects (the Light class)
3599
+ * - Each Light draws a soft falloff blob of its color into a shared lightmap
3600
+ * - Lights accumulate ADDITIVELY in the lightmap (red + blue = magenta)
3601
+ * - The lightmap is then MULTIPLIED with the scene during composite, so unlit
3602
+ * areas go to the ambient color and lit areas show the scene tinted by the
3603
+ * accumulated light color
3604
+ * - Draw the world at full brightness — the lightmap does the darkening
3605
+ * - Any EngineObject may override renderLight() to additively contribute to the
3606
+ * lightmap (e.g. emissive lava tiles, weapon flashes, glowing crystals)
3607
+ * - Must be constructed BEFORE PostProcessPlugin so post-process sees lit pixels
3608
+ * @namespace LightSystem
3609
+ */
3610
+ /** Global Light System plugin object
3611
+ * @type {LightSystemPlugin}
3612
+ * @memberof LightSystem */
3613
+ export let lightSystem: LightSystemPlugin;
3614
+ /**
3615
+ * LightSystemPlugin
3616
+ * - Owns the offscreen lightmap texture, falloff/composite shaders, and the
3617
+ * per-frame render pass that multiplies the lightmap onto the WebGL scene
3618
+ * - The composite is MULTIPLICATIVE: unlit areas get the ambient color, lit
3619
+ * areas show the scene tinted by the accumulated light color. So you should
3620
+ * draw your world at full brightness — the lightmap handles the darkening.
3621
+ * @memberof LightSystem
3622
+ */
3623
+ export class LightSystemPlugin {
3624
+ /** Create the global light system plugin.
3625
+ * @param {Vector2} [textureSize] - Size of the lightmap texture (defaults to mainCanvasSize)
3626
+ * @param {Color} [ambientColor] - Color applied to unlit areas of the scene (defaults to BLACK = pitch dark). Set a small RGB like rgb(0.1,0.1,0.15) for a faint "moonlight" baseline so unlit areas aren't fully black.
3627
+ * @example
3628
+ * // simplest usage
3629
+ * new LightSystemPlugin();
3630
+ */
3631
+ constructor(textureSize?: Vector2, ambientColor?: Color);
3632
+ /** @property {boolean} - When false, the render pass is skipped entirely */
3633
+ enabled: boolean;
3634
+ /** @property {Color} - Baseline color applied to unlit areas of the scene. Defaults to BLACK (pitch dark). Set to a small RGB for a faint ambient. The lightmap is cleared to this color each frame, then lights add on top, then the result multiplies the scene. */
3635
+ ambientColor: Color;
3636
+ /** @property {Vector2} - Size of the lightmap texture (set at construction; falls back to mainCanvasSize at init time) */
3637
+ textureSize: Vector2;
3638
+ /** @property {WebGLTexture} - The lightmap texture */
3639
+ texture: any;
3640
+ /** @property {WebGLProgram} - Shader for drawing per-Light falloff blobs into the lightmap */
3641
+ lightShader: any;
3642
+ /** @property {WebGLProgram} - Shader for compositing the lightmap over the main scene */
3643
+ compositeShader: any;
3644
+ /** @property {WebGLVertexArrayObject} - Vertex array object for the light shader */
3645
+ lightVAO: any;
3646
+ /** @property {WebGLVertexArrayObject} - Vertex array object for the composite shader */
3647
+ compositeVAO: any;
3648
+ /** Draw a single Light's falloff blob into the currently bound lightmap.
3649
+ * Called by Light.renderLight() during the plugin's render pass.
3650
+ * @param {Light} light */
3651
+ drawLight(light: Light): void;
3652
+ }
3653
+ /**
3654
+ * A Light is an EngineObject that contributes a soft additive blob of color
3655
+ * to the LightSystem plugin's lightmap.
3656
+ * @extends EngineObject
3657
+ * @memberof LightSystem
3658
+ * @example
3659
+ * new Light(vec2(5, 5), 4, rgb(1, 0.5, 0)); // orange light, full soft blob
3660
+ * new Light(vec2(0, 0), 8, rgb(1, 1, 1), 2); // white core with 2-unit soft halo
3661
+ */
3662
+ export class Light extends EngineObject {
3663
+ /** Create a light object and add it to the engine object list
3664
+ * @param {Vector2} pos - World space position
3665
+ * @param {number} radius - Total extent of the light in world units
3666
+ * @param {Color} [color] - Color of the light; alpha modulates intensity
3667
+ * @param {number} [fadeRange] - Width of the soft edge in world units (defaults to radius) */
3668
+ constructor(pos: Vector2, radius: number, color?: Color, fadeRange?: number);
3669
+ /** @property {number} - Total extent of the light in world units */
3670
+ radius: number;
3671
+ /** @property {number} - Width of the soft edge in world units */
3672
+ fadeRange: number;
3673
+ }
3469
3674
  /**
3470
3675
  * LittleJS ZzFXM Plugin
3471
3676
  * @namespace ZzFXM
@@ -3730,10 +3935,15 @@ declare module "littlejsengine" {
3730
3935
  * @param {Vector2} [size=vec2(1)]
3731
3936
  */
3732
3937
  constructor(pos?: Vector2, size?: Vector2);
3733
- /** @property {Vector2} - Local position of the object */
3938
+ /** @property {Vector2} - Position you set: an offset from this object's
3939
+ * anchor point (the parent box, or the canvas for roots). This is the
3940
+ * input that controls placement — set this, not nativePos. */
3734
3941
  localPos: Vector2;
3735
- /** @property {Vector2} - Screen space position of the object */
3736
- pos: Vector2;
3942
+ /** @property {Vector2} - Resolved position in native UI space, recomputed
3943
+ * every frame from localPos + anchor (and nativeHeight, if set). This is a
3944
+ * derived output used for drawing and hit-testing; assigning to it has no
3945
+ * effect since it is overwritten each frame. Set localPos instead. */
3946
+ nativePos: Vector2;
3737
3947
  /** @property {Vector2} - Screen space size of the object */
3738
3948
  size: Vector2;
3739
3949
  /** @property {Color} - Color of the object */
@@ -5060,11 +5270,16 @@ declare module "littlejsengine" {
5060
5270
  }
5061
5271
  /** Draw a scalable nine-slice UI element in world space
5062
5272
  * This function can apply color and additive color if WebGL is enabled
5273
+ * The nine-slice samples a 3x3 block of tiles from the tilesheet, it does not
5274
+ * subdivide a single tile. Pass the top-left tile of that block as startTile;
5275
+ * the other 8 tiles (edges, corners, and center) are taken automatically from
5276
+ * the 3x3 grid of tiles extending right and down from it. borderSize only sets
5277
+ * the rendered thickness of the edges and corners, not how the texture is cut.
5063
5278
  * @param {Vector2} pos - World space position
5064
5279
  * @param {Vector2} size - World space size
5065
- * @param {TileInfo} startTile - Starting tile for the nine-slice pattern
5280
+ * @param {TileInfo} startTile - Top-left tile of the 3x3 block to sample the nine-slice from
5066
5281
  * @param {Color} [color] - Color to modulate with
5067
- * @param {number} [borderSize] - Width of the border sections
5282
+ * @param {number} [borderSize] - Rendered thickness of the border sections
5068
5283
  * @param {Color} [additiveColor] - Additive color
5069
5284
  * @param {number} [extraSpace] - Extra spacing adjustment
5070
5285
  * @param {number} [angle] - Angle to rotate by
@@ -5083,19 +5298,23 @@ declare module "littlejsengine" {
5083
5298
  * This function can not apply color because it draws using the 2d context
5084
5299
  * @param {Vector2} pos - Screen space position
5085
5300
  * @param {Vector2} size - Screen space size
5086
- * @param {TileInfo} startTile - Starting tile for the nine-slice pattern
5087
- * @param {number} [borderSize] - Width of the border sections
5301
+ * @param {TileInfo} startTile - Top-left tile of the 3x3 block to sample (see drawNineSlice)
5302
+ * @param {number} [borderSize] - Rendered thickness of the border sections
5088
5303
  * @param {number} [extraSpace] - Extra spacing adjustment
5089
5304
  * @param {number} [angle] - Angle to rotate by
5090
5305
  * @memberof DrawUtilities */
5091
5306
  export function drawNineSliceScreen(pos: Vector2, size: Vector2, startTile: TileInfo, borderSize?: number, extraSpace?: number, angle?: number): void;
5092
5307
  /** Draw a scalable three-slice UI element in world space
5093
5308
  * This function can apply color and additive color if WebGL is enabled
5309
+ * The three-slice samples 3 consecutive tiles from the tilesheet, it does not
5310
+ * subdivide a single tile. Pass the first tile as startTile; the three tiles
5311
+ * are used in order as corner, side, and center, then rotated and mirrored to
5312
+ * build all four edges and corners. borderSize only sets the rendered thickness.
5094
5313
  * @param {Vector2} pos - World space position
5095
5314
  * @param {Vector2} size - World space size
5096
- * @param {TileInfo} startTile - Starting tile for the three-slice pattern
5315
+ * @param {TileInfo} startTile - First of 3 consecutive tiles (corner, side, center) for the three-slice
5097
5316
  * @param {Color} [color] - Color to modulate with
5098
- * @param {number} [borderSize] - Width of the border sections
5317
+ * @param {number} [borderSize] - Rendered thickness of the border sections
5099
5318
  * @param {Color} [additiveColor] - Additive color
5100
5319
  * @param {number} [extraSpace] - Extra spacing adjustment
5101
5320
  * @param {number} [angle] - Angle to rotate by
@@ -5108,12 +5327,38 @@ declare module "littlejsengine" {
5108
5327
  * This function can not apply color because it draws using the 2d context
5109
5328
  * @param {Vector2} pos - Screen space position
5110
5329
  * @param {Vector2} size - Screen space size
5111
- * @param {TileInfo} startTile - Starting tile for the three-slice pattern
5112
- * @param {number} [borderSize] - Width of the border sections
5330
+ * @param {TileInfo} startTile - First of 3 consecutive tiles: corner, side, center (see drawThreeSlice)
5331
+ * @param {number} [borderSize] - Rendered thickness of the border sections
5113
5332
  * @param {number} [extraSpace] - Extra spacing adjustment
5114
5333
  * @param {number} [angle] - Angle to rotate by
5115
5334
  * @memberof DrawUtilities */
5116
5335
  export function drawThreeSliceScreen(pos: Vector2, size: Vector2, startTile: TileInfo, borderSize?: number, extraSpace?: number, angle?: number): void;
5336
+ /** Draw a crescent / moon-phase shape built from a polygon
5337
+ * Routes through drawPoly, so it supports WebGL, screen space, color, and outlines
5338
+ * @param {Vector2} pos - Center position
5339
+ * @param {number} [size] - Diameter
5340
+ * @param {number} [percent] - Moon phase over a full cycle (0=new, .25=first quarter, .5=full, .75=last quarter), wraps
5341
+ * @param {Color} [color] - Fill color
5342
+ * @param {number} [angle] - Angle to rotate by
5343
+ * @param {boolean} [invert] - Flip which side is illuminated
5344
+ * @param {number} [lineWidth] - Outline width, 0 for no outline
5345
+ * @param {Color} [lineColor] - Outline color
5346
+ * @param {boolean} [useWebGL=glEnable] - Use WebGL for rendering
5347
+ * @param {boolean} [screenSpace] - Use screen space coordinates
5348
+ * @param {CanvasRenderingContext2D} [context] - Canvas context to use
5349
+ * @memberof DrawUtilities */
5350
+ export function drawCrescent(pos: Vector2, size?: number, percent?: number, color?: Color, angle?: number, invert?: boolean, lineWidth?: number, lineColor?: Color, useWebGL?: boolean, screenSpace?: boolean, context?: CanvasRenderingContext2D): void;
5351
+ /** Get the list of points that make up a crescent / moon-phase shape
5352
+ * Returns world-space points with pos and angle baked in, ready for drawPoly or other use
5353
+ * @param {Vector2} pos - Center position
5354
+ * @param {number} [size] - Diameter
5355
+ * @param {number} [percent] - Moon phase over a full cycle (0=new, .25=first quarter, .5=full, .75=last quarter), wraps
5356
+ * @param {number} [angle] - Angle to rotate by
5357
+ * @param {boolean} [invert] - Flip which side is illuminated
5358
+ * @param {number} [sides=glCircleSides] - Number of sides for a full circle (halved per arc)
5359
+ * @return {Array<Vector2>} - List of points making up the crescent
5360
+ * @memberof DrawUtilities */
5361
+ export function getCrescentPoints(pos: Vector2, size?: number, percent?: number, angle?: number, invert?: boolean, sides?: number): Array<Vector2>;
5117
5362
  /** A numeric tween: drives a callback with a value interpolated between
5118
5363
  * `start` and `end` over `duration` seconds. Pauses with the game by default.
5119
5364
  * @memberof TweenSystem