littlejsengine 1.25.0 → 1.26.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +99 -0
  2. package/FAQ.md +49 -11
  3. package/README.md +6 -2
  4. package/REFERENCE.md +129 -21
  5. package/dist/littlejs.d.ts +487 -102
  6. package/dist/littlejs.esm.js +2898 -719
  7. package/dist/littlejs.esm.min.js +3 -3
  8. package/dist/littlejs.js +2888 -716
  9. package/dist/littlejs.min.js +2 -2
  10. package/dist/littlejs.release.js +2702 -527
  11. package/package.json +4 -4
  12. package/plugins/box2d.js +110 -34
  13. package/plugins/gltf.js +74 -22
  14. package/plugins/lightSystem.js +410 -28
  15. package/plugins/math3d.js +4 -2
  16. package/plugins/medalSystem.js +19 -7
  17. package/plugins/newgrounds.js +4 -2
  18. package/plugins/parallax.js +1 -0
  19. package/plugins/particleEffects.js +44 -10
  20. package/plugins/pathFinder.js +9 -11
  21. package/plugins/pluginExport.js +9 -0
  22. package/plugins/postProcess.js +9 -3
  23. package/plugins/render3d.js +499 -2389
  24. package/plugins/render3dDebug.js +5 -8
  25. package/plugins/render3dEditor.js +81 -6
  26. package/plugins/render3dExtras.js +103 -31
  27. package/plugins/render3dLevel.js +53 -5
  28. package/plugins/render3dMesh.js +1158 -0
  29. package/plugins/render3dObject.js +1451 -0
  30. package/plugins/render3dVoxels.js +15 -3
  31. package/plugins/textureSheet.js +9 -8
  32. package/plugins/threejs.js +1 -1
  33. package/plugins/tweenSystem.js +76 -51
  34. package/plugins/uiSystem.js +37 -8
  35. package/plugins/wavedash.js +229 -0
  36. package/src/engine.js +199 -40
  37. package/src/engineAudio.js +37 -21
  38. package/src/engineBuild.mjs +6 -1
  39. package/src/engineDebug.js +22 -162
  40. package/src/engineDraw.js +142 -34
  41. package/src/engineEditor.js +79 -18
  42. package/src/engineExport.js +1 -3
  43. package/src/engineInput.js +34 -24
  44. package/src/engineMath.js +35 -14
  45. package/src/engineObject.js +60 -41
  46. package/src/engineParticles.js +58 -11
  47. package/src/engineRelease.js +1 -5
  48. package/src/engineSettings.js +48 -9
  49. package/src/engineTileLayer.js +11 -4
  50. package/src/engineUtilities.js +41 -9
  51. package/src/engineWebGL.js +37 -13
@@ -85,7 +85,7 @@ declare module "littlejsengine" {
85
85
  */
86
86
  export type SpriteAnimationEndCallback = () => void;
87
87
  /**
88
- * - Function called when sound is loaded
88
+ * - Function called once a sound has loaded, or failed to, which sound.isLoaded() tells
89
89
  */
90
90
  export type SoundLoadCallback = (sound: Sound) => any;
91
91
  /**
@@ -191,6 +191,7 @@ declare module "littlejsengine" {
191
191
  reflectivity: number;
192
192
  emissiveMap: TextureInfo | undefined;
193
193
  emissiveMapColor: Color;
194
+ environmentMap: CubeMap | undefined;
194
195
  emissiveR: number;
195
196
  emissiveG: number;
196
197
  emissiveB: number;
@@ -295,7 +296,8 @@ declare module "littlejsengine" {
295
296
  */
296
297
  objects: Array<any>;
297
298
  /**
298
- * - The scene block: sky, ambient, sunDirection, sunColor, fog, fogColor, shadows, lensFlare
299
+ * - The scene block: sky, ambient, sunDirection, sunColor, fog, fogColor, shadows, lensFlare,
300
+ * skyBox, environment
299
301
  */
300
302
  scene?: any;
301
303
  /**
@@ -604,6 +606,8 @@ declare module "littlejsengine" {
604
606
  * @memberof Engine */
605
607
  export let frame: number;
606
608
  /** Current engine time since start in seconds
609
+ * - Below 20 FPS it falls behind the clock, since a frame catches up at most 50 ms of updates, so a timer in
610
+ * real seconds, one that must keep up on a slow device, goes by timeReal
607
611
  * @type {number}
608
612
  * @memberof Engine */
609
613
  export let time: number;
@@ -611,6 +615,10 @@ declare module "littlejsengine" {
611
615
  * @type {number}
612
616
  * @memberof Engine */
613
617
  export let timeReal: number;
618
+ /** Frames drawn per second, smoothed over the last few seconds, in release builds too
619
+ * @type {number}
620
+ * @memberof Engine */
621
+ export let averageFPS: number;
614
622
  /** Is the game paused? Causes time and objects to not be updated
615
623
  * @type {boolean}
616
624
  * @default false
@@ -644,8 +652,10 @@ declare module "littlejsengine" {
644
652
  * @param {GameCallback} [gameUpdatePost] - Called after physics and objects are updated, even when paused, use for UI updates
645
653
  * @param {GameCallback} [gameRender] - Called before objects are rendered, use for drawing backgrounds/world elements
646
654
  * @param {GameCallback} [gameRenderPost] - Called after objects are rendered, use for drawing UI/overlays
647
- * @param {Array<string>} [imageSources=[]] - List of image file paths to preload (e.g., ['player.png', 'tiles.png'])
648
- * @param {HTMLElement} [rootElement] - Root DOM element to attach canvas to, defaults to document.body
655
+ * @param {Array<string>|string} [imageSources=[]] - List of image file paths to preload (e.g., ['player.png', 'tiles.png']), or one path
656
+ * @param {HTMLElement} [rootElement] - Root DOM element to attach canvas to, defaults to document.body; it is
657
+ * styled for a game (no scroll bars or selection, touch-action none),
658
+ * where its own inline style does not say otherwise
649
659
  * It keeps its own inline styles and the canvas centers inside it, but the canvas is still sized from the window,
650
660
  * so set canvasFixedSize or canvasMaxSize to fit a smaller element
651
661
  * @example
@@ -660,7 +670,7 @@ declare module "littlejsengine" {
660
670
  * );
661
671
  * @memberof Engine
662
672
  * @return {Promise<void>} - Done when the images have loaded and gameInit has run */
663
- export function engineInit(gameInit?: GameInitCallback, gameUpdate?: GameCallback, gameUpdatePost?: GameCallback, gameRender?: GameCallback, gameRenderPost?: GameCallback, imageSources?: string[], rootElement?: HTMLElement): Promise<void>;
673
+ export function engineInit(gameInit?: GameInitCallback, gameUpdate?: GameCallback, gameUpdatePost?: GameCallback, gameRender?: GameCallback, gameRenderPost?: GameCallback, imageSources?: string | string[], rootElement?: HTMLElement): Promise<void>;
664
674
  /** Advance the engine by a number of frames
665
675
  * Requires setEngineManualStep(true), before engineInit or while running; it stops early if an update turns it off
666
676
  * Respects paused exactly as the normal update loop does
@@ -670,7 +680,7 @@ declare module "littlejsengine" {
670
680
  * setHeadlessMode(true);
671
681
  * setEngineManualStep(true);
672
682
  * await engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost);
673
- * engineStep(600); // advance 10 seconds of game time
683
+ * engineStep(600); // 600 updates of 1/60 second; the first is at time 0, so time is then 599/60
674
684
  * @memberof Engine */
675
685
  export function engineStep(frames?: number): void;
676
686
  /** Update each engine object and remove destroyed objects; time and frame are advanced by the engine loop, not here
@@ -747,7 +757,7 @@ declare module "littlejsengine" {
747
757
  * - setDebugKeysAlways lets those keys work with the overlay closed too
748
758
  * - ASSERT and LOG macros for development (removed in release builds)
749
759
  * - Debug primitive rendering (rectangles, circles, lines, points, text)
750
- * - Screenshot and video capture support
760
+ * - Screenshot support
751
761
  * - FPS counter and performance watermark
752
762
  * - Debug overlay shows mouse position and picked objects
753
763
  * @namespace Debug
@@ -1113,16 +1123,6 @@ declare module "littlejsengine" {
1113
1123
  * In release builds this function has no effect
1114
1124
  * @memberof Debug */
1115
1125
  export function debugShowErrors(): void;
1116
- /** Start capturing video
1117
- * @memberof Debug */
1118
- export function debugVideoCaptureStart(): void;
1119
- /** Stop capturing video and save to disk
1120
- * @memberof Debug */
1121
- export function debugVideoCaptureStop(): void;
1122
- /** Check if video capture is active
1123
- * @memberof Debug
1124
- * @return {boolean} */
1125
- export function debugVideoCaptureIsActive(): boolean;
1126
1126
  /**
1127
1127
  * LittleJS Engine Settings
1128
1128
  * - All settings for the engine are here
@@ -1504,6 +1504,7 @@ declare module "littlejsengine" {
1504
1504
  export function setCameraScale(scale: number): void;
1505
1505
  /** Set scale applied to engine time
1506
1506
  * - 0 freezes the game like a pause, gameUpdatePost and input still run so the game can set it back
1507
+ * - Above 1 the fixed step runs that many updates each frame, so a large scale costs as many updates
1507
1508
  * @param {number} scale - 0 or more
1508
1509
  * @memberof Settings */
1509
1510
  export function setTimeScale(scale: number): void;
@@ -1563,6 +1564,7 @@ declare module "littlejsengine" {
1563
1564
  * @memberof Settings */
1564
1565
  export function getCanvasPixelRatio(): number;
1565
1566
  /** Set default font used for text rendering
1567
+ * - A family name with spaces or digits goes in quotes, as "'Press Start 2P'", or the canvas does not take it
1566
1568
  * @param {string} font
1567
1569
  * @memberof Settings */
1568
1570
  export function setFontDefault(font: string): void;
@@ -1732,7 +1734,8 @@ declare module "littlejsengine" {
1732
1734
  * @param {boolean} enable
1733
1735
  * @memberof Settings */
1734
1736
  export function setVibrateEnable(enable: boolean): void;
1735
- /** Set if audio is enabled, false turns all sound off
1737
+ /** Set if audio is enabled, false turns all sound off; a setting for before sounds are made, since a sound made
1738
+ * while it is off has nothing to play and one already playing goes on; to mute while the game runs, setSoundVolume(0)
1736
1739
  * @param {boolean} enable
1737
1740
  * @memberof Settings */
1738
1741
  export function setSoundEnable(enable: boolean): void;
@@ -1835,7 +1838,7 @@ declare module "littlejsengine" {
1835
1838
  * @param {...number} values
1836
1839
  * @return {number}
1837
1840
  * @memberof Math */
1838
- export function hypot(...values: number[]): number;
1841
+ export const hypot: (...values: number[]) => number;
1839
1842
  /** Returns log2 of value passed in
1840
1843
  * @param {number} x
1841
1844
  * @return {number}
@@ -2073,7 +2076,7 @@ declare module "littlejsengine" {
2073
2076
  * @return {number}
2074
2077
  * @memberof Utilities */
2075
2078
  export function noise1D(x: number): number;
2076
- /** 2D value noise — returns a smooth value in [0, 1] for any real (x, y).
2079
+ /** 2D value noise — returns a smooth value in [0, 1] for any real (x, y)
2077
2080
  * @param {number} x
2078
2081
  * @param {number} y
2079
2082
  * @return {number}
@@ -2895,6 +2898,9 @@ declare module "littlejsengine" {
2895
2898
  * across the sprite or the mesh's own uv
2896
2899
  * - Names in 3D only: worldPos, worldNormal, cameraPos, sunDirection, sunColor, ambientColor, ambientGroundColor,
2897
2900
  * lightCount, lights[i], lightColors[i] and shadow()
2901
+ * - In 3D the snippet may also define void mainNormal(inout vec3 n), given the normal facing the camera after the
2902
+ * normal map, in world space, to bend it per pixel for waves or ripples; the lighting, specular, reflection and
2903
+ * fog then all use it, as they use a normal map
2898
2904
  * - In 3D the shadow map is drawn without the Shader, cut only by the texture's alpha, so a snippet that removes
2899
2905
  * parts of a surface still shadows with the whole of it
2900
2906
  * @example
@@ -2921,6 +2927,11 @@ declare module "littlejsengine" {
2921
2927
  /** @property {WebGLProgram|undefined} - The 3D program, compiled by the 3D plugin the same way, read only
2922
2928
  * @type {WebGLProgram|undefined} */
2923
2929
  program3D: WebGLProgram | undefined;
2930
+ /** Let go of this shader: its compiled programs are freed and it leaves the engine's list of shaders, which
2931
+ * keeps every one made for a lost context, so a scene made again and again, or an editor trying snippets, does
2932
+ * not keep them all; calling it again does nothing, and a draw with it afterwards compiles it again and takes it
2933
+ * back, so only let go of one no object still draws with when it should stay freed */
2934
+ dispose(): void;
2924
2935
  }
2925
2936
  /**
2926
2937
  * LittleJS Drawing System
@@ -3236,7 +3247,7 @@ declare module "littlejsengine" {
3236
3247
  export function setShader(shader?: Shader): void;
3237
3248
  /** Set an extra canvas to composite behind the engine canvases when combining
3238
3249
  * Plugins that insert their own canvas below the LittleJS canvases should set
3239
- * this so it appears in screenshots and video capture
3250
+ * this so it appears in screenshots
3240
3251
  * @param {HTMLCanvasElement} [canvas]
3241
3252
  * @memberof Draw */
3242
3253
  export function setBackgroundCanvas(canvas?: HTMLCanvasElement): void;
@@ -3760,7 +3771,6 @@ declare module "littlejsengine" {
3760
3771
  * - The output node is disconnected from everything else first, so it only feeds the speakers
3761
3772
  * - The two ends of a chain must already be connected to each other, like effectA.connect(effectB)
3762
3773
  * - Call with no arguments to remove the effect, an effect that was the master goes back to feeding the master gain
3763
- * - Debug video capture records the end of the master chain, but loses its tap if the effect changes mid-capture
3764
3774
  * @param {AudioNode|AudioEffectNodes} [input] - Node or effect the master gain connects to
3765
3775
  * @param {AudioNode|AudioEffectNodes} [output] - Node or effect that connects to the audio destination, defaults to the input's output
3766
3776
  * @memberof Audio */
@@ -3774,7 +3784,7 @@ declare module "littlejsengine" {
3774
3784
  * @memberof Audio */
3775
3785
  export function audioIsRunning(): boolean;
3776
3786
  /**
3777
- * @callback SoundLoadCallback - Function called when sound is loaded
3787
+ * @callback SoundLoadCallback - Function called once a sound has loaded, or failed to, which sound.isLoaded() tells
3778
3788
  * @param {Sound} sound
3779
3789
  * @memberof Audio
3780
3790
  */
@@ -3803,7 +3813,8 @@ declare module "littlejsengine" {
3803
3813
  * @param {number} [randomness] - How much to randomize frequency each time sound plays, for zzfx sounds it overrides the array's own randomness, which is used if undefined
3804
3814
  * @param {number} [range=soundDefaultRange] - World space max range of sound
3805
3815
  * @param {number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering
3806
- * @param {SoundLoadCallback} [onloadCallback] - callback function to call when sound is loaded
3816
+ * @param {SoundLoadCallback} [onloadCallback] - Called once the sound has loaded, or its file failed to, so a
3817
+ * game counting its sounds goes on; isLoaded says which
3807
3818
  */
3808
3819
  constructor(asset?: string | URL | (number | undefined)[], randomness?: number, range?: number, taper?: number, onloadCallback?: SoundLoadCallback);
3809
3820
  loadedPercent: number;
@@ -3893,7 +3904,7 @@ declare module "littlejsengine" {
3893
3904
  * @return {boolean} - True if sound is loaded and ready to play
3894
3905
  */
3895
3906
  isLoaded(): boolean;
3896
- /** Loads a sound from a URL and decodes it into sample data.
3907
+ /** Loads a sound from a URL and decodes it into sample data
3897
3908
  * @param {string} filename
3898
3909
  * @return {Promise} */
3899
3910
  loadSound(filename: string): Promise<any>;
@@ -3925,11 +3936,11 @@ declare module "littlejsengine" {
3925
3936
  /** @property {Sound} - The sound object */
3926
3937
  sound: Sound;
3927
3938
  /** @property {number} - How much to scale volume by */
3928
- volume: number;
3939
+ volume: any;
3929
3940
  /** @property {number} - The playback rate to use */
3930
- rate: number;
3941
+ rate: any;
3931
3942
  /** @property {number} - How much to apply stereo panning */
3932
- pan: number;
3943
+ pan: any;
3933
3944
  /** @property {boolean} - Should the sound loop */
3934
3945
  loop: boolean;
3935
3946
  /** @property {number|undefined} - Where it is in the sound while not playing, in the sound's own seconds, undefined while playing
@@ -4082,8 +4093,8 @@ declare module "littlejsengine" {
4082
4093
  * @param {number} [release] - Release time, how fast sound fades out (seconds)
4083
4094
  * @param {number} [shape] - Shape of the sound wave
4084
4095
  * @param {number} [shapeCurve] - Squareness of wave (0=square, 1=normal, 2=pointy)
4085
- * @param {number} [slide] - How much to slide frequency (kHz/s)
4086
- * @param {number} [deltaSlide] - How much to change slide (kHz/s/s)
4096
+ * @param {number} [slide] - How much to slide frequency, 1 is about 500 Hz a second, as ZzFX has it
4097
+ * @param {number} [deltaSlide] - How much to change slide each second, in the units of slide
4087
4098
  * @param {number} [pitchJump] - Frequency of pitch jump (Hz)
4088
4099
  * @param {number} [pitchJumpTime] - Time of pitch jump (seconds)
4089
4100
  * @param {number} [repeatTime] - Resets some parameters periodically (seconds)
@@ -4094,7 +4105,8 @@ declare module "littlejsengine" {
4094
4105
  * @param {number} [sustainVolume] - Volume level for sustain (percent)
4095
4106
  * @param {number} [decay] - Decay time, how long to reach sustain after attack (seconds)
4096
4107
  * @param {number} [tremolo] - Trembling effect, rate controlled by repeat time (percent)
4097
- * @param {number} [filter] - Filter cutoff frequency, positive for HPF, negative for LPF (Hz)
4108
+ * @param {number} [filter] - Filter cutoff, positive for HPF, negative for LPF; the cutoff is about twice this in
4109
+ * Hz, as ZzFX has it, and its resonance can take the samples past 1
4098
4110
  * @return {Float32Array} - The audio samples
4099
4111
  * @memberof Audio */
4100
4112
  export function zzfxG(volume?: number, randomness?: number, frequency?: number, attack?: number, sustain?: number, release?: number, shape?: number, shapeCurve?: number, slide?: number, deltaSlide?: number, pitchJump?: number, pitchJumpTime?: number, repeatTime?: number, noise?: number, modulation?: number, bitCrush?: number, delay?: number, sustainVolume?: number, decay?: number, tremolo?: number, filter?: number): Float32Array;
@@ -4167,6 +4179,9 @@ declare module "littlejsengine" {
4167
4179
  shader: Shader | undefined;
4168
4180
  /** @property {boolean} - Does this object draw into the light system's shadow map; false for a floor layer, a background, a pickup */
4169
4181
  castShadow: boolean;
4182
+ /** @property {boolean} - Does this object draw into the light system's background map, which a
4183
+ * DirectionalLight lights only at its edges facing the light; for a background layer, with castShadow false */
4184
+ castBackgroundShadow: boolean;
4170
4185
  /** @property {number} - With the light system, how much it lights itself: 0 lit only by the lights, 1 full
4171
4186
  * brightness in its own colors whatever the lights do, between partly; drawn into the lightmap through
4172
4187
  * renderEmissive, as 3D's emissive. Exact for solid pixels; a partly transparent one is self lit by its alpha
@@ -4230,15 +4245,19 @@ declare module "littlejsengine" {
4230
4245
  /** Update the object transform, called automatically by engine even when paused
4231
4246
  * @param {boolean} [updateChildren] - Also update the children's transforms */
4232
4247
  updateTransforms(updateChildren?: boolean): void;
4233
- /** Update the object physics, called automatically by engine once each frame. Can be overridden to stop or change how physics works for an object. */
4248
+ /** Update the object physics, called automatically by engine once each frame. Can be overridden to stop or change how physics works for an object
4249
+ * - With many solids each mover finds those near it through a grid, which follows a solid after its own physics
4250
+ * update: a solid an override moves for another object, a lift carrying a crate, is found there from the next
4251
+ * update on */
4234
4252
  updatePhysics(): void;
4235
- /** Update the object, called automatically by engine once each frame. Does nothing by default. */
4253
+ /** Update the object, called automatically by engine once each frame. Does nothing by default */
4236
4254
  update(): void;
4237
4255
  /** Render the object, draws a tile by default, automatically called each frame, sorted by renderOrder */
4238
4256
  render(): void;
4239
- /** Optional hook called during the light system plugin's lightmap pass to draw this object's lightmap contribution. Does nothing by default. */
4257
+ /** Optional hook called during the light system plugin's lightmap pass to draw this object's lightmap contribution. Does nothing by default */
4240
4258
  renderLight(): void;
4241
- /** Draw this object into the light system's shadow map, called during its shadow pass when castShadow is set.
4259
+ /** Draw this object into the light system's shadow map, called during its shadow pass when castShadow is set, and into
4260
+ * its background map when castBackgroundShadow is set and a DirectionalLight is out.
4242
4261
  * Calls render() by default so the object casts its own shape; override to cast a different one, like a blob at a character's feet so its body stays lit;
4243
4262
  * screen space WebGL draws in render() are skipped during the pass */
4244
4263
  renderShadow(): void;
@@ -4265,19 +4284,23 @@ declare module "littlejsengine" {
4265
4284
  * @param {Vector2} vec - world space vector
4266
4285
  * @return {Vector2} */
4267
4286
  worldToLocalVector(vec: Vector2): Vector2;
4268
- /** Called to check if a tile collision should be resolved. Return true for physics to resolve the collision or false to ignore and resolve it manually.
4287
+ /** Called to check if a tile collision should be resolved. Return true for physics to resolve the collision or false to ignore and resolve it manually
4269
4288
  * - Called for each solid tile the physics tests, which can be several times a frame for the same tile, and for
4270
4289
  * positions it only tries, so keep it free of side effects or guard them to once a frame
4271
4290
  * - this.pos has already moved, so a check on where it came from, like a one way platform, needs the position
4272
4291
  * saved in update, as the platformer example does
4292
+ * - For the point of impact, like sparks where a bullet hit, raycast from where this frame's move started,
4293
+ * this.pos minus this.velocity, to this.pos with tileCollisionRaycast, as the platformer's Bullet does
4273
4294
  * @param {number} tileData - the value of the tile at the position
4274
4295
  * @param {Vector2} pos - the tile's bottom left corner in world space
4275
4296
  * @return {boolean} - true if the collision should be resolved by modifying it's position and velocity */
4276
4297
  collideWithTile(tileData: number, pos: Vector2): boolean;
4277
- /** Called by the engine to check if an object collision should be resolved. Return true for physics to resolve the collision or false to ignore and resolve it manually.
4298
+ /** Called by the engine to check if an object collision should be resolved. Return true for physics to resolve the collision or false to ignore and resolve it manually
4278
4299
  * - Both objects of a touching pair are asked once a frame, whichever order they update in; an object that
4279
4300
  * destroys itself here is gone at the end of the frame and is still asked about the pairs left this frame, so a
4280
4301
  * bullet that should hit one thing checks its own destroyed flag first
4302
+ * - With many solids each mover finds those near it through a grid, which follows the other object after this
4303
+ * returns; a third object moved here is found where it is now from the next update on
4281
4304
  * @param {EngineObject} object - the object to test against
4282
4305
  * @param {Vector3} [push] - what it would take to move this object clear, a Vector3 from the 3D plugin, undefined in 2D
4283
4306
  * @return {boolean} - true if the collision should be resolved by modifying it's position and velocity
@@ -4781,7 +4804,7 @@ declare module "littlejsengine" {
4781
4804
  * @param {number} [angleSpeed] - How fast are particles rotating, in radians per frame (at 60fps)
4782
4805
  * @param {number} [damping] - How much to dampen particle speed, per-frame velocity multiplier (1 = no damping, .9 = lose 10% speed each frame)
4783
4806
  * @param {number} [angleDamping] - How much to dampen particle angular speed, per-frame multiplier (1 = no damping)
4784
- * @param {number} [gravityScale] - How much gravity effect particles
4807
+ * @param {number} [gravityScale] - How much gravity affects particles
4785
4808
  * @param {number} [particleConeAngle] - Half angle each side of the emitter's angle for a particle's start angle, PI is any angle
4786
4809
  * @param {number} [fadeRate] - Fraction of life spent fading: half at fade-in (start), half at fade-out (end). e.g. .2 = 10% fade-in, 80% full opacity, 10% fade-out
4787
4810
  * @param {number} [randomness] - Apply extra randomness percent
@@ -4796,7 +4819,8 @@ declare module "littlejsengine" {
4796
4819
  emitCircle: boolean;
4797
4820
  /** @property {Vector2} - World space size of the emitter, x is the diameter when emitCircle is set */
4798
4821
  emitSize: Vector2;
4799
- /** @property {number} - How long to stay alive (0 is forever) */
4822
+ /** @property {number} - How long to emit for in seconds, 0 is forever; raised while its particles are still
4823
+ * alive, it emits again for the added time */
4800
4824
  emitTime: number;
4801
4825
  /** @property {number} - How many particles per second to spawn, does not emit if 0 */
4802
4826
  emitRate: number;
@@ -4857,12 +4881,17 @@ declare module "littlejsengine" {
4857
4881
  velocityInheritance: number;
4858
4882
  /** @property {number} - Particles owed to the emit rate, starts at one so the first comes out at once */
4859
4883
  emitTimeBuffer: number;
4884
+ /** @property {number} - Seconds of its emit time it has emitted for, counted by its updates
4885
+ * @type {number} */
4886
+ emitElapsed: number;
4860
4887
  /** @property {Array<Particle>} - Array of particles for this emitter
4861
4888
  * @type {Array<Particle>} */
4862
4889
  particles: Array<Particle>;
4863
4890
  /** @type {Vector2|undefined} */
4864
4891
  previousPos: Vector2 | undefined;
4865
4892
  previousAngle: number;
4893
+ emitFrom: Vector2;
4894
+ emitBehind: number;
4866
4895
  /** Spawn one particle
4867
4896
  * @return {Particle} */
4868
4897
  emitParticle(): Particle;
@@ -4966,6 +4995,7 @@ declare module "littlejsengine" {
4966
4995
  * - Call this after creating all medals
4967
4996
  * - Loads which medals are unlocked from the save, and writes the catalog back
4968
4997
  * - A medal a service like Newgrounds holds is left as it is, see Medal.isLocal
4998
+ * - A medal unlocked before the first call stays unlocked and is saved by it
4969
4999
  * @param {string} saveName - The localStorage key the medals are kept under, a different one from the game's own
4970
5000
  * readSaveData and writeSaveData, or each would overwrite the other
4971
5001
  * @memberof Medals */
@@ -5097,10 +5127,12 @@ declare module "littlejsengine" {
5097
5127
  cryptoKey: CryptoKey | undefined;
5098
5128
  /** @property {string} - Hostname sent with the view the plugin logs when it starts */
5099
5129
  host: string;
5100
- /** @property {Array} - Medals fetched from Newgrounds, empty until ready, with the unlocks only when logged in */
5101
- medals: any[];
5102
- /** @property {Array} - Scoreboards fetched from Newgrounds, empty until ready */
5103
- scoreboards: any[];
5130
+ /** @property {Array<Object>} - Medals fetched from Newgrounds, empty until ready, with the unlocks only when logged in
5131
+ * @type {Array<Object>} */
5132
+ medals: Array<any>;
5133
+ /** @property {Array<Object>} - Scoreboards fetched from Newgrounds, empty until ready
5134
+ * @type {Array<Object>} */
5135
+ scoreboards: Array<any>;
5104
5136
  /** @property {{id: number, name: string, url: string, supporter: boolean}|null} - The logged in player once ready, null when not logged in
5105
5137
  * @type {{id: number, name: string, url: string, supporter: boolean}|null} */
5106
5138
  user: {
@@ -5176,6 +5208,123 @@ declare module "littlejsengine" {
5176
5208
  * @type {number|undefined} */
5177
5209
  value: number | undefined;
5178
5210
  }
5211
+ /**
5212
+ * LittleJS Wavedash Plugin
5213
+ * - The Wavedash twin of the Newgrounds plugin: achievements and leaderboards, the same shape so a game can switch
5214
+ * - Wavedash serves the game's page and puts its SDK in window.Wavedash before the game runs, so nothing is bundled;
5215
+ * off Wavedash (local, itch, GitHub Pages) there is none, and every call does nothing
5216
+ * - Make the plugin when the game can draw, at the end of gameInit: Wavedash.init is called then, and until it is
5217
+ * Wavedash keeps its loading screen over the game
5218
+ * - WavedashMedal is a Medal with the identifier of its Wavedash achievement; on Wavedash an unlock is sent as that
5219
+ * achievement and Wavedash shows its own toast in place of the engine's popup, off it the medal unlocks as any does
5220
+ * - Wavedash refuses an achievement until it has loaded the player's, a moment after launch, so refused and earlier
5221
+ * unlocks are sent again every two seconds until it takes them; medals unlocked before, in the save, are sent too
5222
+ * - Leaderboards are made from code: give the plugin a table of them, each with how it sorts and shows its scores,
5223
+ * and they are made at once, so each one exists from the first launch
5224
+ * - The SDK checks its arguments' types and throws on a wrong one, so every call passes real booleans and whole
5225
+ * numbers and is caught; a game built with its own minifier keeps the SDK's names, see REFERENCE
5226
+ * @namespace Wavedash
5227
+ */
5228
+ /** Global Wavedash plugin object
5229
+ * @type {WavedashPlugin}
5230
+ * @memberof Wavedash */
5231
+ export let wavedash: WavedashPlugin;
5232
+ /**
5233
+ * Wavedash plugin: starts the Wavedash SDK, sends achievements and posts and reads leaderboards
5234
+ * @memberof Wavedash
5235
+ * @example
5236
+ * // at the end of gameInit, with the leaderboards the game posts to
5237
+ * new WavedashPlugin({LEVEL_1: {lowerWins: true, display: 'milliseconds'}, HIGH_SCORE: {}});
5238
+ * wavedash.postScore('LEVEL_1', timeMs);
5239
+ */
5240
+ export class WavedashPlugin {
5241
+ /** Start the Wavedash SDK when the game is on Wavedash, and make its leaderboards
5242
+ * @param {Object<string, {lowerWins?: boolean, display?: string}>} [leaderboards] - The game's leaderboards by
5243
+ * name: lowerWins for times and golf, where a lower score is better, higher wins when left out; display how
5244
+ * Wavedash shows a score, 'number', 'seconds', 'milliseconds' or 'ticks' (60 a second), 'number' when left out
5245
+ */
5246
+ constructor(leaderboards?: {
5247
+ [x: string]: {
5248
+ lowerWins?: boolean;
5249
+ display?: string;
5250
+ };
5251
+ });
5252
+ /** @property {Object<string, Promise<string|undefined>>} - Each leaderboard's id by its name, once Wavedash
5253
+ * has made or found it, undefined when it could not
5254
+ * @type {Object<string, Promise<string|undefined>>} */
5255
+ leaderboards: {
5256
+ [x: string]: Promise<string | undefined>;
5257
+ };
5258
+ /** @type {Object<string, {lowerWins?: boolean, display?: string}>} */
5259
+ leaderboardSettings: {
5260
+ [x: string]: {
5261
+ lowerWins?: boolean;
5262
+ display?: string;
5263
+ };
5264
+ };
5265
+ /** @type {Set<string>} */
5266
+ achievementsSent: Set<string>;
5267
+ /** @type {Object<string, number>} */
5268
+ achievementTries: {
5269
+ [x: string]: number;
5270
+ };
5271
+ /** @type {number|undefined} */
5272
+ achievementRetry: number | undefined;
5273
+ /** Whether the game is on Wavedash, its SDK on the page
5274
+ * @return {boolean} */
5275
+ isActive(): boolean;
5276
+ /** Call the SDK, undefined off Wavedash; a call that throws, as on an argument of the wrong type, says so in
5277
+ * the console and gives undefined
5278
+ * @param {string} name - The SDK function
5279
+ * @param {...*} args
5280
+ * @return {*}
5281
+ * @ignore */
5282
+ call(name: string, ...args: any[]): any;
5283
+ /** A leaderboard's id by its name, made on Wavedash the first time it is asked for, with the settings it was given
5284
+ * @param {string} name
5285
+ * @return {Promise<string|undefined>}
5286
+ * @ignore */
5287
+ leaderboard(name: string): Promise<string | undefined>;
5288
+ /** Post a score to a leaderboard, Wavedash keeping the player's best; off Wavedash it does nothing
5289
+ * - A leaderboard not in the table given to the plugin is made the first time, higher wins and shown as a number
5290
+ * @param {string} name - The leaderboard's name
5291
+ * @param {number} score - A whole number, milliseconds for a time
5292
+ * @return {Promise<boolean>} - Whether it was posted */
5293
+ postScore(name: string, score: number): Promise<boolean>;
5294
+ /** Read a leaderboard's entries, undefined off Wavedash or when it could not be read
5295
+ * @param {string} name - The leaderboard's name
5296
+ * @param {number} [offset] - How many entries to skip over
5297
+ * @param {number} [limit] - How many entries to read
5298
+ * @param {boolean} [friendsOnly] - Only the player and their friends
5299
+ * @return {Promise<Array<Object>|undefined>} - The entries, as Wavedash gives them */
5300
+ getScores(name: string, offset?: number, limit?: number, friendsOnly?: boolean): Promise<Array<any> | undefined>;
5301
+ /** Send every unlocked WavedashMedal's achievement Wavedash has not taken yet, again every two seconds while it
5302
+ * refuses some, as it does until it has loaded the player's achievements; one refused for about a minute is
5303
+ * taken as an identifier Wavedash does not have, said once in the console, and not sent again this visit
5304
+ * @ignore */
5305
+ sendAchievements(): void;
5306
+ }
5307
+ /**
5308
+ * WavedashMedal: a medal that is also a Wavedash achievement, unlocked on Wavedash by its identifier
5309
+ * @extends Medal
5310
+ * @memberof Wavedash
5311
+ * @example
5312
+ * const medal_finish = new WavedashMedal(0, 'ACH_01_FINISH', 'Finish', 'Finish a level');
5313
+ * medal_finish.unlock(); // Wavedash's toast on Wavedash, the engine's popup anywhere else
5314
+ */
5315
+ export class WavedashMedal extends Medal {
5316
+ /** Create a WavedashMedal and add it to the list of medals
5317
+ * @param {number} id - The unique identifier of the medal, as for any Medal
5318
+ * @param {string} achievement - The identifier of its Wavedash achievement, as made with the Wavedash CLI
5319
+ * @param {string} name - Name of the medal
5320
+ * @param {string} [description] - Description of the medal
5321
+ * @param {string} [icon] - Icon for the medal
5322
+ * @param {string} [src] - Image location for the medal
5323
+ */
5324
+ constructor(id: number, achievement: string, name: string, description?: string, icon?: string, src?: string);
5325
+ /** @property {string} - The identifier of its Wavedash achievement */
5326
+ achievement: string;
5327
+ }
5179
5328
  /**
5180
5329
  * LittleJS Post Processing Plugin
5181
5330
  * - Supports shadertoy style post processing shaders
@@ -5212,6 +5361,9 @@ declare module "littlejsengine" {
5212
5361
  constructor(shaderCode?: string, includeMainCanvas?: boolean, feedbackTexture?: boolean);
5213
5362
  /** @property {string} - The shadertoy style mainImage code it shades with, see setShaderCode */
5214
5363
  shaderCode: string;
5364
+ /** @property {boolean} - Is the pass on? Off, the frame shows as the engine drew it, the shader is kept,
5365
+ * and the feedback texture holds the last frame drawn with it on */
5366
+ enabled: boolean;
5215
5367
  /** @property {Object<string, number|Array<number>>} - The game's own values for the shader, a uniform each
5216
5368
  * by its name, a number a float and a list of 2 to 4 numbers a vector, set every frame as they are; an
5217
5369
  * effect setting can be one of these names, so it changes every frame without making the shader again, all
@@ -5408,6 +5560,8 @@ declare module "littlejsengine" {
5408
5560
  * setShadowTransparent lets its color tint the light
5409
5561
  * - Set light.glow for a soft hazy glow over a light, like a lamp at night; it is added over the lit scene after the
5410
5562
  * lightmap, so it shows in the dark and sits in front of everything there
5563
+ * - A DirectionalLight is a sun: one per scene, it lights everything from one direction, foreground casters throw long
5564
+ * shadows and objects with castBackgroundShadow are lit only at their edges facing it
5411
5565
  * - Must be constructed BEFORE PostProcessPlugin so post-process sees lit pixels
5412
5566
  * @namespace LightSystem
5413
5567
  */
@@ -5425,7 +5579,7 @@ declare module "littlejsengine" {
5425
5579
  * @memberof LightSystem
5426
5580
  */
5427
5581
  export class LightSystemPlugin {
5428
- /** Create the global light system plugin.
5582
+ /** Create the global light system plugin
5429
5583
  * @param {Vector2} [textureSize] - Size of the lightmap texture (defaults to following mainCanvasSize, which is css pixels, so the lightmap is not scaled by canvasPixelRatio; pass mainCanvasSize.scale(getCanvasPixelRatio()) for a full resolution lightmap)
5430
5584
  * @param {Color} [ambientColor] - Color applied to unlit areas of the scene (defaults to BLACK = pitch dark). Set a small RGB like rgb(0.1,0.1,0.15) for a faint "moonlight" baseline so unlit areas aren't fully black.
5431
5585
  * @example
@@ -5435,6 +5589,7 @@ declare module "littlejsengine" {
5435
5589
  constructor(textureSize?: Vector2, ambientColor?: Color);
5436
5590
  /** @property {boolean} - When false, the render pass is skipped entirely */
5437
5591
  enabled: boolean;
5592
+ shadersFailed: boolean;
5438
5593
  /** @property {Color} - Baseline color applied to unlit areas of the scene. Defaults to BLACK (pitch dark). Set to a small RGB for a faint ambient. The lightmap is cleared to this color each frame, then lights add on top, then the result multiplies the scene. */
5439
5594
  ambientColor: Color;
5440
5595
  /** @property {Vector2} - Size of the lightmap texture, follows mainCanvasSize (css pixels, so it is not scaled by canvasPixelRatio) unless a size was passed */
@@ -5478,6 +5633,10 @@ declare module "littlejsengine" {
5478
5633
  /** @property {WebGLTexture|undefined} - The shadow map, casters drawn black on white around the camera, read only
5479
5634
  * @type {WebGLTexture|undefined} */
5480
5635
  shadowMap: WebGLTexture | undefined;
5636
+ /** @property {WebGLTexture|undefined} - The background map, objects with castBackgroundShadow drawn black on
5637
+ * white, the shadow map's size and place, made by a directional light when something casts into it and kept while the light is, read only
5638
+ * @type {WebGLTexture|undefined} */
5639
+ backgroundMap: WebGLTexture | undefined;
5481
5640
  /** @property {WebGLTexture|undefined} - One of the two textures each light's shadow is built in
5482
5641
  * @type {WebGLTexture|undefined} */
5483
5642
  shadowTextureA: WebGLTexture | undefined;
@@ -5503,6 +5662,26 @@ declare module "littlejsengine" {
5503
5662
  shadowMapOrigin: Vector2;
5504
5663
  /** @property {number} - World size the shadow map covers, set each shadow pass */
5505
5664
  shadowMapWorldSize: number;
5665
+ /** @property {DirectionalLight|undefined} - The scene's directional light, a sun, or undefined, read only
5666
+ * @type {DirectionalLight|undefined} */
5667
+ directionalLight: DirectionalLight | undefined;
5668
+ /** @property {number} - Pixels across the square textures a directional light is built in, covering the
5669
+ * shadow map's area; larger is sharper and slower; a power of two, as shadowMapSize, so their texels line up */
5670
+ directionalTextureSize: number;
5671
+ /** @property {WebGLTexture|undefined} - The directional light as built this frame, white where it reaches,
5672
+ * over the shadow map's area, read only
5673
+ * @type {WebGLTexture|undefined} */
5674
+ directionalTexture: WebGLTexture | undefined;
5675
+ /** @type {WebGLTexture|undefined} */
5676
+ directionalTextureA: WebGLTexture | undefined;
5677
+ /** @type {WebGLTexture|undefined} */
5678
+ directionalTextureB: WebGLTexture | undefined;
5679
+ directionalTextureSizeAllocated: number;
5680
+ backgroundCasters: boolean;
5681
+ /** @type {Object<string, WebGLProgram|WebGLVertexArrayObject>} */
5682
+ directionalPrograms: {
5683
+ [x: string]: WebGLProgram | WebGLVertexArrayObject;
5684
+ };
5506
5685
  shadowMapSizeAllocated: number;
5507
5686
  shadowTextureSizeAllocated: number;
5508
5687
  /** Bring the sizes of the textures it makes down to what the device can make: shadowMapSize, shadowTextureSize
@@ -5567,6 +5746,34 @@ declare module "littlejsengine" {
5567
5746
  * called by LightSystemPlugin after the lightmap is applied */
5568
5747
  renderGlow(): void;
5569
5748
  }
5749
+ /**
5750
+ * A DirectionalLight is a sun for the 2D light system: it lights the whole scene from one direction, added into the
5751
+ * lightmap with the point lights
5752
+ * - One at a time, made after the LightSystemPlugin, lightSystem.directionalLight is the one; a debug build asserts on
5753
+ * a second while the first lives, a release build destroys the first
5754
+ * - Its castShadow lets foreground casters, objects with castShadow, throw long shadows across open space, fading out
5755
+ * by shadowLength; a light does not need lightSystem.shadows for that
5756
+ * - Objects with castBackgroundShadow, a background layer, are dark to it inside and lit at the edges that face it,
5757
+ * fading in by backgroundDepth
5758
+ * @extends EngineObject
5759
+ * @memberof LightSystem
5760
+ * @example
5761
+ * new DirectionalLight(vec2(-1, 1), hsl(.1, .3, 1)); // a warm sun up and to the left, shining down and to the right
5762
+ */
5763
+ export class DirectionalLight extends EngineObject {
5764
+ /** Create the scene's directional light
5765
+ * @param {Vector2} [sunDirection] - Toward the sun, it shines the other way, as render3D.sunDirection
5766
+ * @param {Color} [color] - Color of the light; alpha modulates intensity */
5767
+ constructor(sunDirection?: Vector2, color?: Color);
5768
+ /** @property {Vector2} - Toward the sun, it shines the other way, as render3D.sunDirection */
5769
+ sunDirection: Vector2;
5770
+ /** @property {number} - World units a long shadow reaches before it has faded out; a caster casts only from
5771
+ * inside the shadow map, shadowMapScale views across, so past (shadowMapScale - 1) / 2 of a view beyond the
5772
+ * screen it throws none in */
5773
+ shadowLength: number;
5774
+ /** @property {number} - World units the light gets into a background area from its edges facing it */
5775
+ backgroundDepth: number;
5776
+ }
5570
5777
  /**
5571
5778
  * LittleJS Audio Effects Plugin
5572
5779
  * - Web Audio effects with a wet/dry mix: filter, reverb, delay, distortion, compressor
@@ -6057,6 +6264,7 @@ declare module "littlejsengine" {
6057
6264
  textLineWidth: number;
6058
6265
  /** @property {boolean} - Should this object be drawn */
6059
6266
  visible: boolean;
6267
+ uiUpdatePass: number;
6060
6268
  /** @property {Array<UIObject>} - A list of this object's children
6061
6269
  * @type {Array<UIObject>} */
6062
6270
  children: Array<UIObject>;
@@ -6203,7 +6411,7 @@ declare module "littlejsengine" {
6203
6411
  * @param {string} [text]
6204
6412
  */
6205
6413
  constructor(pos?: Vector2, size?: Vector2, text?: string);
6206
- /** @property {number} - Max length of input (0 = no limit) */
6414
+ /** @property {number} - Max length of input in characters as a reader counts them (0 = no limit) */
6207
6415
  maxLength: number;
6208
6416
  text: string;
6209
6417
  /** Stop editing the text */
@@ -6549,6 +6757,10 @@ declare module "littlejsengine" {
6549
6757
  * - Provides interface for Box2D body and fixture functions
6550
6758
  * - Each object can have multiple fixtures and joints
6551
6759
  * - Angular values are clockwise like angle: angular velocity, torque, joint angles, limits and motor speeds
6760
+ * - Box2D moves the body, so the EngineObject physics fields do nothing on it: velocity, angleVelocity, damping,
6761
+ * angleDamping, mass, friction, restitution and gravityScale; use setLinearVelocity, setAngularVelocity,
6762
+ * setLinearDamping, setAngularDamping, setMass, the friction and restitution of its shapes and setGravityScale.
6763
+ * A debug build warns once when one of them is set
6552
6764
  * @extends EngineObject
6553
6765
  * @memberof Box2D
6554
6766
  */
@@ -6575,7 +6787,7 @@ declare module "littlejsengine" {
6575
6787
  * @type {Array<Array<Vector2>>} */
6576
6788
  edgeLoops: Array<Array<Vector2>>;
6577
6789
  edgeListFixtures: Map<any, any>;
6578
- /** Draws all this object's fixtures
6790
+ /** Draw all this object's fixtures
6579
6791
  * @param {Color} [color]
6580
6792
  * @param {Color} [lineColor]
6581
6793
  * @param {number} [lineWidth]
@@ -6649,8 +6861,8 @@ declare module "littlejsengine" {
6649
6861
  * @param {number} [friction]
6650
6862
  * @param {number} [restitution]
6651
6863
  * @param {boolean} [isSensor]
6652
- * @return {Object} - The fixture made, Box2D's own */
6653
- addCircle(diameter?: number, offset?: Vector2, density?: number, friction?: number, restitution?: number, isSensor?: boolean): any;
6864
+ * @return {Object|undefined} - The fixture made, Box2D's own, undefined for a circle too big to make */
6865
+ addCircle(diameter?: number, offset?: Vector2, density?: number, friction?: number, restitution?: number, isSensor?: boolean): any | undefined;
6654
6866
  /** Add an edge shape to the body
6655
6867
  * @param {Vector2} point1
6656
6868
  * @param {Vector2} point2
@@ -6718,10 +6930,12 @@ declare module "littlejsengine" {
6718
6930
  /** Sets the angular velocity, clockwise like angle
6719
6931
  * @param {number} angularVelocity */
6720
6932
  setAngularVelocity(angularVelocity: number): void;
6721
- /** Sets the linear damping
6933
+ /** Sets the linear damping, Box2D's: a rate, 0 none and larger slows it faster, with no upper limit, where the
6934
+ * damping of an EngineObject is the fraction it keeps each frame and does nothing on a Box2dObject
6722
6935
  * @param {number} damping */
6723
6936
  setLinearDamping(damping: number): void;
6724
- /** Sets the angular damping
6937
+ /** Sets the angular damping, Box2D's: a rate, 0 none and larger slows its turning faster, with no upper limit;
6938
+ * angleDamping does nothing on a Box2dObject
6725
6939
  * @param {number} damping */
6726
6940
  setAngularDamping(damping: number): void;
6727
6941
  /** Sets the gravity scale
@@ -6991,10 +7205,10 @@ declare module "littlejsengine" {
6991
7205
  /** Get the frequency in Hertz
6992
7206
  * @return {number} */
6993
7207
  getFrequency(): number;
6994
- /** Set the damping ratio
7208
+ /** Set how much the spring is damped, 0 for none and 1 to stop it bouncing
6995
7209
  * @param {number} ratio */
6996
7210
  setDampingRatio(ratio: number): void;
6997
- /** Get the damping ratio
7211
+ /** Get how much the spring is damped, 0 for none and 1 to stop it bouncing
6998
7212
  * @return {number} */
6999
7213
  getDampingRatio(): number;
7000
7214
  }
@@ -7100,7 +7314,7 @@ declare module "littlejsengine" {
7100
7314
  /** Set the max motor torque, a magnitude
7101
7315
  * @param {number} torque */
7102
7316
  setMaxMotorTorque(torque: number): void;
7103
- /** Get the max motor torque
7317
+ /** Get the most torque the motor can apply, a magnitude
7104
7318
  * @return {number} */
7105
7319
  getMaxMotorTorque(): number;
7106
7320
  /** Get the motor torque over the last step, clockwise like angle
@@ -7200,10 +7414,10 @@ declare module "littlejsengine" {
7200
7414
  /** Enable/disable the joint motor
7201
7415
  * @param {boolean} [enable] */
7202
7416
  enableMotor(enable?: boolean): void;
7203
- /** Set the motor speed
7417
+ /** Set the speed the motor drives the bodies apart along the axis, in meters per second
7204
7418
  * @param {number} speed */
7205
7419
  setMotorSpeed(speed: number): void;
7206
- /** Get the motor speed
7420
+ /** Get the speed the motor drives the bodies apart along the axis, in meters per second
7207
7421
  * @return {number} */
7208
7422
  getMotorSpeed(): number;
7209
7423
  /** Set the maximum motor force
@@ -7264,7 +7478,7 @@ declare module "littlejsengine" {
7264
7478
  /** Set the maximum motor torque, a magnitude
7265
7479
  * @param {number} torque */
7266
7480
  setMaxMotorTorque(torque: number): void;
7267
- /** Get the max motor torque
7481
+ /** Get the most torque the wheel's motor can apply, a magnitude
7268
7482
  * @return {number} */
7269
7483
  getMaxMotorTorque(): number;
7270
7484
  /** Get the motor torque over the last step, clockwise like angle
@@ -7277,10 +7491,10 @@ declare module "littlejsengine" {
7277
7491
  /** Get the spring frequency in Hertz
7278
7492
  * @return {number} */
7279
7493
  getSpringFrequencyHz(): number;
7280
- /** Set the spring damping ratio
7494
+ /** Set how much the suspension spring is damped, 0 for none and 1 to stop it bouncing
7281
7495
  * @param {number} ratio */
7282
7496
  setSpringDampingRatio(ratio: number): void;
7283
- /** Get the spring damping ratio
7497
+ /** Get how much the suspension spring is damped, 0 for none and 1 to stop it bouncing
7284
7498
  * @return {number} */
7285
7499
  getSpringDampingRatio(): number;
7286
7500
  }
@@ -7313,10 +7527,10 @@ declare module "littlejsengine" {
7313
7527
  /** Get the frequency in Hertz
7314
7528
  * @return {number} */
7315
7529
  getFrequency(): number;
7316
- /** Set the damping ratio
7530
+ /** Set how much the weld's spring is damped, 0 for none and 1 to stop it bouncing
7317
7531
  * @param {number} ratio */
7318
7532
  setDampingRatio(ratio: number): void;
7319
- /** Get the damping ratio
7533
+ /** Get how much the weld's spring is damped, 0 for none and 1 to stop it bouncing
7320
7534
  * @return {number} */
7321
7535
  getDampingRatio(): number;
7322
7536
  }
@@ -7406,10 +7620,10 @@ declare module "littlejsengine" {
7406
7620
  * @param {Box2dObject} objectA
7407
7621
  * @param {Box2dObject} objectB */
7408
7622
  constructor(objectA: Box2dObject, objectB: Box2dObject);
7409
- /** Set the target linear offset, in frame A, in meters.
7623
+ /** Set the target linear offset, in frame A, in meters
7410
7624
  * @param {Vector2} offset */
7411
7625
  setLinearOffset(offset: Vector2): void;
7412
- /** Get the target linear offset, in frame A, in meters.
7626
+ /** Get the target linear offset, in frame A, in meters
7413
7627
  * @return {Vector2} */
7414
7628
  getLinearOffset(): Vector2;
7415
7629
  /** Set the target angular offset, objectB angle minus objectA angle, clockwise like angle
@@ -7647,10 +7861,10 @@ declare module "littlejsengine" {
7647
7861
  * the last iteration of a loop or pingPong, and again each time a restart plays through; then() sets it
7648
7862
  * @type {undefined|function():void} */
7649
7863
  onComplete: undefined | (() => void);
7650
- /** Continuation when a pass ends, set by loop() and pingPong() to start the next iteration.
7864
+ /** Continuation when a pass ends, set by loop() and pingPong() to start the next iteration
7651
7865
  * @private */
7652
7866
  private thenCallback;
7653
- /** Remaining iterations including the current run (loop/pingPong only).
7867
+ /** Remaining iterations including the current run (loop/pingPong only)
7654
7868
  * @private */
7655
7869
  private loopRemaining;
7656
7870
  /** Whether it is running, see isActive
@@ -7673,7 +7887,7 @@ declare module "littlejsengine" {
7673
7887
  target: {
7674
7888
  destroyed?: boolean;
7675
7889
  } | undefined;
7676
- /** Set the easing curve and return this for chaining.
7890
+ /** Set the easing curve and return this for chaining
7677
7891
  * @param {function(number):number} easeFn
7678
7892
  * @return {Tween<T>} */
7679
7893
  setEase(easeFn: (arg0: number) => number): Tween<T>;
@@ -7707,9 +7921,9 @@ declare module "littlejsengine" {
7707
7921
  * @param {number} [count=Infinity]
7708
7922
  * @return {Tween<T>} */
7709
7923
  pingPong(count?: number): Tween<T>;
7710
- /** Pause this tween. While paused, tweenUpdate skips it. */
7924
+ /** Pause this tween. While paused, tweenUpdate skips it */
7711
7925
  pause(): void;
7712
- /** Resume a paused tween. */
7926
+ /** Resume a paused tween */
7713
7927
  resume(): void;
7714
7928
  /** Reset this tween to the start: life back to duration, pause cleared,
7715
7929
  * re-added to the active list if previously stopped, and the callback
@@ -7720,7 +7934,7 @@ declare module "littlejsengine" {
7720
7934
  * after restart to repeat it. The `then` callback is kept and is called
7721
7935
  * again when it completes. */
7722
7936
  restart(): void;
7723
- /** True if this tween is in the active list and not paused.
7937
+ /** True if this tween is in the active list and not paused
7724
7938
  * @return {boolean} */
7725
7939
  isActive(): boolean;
7726
7940
  /** Get how far this tween has progressed, from 0 (just started) to 1
@@ -7891,7 +8105,7 @@ declare module "littlejsengine" {
7891
8105
  * @return {function(OffscreenCanvasRenderingContext2D, Vector2): void}
7892
8106
  * @memberof Parallax */
7893
8107
  export function parallaxMountains(topColor?: Color, bottomColor?: Color, seed?: number): (arg0: OffscreenCanvasRenderingContext2D, arg1: Vector2) => void;
7894
- /** Grid pathfinder using A* with two optional smoothing passes.
8108
+ /** Grid pathfinder using A* with two optional smoothing passes
7895
8109
  * @memberof PathFinding
7896
8110
  * @example
7897
8111
  * // Tile-layer driven (most common):
@@ -7953,16 +8167,16 @@ declare module "littlejsengine" {
7953
8167
  * @param {number} y - Tile y
7954
8168
  * @return {number} */
7955
8169
  getCost(x: number, y: number): number;
7956
- /** Get the node at tile coords, or null if out of bounds.
8170
+ /** Get the node at tile coords, or null if out of bounds
7957
8171
  * @param {number} x
7958
8172
  * @param {number} y
7959
8173
  * @return {PathFinderNode|null} */
7960
8174
  getNode(x: number, y: number): PathFinderNode | null;
7961
- /** Convert a world-space position to integer tile coords (no clamping).
8175
+ /** Convert a world-space position to integer tile coords (no clamping)
7962
8176
  * @param {Vector2} worldPos
7963
8177
  * @return {Vector2} */
7964
8178
  worldToTile(worldPos: Vector2): Vector2;
7965
- /** Convert integer tile coords to the world-space center of that tile.
8179
+ /** Convert integer tile coords to the world-space center of that tile
7966
8180
  * @param {number} x
7967
8181
  * @param {number} y
7968
8182
  * @return {Vector2} */
@@ -8092,9 +8306,9 @@ declare module "littlejsengine" {
8092
8306
  heapIndex: number;
8093
8307
  /** Clear what a search left on this node, keeping walkable and cost */
8094
8308
  resetSearch(): void;
8095
- /** Reset per-search state and walkability (called by buildNodeData). */
8309
+ /** Reset per-search state and walkability (called by buildNodeData) */
8096
8310
  reset(): void;
8097
- /** True if walkable and not blocked by cost.
8311
+ /** True if walkable and not blocked by cost
8098
8312
  * @return {boolean} */
8099
8313
  isClear(): boolean;
8100
8314
  }
@@ -8588,9 +8802,11 @@ declare module "littlejsengine" {
8588
8802
  * - EngineObject3D is an EngineObject with a 3D position, rotation and mesh
8589
8803
  * - The 3D scene draws under the 2D sprites, so HUD and text land on top
8590
8804
  * - Lighting is the sun plus ambient, with optional extra lights, fog and shadows
8591
- * - Any object or draw can bring its own Shader, a mainImage snippet the lighting then applies to
8592
- * - Build shapes with buildBox, buildSphere, buildGrid and buildLathe; the other builders, terrain, particles,
8593
- * camera controls and the OBJ loader are in the Render3D Extras plugin, which goes after this one
8805
+ * - Any object or draw can bring its own Shader, a mainImage snippet the lighting then applies to, and a
8806
+ * mainNormal in it bends the normal the lighting uses
8807
+ * - Meshes and the basic builders are in render3dMesh.js, EngineObject3D, instancing and lights in
8808
+ * render3dObject.js, both right after this one; the other builders, terrain, particles, camera controls and the
8809
+ * OBJ loader are in the Render3D Extras plugin, which goes after those
8594
8810
  * - Requires the Math3D plugin
8595
8811
  * @namespace Render3D
8596
8812
  */
@@ -8672,7 +8888,9 @@ declare module "littlejsengine" {
8672
8888
  /** @property {Vector3|undefined} - Center of the shadowed area, read each frame, undefined follows the camera
8673
8889
  * @type {Vector3|undefined} */
8674
8890
  shadowCenter: Vector3 | undefined;
8675
- /** @property {number} - Stops surfaces shadowing themselves, raise for speckles, lower if shadows drift off */
8891
+ /** @property {number} - Stops surfaces shadowing themselves, raise for speckles, lower if shadows drift off;
8892
+ * a share of the shadow map's depth, twice shadowRange for the sun and a spotlight's radius, so the gap behind
8893
+ * a caster grows with the range as the map's texels do, and the speckles they make stay away */
8676
8894
  shadowBias: number;
8677
8895
  /** @property {number} - How much to blur the shadow edges */
8678
8896
  shadowSoftness: number;
@@ -8685,6 +8903,18 @@ declare module "littlejsengine" {
8685
8903
  /** @property {Mesh|undefined} - Sky dome from buildSky or setSky, drawn around the camera behind everything
8686
8904
  * @type {Mesh|undefined} */
8687
8905
  sky: Mesh | undefined;
8906
+ /** @property {CubeMap|undefined} - A cube map drawn as the sky, behind everything, in place of the sky dome;
8907
+ * an orthographic camera looks the same way through every pixel, so it sees one color of it; fog fades to
8908
+ * fogColor, not to the sky box, so with fog set fogColor to its horizon's color
8909
+ * @type {CubeMap|undefined} */
8910
+ skyBox: CubeMap | undefined;
8911
+ /** @property {CubeMap|undefined} - The world around, what reflective surfaces reflect: an object's
8912
+ * reflectivity says how much and its shininess how sharp, the same shininess that tightens its highlight:
8913
+ * 10000 a mirror, 1000 polished, 10 a wide blur; undefined reflects the sky's colors as setSky gave them; a cube map holds GPU
8914
+ * memory until its dispose(), so one made again and again, as for a sky that changes, disposes the one it
8915
+ * replaces, or a captured one is captured into again
8916
+ * @type {CubeMap|undefined} */
8917
+ environment: CubeMap | undefined;
8688
8918
  /** @property {boolean} - Draw the 3D scene on top of the 2D scene instead of under it */
8689
8919
  renderAfter2D: boolean;
8690
8920
  /** @property {boolean} - Draw see through things far to near so they blend correctly */
@@ -8745,6 +8975,19 @@ declare module "littlejsengine" {
8745
8975
  shadowShader: WebGLProgram | undefined;
8746
8976
  /** @type {WebGLVertexArrayObject|undefined} */
8747
8977
  vao: WebGLVertexArrayObject | undefined;
8978
+ /** @type {Set<CubeMap>} */
8979
+ cubeCaptures: Set<CubeMap>;
8980
+ /** @type {CubeMap|undefined} */
8981
+ capturingCube: CubeMap | undefined;
8982
+ /** @type {WebGLFramebuffer|undefined} */
8983
+ captureFramebuffer: WebGLFramebuffer | undefined;
8984
+ /** @type {WebGLRenderbuffer|undefined} */
8985
+ captureDepth: WebGLRenderbuffer | undefined;
8986
+ captureDepthSize: number;
8987
+ /** @type {WebGLProgram|undefined} */
8988
+ skyBoxProgram: WebGLProgram | undefined;
8989
+ /** @type {WebGLVertexArrayObject|undefined} */
8990
+ skyBoxVao: WebGLVertexArrayObject | undefined;
8748
8991
  /** @type {WebGLTexture|undefined} */
8749
8992
  whiteTexture: WebGLTexture | undefined;
8750
8993
  /** @type {Map<number, WebGLSampler>} */
@@ -8764,7 +9007,10 @@ declare module "littlejsengine" {
8764
9007
  cameraDepthHeight: number;
8765
9008
  depthPass: boolean;
8766
9009
  contextGeneration: number;
8767
- uniforms: Map<any, any>;
9010
+ /** @type {WeakMap<WebGLProgram, Object<string, WebGLUniformLocation|null>>} */
9011
+ uniforms: WeakMap<WebGLProgram, {
9012
+ [x: string]: WebGLUniformLocation | null;
9013
+ }>;
8768
9014
  /** @type {Object<string, Array<number>>} */
8769
9015
  uniformValues: {
8770
9016
  [x: string]: Array<number>;
@@ -8861,6 +9107,10 @@ declare module "littlejsengine" {
8861
9107
  /** Emissive map for the next draws, set from each object's emissiveMap
8862
9108
  * @return {TextureInfo|undefined} */
8863
9109
  get emissiveMap(): TextureInfo | undefined;
9110
+ set environmentMap(arg: CubeMap | undefined);
9111
+ /** The cube map the next draws reflect in place of render3D.environment, set from each object's environment
9112
+ * @return {CubeMap|undefined} */
9113
+ get environmentMap(): CubeMap | undefined;
8864
9114
  set emissiveMapColor(arg: Color);
8865
9115
  /** Multiplies the emissive map, set from each object's emissiveMapColor; compared by its rgb, so a Color
8866
9116
  * changed in place is seen when it is set again, and undefined is white
@@ -9003,7 +9253,8 @@ declare module "littlejsengine" {
9003
9253
  /** Draw the queued transparent draws far to near with the state each was drawn under, called automatically at the
9004
9254
  * end of the transparent stage */
9005
9255
  flushTransparentQueue(): void;
9006
- /** Draw render3D.sky around the camera, unlit, unfogged and behind everything, called automatically by the pass */
9256
+ /** Draw render3D.skyBox, or render3D.sky around the camera, unlit, unfogged and behind everything, called
9257
+ * automatically by the pass */
9007
9258
  drawSky(): void;
9008
9259
  /** Rebuild the light's view projection around the shadow center, called automatically each frame shadows are on */
9009
9260
  updateShadowMatrix(): void;
@@ -9090,6 +9341,78 @@ declare module "littlejsengine" {
9090
9341
  * @return {void} */
9091
9342
  drawSoftShadow(pos: Vector3, size?: number, floorHeight?: number | HeightMap | ((arg0: number, arg1: number) => number), color?: Color, lift?: number): void;
9092
9343
  }
9344
+ /**
9345
+ * CubeMap - Six square images all around a point, the world far away: what reflective surfaces reflect as
9346
+ * render3D.environment, and the sky as render3D.skyBox
9347
+ * - makeCubeMap paints one from a function of direction, loadCubeMap loads six images
9348
+ * - Made with no faces it is drawn from the scene: capture(pos3D) draws everything around that point into it in the
9349
+ * next frame's 3D pass, six views of the whole scene, so capture once for a still scene or now and then for one
9350
+ * that moves
9351
+ * - Its faces are in WebGL's order and lay out, +x, -x, +y, -y, +z, -z: WebGL's cube is left handed, so in this right
9352
+ * handed world a face seen from the middle is mirrored; loadCubeMap turns a sky box set's images to it
9353
+ * @memberof Render3D
9354
+ * @example
9355
+ * render3D.environment = render3D.skyBox = makeCubeMap(64, (d)=> hsl(.6, .8, .4 + d.y * .4));
9356
+ * @example
9357
+ * // a chrome ball that reflects the scene around it, captured once
9358
+ * const ball = new EngineObject3D(vec3(0, 1, 0), render3D.sphereMesh, undefined, BLACK);
9359
+ * ball.reflectivity = 1;
9360
+ * ball.shininess = 1e4;
9361
+ * render3D.environment = new CubeMap(128);
9362
+ * render3D.environment.capture(ball.pos3D);
9363
+ */
9364
+ export class CubeMap {
9365
+ /** Make a cube map from its six faces, as makeCubeMap and loadCubeMap do, or with none to capture the scene into
9366
+ * @param {number} size - Pixels a side of each face
9367
+ * @param {Array<Uint8Array|HTMLImageElement|HTMLCanvasElement|ImageBitmap|OffscreenCanvas>} [faces] - +x, -x,
9368
+ * +y, -y, +z and -z, RGBA pixels row by row or images; none for a cube map drawn by capture */
9369
+ constructor(size: number, faces?: (Uint8Array | OffscreenCanvas | ImageBitmap | HTMLCanvasElement | HTMLImageElement)[]);
9370
+ /** @property {number} - Pixels a side of each face */
9371
+ size: number;
9372
+ /** @property {Array<Uint8Array|HTMLImageElement|HTMLCanvasElement|ImageBitmap|OffscreenCanvas>|undefined} -
9373
+ * Its faces, kept to upload again after a lost context, undefined for one drawn by capture
9374
+ * @type {Array<Uint8Array|HTMLImageElement|HTMLCanvasElement|ImageBitmap|OffscreenCanvas>|undefined} */
9375
+ faces: Array<Uint8Array | HTMLImageElement | HTMLCanvasElement | ImageBitmap | OffscreenCanvas> | undefined;
9376
+ /** @property {Vector3|undefined} - Where it was last captured from, and is captured from again after a lost
9377
+ * context
9378
+ * @type {Vector3|undefined} */
9379
+ capturePos: Vector3 | undefined;
9380
+ /** @type {WebGLTexture|undefined} */
9381
+ glTexture: WebGLTexture | undefined;
9382
+ contextGeneration: number;
9383
+ /** Draw the scene around a point into a cube map made with no faces, in the next frame's 3D pass
9384
+ * - Every object of the layer render3D.renderAfter2D picks is drawn, with the sky and the render callbacks; the
9385
+ * camera's near and far planes, the lights and the fog are the scene's
9386
+ * - It is six more draws of the scene, so capture once for a still scene, or every few frames for a moving one
9387
+ * - A closed mesh around the point, like the ball that reflects it, is not seen from inside, so it hides nothing
9388
+ * - While it is drawn, what would reflect it reflects the sky's colors in its place
9389
+ * - It is seen from one point, so it suits what is near that point best, give each mirror its own with
9390
+ * obj.environment
9391
+ * @param {Vector3} pos3D - The point it is seen from */
9392
+ capture(pos3D: Vector3): void;
9393
+ /** Free its texture, which is made again if it is used after */
9394
+ dispose(): void;
9395
+ }
9396
+ /** Make a cube map by asking a function the color of each direction
9397
+ * - The function gets a unit Vector3 for each pixel of each face and gives a Color
9398
+ * - It runs size * size * 6 times, so a size of 64 or 128 makes one at once, larger takes a moment
9399
+ * @param {number} size - Pixels a side of each face
9400
+ * @param {function(Vector3): Color} colorOf - The color seen looking that way
9401
+ * @return {CubeMap}
9402
+ * @example
9403
+ * // a sky, blue above and pale at the horizon, with a sun
9404
+ * const sun = vec3(1, 1, -1).normalize();
9405
+ * render3D.environment = makeCubeMap(64, (d)=> hsl(.6, .7, .9 - max(d.y, 0) * .5).lerp(WHITE, max(0, d.dot(sun)) ** 64));
9406
+ * @memberof Render3D */
9407
+ export function makeCubeMap(size: number, colorOf: (arg0: Vector3) => Color): CubeMap;
9408
+ /** Load a cube map from six square images of one size
9409
+ * - The images are a sky box set as three.js's CubeTextureLoader takes them, and show the same: each face seen from
9410
+ * inside as its image is drawn
9411
+ * @param {Array<string>} sources - The images of +x, -x, +y, -y, +z and -z, as a sky box set names them right,
9412
+ * left, top, bottom, front and back
9413
+ * @return {Promise<CubeMap>}
9414
+ * @memberof Render3D */
9415
+ export function loadCubeMap(sources: Array<string>): Promise<CubeMap>;
9093
9416
  /**
9094
9417
  * Camera3D - Position, rotation and lens for the 3D view
9095
9418
  * - Looks down its -Z axis, rotation is vec3(pitch, yaw, roll)
@@ -9108,8 +9431,12 @@ declare module "littlejsengine" {
9108
9431
  far: number;
9109
9432
  /** @property {number} - Visible height in world units for an orthographic view, 0 is perspective */
9110
9433
  orthographic: number;
9111
- /** @property {boolean} - Line the 3D camera up with the 2D camera, so 3D things at z=0 sit on the 2D sprites */
9434
+ /** @property {boolean} - Line the 3D camera up with the 2D camera, so 3D things at z=0 sit on the 2D sprites;
9435
+ * it lines up with the 2D view of the main canvas, whatever canvas size a screenToRay is given */
9112
9436
  align2D: boolean;
9437
+ /** @property {number} - The z of the plane align2D lines up with the 2D view, the camera sitting its
9438
+ * distance in front of it */
9439
+ align2DZ: number;
9113
9440
  /** Returns the camera's world transform
9114
9441
  * @return {Matrix4} */
9115
9442
  getMatrix(): Matrix4;
@@ -9238,6 +9565,10 @@ declare module "littlejsengine" {
9238
9565
  emissiveMap: TextureInfo | undefined;
9239
9566
  /** @property {Color} - Multiplies the emissive map, as glTF's emissiveFactor */
9240
9567
  emissiveMapColor: Color;
9568
+ /** @property {CubeMap|undefined} - What it reflects in place of render3D.environment, as a mirror captures
9569
+ * the scene from its own middle
9570
+ * @type {CubeMap|undefined} */
9571
+ environment: CubeMap | undefined;
9241
9572
  /** @property {boolean} - Collide as the sphere that fits size3D instead of as the size3D box, so it rolls
9242
9573
  * around corners */
9243
9574
  collideAsSphere3D: boolean;
@@ -9260,6 +9591,10 @@ declare module "littlejsengine" {
9260
9591
  matrixParent: EngineObject3D | undefined;
9261
9592
  matrixParentVersion: number;
9262
9593
  movePass: number;
9594
+ collideFrom: Vector3;
9595
+ collideFromPass: number;
9596
+ /** @type {EngineObject3D|undefined} */
9597
+ drawOwner: EngineObject3D | undefined;
9263
9598
  /** Called by a VoxelMap to ask whether a block stops this object, a hook to let one through or react to it
9264
9599
  * @param {number} type - The block's type, 1 to 255
9265
9600
  * @param {Vector3} cell - The block's cell in the map
@@ -9282,6 +9617,13 @@ declare module "littlejsengine" {
9282
9617
  * cheap to call
9283
9618
  * @return {Matrix4} */
9284
9619
  getMatrix(): Matrix4;
9620
+ set roughness(arg: number);
9621
+ /** How rough the surface is, 0 a mirror to 1 matte, as glTF and three.js's MeshStandardMaterial have it: another
9622
+ * way to set shininess, which is what is kept, shininess = 2 / roughness^4 - 2 and at least 1; it sets both the
9623
+ * highlight and how blurred a reflection is; read back it is the same up to about .9, above which shininess is 1
9624
+ * and it reads .9
9625
+ * @return {number} */
9626
+ get roughness(): number;
9285
9627
  /** Turn the object so its -Z axis points at a world space target, sets pitch and yaw and clears roll
9286
9628
  * @param {Vector3} target */
9287
9629
  lookAt(target: Vector3): void;
@@ -9365,6 +9707,7 @@ declare module "littlejsengine" {
9365
9707
  pointCount: number;
9366
9708
  data: ArrayBuffer;
9367
9709
  } | undefined;
9710
+ vertexDataPacked: boolean;
9368
9711
  instanceCount: number;
9369
9712
  /** @type {Float32Array|undefined} */
9370
9713
  instanceData: Float32Array | undefined;
@@ -9950,7 +10293,8 @@ declare module "littlejsengine" {
9950
10293
  chunkTransparentMeshes: Array<Mesh | undefined>;
9951
10294
  /** @type {Array<Vector3>} */
9952
10295
  chunkCenters: Array<Vector3>;
9953
- chunksChanged: Set<any>;
10296
+ /** @type {Set<number>} */
10297
+ chunksChanged: Set<number>;
9954
10298
  /** @type {Array<{faces: Array<number>, seeThrough: boolean, transparent: boolean, doubleSided: boolean}|undefined>} */
9955
10299
  blockTypes: Array<{
9956
10300
  faces: Array<number>;
@@ -9958,7 +10302,8 @@ declare module "littlejsengine" {
9958
10302
  transparent: boolean;
9959
10303
  doubleSided: boolean;
9960
10304
  } | undefined>;
9961
- tiles: Map<any, any>;
10305
+ /** @type {Map<number, Array<Vector2>>} */
10306
+ tiles: Map<number, Array<Vector2>>;
9962
10307
  /** The block type at a cell, 0 for empty or outside the map
9963
10308
  * @param {Vector3} cell
9964
10309
  * @return {number} */
@@ -10050,7 +10395,8 @@ declare module "littlejsengine" {
10050
10395
  * @ignore */
10051
10396
  levelRaycast3D(ray: Ray3D): number | undefined;
10052
10397
  /** Where a short move goes into a block, for a particle's move in one frame: the part of the move made before it,
10053
- * 0 to 1, and the normal of the face it comes in through; undefined when it hits none, or starts inside one
10398
+ * 0 to 1, and the normal of the face it comes in through; undefined when it hits none, or starts inside one; a
10399
+ * move that starts on a block's face, coming in, hits it at 0
10054
10400
  * @param {Vector3} from
10055
10401
  * @param {Vector3} to
10056
10402
  * @return {{distance: number, normal: Vector3}|undefined}
@@ -10315,7 +10661,8 @@ declare module "littlejsengine" {
10315
10661
  /** @property {boolean} - Flatten the spawn area across the way it emits, its own up: a sphere becomes a disc
10316
10662
  * and a box a flat rectangle, for rain from a sheet of sky or flames from a patch of ground */
10317
10663
  emitFlat: boolean;
10318
- /** @property {number} - How long to keep emitting, 0 is forever */
10664
+ /** @property {number} - How long to keep emitting, 0 is forever; raised while its particles are still alive,
10665
+ * it emits again for the added time */
10319
10666
  emitTime: number;
10320
10667
  /** @property {number} - Particles per second, 0 does not emit */
10321
10668
  emitRate: number;
@@ -10381,10 +10728,16 @@ declare module "littlejsengine" {
10381
10728
  * @type {Vector3|undefined} */
10382
10729
  worldPos3D: Vector3 | undefined;
10383
10730
  emitTimeBuffer: number;
10731
+ emitElapsed: number;
10732
+ /** @type {Vector3|undefined} */
10733
+ emitFrom: Vector3 | undefined;
10734
+ emitBehind: number;
10384
10735
  /** Spawn one particle now */
10385
10736
  emitParticle(): void;
10386
- particleCall(callback: any, k: any, level: any, pos: any): any;
10387
- particleCollide(k: any, x: any, y: any, z: any): boolean;
10737
+ /** @private */
10738
+ private particleCall;
10739
+ /** @private */
10740
+ private particleCollide;
10388
10741
  }
10389
10742
  /**
10390
10743
  * Trail3D - A ribbon through where the object has been, thinning and fading with age
@@ -10506,8 +10859,9 @@ declare module "littlejsengine" {
10506
10859
  /** @property {number} - Seconds the flare takes to fade out or in when the sun is hidden or shows again */
10507
10860
  fadeTime: number;
10508
10861
  /** @property {number} - How much of the sun shows, 0 hidden, off the screen or behind the camera to 1 in
10509
- * plain view, eased */
10862
+ * plain view, eased; the first update sets it at once, so a sun hidden from the start never shows */
10510
10863
  visible: number;
10864
+ visibleFound: boolean;
10511
10865
  madeKey: string;
10512
10866
  /** @type {Array<LensFlareElement>} */
10513
10867
  made: Array<LensFlareElement>;
@@ -10558,6 +10912,11 @@ declare module "littlejsengine" {
10558
10912
  * it is doubleSided
10559
10913
  * @return {boolean} */
10560
10914
  isHidden(): boolean;
10915
+ /** Ease visible toward whether the sun shows over some seconds; the first time it is found at once, from the
10916
+ * camera as it is, its matrices made, by the first update or the first draw, whichever comes first
10917
+ * @param {number} seconds
10918
+ * @ignore */
10919
+ updateVisible(seconds: number): void;
10561
10920
  }
10562
10921
  /**
10563
10922
  * Collect the EngineObject3D objects whose boxes overlap a sphere or a box, the 3D twin of engineObjectsCollect
@@ -10629,7 +10988,14 @@ declare module "littlejsengine" {
10629
10988
  /** @property {Array<GLTFAnimation>} - The animations, play one through createObject's GLTFObject
10630
10989
  * @type {Array<GLTFAnimation>} */
10631
10990
  animations: Array<GLTFAnimation>;
10632
- nodeTree: any;
10991
+ /** @type {{nodes: Array<Object>, parents: Array<number|undefined>, restInverse: Array<Matrix4>,
10992
+ * restPose: Array<Matrix4|undefined>}|undefined} */
10993
+ nodeTree: {
10994
+ nodes: Array<any>;
10995
+ parents: Array<number | undefined>;
10996
+ restInverse: Array<Matrix4>;
10997
+ restPose: Array<Matrix4 | undefined>;
10998
+ } | undefined;
10633
10999
  modelMatrix: Matrix4;
10634
11000
  /** @property {Mesh} - Every part combined, each tinted with its material color; the texture is textureInfo,
10635
11001
  * and blending and unlit stay with the parts, which createObject draws */
@@ -10751,6 +11117,9 @@ declare module "littlejsengine" {
10751
11117
  emissiveMap: TextureInfo | undefined;
10752
11118
  /** @property {Color} - The emissiveFactor, which multiplies the emissive map */
10753
11119
  emissiveMapColor: Color;
11120
+ /** @property {number} - The material's roughnessFactor, 0 a mirror to 1 matte, 1 when it has none as the
11121
+ * format says; the object createObject makes takes it as its roughness, which sets its shininess */
11122
+ roughness: number;
10754
11123
  /** @property {GLTFSkin|undefined} - For a skinned mesh, what bends it: mesh is its resting pose, and the
10755
11124
  * object createObject makes bends a copy of its own to each pose
10756
11125
  * @type {GLTFSkin|undefined} */
@@ -10865,7 +11234,7 @@ declare module "littlejsengine" {
10865
11234
  * is fetched then
10866
11235
  * - A file the model needs that is not found is named in the error, and an image that can not be read is named in
10867
11236
  * a warning and left out
10868
- * @param {ArrayBuffer|Object|string} data - GLB bytes, or the glTF JSON as bytes, text or an object
11237
+ * @param {ArrayBuffer|ArrayBufferView|Object<string, any>|string} data - GLB bytes, or the glTF JSON as bytes, text or an object
10869
11238
  * @param {string} [baseUrl] - Where the .bin and image files are, with its trailing slash; loadGLTF passes the file's folder
10870
11239
  * @param {Map<string, Blob>} [files] - The files it refers to, by their paths, in place of fetching them
10871
11240
  * @return {Promise<GLTFModel>}
@@ -10875,7 +11244,9 @@ declare module "littlejsengine" {
10875
11244
  * const gltf = [...files.values()].find((file)=> file.name.endsWith('.gltf'));
10876
11245
  * const model = await parseGLTF(await gltf.text(), '', files);
10877
11246
  * @memberof GLTF */
10878
- export function parseGLTF(data: ArrayBuffer | any | string, baseUrl?: string, files?: Map<string, Blob>): Promise<GLTFModel>;
11247
+ export function parseGLTF(data: ArrayBuffer | ArrayBufferView | {
11248
+ [x: string]: any;
11249
+ } | string, baseUrl?: string, files?: Map<string, Blob>): Promise<GLTFModel>;
10879
11250
  /** Load a glTF or GLB model, the .bin and images of a .gltf from beside it
10880
11251
  * - A texture only OPAQUE materials use loads with its alpha set to 1, so the 3D pass cuts no holes in it
10881
11252
  * @param {string} url
@@ -10963,9 +11334,10 @@ declare module "littlejsengine" {
10963
11334
  * are added before its objects are made, one the game added itself keeps its place
10964
11335
  * - A level may set the scene too, in a scene block beside its objects: sky, three colors for straight up, the
10965
11336
  * horizon and straight down, ambient, how much of them lights the scene, .5 when not given, sunDirection and
10966
- * sunColor, fog, its start and end, fogColor, the horizon color when not given, shadows, and lensFlare, the
10967
- * sun's lens flare; what the block leaves out stays as the game set it, and a level with no block changes
10968
- * nothing
11337
+ * sunColor, fog, its start and end, fogColor, the horizon color when not given, shadows, lensFlare, the
11338
+ * sun's lens flare, and skyBox and environment, each six image urls as loadCubeMap takes them, which load in
11339
+ * the background and are set when they have; what the block leaves out stays as the game set it, and a level
11340
+ * with no block changes nothing
10969
11341
  * @param {Level3D} level - The level, the level editor edits this same object
10970
11342
  * @return {Array<any>} - What each object's type made, a function that made nothing is left out
10971
11343
  * @memberof Level3D */
@@ -11032,13 +11404,22 @@ declare module "littlejsengine" {
11032
11404
  prefabName: string;
11033
11405
  /** @property {boolean} - Are its parts its children, moving with it as one body */
11034
11406
  attached: boolean;
11035
- /** @property {Array<any>} - What the prefab's objects made, in the prefab's order */
11036
- parts: any[];
11407
+ /** @property {Array<EngineObject3D>} - What the prefab's objects made, in the prefab's order
11408
+ * @type {Array<EngineObject3D>} */
11409
+ parts: Array<EngineObject3D>;
11037
11410
  /** @property {Vector3} - From the prefab's origin to the handle, in the prefab's own space: nothing for
11038
11411
  * separate parts, and for an attached prefab the middle of the box around its parts, where its handle
11039
11412
  * is, as an object's place is the middle of its body */
11040
11413
  originOffset: Vector3;
11041
- partObjects: any[];
11414
+ /** @type {Array<{id?: number, type: string, pos?: Array<number>, rotation?: Array<number>, scale?: Array<number>|number, properties?: Object}>} */
11415
+ partObjects: Array<{
11416
+ id?: number;
11417
+ type: string;
11418
+ pos?: Array<number>;
11419
+ rotation?: Array<number>;
11420
+ scale?: Array<number> | number;
11421
+ properties?: any;
11422
+ }>;
11042
11423
  partsPlaced: string;
11043
11424
  partsMade: boolean;
11044
11425
  /** Put the instance with its prefab's origin at a place, turned and sized as the handle is: where a level's
@@ -11277,9 +11658,12 @@ declare module "littlejsengine" {
11277
11658
  * - Accepts TexturePacker json (hash and array) and Aseprite json
11278
11659
  * - Frames tagged in Aseprite or named like run_0, run_1 group into animations
11279
11660
  * @param {Object} data - Parsed atlas json data
11280
- * @return {Array<Object>} List of {name, frames} groups in atlas order
11661
+ * @return {Array<{name: string, frames: Array<Object>}>} List of {name, frames} groups in atlas order
11281
11662
  * @memberof TextureSheets */
11282
- export function parseAtlas(data: any): Array<any>;
11663
+ export function parseAtlas(data: any): {
11664
+ name: string;
11665
+ frames: Array<any>;
11666
+ }[];
11283
11667
  /** Wait for everything started by loadSprite and loadAtlas to finish packing
11284
11668
  * @return {Promise}
11285
11669
  * @example
@@ -11437,8 +11821,9 @@ declare module "littlejsengine" {
11437
11821
  * @memberof ParticleEffects */
11438
11822
  export function particleEffectApply3D(emitter: ParticleEmitter3D, effect: any): void;
11439
11823
  /** An effect with a 2D emitter's settings, to save, build again, or build in 3D with particleEffect3D; its tile is
11440
- * left out, since a hand made emitter's tile is its own texture and not one an effect can name, and so is its
11441
- * scale, which an effect does not keep: pass it again with options.scale
11824
+ * left out, since a hand made emitter's tile is its own texture and not one an effect can name, and so are its
11825
+ * scale, which an effect does not keep: pass it again with options.scale, and its renderOrder, which an effect takes
11826
+ * from additive; a finished emitter's emit time is the time it emitted for
11442
11827
  * @param {ParticleEmitter} emitter
11443
11828
  * @param {string} [name]
11444
11829
  * @return {Object}
@@ -11448,7 +11833,7 @@ declare module "littlejsengine" {
11448
11833
  * @param {string} name
11449
11834
  * @param {function(Particle, number): void} update - Pushes a 2D particle, given the strength
11450
11835
  * @param {function(Particle3D, number): void} [update3D] - The same for a 3D particle, none leaves 3D alone
11451
- * @param {number} [min] - Strength range the designer offers
11836
+ * @param {number} [min] - Strength range the designer offers, and the range a strength is clamped to
11452
11837
  * @param {number} [max]
11453
11838
  * @param {number} [value] - Strength when first added
11454
11839
  * @param {string} [description]