littlejsengine 1.18.4 → 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 (177) hide show
  1. package/COPYRIGHT.txt +38 -0
  2. package/FAQ.md +633 -0
  3. package/README.md +19 -1
  4. package/dist/littlejs.d.ts +349 -54
  5. package/dist/littlejs.esm.js +1469 -448
  6. package/dist/littlejs.esm.min.js +1 -1
  7. package/dist/littlejs.js +1438 -436
  8. package/dist/littlejs.min.js +1 -1
  9. package/dist/littlejs.release.js +1438 -436
  10. package/package.json +8 -1
  11. package/plugins/box2d.js +32 -7
  12. package/{src/engineMedals.js → plugins/medalSystem.js} +248 -196
  13. package/plugins/pathFinder.js +758 -0
  14. package/plugins/pluginExport.js +19 -0
  15. package/plugins/tween.js +1 -1
  16. package/plugins/tweenSystem.js +509 -0
  17. package/plugins/uiSystem.js +150 -11
  18. package/src/engine.js +2 -141
  19. package/src/engineAudio.js +8 -5
  20. package/src/engineBuild.mjs +4 -2
  21. package/src/engineDebug.js +1 -1
  22. package/src/engineDraw.js +21 -3
  23. package/src/engineExport.js +12 -12
  24. package/src/engineInput.js +1 -1
  25. package/src/engineLogo.js +146 -0
  26. package/src/engineMath.js +10 -3
  27. package/src/engineObject.js +11 -5
  28. package/src/engineParticles.js +6 -3
  29. package/src/engineRelease.js +1 -1
  30. package/src/engineSettings.js +0 -47
  31. package/src/engineUtilities.js +7 -2
  32. package/src/engineWebGL.js +34 -7
  33. package/src/jsconfig.json +3 -1
  34. package/.github/workflows/test.yml +0 -17
  35. package/AI.md +0 -173
  36. package/CLAUDE.md +0 -1
  37. package/examples/box2d/game.js +0 -192
  38. package/examples/box2d/gameObjects.js +0 -564
  39. package/examples/box2d/index.html +0 -9
  40. package/examples/box2d/scenes.js +0 -194
  41. package/examples/box2d/tiles.png +0 -0
  42. package/examples/breakout/game.js +0 -175
  43. package/examples/breakout/gameObjects.js +0 -147
  44. package/examples/breakout/index.html +0 -8
  45. package/examples/breakout/tiles.png +0 -0
  46. package/examples/breakoutTutorial/README.md +0 -521
  47. package/examples/breakoutTutorial/game.js +0 -191
  48. package/examples/breakoutTutorial/images/1.png +0 -0
  49. package/examples/breakoutTutorial/images/10.png +0 -0
  50. package/examples/breakoutTutorial/images/11.png +0 -0
  51. package/examples/breakoutTutorial/images/2.png +0 -0
  52. package/examples/breakoutTutorial/images/3.png +0 -0
  53. package/examples/breakoutTutorial/images/4.png +0 -0
  54. package/examples/breakoutTutorial/images/5.png +0 -0
  55. package/examples/breakoutTutorial/images/6.png +0 -0
  56. package/examples/breakoutTutorial/images/7.png +0 -0
  57. package/examples/breakoutTutorial/images/8.png +0 -0
  58. package/examples/breakoutTutorial/images/9.png +0 -0
  59. package/examples/breakoutTutorial/index.html +0 -8
  60. package/examples/electron/build.mjs +0 -127
  61. package/examples/electron/electron.js +0 -35
  62. package/examples/electron/game.js +0 -54
  63. package/examples/electron/index.html +0 -13
  64. package/examples/electron/package.json +0 -5
  65. package/examples/electron/tiles.png +0 -0
  66. package/examples/empty/game.js +0 -51
  67. package/examples/empty/index.html +0 -5
  68. package/examples/empty/tiles.png +0 -0
  69. package/examples/favicon.png +0 -0
  70. package/examples/games.jpg +0 -0
  71. package/examples/htmlMenu/game.js +0 -82
  72. package/examples/htmlMenu/index.html +0 -45
  73. package/examples/htmlMenu/tiles.png +0 -0
  74. package/examples/index.html +0 -62
  75. package/examples/logo.png +0 -0
  76. package/examples/logo2.png +0 -0
  77. package/examples/module/build.mjs +0 -124
  78. package/examples/module/game.js +0 -132
  79. package/examples/module/index.html +0 -10
  80. package/examples/module/tiles.png +0 -0
  81. package/examples/particles/index.html +0 -426
  82. package/examples/particles/tiles.png +0 -0
  83. package/examples/platformer/data/gameLevelData.tmx +0 -143
  84. package/examples/platformer/data/gameLevelData.tsx +0 -4
  85. package/examples/platformer/game.js +0 -147
  86. package/examples/platformer/gameCharacter.js +0 -309
  87. package/examples/platformer/gameEffects.js +0 -278
  88. package/examples/platformer/gameLevel.js +0 -205
  89. package/examples/platformer/gameLevelData.json +0 -171
  90. package/examples/platformer/gameObjects.js +0 -378
  91. package/examples/platformer/gamePlayer.js +0 -35
  92. package/examples/platformer/index.html +0 -9
  93. package/examples/platformer/tiles.png +0 -0
  94. package/examples/platformer/tilesLevel.png +0 -0
  95. package/examples/puzzle/game.js +0 -331
  96. package/examples/puzzle/index.html +0 -8
  97. package/examples/puzzle/tiles.png +0 -0
  98. package/examples/screenshot.jpg +0 -0
  99. package/examples/shorts/animation.js +0 -18
  100. package/examples/shorts/base.html +0 -54
  101. package/examples/shorts/blending.js +0 -14
  102. package/examples/shorts/box2d.js +0 -51
  103. package/examples/shorts/box2dCar.js +0 -59
  104. package/examples/shorts/box2dPool.js +0 -107
  105. package/examples/shorts/box2dTileLayer.js +0 -48
  106. package/examples/shorts/cameraDrag.js +0 -22
  107. package/examples/shorts/clock.js +0 -21
  108. package/examples/shorts/colors.js +0 -25
  109. package/examples/shorts/debugDraw.js +0 -37
  110. package/examples/shorts/empty.js +0 -30
  111. package/examples/shorts/flappyGame.js +0 -55
  112. package/examples/shorts/fontImage.js +0 -17
  113. package/examples/shorts/fps.js +0 -90
  114. package/examples/shorts/helloWorld.js +0 -11
  115. package/examples/shorts/hillGlideGame.js +0 -63
  116. package/examples/shorts/input.js +0 -64
  117. package/examples/shorts/landerGame.js +0 -57
  118. package/examples/shorts/maze.js +0 -48
  119. package/examples/shorts/medals.js +0 -51
  120. package/examples/shorts/music.js +0 -78
  121. package/examples/shorts/musicPlayer.js +0 -137
  122. package/examples/shorts/nineSlice.js +0 -40
  123. package/examples/shorts/parallax.js +0 -72
  124. package/examples/shorts/particles.js +0 -28
  125. package/examples/shorts/piano.js +0 -44
  126. package/examples/shorts/platformer.js +0 -45
  127. package/examples/shorts/pongGame.js +0 -41
  128. package/examples/shorts/postProcess.js +0 -62
  129. package/examples/shorts/sequencer.js +0 -124
  130. package/examples/shorts/shader.js +0 -29
  131. package/examples/shorts/shapes.js +0 -21
  132. package/examples/shorts/slidingPuzzle.js +0 -52
  133. package/examples/shorts/song.mp3 +0 -0
  134. package/examples/shorts/sound.js +0 -36
  135. package/examples/shorts/spaceGame.js +0 -58
  136. package/examples/shorts/spriteAtlas.js +0 -31
  137. package/examples/shorts/starfield.js +0 -15
  138. package/examples/shorts/texture.js +0 -16
  139. package/examples/shorts/textureWrapped.js +0 -12
  140. package/examples/shorts/tileLayer.js +0 -48
  141. package/examples/shorts/tileRaycast.js +0 -39
  142. package/examples/shorts/tiles.png +0 -0
  143. package/examples/shorts/tiltedView.js +0 -63
  144. package/examples/shorts/timers.js +0 -53
  145. package/examples/shorts/topDown.js +0 -38
  146. package/examples/shorts/tween.js +0 -24
  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/shorts.js +0 -743
  151. package/examples/starter/build.bat +0 -7
  152. package/examples/starter/build.mjs +0 -126
  153. package/examples/starter/game.js +0 -137
  154. package/examples/starter/index.html +0 -35
  155. package/examples/starter/tiles.png +0 -0
  156. package/examples/stress/index.html +0 -173
  157. package/examples/style.css +0 -150
  158. package/examples/tweenSystem/game.js +0 -171
  159. package/examples/tweenSystem/index.html +0 -10
  160. package/examples/tweenSystem/tiles.png +0 -0
  161. package/examples/typescript/build.mjs +0 -60
  162. package/examples/typescript/game.js +0 -100
  163. package/examples/typescript/game.ts +0 -132
  164. package/examples/typescript/index.html +0 -10
  165. package/examples/typescript/tiles.png +0 -0
  166. package/examples/typescript/tsconfig.json +0 -17
  167. package/examples/uiSystem/game.js +0 -139
  168. package/examples/uiSystem/index.html +0 -10
  169. package/examples/uiSystem/tiles.png +0 -0
  170. package/jsconfig.json +0 -12
  171. package/plugins/desktop.ini +0 -2
  172. package/reference.md +0 -448
  173. package/test/math.test.mjs +0 -774
  174. package/test/setup.mjs +0 -22
  175. package/test/smoke.test.mjs +0 -274
  176. package/test/tween.test.mjs +0 -576
  177. package/test/util.test.mjs +0 -80
package/README.md CHANGED
@@ -54,11 +54,13 @@ The code is very clean and well documented with many examples to get you started
54
54
  - Robust arcade physics system with collision handling
55
55
  - Fast tilemap collision and raycasting
56
56
  - Full Box2D integration for realistic physics
57
+ - Grid-based A* pathfinding plugin with optional path smoothing
57
58
 
58
59
  ### 🚀 Flexibility
59
60
 
60
61
  - Compatible with all modern web browsers and mobile devices
61
62
  - Full TypeScript and Module support with example projects for both
63
+ - [Vite](https://vite.dev) starter template for instant dev server with hot reload
62
64
  - Great for size coding competitions like [Js13kGames](https://js13kgames.com/)
63
65
  - Open Source and [MIT licensed](https://github.com/KilledByAPixel/LittleJS/blob/main/LICENSE)
64
66
 
@@ -72,7 +74,23 @@ The code is very clean and well documented with many examples to get you started
72
74
 
73
75
  ## How To Use LittleJS
74
76
 
75
- To get started download the latest LittleJS package from GitHub or install via npm: ```npm install littlejsengine```
77
+
78
+ To get started download the latest LittleJS package from GitHub or install via npm:
79
+
80
+ ```
81
+ npm install littlejsengine
82
+ ```
83
+
84
+ or use `degit` for an empty Vite template
85
+
86
+ ```
87
+ npx degit KilledByAPixel/LittleJS/examples/vite-starter my-game
88
+ cd my-game
89
+ npm install
90
+ npm run dev
91
+ ```
92
+
93
+ ## Tutorials
76
94
 
77
95
  - [Making Awesome Games With LittleJS](https://youtu.be/_dXKU0WgAj8?si=ZDXLYAFDWp54hrGT) - A short talk about LittleJS with some tips on how to use it.
78
96
  - [Tutorial: Breakout](https://github.com/KilledByAPixel/LittleJS/tree/main/examples/breakoutTutorial) - Learn how to make a simple game from scratch
@@ -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 */
@@ -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)]
@@ -471,6 +480,11 @@ declare module "littlejsengine" {
471
480
  * @default
472
481
  * @memberof Settings */
473
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;
474
488
  /** Should gamepads be allowed
475
489
  * @type {boolean}
476
490
  * @default
@@ -486,6 +500,12 @@ declare module "littlejsengine" {
486
500
  * @default
487
501
  * @memberof Settings */
488
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;
489
509
  /** True if touch gamepad should appear on mobile devices
490
510
  * - Supports left analog stick, 4 face buttons and start button (button 9)
491
511
  * - setTouchGamepadButtonCount(1) to use face buttons as right analog stick
@@ -503,6 +523,11 @@ declare module "littlejsengine" {
503
523
  * @default
504
524
  * @memberof Settings */
505
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;
506
531
  /** True if touch gamepad should be analog stick or false to use if 8 way dpad
507
532
  * @type {boolean}
508
533
  * @default
@@ -548,21 +573,6 @@ declare module "littlejsengine" {
548
573
  * @default
549
574
  * @memberof Settings */
550
575
  export let soundDefaultTaper: number;
551
- /** How long to show medals for in seconds
552
- * @type {number}
553
- * @default
554
- * @memberof Settings */
555
- export let medalDisplayTime: number;
556
- /** How quickly to slide on/off medals in seconds
557
- * @type {number}
558
- * @default
559
- * @memberof Settings */
560
- export let medalDisplaySlideTime: number;
561
- /** Size of medal display
562
- * @type {Vector2}
563
- * @default Vector2(640,80)
564
- * @memberof Settings */
565
- export let medalDisplaySize: Vector2;
566
576
  /** Set position of camera in world space
567
577
  * @param {Vector2} pos
568
578
  * @memberof Settings */
@@ -683,6 +693,10 @@ declare module "littlejsengine" {
683
693
  * @param {number} scale
684
694
  * @memberof Settings */
685
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;
686
700
  /** Set if touch input is allowed
687
701
  * @param {boolean} enable
688
702
  * @memberof Settings */
@@ -745,22 +759,6 @@ declare module "littlejsengine" {
745
759
  * @param {number} taper
746
760
  * @memberof Settings */
747
761
  export function setSoundDefaultTaper(taper: number): void;
748
- /** Set how long to show medals for in seconds
749
- * @param {number} time
750
- * @memberof Settings */
751
- export function setMedalDisplayTime(time: number): void;
752
- /** Set how quickly to slide on/off medals in seconds
753
- * @param {number} time
754
- * @memberof Settings */
755
- export function setMedalDisplaySlideTime(time: number): void;
756
- /** Set size of medal display
757
- * @param {Vector2} size
758
- * @memberof Settings */
759
- export function setMedalDisplaySize(size: Vector2): void;
760
- /** Set to stop medals from being unlockable
761
- * @param {boolean} preventUnlock
762
- * @memberof Settings */
763
- export function setMedalsPreventUnlock(preventUnlock: boolean): void;
764
762
  /** Set if watermark with FPS should be shown
765
763
  * @param {boolean} show
766
764
  * @memberof Debug */
@@ -823,17 +821,17 @@ declare module "littlejsengine" {
823
821
  * @param {number} x
824
822
  * @return {number}
825
823
  * @memberof Math */
826
- export const sign: (x: number) => number;
824
+ export const sign: any;
827
825
  /** Returns hypotenuse of values passed in
828
826
  * @param {...number} values
829
827
  * @return {number}
830
828
  * @memberof Math */
831
- export const hypot: (...values: number[]) => number;
829
+ export const hypot: any;
832
830
  /** Returns log2 of value passed in
833
831
  * @param {number} x
834
832
  * @return {number}
835
833
  * @memberof Math */
836
- export const log2: (x: number) => number;
834
+ export const log2: any;
837
835
  /** Returns sin of value passed in
838
836
  * @param {number} x
839
837
  * @return {number}
@@ -930,6 +928,11 @@ declare module "littlejsengine" {
930
928
  * @return {number}
931
929
  * @memberof Math */
932
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;
933
936
  /** Returns true if two axis aligned bounding boxes are overlapping
934
937
  * this can be used for simple collision detection between objects
935
938
  * @param {Vector2} posA - Center of box A
@@ -1229,8 +1232,10 @@ declare module "littlejsengine" {
1229
1232
  /** Returns a copy of this vector with each axis floored
1230
1233
  * @return {Vector2} */
1231
1234
  floor(): Vector2;
1232
- /** Returns a copy of this vector snapped to a grid
1233
- * @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
1234
1239
  * @return {Vector2} */
1235
1240
  snap(grid: number): Vector2;
1236
1241
  /** Returns new vec2 with modded values
@@ -1605,8 +1610,9 @@ declare module "littlejsengine" {
1605
1610
  * Create a TextureInfo, called automatically by the engine
1606
1611
  * @param {HTMLImageElement|OffscreenCanvas} image
1607
1612
  * @param {boolean} [useWebGL] - Should use WebGL if available?
1613
+ * @param {boolean} [wrap] - Should the texture wrap (REPEAT) or clamp (CLAMP_TO_EDGE)?
1608
1614
  */
1609
- constructor(image: HTMLImageElement | OffscreenCanvas, useWebGL?: boolean);
1615
+ constructor(image: HTMLImageElement | OffscreenCanvas, useWebGL?: boolean, wrap?: boolean);
1610
1616
  /** @property {HTMLImageElement|OffscreenCanvas} - image source */
1611
1617
  image: OffscreenCanvas | HTMLImageElement;
1612
1618
  /** @property {Vector2} - size of the image */
@@ -1615,6 +1621,8 @@ declare module "littlejsengine" {
1615
1621
  sizeInverse: Vector2;
1616
1622
  /** @property {WebGLTexture} - WebGL texture */
1617
1623
  glTexture: any;
1624
+ /** @property {boolean} - true for REPEAT wrap mode, false for CLAMP_TO_EDGE */
1625
+ wrap: boolean;
1618
1626
  /** Creates the WebGL texture, updates if already created */
1619
1627
  createWebGLTexture(): void;
1620
1628
  /** Destroys the WebGL texture */
@@ -1622,6 +1630,9 @@ declare module "littlejsengine" {
1622
1630
  /** Check if the texture is webgl enabled
1623
1631
  * @return {boolean} */
1624
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;
1625
1636
  }
1626
1637
  /**
1627
1638
  * LittleJS Drawing System
@@ -1796,6 +1807,19 @@ declare module "littlejsengine" {
1796
1807
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
1797
1808
  * @memberof Draw */
1798
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;
1799
1823
  /** Draw colored ellipse using passed in point
1800
1824
  * @param {Vector2} pos
1801
1825
  * @param {Vector2} [size=vec2(1)] - Width and height diameter
@@ -1937,6 +1961,14 @@ declare module "littlejsengine" {
1937
1961
  * @return {Vector2}
1938
1962
  * @memberof Draw */
1939
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;
1940
1972
  /**
1941
1973
  * LittleJS WebGL Interface
1942
1974
  * - WebGL2 rendering engine for high-performance graphics
@@ -1972,6 +2004,12 @@ declare module "littlejsengine" {
1972
2004
  * @param {WebGLTexture} texture
1973
2005
  * @memberof WebGL */
1974
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;
1975
2013
  /** Compile WebGL shader of the given type, will throw errors if in debug mode
1976
2014
  * @param {string} source
1977
2015
  * @param {number} type
@@ -1987,9 +2025,10 @@ declare module "littlejsengine" {
1987
2025
  /** Create WebGL texture from an image and init the texture settings
1988
2026
  * Restores the active texture when done
1989
2027
  * @param {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas} [image]
2028
+ * @param {boolean} [wrap] - true for REPEAT, false for CLAMP_TO_EDGE
1990
2029
  * @return {WebGLTexture}
1991
2030
  * @memberof WebGL */
1992
- export function glCreateTexture(image?: HTMLImageElement | HTMLCanvasElement | OffscreenCanvas): WebGLTexture;
2031
+ export function glCreateTexture(image?: HTMLImageElement | HTMLCanvasElement | OffscreenCanvas, wrap?: boolean): WebGLTexture;
1993
2032
  /** Deletes a WebGL texture
1994
2033
  * @param {WebGLTexture} [texture]
1995
2034
  * @memberof WebGL */
@@ -2180,7 +2219,7 @@ declare module "littlejsengine" {
2180
2219
  * This is useful to disable for html menus so the browser can handle input normally
2181
2220
  * @param {boolean} preventDefault
2182
2221
  * @memberof Input */
2183
- export function setInputPreventDefault(preventDefault: boolean): void;
2222
+ export function setInputPreventDefault(preventDefault?: boolean): void;
2184
2223
  /** Returns true if gamepad button is down
2185
2224
  * @param {number} button
2186
2225
  * @param {number} [gamepad]
@@ -2205,6 +2244,11 @@ declare module "littlejsengine" {
2205
2244
  * @return {Vector2}
2206
2245
  * @memberof Input */
2207
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;
2208
2252
  /** Returns gamepad dpad value
2209
2253
  * @param {number} [gamepad]
2210
2254
  * @return {Vector2}
@@ -2257,7 +2301,9 @@ declare module "littlejsengine" {
2257
2301
  * - Web Audio API integration with master gain control
2258
2302
  * @namespace Audio
2259
2303
  */
2260
- /** 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.
2261
2307
  * @type {AudioContext}
2262
2308
  * @memberof Audio */
2263
2309
  export let audioContext: AudioContext;
@@ -2269,6 +2315,10 @@ declare module "littlejsengine" {
2269
2315
  * @default 44100
2270
2316
  * @memberof Audio */
2271
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;
2272
2322
  /**
2273
2323
  * Sound Object - Stores a sound for later
2274
2324
  * - this can be used to load and play wave, mp3, and ogg files
@@ -3158,16 +3208,6 @@ declare module "littlejsengine" {
3158
3208
  /** Render the particle, automatically called each frame */
3159
3209
  render(): void;
3160
3210
  }
3161
- /**
3162
- * LittleJS Medal System
3163
- * - Achievement/trophy system for games
3164
- * - Medal class with name, description, icon, and unlock tracking
3165
- * - Automatic saving to local storage
3166
- * - Visual display queue with slide-in notifications
3167
- * - Newgrounds API integration for online achievements
3168
- * - Debug mode to unlock/reset medals during development
3169
- * @namespace Medals
3170
- */
3171
3211
  /** List of all medals
3172
3212
  * @type {Object}
3173
3213
  * @memberof Medals */
@@ -3183,6 +3223,15 @@ declare module "littlejsengine" {
3183
3223
  * @param {string} saveName
3184
3224
  * @memberof Medals */
3185
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;
3186
3235
  /**
3187
3236
  * Medal - Tracks an unlockable medal
3188
3237
  * @memberof Medals
@@ -3229,6 +3278,37 @@ declare module "littlejsengine" {
3229
3278
  renderIcon(pos: Vector2, size: number): void;
3230
3279
  storageKey(): string;
3231
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;
3232
3312
  /**
3233
3313
  * LittleJS Newgrounds Plugin
3234
3314
  * - NewgroundsMedal extends Medal with Newgrounds API functionality
@@ -3478,8 +3558,10 @@ declare module "littlejsengine" {
3478
3558
  lastHoverObject: any;
3479
3559
  /** @property {UIObject} - Current confirm menu being shown */
3480
3560
  confirmDialog: any;
3481
- /** @property {UIObject} - Object to send keyboard input to */
3482
- keyInputObject: any;
3561
+ /** @private */
3562
+ private _keyInputObject;
3563
+ /** @private */
3564
+ private _onKeyDown;
3483
3565
  /** Draw a rectangle to the UI context
3484
3566
  * @param {Vector2} pos
3485
3567
  * @param {Vector2} size
@@ -3541,8 +3623,14 @@ declare module "littlejsengine" {
3541
3623
  * @param {Vector2} pos
3542
3624
  * @return {Vector2} */
3543
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;
3544
3632
  /** Destroy and remove all objects
3545
- * @memberof Engine */
3633
+ * @memberof UISystem */
3546
3634
  destroyObjects(): void;
3547
3635
  /** Get all navigable UI objects sorted by navigationIndex
3548
3636
  * @return {Array<UIObject>} */
@@ -3891,6 +3979,37 @@ declare module "littlejsengine" {
3891
3979
  * @param {number} time - Time in seconds to seek to */
3892
3980
  setTime(time: number): void;
3893
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
+ }
3894
4013
  /**
3895
4014
  * LittleJS Box2D Physics Plugin
3896
4015
  * - Box2dObject extends EngineObject with Box2D physics
@@ -4214,13 +4333,25 @@ declare module "littlejsengine" {
4214
4333
  * @param {Vector2} force
4215
4334
  * @param {Vector2} [pos] */
4216
4335
  applyForce(force: Vector2, pos?: Vector2): void;
4217
- /** 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.
4218
4340
  * @param {Vector2} acceleration
4219
4341
  * @param {Vector2} [pos] */
4220
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;
4221
4348
  /** Apply torque to this object
4222
4349
  * @param {number} torque */
4223
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;
4224
4355
  /** Check if this object has any fixtures
4225
4356
  * @return {boolean} */
4226
4357
  hasFixtures(): boolean;
@@ -5071,4 +5202,168 @@ declare module "littlejsengine" {
5071
5202
  function PIECEWISE(...fns: ((arg0: number) => number)[]): (arg0: number) => number;
5072
5203
  function BEZIER(x1: number, y1: number, x2: number, y2: number): (arg0: number) => number;
5073
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
+ }
5074
5369
  }