littlejsengine 1.18.2 → 1.18.7

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.
Files changed (172) hide show
  1. package/COPYRIGHT.txt +38 -0
  2. package/FAQ.md +633 -0
  3. package/LICENSE +5 -27
  4. package/README.md +19 -1
  5. package/dist/littlejs.d.ts +550 -57
  6. package/dist/littlejs.esm.js +2208 -492
  7. package/dist/littlejs.esm.min.js +1 -1
  8. package/dist/littlejs.js +2165 -480
  9. package/dist/littlejs.min.js +1 -1
  10. package/dist/littlejs.release.js +2166 -481
  11. package/package.json +8 -1
  12. package/plugins/box2d.js +36 -9
  13. package/{src/engineMedals.js → plugins/medalSystem.js} +248 -196
  14. package/plugins/pathFinder.js +758 -0
  15. package/plugins/pluginExport.js +26 -0
  16. package/plugins/tween.js +509 -0
  17. package/plugins/tweenSystem.js +509 -0
  18. package/plugins/uiSystem.js +151 -12
  19. package/src/engine.js +9 -145
  20. package/src/engineAudio.js +8 -5
  21. package/src/engineBuild.mjs +4 -1
  22. package/src/engineDebug.js +1 -1
  23. package/src/engineDraw.js +154 -5
  24. package/src/engineExport.js +17 -12
  25. package/src/engineInput.js +27 -1
  26. package/src/engineLogo.js +146 -0
  27. package/src/engineMath.js +10 -3
  28. package/src/engineObject.js +11 -5
  29. package/src/engineParticles.js +6 -3
  30. package/src/engineRelease.js +1 -1
  31. package/src/engineSettings.js +17 -47
  32. package/src/engineUtilities.js +7 -2
  33. package/src/engineWebGL.js +31 -8
  34. package/src/jsconfig.json +3 -1
  35. package/.claude/settings.local.json +0 -7
  36. package/.github/workflows/test.yml +0 -17
  37. package/AI.md +0 -172
  38. package/CLAUDE.md +0 -1
  39. package/examples/box2d/game.js +0 -192
  40. package/examples/box2d/gameObjects.js +0 -564
  41. package/examples/box2d/index.html +0 -9
  42. package/examples/box2d/scenes.js +0 -194
  43. package/examples/box2d/tiles.png +0 -0
  44. package/examples/breakout/game.js +0 -175
  45. package/examples/breakout/gameObjects.js +0 -147
  46. package/examples/breakout/index.html +0 -8
  47. package/examples/breakout/tiles.png +0 -0
  48. package/examples/breakoutTutorial/README.md +0 -521
  49. package/examples/breakoutTutorial/game.js +0 -191
  50. package/examples/breakoutTutorial/images/1.png +0 -0
  51. package/examples/breakoutTutorial/images/10.png +0 -0
  52. package/examples/breakoutTutorial/images/11.png +0 -0
  53. package/examples/breakoutTutorial/images/2.png +0 -0
  54. package/examples/breakoutTutorial/images/3.png +0 -0
  55. package/examples/breakoutTutorial/images/4.png +0 -0
  56. package/examples/breakoutTutorial/images/5.png +0 -0
  57. package/examples/breakoutTutorial/images/6.png +0 -0
  58. package/examples/breakoutTutorial/images/7.png +0 -0
  59. package/examples/breakoutTutorial/images/8.png +0 -0
  60. package/examples/breakoutTutorial/images/9.png +0 -0
  61. package/examples/breakoutTutorial/index.html +0 -8
  62. package/examples/electron/build.mjs +0 -127
  63. package/examples/electron/electron.js +0 -35
  64. package/examples/electron/game.js +0 -54
  65. package/examples/electron/index.html +0 -13
  66. package/examples/electron/package.json +0 -5
  67. package/examples/electron/tiles.png +0 -0
  68. package/examples/empty/game.js +0 -51
  69. package/examples/empty/index.html +0 -5
  70. package/examples/empty/tiles.png +0 -0
  71. package/examples/favicon.png +0 -0
  72. package/examples/games.jpg +0 -0
  73. package/examples/htmlMenu/game.js +0 -82
  74. package/examples/htmlMenu/index.html +0 -45
  75. package/examples/htmlMenu/tiles.png +0 -0
  76. package/examples/index.html +0 -800
  77. package/examples/logo.png +0 -0
  78. package/examples/logo2.png +0 -0
  79. package/examples/module/build.mjs +0 -124
  80. package/examples/module/game.js +0 -132
  81. package/examples/module/index.html +0 -10
  82. package/examples/module/tiles.png +0 -0
  83. package/examples/particles/index.html +0 -426
  84. package/examples/particles/tiles.png +0 -0
  85. package/examples/platformer/data/gameLevelData.tmx +0 -143
  86. package/examples/platformer/data/gameLevelData.tsx +0 -4
  87. package/examples/platformer/game.js +0 -147
  88. package/examples/platformer/gameCharacter.js +0 -309
  89. package/examples/platformer/gameEffects.js +0 -278
  90. package/examples/platformer/gameLevel.js +0 -205
  91. package/examples/platformer/gameLevelData.json +0 -171
  92. package/examples/platformer/gameObjects.js +0 -378
  93. package/examples/platformer/gamePlayer.js +0 -35
  94. package/examples/platformer/index.html +0 -9
  95. package/examples/platformer/tiles.png +0 -0
  96. package/examples/platformer/tilesLevel.png +0 -0
  97. package/examples/puzzle/game.js +0 -331
  98. package/examples/puzzle/index.html +0 -8
  99. package/examples/puzzle/tiles.png +0 -0
  100. package/examples/screenshot.jpg +0 -0
  101. package/examples/shorts/animation.js +0 -18
  102. package/examples/shorts/base.html +0 -54
  103. package/examples/shorts/blending.js +0 -14
  104. package/examples/shorts/box2d.js +0 -51
  105. package/examples/shorts/box2dCar.js +0 -59
  106. package/examples/shorts/box2dPool.js +0 -107
  107. package/examples/shorts/box2dTileLayer.js +0 -48
  108. package/examples/shorts/cameraDrag.js +0 -22
  109. package/examples/shorts/clock.js +0 -21
  110. package/examples/shorts/colors.js +0 -25
  111. package/examples/shorts/debugDraw.js +0 -37
  112. package/examples/shorts/empty.js +0 -30
  113. package/examples/shorts/flappyGame.js +0 -55
  114. package/examples/shorts/fontImage.js +0 -17
  115. package/examples/shorts/fps.js +0 -90
  116. package/examples/shorts/helloWorld.js +0 -11
  117. package/examples/shorts/hillGlideGame.js +0 -63
  118. package/examples/shorts/input.js +0 -64
  119. package/examples/shorts/landerGame.js +0 -57
  120. package/examples/shorts/maze.js +0 -48
  121. package/examples/shorts/medals.js +0 -51
  122. package/examples/shorts/music.js +0 -78
  123. package/examples/shorts/musicPlayer.js +0 -137
  124. package/examples/shorts/nineSlice.js +0 -40
  125. package/examples/shorts/parallax.js +0 -72
  126. package/examples/shorts/particles.js +0 -28
  127. package/examples/shorts/piano.js +0 -44
  128. package/examples/shorts/platformer.js +0 -45
  129. package/examples/shorts/pongGame.js +0 -41
  130. package/examples/shorts/postProcess.js +0 -62
  131. package/examples/shorts/sequencer.js +0 -124
  132. package/examples/shorts/shader.js +0 -29
  133. package/examples/shorts/shapes.js +0 -21
  134. package/examples/shorts/slidingPuzzle.js +0 -52
  135. package/examples/shorts/song.mp3 +0 -0
  136. package/examples/shorts/sound.js +0 -36
  137. package/examples/shorts/spaceGame.js +0 -58
  138. package/examples/shorts/spriteAtlas.js +0 -31
  139. package/examples/shorts/starfield.js +0 -15
  140. package/examples/shorts/texture.js +0 -16
  141. package/examples/shorts/tileLayer.js +0 -48
  142. package/examples/shorts/tileRaycast.js +0 -39
  143. package/examples/shorts/tiles.png +0 -0
  144. package/examples/shorts/tiltedView.js +0 -63
  145. package/examples/shorts/timers.js +0 -53
  146. package/examples/shorts/topDown.js +0 -38
  147. package/examples/shorts/uiSystem.js +0 -61
  148. package/examples/shorts/video.webm +0 -0
  149. package/examples/shorts/videoPlayer.js +0 -34
  150. package/examples/starter/build.bat +0 -7
  151. package/examples/starter/build.mjs +0 -126
  152. package/examples/starter/game.js +0 -137
  153. package/examples/starter/index.html +0 -35
  154. package/examples/starter/tiles.png +0 -0
  155. package/examples/stress/index.html +0 -173
  156. package/examples/style.css +0 -150
  157. package/examples/typescript/build.mjs +0 -60
  158. package/examples/typescript/game.js +0 -100
  159. package/examples/typescript/game.ts +0 -132
  160. package/examples/typescript/index.html +0 -10
  161. package/examples/typescript/tiles.png +0 -0
  162. package/examples/typescript/tsconfig.json +0 -17
  163. package/examples/uiSystem/game.js +0 -139
  164. package/examples/uiSystem/index.html +0 -10
  165. package/examples/uiSystem/tiles.png +0 -0
  166. package/jsconfig.json +0 -12
  167. package/plugins/desktop.ini +0 -2
  168. package/reference.md +0 -447
  169. package/test/math.test.mjs +0 -774
  170. package/test/setup.mjs +0 -22
  171. package/test/smoke.test.mjs +0 -258
  172. package/test/util.test.mjs +0 -80
@@ -88,6 +88,10 @@ declare module "littlejsengine" {
88
88
  * @type {Array<EngineObject>}
89
89
  * @memberof Engine */
90
90
  export let engineObjects: Array<EngineObject>;
91
+ /** Array with only objects set to collide with other objects this frame (for optimization)
92
+ * @type {Array<EngineObject>}
93
+ * @memberof Engine */
94
+ export let engineObjectsCollide: Array<EngineObject>;
91
95
  /** Current update frame, used to calculate time
92
96
  * @type {number}
93
97
  * @memberof Engine */
@@ -96,7 +100,7 @@ declare module "littlejsengine" {
96
100
  * @type {number}
97
101
  * @memberof Engine */
98
102
  export let time: number;
99
- /** Actual clock time since start in seconds (not affected by pause or frame rate clamping)
103
+ /** Actual clock time since start in seconds (not affected by pause, timescale, or frame rate clamping)
100
104
  * @type {number}
101
105
  * @memberof Engine */
102
106
  export let timeReal: number;
@@ -226,6 +230,11 @@ declare module "littlejsengine" {
226
230
  * @param {...Object} output - message output
227
231
  * @memberof Debug */
228
232
  export function LOG(...output: any[]): void;
233
+ /** Size to render debug points by default
234
+ * @type {number}
235
+ * @default
236
+ * @memberof Debug */
237
+ export const debugPointSize: number;
229
238
  /** Draw a debug rectangle in world space
230
239
  * @param {Vector2} pos
231
240
  * @param {Vector2} [size=vec2(0)]
@@ -333,6 +342,14 @@ declare module "littlejsengine" {
333
342
  * @default
334
343
  * @memberof Settings */
335
344
  export let cameraScale: number;
345
+ /** Scale applied to engine time, can be used for slow motion or fast forward
346
+ * - 1 is normal speed, 2 is double speed, 0.5 is half speed
347
+ * - 0 freezes the simulation without setting the paused flag
348
+ * - Should be >= 0; stacks multiplicatively with the debug +/- shortcut
349
+ * @type {number}
350
+ * @default
351
+ * @memberof Settings */
352
+ export let timeScale: number;
336
353
  /** Enable applying color to tiles when using canvas2d
337
354
  * - This is slower but should be the same as WebGL rendering
338
355
  * @type {boolean}
@@ -463,6 +480,11 @@ declare module "littlejsengine" {
463
480
  * @default
464
481
  * @memberof Settings */
465
482
  export let glEnable: boolean;
483
+ /** How many sided poly to use when drawing circles and ellipses with WebGL
484
+ * @type {number}
485
+ * @default
486
+ * @memberof Settings */
487
+ export let glCircleSides: number;
466
488
  /** Should gamepads be allowed
467
489
  * @type {boolean}
468
490
  * @default
@@ -478,6 +500,12 @@ declare module "littlejsengine" {
478
500
  * @default
479
501
  * @memberof Settings */
480
502
  export let inputWASDEmulateDirection: boolean;
503
+ /** True if touch input is enabled for mobile devices
504
+ * - Touch events will be routed to mouse events
505
+ * @type {boolean}
506
+ * @default
507
+ * @memberof Settings */
508
+ export let touchInputEnable: boolean;
481
509
  /** True if touch gamepad should appear on mobile devices
482
510
  * - Supports left analog stick, 4 face buttons and start button (button 9)
483
511
  * - setTouchGamepadButtonCount(1) to use face buttons as right analog stick
@@ -495,6 +523,11 @@ declare module "littlejsengine" {
495
523
  * @default
496
524
  * @memberof Settings */
497
525
  export let touchGamepadCenterButtonSize: number;
526
+ /** Number of buttons on touch gamepad (0-4), if 1 also acts as right analog stick
527
+ * @type {number}
528
+ * @default
529
+ * @memberof Settings */
530
+ export let touchGamepadButtonCount: number;
498
531
  /** True if touch gamepad should be analog stick or false to use if 8 way dpad
499
532
  * @type {boolean}
500
533
  * @default
@@ -540,21 +573,6 @@ declare module "littlejsengine" {
540
573
  * @default
541
574
  * @memberof Settings */
542
575
  export let soundDefaultTaper: number;
543
- /** How long to show medals for in seconds
544
- * @type {number}
545
- * @default
546
- * @memberof Settings */
547
- export let medalDisplayTime: number;
548
- /** How quickly to slide on/off medals in seconds
549
- * @type {number}
550
- * @default
551
- * @memberof Settings */
552
- export let medalDisplaySlideTime: number;
553
- /** Size of medal display
554
- * @type {Vector2}
555
- * @default Vector2(640,80)
556
- * @memberof Settings */
557
- export let medalDisplaySize: Vector2;
558
576
  /** Set position of camera in world space
559
577
  * @param {Vector2} pos
560
578
  * @memberof Settings */
@@ -567,6 +585,10 @@ declare module "littlejsengine" {
567
585
  * @param {number} scale
568
586
  * @memberof Settings */
569
587
  export function setCameraScale(scale: number): void;
588
+ /** Set scale applied to engine time
589
+ * @param {number} scale
590
+ * @memberof Settings */
591
+ export function setTimeScale(scale: number): void;
570
592
  /** Set if tiles should be colorized when using canvas2d
571
593
  * This can be slower but results should look nearly identical to WebGL rendering
572
594
  * It can be enabled/disabled at any time
@@ -671,6 +693,10 @@ declare module "littlejsengine" {
671
693
  * @param {number} scale
672
694
  * @memberof Settings */
673
695
  export function setParticleEmitRateScale(scale: number): void;
696
+ /** Set how many sided polygons to use when drawing circles and ellipses with WebGL
697
+ * @param {number} sides
698
+ * @memberof Settings */
699
+ export function setGLCircleSides(sides: number): void;
674
700
  /** Set if touch input is allowed
675
701
  * @param {boolean} enable
676
702
  * @memberof Settings */
@@ -733,22 +759,6 @@ declare module "littlejsengine" {
733
759
  * @param {number} taper
734
760
  * @memberof Settings */
735
761
  export function setSoundDefaultTaper(taper: number): void;
736
- /** Set how long to show medals for in seconds
737
- * @param {number} time
738
- * @memberof Settings */
739
- export function setMedalDisplayTime(time: number): void;
740
- /** Set how quickly to slide on/off medals in seconds
741
- * @param {number} time
742
- * @memberof Settings */
743
- export function setMedalDisplaySlideTime(time: number): void;
744
- /** Set size of medal display
745
- * @param {Vector2} size
746
- * @memberof Settings */
747
- export function setMedalDisplaySize(size: Vector2): void;
748
- /** Set to stop medals from being unlockable
749
- * @param {boolean} preventUnlock
750
- * @memberof Settings */
751
- export function setMedalsPreventUnlock(preventUnlock: boolean): void;
752
762
  /** Set if watermark with FPS should be shown
753
763
  * @param {boolean} show
754
764
  * @memberof Debug */
@@ -811,17 +821,17 @@ declare module "littlejsengine" {
811
821
  * @param {number} x
812
822
  * @return {number}
813
823
  * @memberof Math */
814
- export const sign: (x: number) => number;
824
+ export const sign: any;
815
825
  /** Returns hypotenuse of values passed in
816
826
  * @param {...number} values
817
827
  * @return {number}
818
828
  * @memberof Math */
819
- export const hypot: (...values: number[]) => number;
829
+ export const hypot: any;
820
830
  /** Returns log2 of value passed in
821
831
  * @param {number} x
822
832
  * @return {number}
823
833
  * @memberof Math */
824
- export const log2: (x: number) => number;
834
+ export const log2: any;
825
835
  /** Returns sin of value passed in
826
836
  * @param {number} x
827
837
  * @return {number}
@@ -918,6 +928,11 @@ declare module "littlejsengine" {
918
928
  * @return {number}
919
929
  * @memberof Math */
920
930
  export function nearestPowerOfTwo(value: number): number;
931
+ /** Checks if the value passed in is a power of two
932
+ * @param {number} value
933
+ * @return {boolean}
934
+ * @memberof Math */
935
+ export function isPowerOfTwo(value: number): boolean;
921
936
  /** Returns true if two axis aligned bounding boxes are overlapping
922
937
  * this can be used for simple collision detection between objects
923
938
  * @param {Vector2} posA - Center of box A
@@ -1217,8 +1232,10 @@ declare module "littlejsengine" {
1217
1232
  /** Returns a copy of this vector with each axis floored
1218
1233
  * @return {Vector2} */
1219
1234
  floor(): Vector2;
1220
- /** Returns a copy of this vector snapped to a grid
1221
- * @param {number} grid - grid size to snap to
1235
+ /** Returns a copy of this vector snapped to a grid. Note that `grid` is
1236
+ * the number of snap steps per unit (so `grid=2` snaps to halves and
1237
+ * `grid=0.5` snaps to twos), not the cell size.
1238
+ * @param {number} grid - snap steps per unit
1222
1239
  * @return {Vector2} */
1223
1240
  snap(grid: number): Vector2;
1224
1241
  /** Returns new vec2 with modded values
@@ -1593,8 +1610,9 @@ declare module "littlejsengine" {
1593
1610
  * Create a TextureInfo, called automatically by the engine
1594
1611
  * @param {HTMLImageElement|OffscreenCanvas} image
1595
1612
  * @param {boolean} [useWebGL] - Should use WebGL if available?
1613
+ * @param {boolean} [wrap] - Should the texture wrap (REPEAT) or clamp (CLAMP_TO_EDGE)?
1596
1614
  */
1597
- constructor(image: HTMLImageElement | OffscreenCanvas, useWebGL?: boolean);
1615
+ constructor(image: HTMLImageElement | OffscreenCanvas, useWebGL?: boolean, wrap?: boolean);
1598
1616
  /** @property {HTMLImageElement|OffscreenCanvas} - image source */
1599
1617
  image: OffscreenCanvas | HTMLImageElement;
1600
1618
  /** @property {Vector2} - size of the image */
@@ -1603,6 +1621,8 @@ declare module "littlejsengine" {
1603
1621
  sizeInverse: Vector2;
1604
1622
  /** @property {WebGLTexture} - WebGL texture */
1605
1623
  glTexture: any;
1624
+ /** @property {boolean} - true for REPEAT wrap mode, false for CLAMP_TO_EDGE */
1625
+ wrap: boolean;
1606
1626
  /** Creates the WebGL texture, updates if already created */
1607
1627
  createWebGLTexture(): void;
1608
1628
  /** Destroys the WebGL texture */
@@ -1610,6 +1630,9 @@ declare module "littlejsengine" {
1610
1630
  /** Check if the texture is webgl enabled
1611
1631
  * @return {boolean} */
1612
1632
  hasWebGL(): boolean;
1633
+ /** Set the wrap mode for this texture
1634
+ * @param {boolean} [wrap] - true for REPEAT, false for CLAMP_TO_EDGE */
1635
+ setWrap(wrap?: boolean): void;
1613
1636
  }
1614
1637
  /**
1615
1638
  * LittleJS Drawing System
@@ -1733,6 +1756,21 @@ declare module "littlejsengine" {
1733
1756
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
1734
1757
  * @memberof Draw */
1735
1758
  export function drawRectGradient(pos: Vector2, size?: Vector2, colorTop?: Color, colorBottom?: Color, angle?: number, useWebGL?: boolean, screenSpace?: boolean, context?: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D): void;
1759
+ /** Draw a texture tiled (wrapped) across a rectangle in world space.
1760
+ * Useful for backgrounds, repeating patterns, and seamless fills.
1761
+ * The whole texture is tiled — sub-region (TileInfo) wrapping is not supported.
1762
+ * @param {Vector2} pos - Center of the rect in world space
1763
+ * @param {Vector2} size - Size of the rect in world space
1764
+ * @param {Vector2} wrapCount - How many times the texture repeats (x, y)
1765
+ * @param {TextureInfo|number} [texture=0] - TextureInfo or texture index into textureInfos
1766
+ * @param {Color} [color=WHITE] - Color to modulate with
1767
+ * @param {number} [angle=0] - Angle to rotate by
1768
+ * @param {Color} [additiveColor] - Additive color to be applied if any
1769
+ * @param {boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering?
1770
+ * @param {boolean} [screenSpace=false] - Are pos and size in screen space?
1771
+ * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context] - Canvas 2D context to draw to
1772
+ * @memberof Draw */
1773
+ export function drawTextureWrapped(pos: Vector2, size: Vector2, wrapCount: Vector2, texture?: TextureInfo | number, color?: Color, angle?: number, additiveColor?: Color, useWebGL?: boolean, screenSpace?: boolean, context?: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D): void;
1736
1774
  /** Draw connected lines between a series of points
1737
1775
  * @param {Array<Vector2>} points
1738
1776
  * @param {number} [width]
@@ -1769,6 +1807,19 @@ declare module "littlejsengine" {
1769
1807
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
1770
1808
  * @memberof Draw */
1771
1809
  export function drawPoly(points: Array<Vector2>, color?: Color, lineWidth?: number, lineColor?: Color, pos?: Vector2, angle?: number, useWebGL?: boolean, screenSpace?: boolean, context?: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D): void;
1810
+ /** Draw colored regular polygon using passed in number of sides
1811
+ * @param {Vector2} pos
1812
+ * @param {Vector2} [size=vec2(1)]
1813
+ * @param {number} [sides]
1814
+ * @param {Color} [color=WHITE]
1815
+ * @param {number} [angle]
1816
+ * @param {number} [lineWidth]
1817
+ * @param {Color} [lineColor=BLACK]
1818
+ * @param {boolean} [useWebGL=glEnable]
1819
+ * @param {boolean} [screenSpace]
1820
+ * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
1821
+ * @memberof Draw */
1822
+ export function drawRegularPoly(pos: Vector2, size?: Vector2, sides?: number, color?: Color, lineWidth?: number, lineColor?: Color, angle?: number, useWebGL?: boolean, screenSpace?: boolean, context?: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D): void;
1772
1823
  /** Draw colored ellipse using passed in point
1773
1824
  * @param {Vector2} pos
1774
1825
  * @param {Vector2} [size=vec2(1)] - Width and height diameter
@@ -1910,6 +1961,14 @@ declare module "littlejsengine" {
1910
1961
  * @return {Vector2}
1911
1962
  * @memberof Draw */
1912
1963
  export function getCameraSize(): Vector2;
1964
+ /** Check if a box, point, or circle is on screen with a circle test
1965
+ * If size is a Vector2, uses the length as diameter
1966
+ * This can be used to cull offscreen objects from render or update
1967
+ * @param {Vector2} pos - world space position
1968
+ * @param {Vector2|number} size - world space size or diameter
1969
+ * @return {boolean}
1970
+ * @memberof Draw */
1971
+ export function isOnScreen(pos: Vector2, size?: Vector2 | number): boolean;
1913
1972
  /**
1914
1973
  * LittleJS WebGL Interface
1915
1974
  * - WebGL2 rendering engine for high-performance graphics
@@ -1943,9 +2002,14 @@ declare module "littlejsengine" {
1943
2002
  /** Set the WebGL texture, called automatically if using multiple textures
1944
2003
  * - This may also flush the gl buffer resulting in more draw calls and worse performance
1945
2004
  * @param {WebGLTexture} texture
1946
- * @param {boolean} [wrap] - Should the texture wrap or clamp
1947
2005
  * @memberof WebGL */
1948
- export function glSetTexture(texture: WebGLTexture, wrap?: boolean): void;
2006
+ export function glSetTexture(texture: WebGLTexture): void;
2007
+ /** Set the wrap mode (REPEAT or CLAMP_TO_EDGE) on an existing WebGL texture
2008
+ * Flushes the current batch only if the texture is the active one
2009
+ * @param {WebGLTexture} texture
2010
+ * @param {boolean} [wrap] - true for REPEAT, false for CLAMP_TO_EDGE
2011
+ * @memberof WebGL */
2012
+ export function glSetTextureWrap(texture: WebGLTexture, wrap?: boolean): void;
1949
2013
  /** Compile WebGL shader of the given type, will throw errors if in debug mode
1950
2014
  * @param {string} source
1951
2015
  * @param {number} type
@@ -1961,9 +2025,10 @@ declare module "littlejsengine" {
1961
2025
  /** Create WebGL texture from an image and init the texture settings
1962
2026
  * Restores the active texture when done
1963
2027
  * @param {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas} [image]
2028
+ * @param {boolean} [wrap] - true for REPEAT, false for CLAMP_TO_EDGE
1964
2029
  * @return {WebGLTexture}
1965
2030
  * @memberof WebGL */
1966
- export function glCreateTexture(image?: HTMLImageElement | HTMLCanvasElement | OffscreenCanvas): WebGLTexture;
2031
+ export function glCreateTexture(image?: HTMLImageElement | HTMLCanvasElement | OffscreenCanvas, wrap?: boolean): WebGLTexture;
1967
2032
  /** Deletes a WebGL texture
1968
2033
  * @param {WebGLTexture} [texture]
1969
2034
  * @memberof WebGL */
@@ -2154,7 +2219,7 @@ declare module "littlejsengine" {
2154
2219
  * This is useful to disable for html menus so the browser can handle input normally
2155
2220
  * @param {boolean} preventDefault
2156
2221
  * @memberof Input */
2157
- export function setInputPreventDefault(preventDefault: boolean): void;
2222
+ export function setInputPreventDefault(preventDefault?: boolean): void;
2158
2223
  /** Returns true if gamepad button is down
2159
2224
  * @param {number} button
2160
2225
  * @param {number} [gamepad]
@@ -2179,6 +2244,11 @@ declare module "littlejsengine" {
2179
2244
  * @return {Vector2}
2180
2245
  * @memberof Input */
2181
2246
  export function gamepadStick(stick: number, gamepad?: number): Vector2;
2247
+ /** Returns how many control sticks the passed in gamepad has
2248
+ * @param {number} [gamepad]
2249
+ * @return {number}
2250
+ * @memberof Input */
2251
+ export function gamepadStickCount(gamepad?: number): number;
2182
2252
  /** Returns gamepad dpad value
2183
2253
  * @param {number} [gamepad]
2184
2254
  * @return {Vector2}
@@ -2189,6 +2259,18 @@ declare module "littlejsengine" {
2189
2259
  * @return {boolean}
2190
2260
  * @memberof Input */
2191
2261
  export function gamepadConnected(gamepad?: number): boolean;
2262
+ /** Pulse a gamepad's vibration hardware using the dual-rumble effect if it exists
2263
+ * Strong magnitude is usually the left side motor, weak magnitude is usually the right side motor
2264
+ * @param {number} [gamepad] - gamepad index
2265
+ * @param {number} [duration] - effect duration in ms
2266
+ * @param {number} [strongMagnitude] - strong (left) motor intensity, 0 to 1
2267
+ * @param {number} [weakMagnitude] - weak (right) motor intensity, 0 to 1
2268
+ * @param {number} [startDelay] - delay in ms before the effect starts
2269
+ * @memberof Input */
2270
+ export function gamepadVibrate(gamepad?: number, duration?: number, strongMagnitude?: number, weakMagnitude?: number, startDelay?: number): void;
2271
+ /** Stop vibration on a gamepad
2272
+ * @memberof Input */
2273
+ export function gamepadVibrateStop(gamepad?: number): void;
2192
2274
  /** Pulse the vibration hardware if it exists
2193
2275
  * @param {number|Array} [pattern] - single value in ms or vibration interval array
2194
2276
  * @memberof Input */
@@ -2219,7 +2301,9 @@ declare module "littlejsengine" {
2219
2301
  * - Web Audio API integration with master gain control
2220
2302
  * @namespace Audio
2221
2303
  */
2222
- /** Audio context used by the engine
2304
+ /** Audio context used by the engine. Created lazily in audioInit() to avoid
2305
+ * browser autoplay warnings about constructing an AudioContext before any
2306
+ * user gesture.
2223
2307
  * @type {AudioContext}
2224
2308
  * @memberof Audio */
2225
2309
  export let audioContext: AudioContext;
@@ -2231,6 +2315,10 @@ declare module "littlejsengine" {
2231
2315
  * @default 44100
2232
2316
  * @memberof Audio */
2233
2317
  export const audioDefaultSampleRate: 44100;
2318
+ /** Check if the audio context is running and available for playback
2319
+ * @return {boolean} - True if the audio context is running
2320
+ * @memberof Audio */
2321
+ export function audioIsRunning(): boolean;
2234
2322
  /**
2235
2323
  * Sound Object - Stores a sound for later
2236
2324
  * - this can be used to load and play wave, mp3, and ogg files
@@ -3120,16 +3208,6 @@ declare module "littlejsengine" {
3120
3208
  /** Render the particle, automatically called each frame */
3121
3209
  render(): void;
3122
3210
  }
3123
- /**
3124
- * LittleJS Medal System
3125
- * - Achievement/trophy system for games
3126
- * - Medal class with name, description, icon, and unlock tracking
3127
- * - Automatic saving to local storage
3128
- * - Visual display queue with slide-in notifications
3129
- * - Newgrounds API integration for online achievements
3130
- * - Debug mode to unlock/reset medals during development
3131
- * @namespace Medals
3132
- */
3133
3211
  /** List of all medals
3134
3212
  * @type {Object}
3135
3213
  * @memberof Medals */
@@ -3145,6 +3223,15 @@ declare module "littlejsengine" {
3145
3223
  * @param {string} saveName
3146
3224
  * @memberof Medals */
3147
3225
  export function medalsInit(saveName: string): void;
3226
+ /**
3227
+ * @callback MedalCallbackFunction - Function that processes a medal
3228
+ * @param {Medal} medal
3229
+ * @memberof Medals
3230
+ */
3231
+ /** Calls a function for each medal
3232
+ * @param {MedalCallbackFunction} callback
3233
+ * @memberof Medals */
3234
+ export function medalsForEach(callback: MedalCallbackFunction): void;
3148
3235
  /**
3149
3236
  * Medal - Tracks an unlockable medal
3150
3237
  * @memberof Medals
@@ -3191,6 +3278,37 @@ declare module "littlejsengine" {
3191
3278
  renderIcon(pos: Vector2, size: number): void;
3192
3279
  storageKey(): string;
3193
3280
  }
3281
+ /** How long to show medals for in seconds
3282
+ * @type {number}
3283
+ * @default
3284
+ * @memberof Settings */
3285
+ export let medalDisplayTime: number;
3286
+ /** How quickly to slide on/off medals in seconds
3287
+ * @type {number}
3288
+ * @default
3289
+ * @memberof Settings */
3290
+ export let medalDisplaySlideTime: number;
3291
+ /** Size of medal display
3292
+ * @type {Vector2}
3293
+ * @default Vector2(640,80)
3294
+ * @memberof Settings */
3295
+ export let medalDisplaySize: Vector2;
3296
+ /** Set how long to show medals for in seconds
3297
+ * @param {number} time
3298
+ * @memberof Settings */
3299
+ export function setMedalDisplayTime(time: number): void;
3300
+ /** Set how quickly to slide on/off medals in seconds
3301
+ * @param {number} time
3302
+ * @memberof Settings */
3303
+ export function setMedalDisplaySlideTime(time: number): void;
3304
+ /** Set size of medal display
3305
+ * @param {Vector2} size
3306
+ * @memberof Settings */
3307
+ export function setMedalDisplaySize(size: Vector2): void;
3308
+ /** Set to stop medals from being unlockable
3309
+ * @param {boolean} preventUnlock
3310
+ * @memberof Settings */
3311
+ export function setMedalsPreventUnlock(preventUnlock: boolean): void;
3194
3312
  /**
3195
3313
  * LittleJS Newgrounds Plugin
3196
3314
  * - NewgroundsMedal extends Medal with Newgrounds API functionality
@@ -3440,8 +3558,10 @@ declare module "littlejsengine" {
3440
3558
  lastHoverObject: any;
3441
3559
  /** @property {UIObject} - Current confirm menu being shown */
3442
3560
  confirmDialog: any;
3443
- /** @property {UIObject} - Object to send keyboard input to */
3444
- keyInputObject: any;
3561
+ /** @private */
3562
+ private _keyInputObject;
3563
+ /** @private */
3564
+ private _onKeyDown;
3445
3565
  /** Draw a rectangle to the UI context
3446
3566
  * @param {Vector2} pos
3447
3567
  * @param {Vector2} size
@@ -3503,8 +3623,14 @@ declare module "littlejsengine" {
3503
3623
  * @param {Vector2} pos
3504
3624
  * @return {Vector2} */
3505
3625
  screenToNative(pos: Vector2): Vector2;
3626
+ set keyInputObject(arg: UIObject);
3627
+ /** Object to send keyboard input to (typically a UITextInput).
3628
+ * The document keydown listener is only attached while this is set,
3629
+ * so games that never use text input pay no event-handling cost.
3630
+ * @type {UIObject} */
3631
+ get keyInputObject(): UIObject;
3506
3632
  /** Destroy and remove all objects
3507
- * @memberof Engine */
3633
+ * @memberof UISystem */
3508
3634
  destroyObjects(): void;
3509
3635
  /** Get all navigable UI objects sorted by navigationIndex
3510
3636
  * @return {Array<UIObject>} */
@@ -3853,6 +3979,37 @@ declare module "littlejsengine" {
3853
3979
  * @param {number} time - Time in seconds to seek to */
3854
3980
  setTime(time: number): void;
3855
3981
  }
3982
+ /**
3983
+ * UILayout - A container that auto-arranges children in a vertical list, horizontal list, or grid
3984
+ * - Set columns to 1 for a vertical list (default)
3985
+ * - Set columns to children.length for a horizontal list
3986
+ * - Set columns to N (1 < N < children.length) for a grid with N columns
3987
+ * - Per-child sizing: each row's height = max child.size.y in that row, each column's width = max child.size.x in that column
3988
+ * - Children are positioned centered in their cell
3989
+ * - Container auto-sizes to fit children plus padding
3990
+ * @extends UIObject
3991
+ * @memberof UISystem
3992
+ */
3993
+ export class UILayout extends UIObject {
3994
+ /** Create a UILayout container that auto-arranges children
3995
+ * @param {Vector2} [pos]
3996
+ * @param {number} [columns=1] - Number of columns (1 = vertical list)
3997
+ * @param {number} [gap=10] - Space between children
3998
+ * @param {number} [padding=10] - Space between container border and children
3999
+ * @param {boolean} [transparent=false] - If true, draws no background, outline, or shadow
4000
+ */
4001
+ constructor(pos?: Vector2, columns?: number, gap?: number, padding?: number, transparent?: boolean);
4002
+ /** @property {number} - Number of columns in the layout */
4003
+ columns: number;
4004
+ /** @property {number} - Space between children */
4005
+ gap: number;
4006
+ /** @property {number} - Space between container border and children */
4007
+ padding: number;
4008
+ /** Recompute child positions and container size based on per-child sizes.
4009
+ * Called automatically by addChild and removeChild. Call manually if you
4010
+ * mutate a child's size or change columns, gap, or padding. */
4011
+ relayout(): void;
4012
+ }
3856
4013
  /**
3857
4014
  * LittleJS Box2D Physics Plugin
3858
4015
  * - Box2dObject extends EngineObject with Box2D physics
@@ -4176,13 +4333,25 @@ declare module "littlejsengine" {
4176
4333
  * @param {Vector2} force
4177
4334
  * @param {Vector2} [pos] */
4178
4335
  applyForce(force: Vector2, pos?: Vector2): void;
4179
- /** Apply acceleration to this object
4336
+ /** Apply acceleration to this object (changes velocity by acceleration,
4337
+ * mass-independent — matches EngineObject.applyAcceleration semantics).
4338
+ * Use applyImpulse if you want the mass-dependent velocity change
4339
+ * Δv = impulse / mass, or applyForce for a Newton-style sustained force.
4180
4340
  * @param {Vector2} acceleration
4181
4341
  * @param {Vector2} [pos] */
4182
4342
  applyAcceleration(acceleration: Vector2, pos?: Vector2): void;
4343
+ /** Apply an instantaneous linear impulse. Changes velocity immediately by
4344
+ * impulse / mass (so heavier bodies move less for the same impulse).
4345
+ * @param {Vector2} impulse
4346
+ * @param {Vector2} [pos] */
4347
+ applyImpulse(impulse: Vector2, pos?: Vector2): void;
4183
4348
  /** Apply torque to this object
4184
4349
  * @param {number} torque */
4185
4350
  applyTorque(torque: number): void;
4351
+ /** Apply an instantaneous angular impulse. Changes angular velocity by
4352
+ * impulse / inertia immediately.
4353
+ * @param {number} impulse */
4354
+ applyAngularImpulse(impulse: number): void;
4186
4355
  /** Check if this object has any fixtures
4187
4356
  * @return {boolean} */
4188
4357
  hasFixtures(): boolean;
@@ -4873,4 +5042,328 @@ declare module "littlejsengine" {
4873
5042
  * @param {number} [angle] - Angle to rotate by
4874
5043
  * @memberof DrawUtilities */
4875
5044
  export function drawThreeSliceScreen(pos: Vector2, size: Vector2, startTile: TileInfo, borderSize?: number, extraSpace?: number, angle?: number): void;
5045
+ /** A numeric tween: drives a callback with a value interpolated between
5046
+ * `start` and `end` over `duration` seconds. Pauses with the game by default.
5047
+ * @memberof TweenSystem
5048
+ * @example
5049
+ * // Animate a fade-out over 2 seconds with an ease-out sine curve.
5050
+ * new Tween((v) => obj.alpha = v, 1, 0, 2, { ease: Ease.OUT(Ease.SINE) });
5051
+ */
5052
+ export class Tween {
5053
+ /** Create a new tween. The callback fires immediately with `start` so the
5054
+ * target snaps to the start value on the same frame the tween is created.
5055
+ *
5056
+ * `start` and `end` may be numbers, Vector2 instances, Color instances, or
5057
+ * any object exposing a `lerp(other, percent) => sameType` method. The
5058
+ * callback receives the interpolated value (a number, or a fresh instance
5059
+ * for lerp-able types). Both endpoints must be the same type.
5060
+ * @param {function(number|Vector2|Color):void} callback - Called with the interpolated value each frame
5061
+ * @param {number|Vector2|Color} [start=0] - Starting value
5062
+ * @param {number|Vector2|Color} [end=1] - Ending value
5063
+ * @param {number} [duration=1] - Duration in seconds
5064
+ * @param {Object} [options]
5065
+ * @param {function(number):number} [options.ease] - Easing function (defaults to LINEAR)
5066
+ * @param {boolean} [options.useRealTime=false] - Advance even when the game is paused (matches Timer's useRealTime)
5067
+ * @param {boolean} [options.paused=false] - Start in paused state */
5068
+ constructor(callback: (arg0: number | Vector2 | Color) => void, start?: number | Vector2 | Color, end?: number | Vector2 | Color, duration?: number, options?: {
5069
+ ease?: (arg0: number) => number;
5070
+ useRealTime?: boolean;
5071
+ paused?: boolean;
5072
+ });
5073
+ callback: (arg0: number | Vector2 | Color) => void;
5074
+ start: number | Vector2 | Color;
5075
+ end: number | Vector2 | Color;
5076
+ duration: number;
5077
+ life: number;
5078
+ ease: (arg0: number) => number;
5079
+ useRealTime: boolean;
5080
+ paused: boolean;
5081
+ /** @private completion callback set by then(), loop(), pingPong(). */
5082
+ private thenCallback;
5083
+ /** @private remaining iterations including the current run (loop/pingPong only). */
5084
+ private loopRemaining;
5085
+ /** Set the easing curve and return this for chaining.
5086
+ * @param {function(number):number} easeFn
5087
+ * @returns {Tween}
5088
+ * @memberof TweenSystem */
5089
+ setEase(easeFn: (arg0: number) => number): Tween;
5090
+ /** Set a single completion callback. Calling `then` again replaces the
5091
+ * previous callback. Returns this for chaining.
5092
+ *
5093
+ * Calling `then` after `loop` or `pingPong` overrides the loop chain
5094
+ * (last call wins).
5095
+ * @param {function():void} callback
5096
+ * @returns {Tween}
5097
+ * @memberof TweenSystem */
5098
+ then(callback: () => void): Tween;
5099
+ /** Repeat this tween `n` total times. After each iteration finishes, a
5100
+ * fresh tween with the same parameters takes over via the `then` slot.
5101
+ * `loop()` with no argument loops forever.
5102
+ *
5103
+ * Mutually exclusive with `pingPong`; calling either replaces the other,
5104
+ * and calling `then` after either clears the loop (last call wins).
5105
+ * @param {number} [count=Infinity]
5106
+ * @returns {Tween}
5107
+ * @memberof TweenSystem */
5108
+ loop(count?: number): Tween;
5109
+ /** Like `loop`, but swap `start` and `end` between iterations so the value
5110
+ * bounces back and forth. `pingPong()` with no argument bounces forever.
5111
+ *
5112
+ * Mutually exclusive with `loop`; calling either replaces the other, and
5113
+ * calling `then` after either clears the loop (last call wins).
5114
+ * @param {number} [count=Infinity]
5115
+ * @returns {Tween}
5116
+ * @memberof TweenSystem */
5117
+ pingPong(count?: number): Tween;
5118
+ /** Pause this tween. While paused, tweenUpdate skips it.
5119
+ * @memberof TweenSystem */
5120
+ pause(): void;
5121
+ /** Resume a paused tween.
5122
+ * @memberof TweenSystem */
5123
+ resume(): void;
5124
+ /** Reset this tween to the start: life back to duration, pause cleared,
5125
+ * re-added to the active list if previously stopped, and the callback
5126
+ * re-fired with the start value.
5127
+ * @memberof TweenSystem */
5128
+ restart(): void;
5129
+ /** True if this tween is in the active list and not paused.
5130
+ * @returns {boolean}
5131
+ * @memberof TweenSystem */
5132
+ isActive(): boolean;
5133
+ /** Get how far this tween has progressed, from 0 (just started) to 1
5134
+ * (completed). Clamped — overshoot past completion still reads 1.
5135
+ * @returns {number}
5136
+ * @memberof TweenSystem */
5137
+ getPercent(): number;
5138
+ /** Get the current interpolated value (the value most recently passed to
5139
+ * the callback). Returns a number, Vector2, or Color depending on the
5140
+ * tween's start/end types.
5141
+ * @returns {number|Vector2|Color}
5142
+ * @memberof TweenSystem */
5143
+ getValue(): number | Vector2 | Color;
5144
+ /** Compute the interpolated value at the given remaining `life`.
5145
+ * At life === duration the result is `start`; at life === 0 it is `end`.
5146
+ * @param {number} life
5147
+ * @returns {number}
5148
+ * @memberof TweenSystem */
5149
+ interp(life: number): number;
5150
+ /** Remove this tween from the active list and prevent any pending then-callback.
5151
+ * @memberof TweenSystem */
5152
+ stop(): void;
5153
+ }
5154
+ /** Tween a property on an object by dot-path. Returns the underlying Tween
5155
+ * so all chaining methods (`setEase`, `then`, `loop`, `pingPong`, etc.)
5156
+ * remain available.
5157
+ *
5158
+ * `start` and `end` may be numbers, Vector2 instances, Color instances, or
5159
+ * any object with a `lerp(other, percent) => sameType` method.
5160
+ * @param {Object} target - The object whose property is being animated
5161
+ * @param {string} propertyPath - Dot-separated path, e.g. `'pos.x'` or `'color'`
5162
+ * @param {number|Vector2|Color} start - Starting value
5163
+ * @param {number|Vector2|Color} end - Ending value
5164
+ * @param {number} [duration=1] - Duration in seconds
5165
+ * @param {Object} [options] - Same options as the Tween constructor
5166
+ * @returns {Tween}
5167
+ * @memberof TweenSystem
5168
+ * @example
5169
+ * // Numeric: slide an object's x with an ease-out sine curve
5170
+ * tweenProperty(player, 'pos.x', 0, 10, 2).setEase(Ease.OUT(Ease.SINE));
5171
+ * // Vector2: animate a position diagonally
5172
+ * tweenProperty(player, 'pos', vec2(-5, 0), vec2(5, 3), 2);
5173
+ * // Color: pulse between two colors
5174
+ * tweenProperty(sprite, 'color', RED, BLUE, 1).pingPong();
5175
+ */
5176
+ export function tweenProperty(target: any, propertyPath: string, start: number | Vector2 | Color, end: number | Vector2 | Color, duration?: number, options?: any): Tween;
5177
+ /** Stop every active tween and clear their then-callbacks. Useful for resets
5178
+ * on level transitions or when changing scenes.
5179
+ * @memberof TweenSystem */
5180
+ export function tweenStopAll(): void;
5181
+ /** Engine plugin hook: advance every active tween by the appropriate delta.
5182
+ * Called once per render frame by the engine (no arguments). May also be
5183
+ * called explicitly with `(gameDelta, realDelta)` to drive tweens manually
5184
+ * — useful for headless tests or custom replay/scrubbing systems.
5185
+ * @param {number} [gameDelta] - Game-time delta in seconds; default: time - lastTime
5186
+ * @param {number} [realDelta] - Real-time delta in seconds; default: timeReal - lastTimeReal
5187
+ * @memberof TweenSystem */
5188
+ export function tweenUpdate(gameDelta?: number, realDelta?: number): void;
5189
+ export namespace Ease {
5190
+ function LINEAR(x: number): number;
5191
+ function POWER(n: number): (arg0: number) => number;
5192
+ function SINE(x: number): number;
5193
+ function CIRC(x: number): number;
5194
+ function EXPO(x: number): number;
5195
+ function BACK(x: number): number;
5196
+ function ELASTIC(x: number): number;
5197
+ function SPRING(x: number): number;
5198
+ function BOUNCE(x: number): number;
5199
+ function IN(f: (arg0: number) => number): (arg0: number) => number;
5200
+ function OUT(f: (arg0: number) => number): (arg0: number) => number;
5201
+ function IN_OUT(f: (arg0: number) => number): (arg0: number) => number;
5202
+ function PIECEWISE(...fns: ((arg0: number) => number)[]): (arg0: number) => number;
5203
+ function BEZIER(x1: number, y1: number, x2: number, y2: number): (arg0: number) => number;
5204
+ }
5205
+ /** Grid pathfinder using A* with two optional smoothing passes.
5206
+ * @memberof PathFinding
5207
+ * @example
5208
+ * // Tile-layer driven (most common):
5209
+ * const pf = new PathFinder(myTileCollisionLayer);
5210
+ * const path = pf.findPath(player.pos, mousePos);
5211
+ *
5212
+ * // Bare grid with custom walkability:
5213
+ * const pf = new PathFinder(vec2(50, 50));
5214
+ * pf.isWalkable = (x, y) => myGrid[y*50 + x] === 0;
5215
+ */
5216
+ export class PathFinder {
5217
+ /** @param {TileCollisionLayer|Vector2} source - Either a TileCollisionLayer
5218
+ * (size and walkability auto-derived) or a Vector2 grid size (user
5219
+ * overrides isWalkable). */
5220
+ constructor(source: TileCollisionLayer | Vector2);
5221
+ size: any;
5222
+ tileLayer: Vector2 | TileCollisionLayer;
5223
+ heuristicWeight: number;
5224
+ maxLoop: number;
5225
+ smoothPath: boolean;
5226
+ debug: boolean;
5227
+ debugTime: number;
5228
+ nodes: any[];
5229
+ collisionScratch: Vector2;
5230
+ /** Default walkability: if a tile layer was provided, returns true when the
5231
+ * cell has no solid collision data; otherwise returns true. Override on
5232
+ * the instance or via a subclass.
5233
+ * @param {number} x - Tile x
5234
+ * @param {number} y - Tile y
5235
+ * @returns {boolean} */
5236
+ isWalkable(x: number, y: number): boolean;
5237
+ /** Default extra cost for stepping on a cell. Returns 0 (free) by default.
5238
+ * Override to add cost-weighted terrain (mud, swamp, etc).
5239
+ * @param {number} x - Tile x
5240
+ * @param {number} y - Tile y
5241
+ * @returns {number} */
5242
+ getCost(x: number, y: number): number;
5243
+ /** Get the node at tile coords, or null if out of bounds.
5244
+ * @param {number} x
5245
+ * @param {number} y
5246
+ * @returns {PathFinderNode|null} */
5247
+ getNode(x: number, y: number): PathFinderNode | null;
5248
+ /** Convert a world-space position to integer tile coords (no clamping).
5249
+ * @param {Vector2} worldPos
5250
+ * @returns {Vector2}
5251
+ * @memberof PathFinding */
5252
+ worldToTile(worldPos: Vector2): Vector2;
5253
+ /** Convert integer tile coords to the world-space center of that tile.
5254
+ * @param {number} x
5255
+ * @param {number} y
5256
+ * @returns {Vector2}
5257
+ * @memberof PathFinding */
5258
+ tileToWorld(x: number, y: number): Vector2;
5259
+ /** Reset all nodes and re-populate walkable / cost / posWorld from the
5260
+ * current isWalkable / getCost overrides. Called at the start of
5261
+ * findPath; exposed so tests and tooling can drive it directly.
5262
+ * @private */
5263
+ private buildNodeData;
5264
+ /** Core A* search loop. Expects buildNodeData() to have been called first.
5265
+ * Marks node.parent for path reconstruction. Returns true if endNode was
5266
+ * reached; false on disconnected goal or maxLoop exhaustion.
5267
+ * @param {PathFinderNode} startNode
5268
+ * @param {PathFinderNode} endNode
5269
+ * @returns {boolean}
5270
+ * @private */
5271
+ private aStarSearch;
5272
+ /** Find the clear (walkable, zero-cost) node closest to the given world
5273
+ * position. Spirals outward in expanding boxes until a clear node is
5274
+ * found or the search range is exhausted. Useful for snapping a click
5275
+ * or NPC spawn position to the nearest open tile.
5276
+ *
5277
+ * By default, calls `buildNodeData()` first so it works correctly on a
5278
+ * fresh PathFinder. If you're calling it many times in a row with
5279
+ * unchanged walkability, pass `rebuild=false` and call `buildNodeData()`
5280
+ * once externally to avoid redundant work.
5281
+ * @param {Vector2} worldPos
5282
+ * @param {number} [searchRange=10] - Max box-radius in tiles
5283
+ * @param {boolean} [rebuild=true] - Whether to call buildNodeData first
5284
+ * @returns {PathFinderNode|null}
5285
+ * @memberof PathFinding */
5286
+ getNearestClearNode(worldPos: Vector2, searchRange?: number, rebuild?: boolean): PathFinderNode | null;
5287
+ /** Smooth a node path by removing redundant turns and tightening corners
5288
+ * where a grid-aligned diagonal is clear. Modifies the path in place.
5289
+ * Stays on the grid — does not introduce off-tile-center points.
5290
+ * Port of ShortenPath() in pathFinding.cpp.
5291
+ * @param {PathFinderNode[]} path
5292
+ * @private */
5293
+ private smoothPathCorners;
5294
+ /** Smooth a node path via line-of-sight ("string pulling"). Walks the
5295
+ * input path collapsing runs of nodes into straight segments whenever
5296
+ * isLineClear permits, so the result can leave grid centers and cut
5297
+ * cleanly across open spaces.
5298
+ *
5299
+ * Bails (leaves the path unchanged) if any node has nonzero cost — a
5300
+ * straight geometric shortcut can't be trusted to be the lowest-cost
5301
+ * route when cost-weighted terrain is in play.
5302
+ *
5303
+ * Port of ShortenPath2() in pathFinding.cpp.
5304
+ * @param {PathFinderNode[]} path
5305
+ * @private */
5306
+ private smoothPathStringPull;
5307
+ /** Lookup helper: true when the node at tile coords (x, y) is in-bounds
5308
+ * and clear (walkable, zero-cost). Used by isLineClear's hot path.
5309
+ * @param {number} x
5310
+ * @param {number} y
5311
+ * @returns {boolean}
5312
+ * @private */
5313
+ private isNodeClear;
5314
+ /** Check that the line between two tile-coord endpoints stays entirely
5315
+ * inside walkable, zero-cost cells. Stricter than just sampling along
5316
+ * the line — it also checks the diagonal-corner-adjacent cells so the
5317
+ * line can never "scrape past" a wall corner.
5318
+ *
5319
+ * Both endpoints must themselves be clear (asserted in debug). Port of
5320
+ * CheckLine() in pathFinding.cpp.
5321
+ * @param {Vector2} startPos - Tile coords
5322
+ * @param {Vector2} endPos - Tile coords
5323
+ * @returns {boolean}
5324
+ * @private */
5325
+ private isLineClear;
5326
+ /** Find a path from startPos to endPos in world space. Returns an array
5327
+ * of world-space Vector2 points; empty array if no path exists.
5328
+ *
5329
+ * Start and end are snapped to the nearest walkable tile via
5330
+ * getNearestClearNode. Intermediate points are tile centers unless the
5331
+ * string-pulling smoothing pass moves them off-grid.
5332
+ * @param {Vector2} startPos - World-space start
5333
+ * @param {Vector2} endPos - World-space end
5334
+ * @returns {Vector2[]}
5335
+ * @memberof PathFinding */
5336
+ findPath(startPos: Vector2, endPos: Vector2): Vector2[];
5337
+ }
5338
+ /** A single grid cell tracked by the pathfinder. Allocated once per cell at
5339
+ * PathFinder construction; reset (not reallocated) at the start of every
5340
+ * findPath call.
5341
+ * @memberof PathFinding */
5342
+ export class PathFinderNode {
5343
+ /** @param {number} x - Tile x
5344
+ * @param {number} y - Tile y */
5345
+ constructor(x: number, y: number);
5346
+ /** @property {Vector2} - Tile coords (integer) */
5347
+ pos: Vector2;
5348
+ /** @property {Vector2} - World-space center of this tile (set by buildNodeData) */
5349
+ posWorld: Vector2;
5350
+ /** @property {boolean} - True if this cell is passable (cleared each findPath call) */
5351
+ walkable: boolean;
5352
+ /** @property {number} - Extra cost added to A* G-score for stepping on this cell */
5353
+ cost: number;
5354
+ /** @property {number} - A* G-score: actual cost from start to this node */
5355
+ g: number;
5356
+ /** @property {number} - A* F-score: G + heuristic */
5357
+ f: number;
5358
+ /** @property {PathFinderNode|null} - Parent for path reconstruction */
5359
+ parent: any;
5360
+ /** @property {boolean} - In the A* open list */
5361
+ isOpen: boolean;
5362
+ /** @property {boolean} - In the A* closed list */
5363
+ isClosed: boolean;
5364
+ /** Reset per-search state (called at the start of buildNodeData). */
5365
+ reset(): void;
5366
+ /** True if walkable and not blocked by cost. */
5367
+ isClear(): boolean;
5368
+ }
4876
5369
  }