littlejsengine 1.20.0 → 1.22.0

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.
@@ -7,6 +7,10 @@ declare module "littlejsengine" {
7
7
  * - Called after the engine starts, can be async
8
8
  */
9
9
  export type GameInitCallback = () => void | Promise<void>;
10
+ /**
11
+ * - Draws the loading screen on mainContext, each frame while the game loads
12
+ */
13
+ export type LoadingScreenCallback = (progress: number) => any;
10
14
  /**
11
15
  * - Update or render function for the game
12
16
  */
@@ -76,6 +80,10 @@ declare module "littlejsengine" {
76
80
  */
77
81
  object?: any;
78
82
  };
83
+ /**
84
+ * - Called once when a SpriteAnimation's play ends
85
+ */
86
+ export type SpriteAnimationEndCallback = () => void;
79
87
  /**
80
88
  * - Function called when sound is loaded
81
89
  */
@@ -88,6 +96,104 @@ declare module "littlejsengine" {
88
96
  * - Decides whether a particle stops at a tile, it is a filter rather than a notice
89
97
  */
90
98
  export type ParticleCollideCallback = (particle: Particle, tileData: number, pos: Vector2) => boolean;
99
+ /**
100
+ * A scene, any object with the hooks it needs, each optional and called as a method so this is the scene
101
+ */
102
+ export type Scene = {
103
+ /**
104
+ * - Called when the scene starts, after the old one left and the objects were destroyed
105
+ */
106
+ enter?: () => void;
107
+ /**
108
+ * - Called before the next scene starts, while the scene is current and its objects are still there
109
+ */
110
+ leave?: () => void;
111
+ /**
112
+ * - Called each update after gameUpdate, not while paused or at time scale 0
113
+ */
114
+ update?: () => void;
115
+ /**
116
+ * - Called before gameRender, to draw under the objects
117
+ */
118
+ render?: () => void;
119
+ /**
120
+ * - Called after gameRenderPost, to draw over the game, while paused too; plugins made after the first setScene draw over it
121
+ */
122
+ renderPost?: () => void;
123
+ };
124
+ /**
125
+ * The draw state's values, behind render3D's accessors, and the rgb emissiveMapColor had when it was set
126
+ */
127
+ export type Render3DDrawState = {
128
+ blend: boolean;
129
+ additive: boolean;
130
+ depthTest: boolean;
131
+ depthWrite: boolean;
132
+ cullBackFaces: boolean;
133
+ mirrored: boolean;
134
+ lighting: boolean;
135
+ emissive: number;
136
+ receiveShadow: boolean;
137
+ specular: number;
138
+ pixelated: boolean;
139
+ shader: Shader | undefined;
140
+ normalMap: TextureInfo | undefined;
141
+ normalScale: number;
142
+ shininess: number;
143
+ reflectivity: number;
144
+ emissiveMap: TextureInfo | undefined;
145
+ emissiveMapColor: Color;
146
+ emissiveR: number;
147
+ emissiveG: number;
148
+ emissiveB: number;
149
+ };
150
+ /**
151
+ * A particle as a ParticleEmitter3D's callbacks see it: one object the emitter reuses, set from the particle for each
152
+ * call and written back after it, so copy what you keep
153
+ */
154
+ export type Particle3D = {
155
+ /**
156
+ * - The emitter it is in
157
+ */
158
+ emitter: ParticleEmitter3D;
159
+ /**
160
+ * - Where it is, change it to move it
161
+ */
162
+ pos: Vector3;
163
+ /**
164
+ * - How far it moves each frame
165
+ */
166
+ velocity: Vector3;
167
+ /**
168
+ * - Seconds it has lived
169
+ */
170
+ age: number;
171
+ /**
172
+ * - Seconds it lives
173
+ */
174
+ lifeTime: number;
175
+ /**
176
+ * - How much the emitter grows its effect, from its scale3D and its parents', as the 2D
177
+ * particle's scale
178
+ */
179
+ scale: number;
180
+ /**
181
+ * - Set by destroy
182
+ */
183
+ destroyed: boolean;
184
+ /**
185
+ * - End it this update, the destroy callback gets it
186
+ */
187
+ destroy: () => void;
188
+ };
189
+ /**
190
+ * - A function a ParticleEmitter3D calls with one of its particles
191
+ */
192
+ export type Particle3DCallback = (particle: Particle3D) => any;
193
+ /**
194
+ * - Decides whether a particle stops where it hits the level, a filter as in 2D
195
+ */
196
+ export type Particle3DCollideCallback = (particle: Particle3D, level: EngineObject3D, pos: Vector3) => boolean | void;
91
197
  /**
92
198
  * What VoxelMap.raycast finds: how far along the ray, the block's cell and type, and the normal of the face it comes in
93
199
  * through
@@ -146,11 +252,12 @@ declare module "littlejsengine" {
146
252
  * @default
147
253
  * @memberof Engine */
148
254
  export const frameRate: number;
149
- /** How many seconds each frame lasts, engine uses a fixed time step
255
+ /** How many seconds the update covers: 1/60 with the fixed time step, or with engineVariableStep the time of the
256
+ * display frame it runs on, times timeScale; while paused it keeps the last update's
150
257
  * @type {number}
151
258
  * @default 1/60
152
259
  * @memberof Engine */
153
- export const timeDelta: number;
260
+ export let timeDelta: number;
154
261
  /** Array containing all engine objects
155
262
  * @type {Array<EngineObject>}
156
263
  * @memberof Engine */
@@ -189,6 +296,11 @@ declare module "littlejsengine" {
189
296
  * @return {void|Promise<void>}
190
297
  * @memberof Engine
191
298
  */
299
+ /**
300
+ * @callback LoadingScreenCallback - Draws the loading screen on mainContext, each frame while the game loads
301
+ * @param {number} progress - The part of the loads done, 0 to 1
302
+ * @memberof Engine
303
+ */
192
304
  /**
193
305
  * @callback GameCallback - Update or render function for the game
194
306
  * @memberof Engine
@@ -284,6 +396,15 @@ declare module "littlejsengine" {
284
396
  * @param {PluginCallback} [preRender] - Called after the canvas is cleared and before gameRender
285
397
  * @memberof Engine */
286
398
  export function engineAddPlugin(update?: PluginCallback, render?: PluginCallback, glContextLost?: PluginCallback, glContextRestored?: PluginCallback, preRender?: PluginCallback): void;
399
+ /** Add something the game loads to what startup waits for: while engineInit and gameInit run, the game loop starts
400
+ * once it is done, and the loading screen counts it; images from loadTexture and sounds from files are added on
401
+ * their own, and a load that fails counts as done; after startup it does nothing
402
+ * @param {Promise<any>} promise
403
+ * @return {Promise<any>} - The same promise
404
+ * @example
405
+ * async function gameInit() { level = await engineAddLoad(fetchJSON('level.json')); }
406
+ * @memberof Engine */
407
+ export function engineAddLoad(promise: Promise<any>): Promise<any>;
287
408
  /**
288
409
  * LittleJS Debug System
289
410
  * - Press Esc to toggle debug overlay with object picking
@@ -532,6 +653,12 @@ declare module "littlejsengine" {
532
653
  * @default
533
654
  * @memberof Settings */
534
655
  export let showSplashScreen: boolean;
656
+ /** The loading screen, drawn after the splash while the images, gameInit and what they load are loading, once that
657
+ * takes more than half a second: a function given the part done, 0 to 1, or undefined for none, which leaves the
658
+ * screen blank; the default says Loading over a bar
659
+ * @type {LoadingScreenCallback|undefined}
660
+ * @memberof Settings */
661
+ export let loadingScreen: LoadingScreenCallback | undefined;
535
662
  /** Disables all rendering, audio, and input for servers, must be set before engineInit
536
663
  * @type {boolean}
537
664
  * @default
@@ -543,6 +670,14 @@ declare module "littlejsengine" {
543
670
  * @default
544
671
  * @memberof Settings */
545
672
  export let engineManualStep: boolean;
673
+ /** Run one update per display frame with timeDelta the time it covers, in place of fixed updates at frameRate
674
+ * - Per-frame values are not scaled: velocity, gravity, damping and particle speeds act once per update, so a
675
+ * game that turns this on scales its own movement by timeDelta
676
+ * - Values in seconds follow real time as they are: time, timers, particle emit rate and life, animation, Box2D
677
+ * @type {boolean}
678
+ * @default
679
+ * @memberof Settings */
680
+ export let engineVariableStep: boolean;
546
681
  /** Default size of tiles in pixels
547
682
  * @type {Vector2}
548
683
  * @default Vector2(16,16)
@@ -854,6 +989,10 @@ declare module "littlejsengine" {
854
989
  * @param {boolean} show
855
990
  * @memberof Settings */
856
991
  export function setShowSplashScreen(show: boolean): void;
992
+ /** Set the loading screen, drawn after the splash while the game loads, once that takes more than half a second
993
+ * @param {LoadingScreenCallback} [callback] - Draws on mainContext given the part done, 0 to 1; undefined for none
994
+ * @memberof Settings */
995
+ export function setLoadingScreen(callback?: LoadingScreenCallback): void;
857
996
  /** Set to disable rendering, audio, and input for servers, must be set before engineInit
858
997
  * @param {boolean} headless
859
998
  * @memberof Settings */
@@ -864,6 +1003,11 @@ declare module "littlejsengine" {
864
1003
  * @param {boolean} [enable]
865
1004
  * @memberof Settings */
866
1005
  export function setEngineManualStep(enable?: boolean): void;
1006
+ /** Set if the engine runs one update per display frame with timeDelta the time it covers
1007
+ * Can be set before engineInit or while running; turned off it goes back to fixed updates at frameRate
1008
+ * @param {boolean} [enable]
1009
+ * @memberof Settings */
1010
+ export function setEngineVariableStep(enable?: boolean): void;
867
1011
  /** Set if WebGL rendering is enabled
868
1012
  * @param {boolean} enable
869
1013
  * @memberof Settings */
@@ -1973,8 +2117,9 @@ declare module "littlejsengine" {
1973
2117
  * @param {boolean} [useWebGL] - Should use WebGL if available?
1974
2118
  * @param {boolean|Array<number>} [wrap] - Should the texture wrap (REPEAT) or clamp (CLAMP_TO_EDGE)? Or the WebGL
1975
2119
  * modes across and down, like [gl.CLAMP_TO_EDGE, gl.MIRRORED_REPEAT], as a glTF sampler gives them
2120
+ * @param {boolean} [pixelated] - Hard edged or smooth for this texture alone, undefined follows tilesPixelated
1976
2121
  */
1977
- constructor(image: HTMLImageElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap, useWebGL?: boolean, wrap?: boolean | Array<number>);
2122
+ constructor(image: HTMLImageElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap, useWebGL?: boolean, wrap?: boolean | Array<number>, pixelated?: boolean);
1978
2123
  /** @property {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas|ImageBitmap} - image source */
1979
2124
  image: OffscreenCanvas | ImageBitmap | HTMLCanvasElement | HTMLImageElement;
1980
2125
  /** @property {Vector2} - size of the image */
@@ -1988,6 +2133,10 @@ declare module "littlejsengine" {
1988
2133
  * across and down
1989
2134
  * @type {boolean|Array<number>} */
1990
2135
  wrap: boolean | Array<number>;
2136
+ /** @property {boolean|undefined} - Hard edged or smooth for this texture alone, a soft glow in a pixel art
2137
+ * game or pixel art in a smooth one; undefined follows tilesPixelated
2138
+ * @type {boolean|undefined} */
2139
+ pixelated: boolean | undefined;
1991
2140
  /** Creates the WebGL texture, updates if already created */
1992
2141
  createWebGLTexture(): void;
1993
2142
  /** Destroys the WebGL texture */
@@ -1999,6 +2148,10 @@ declare module "littlejsengine" {
1999
2148
  * @param {boolean|Array<number>} [wrap] - true for REPEAT, false for CLAMP_TO_EDGE, or the WebGL modes across
2000
2149
  * and down */
2001
2150
  setWrap(wrap?: boolean | Array<number>): void;
2151
+ /** Make this texture hard edged or smooth on its own, whatever tilesPixelated says for the rest; it is made again
2152
+ * with the new filtering
2153
+ * @param {boolean} [pixelated] - undefined follows tilesPixelated again */
2154
+ setPixelated(pixelated?: boolean): void;
2002
2155
  }
2003
2156
  /** Load a texture at a specific index after engineInit, the images passed to engineInit load this way
2004
2157
  * @param {number} textureIndex - Index to store the texture at, an unused one
@@ -2006,12 +2159,19 @@ declare module "littlejsengine" {
2006
2159
  * @return {Promise<TextureInfo>} Resolves to the texture info once the image loads, or fails to with a warning
2007
2160
  * @memberof Draw */
2008
2161
  export function loadTexture(textureIndex: number, src?: string): Promise<TextureInfo>;
2162
+ /**
2163
+ * @callback SpriteAnimationEndCallback - Called once when a SpriteAnimation's play ends
2164
+ * @return {void}
2165
+ * @memberof Draw
2166
+ */
2009
2167
  /**
2010
2168
  * SpriteAnimation - Steps a tile through its frames over time: looping, once, or there and back
2011
2169
  * - Driven by the engine time like a Timer, so it pauses with the game and needs no update call
2012
2170
  * - Read tileInfo each frame for the frame to draw, from an object's update or before a drawTile
2013
2171
  * - loop, play and pingPong each start over from the first frame; stop holds the current one
2172
+ * - play(onEnd) calls onEnd once the play ends, on the first read after it, since there is no update to call it
2014
2173
  * - Frames follow each other along the row, as tileInfo.frame counts them
2174
+ * - SpriteAnimator switches between a character's animations by name
2015
2175
  * @example
2016
2176
  * const walk = new SpriteAnimation(tile(0, 16), 4, .1); // four frames, a tenth of a second each
2017
2177
  * const attack = new SpriteAnimation(tile(4, 16), 3, .05).play(); // once, then holds the last frame
@@ -2039,19 +2199,23 @@ declare module "littlejsengine" {
2039
2199
  /** @property {number|undefined} - The frame held by stop, undefined while running
2040
2200
  * @type {number|undefined} */
2041
2201
  heldFrame: number | undefined;
2202
+ /** @property {SpriteAnimationEndCallback|undefined} - Called once when a play ends, on the first read after it
2203
+ * @type {SpriteAnimationEndCallback|undefined} */
2204
+ onEnd: SpriteAnimationEndCallback | undefined;
2042
2205
  /** Start over from the first frame and repeat forever
2043
2206
  * @return {SpriteAnimation} */
2044
2207
  loop(): SpriteAnimation;
2045
2208
  /** Start over from the first frame, run through once and hold the last frame, last to first at a negative speed
2209
+ * @param {function():void} [onEnd] - Called once when it ends, on the first read of it after that
2046
2210
  * @return {SpriteAnimation} */
2047
- play(): SpriteAnimation;
2211
+ play(onEnd?: () => void): SpriteAnimation;
2048
2212
  /** Start over from the first frame and run there and back forever
2049
2213
  * @return {SpriteAnimation} */
2050
2214
  pingPong(): SpriteAnimation;
2051
2215
  /** Hold the current frame
2052
2216
  * @return {SpriteAnimation} */
2053
2217
  stop(): SpriteAnimation;
2054
- /** Start over from the first frame in a mode
2218
+ /** Start over from the first frame in a mode, with no end callback
2055
2219
  * @param {string} [mode] - 'loop', 'once' or 'pingPong', the current mode when left out
2056
2220
  * @return {SpriteAnimation} */
2057
2221
  restart(mode?: string): SpriteAnimation;
@@ -2064,7 +2228,52 @@ declare module "littlejsengine" {
2064
2228
  /** The tile of the frame showing now
2065
2229
  * @return {TileInfo} */
2066
2230
  get tileInfo(): TileInfo;
2067
- /** True once a play has shown its last frame for its time
2231
+ /** True once a play has shown its last frame for its time, the first read after that calls onEnd
2232
+ * @return {boolean} */
2233
+ get isDone(): boolean;
2234
+ }
2235
+ /**
2236
+ * SpriteAnimator - A character's animations by name, like idle, walk and attack, and the one showing now
2237
+ * - Each clip is a SpriteAnimation and keeps its own mode, loop, play or pingPong
2238
+ * - set starts a clip over only when it changes or a play of it has ended, so it can be called every update
2239
+ * - Read tileInfo each frame for the frame to draw, as with a SpriteAnimation
2240
+ * @example
2241
+ * const hero = new SpriteAnimator({
2242
+ * idle: new SpriteAnimation(tile(0, 16), 2, .4),
2243
+ * walk: new SpriteAnimation(tile(2, 16), 4, .1),
2244
+ * attack: new SpriteAnimation(tile(6, 16), 3, .05).play(),
2245
+ * });
2246
+ * hero.set('attack', ()=> hero.set('idle')); // back to idle when the attack ends
2247
+ * // in update: this.tileInfo = hero.tileInfo;
2248
+ * @memberof Draw
2249
+ */
2250
+ export class SpriteAnimator {
2251
+ /** Create an animator from its clips, showing the first one
2252
+ * @param {Object<string, SpriteAnimation>} clips - The clips by name */
2253
+ constructor(clips: {
2254
+ [x: string]: SpriteAnimation;
2255
+ });
2256
+ /** @property {Object<string, SpriteAnimation>} - The clips by name */
2257
+ clips: {
2258
+ [x: string]: SpriteAnimation;
2259
+ };
2260
+ /** @property {string} - The name of the clip showing now */
2261
+ name: string;
2262
+ /** Show a clip, starting it over in its own mode unless it is showing and has not ended
2263
+ * @param {string} name - The clip's name
2264
+ * @param {function():void} [onEnd] - Called once when a play clip ends, as with SpriteAnimation.play
2265
+ * @return {SpriteAnimator} */
2266
+ set(name: string, onEnd?: () => void): SpriteAnimator;
2267
+ /** The clip showing now
2268
+ * @return {SpriteAnimation} */
2269
+ get clip(): SpriteAnimation;
2270
+ /** The tile of the frame showing now
2271
+ * @return {TileInfo} */
2272
+ get tileInfo(): TileInfo;
2273
+ /** The frame of the clip showing now
2274
+ * @return {number} */
2275
+ get frame(): number;
2276
+ /** True once the clip showing now is a play that has ended
2068
2277
  * @return {boolean} */
2069
2278
  get isDone(): boolean;
2070
2279
  }
@@ -2590,9 +2799,10 @@ declare module "littlejsengine" {
2590
2799
  * Restores the active texture when done
2591
2800
  * @param {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas|ImageBitmap} [image]
2592
2801
  * @param {boolean|Array<number>} [wrap] - true for REPEAT, false for CLAMP_TO_EDGE, or the WebGL modes across and down
2802
+ * @param {boolean} [pixelated] - Hard edged or smooth, undefined follows tilesPixelated
2593
2803
  * @return {WebGLTexture}
2594
2804
  * @memberof WebGL */
2595
- export function glCreateTexture(image?: HTMLImageElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap, wrap?: boolean | Array<number>): WebGLTexture;
2805
+ export function glCreateTexture(image?: HTMLImageElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap, wrap?: boolean | Array<number>, pixelated?: boolean): WebGLTexture;
2596
2806
  /** Deletes a WebGL texture
2597
2807
  * @param {WebGLTexture} [texture]
2598
2808
  * @memberof WebGL */
@@ -2600,8 +2810,9 @@ declare module "littlejsengine" {
2600
2810
  /** Set WebGL texture data from an image, restores the active texture when done
2601
2811
  * @param {WebGLTexture} texture
2602
2812
  * @param {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas|ImageBitmap} image
2813
+ * @param {boolean} [pixelated] - Hard edged or smooth, undefined follows tilesPixelated
2603
2814
  * @memberof WebGL */
2604
- export function glSetTextureData(texture: WebGLTexture, image: HTMLImageElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap): void;
2815
+ export function glSetTextureData(texture: WebGLTexture, image: HTMLImageElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap, pixelated?: boolean): void;
2605
2816
  /** Draw all sprites and clear out the buffer, called automatically by the system whenever necessary
2606
2817
  * @memberof WebGL */
2607
2818
  export function glFlush(): void;
@@ -2614,6 +2825,17 @@ declare module "littlejsengine" {
2614
2825
  * @param {boolean} [antialias]
2615
2826
  * @memberof WebGL */
2616
2827
  export function glSetAntialias(antialias?: boolean): void;
2828
+ /** The largest texture this device makes, in pixels across, 0 until WebGL starts; at least 2048 with WebGL2
2829
+ * @type {number}
2830
+ * @memberof WebGL */
2831
+ export let glMaxTextureSize: number;
2832
+ /** A texture size this device can make: the size asked for, or the largest it supports when that is smaller
2833
+ * - The engine sizes the textures it makes itself through this, the shadow maps and the like, so a size a device
2834
+ * does not have falls back instead of failing
2835
+ * @param {number} size - Pixels across
2836
+ * @return {number}
2837
+ * @memberof WebGL */
2838
+ export function glClampTextureSize(size: number): number;
2617
2839
  /** Add a sprite to the gl draw list, used by all gl draw functions
2618
2840
  * @param {number} x
2619
2841
  * @param {number} y
@@ -2983,6 +3205,9 @@ declare module "littlejsengine" {
2983
3205
  constructor(asset?: string | URL | any[], randomness?: number, range?: number, taper?: number, onloadCallback?: SoundLoadCallback);
2984
3206
  /** @property {number} - World space max range of sound */
2985
3207
  range: number;
3208
+ /** @property {boolean} - No range was given, so it got soundDefaultRange; played in 3D such a sound is heard
3209
+ * to render3D.soundDefaultRange instead, which is further */
3210
+ rangeIsDefault: boolean;
2986
3211
  /** @property {number} - At what percentage of range should it start tapering */
2987
3212
  taper: number;
2988
3213
  /** @property {number} - How much to randomize frequency each time sound plays
@@ -3266,9 +3491,9 @@ declare module "littlejsengine" {
3266
3491
  * @param {number} [decay] - Decay time, how long to reach sustain after attack (seconds)
3267
3492
  * @param {number} [tremolo] - Trembling effect, rate controlled by repeat time (percent)
3268
3493
  * @param {number} [filter] - Filter cutoff frequency, positive for HPF, negative for LPF (Hz)
3269
- * @return {Array} - Array of audio samples
3494
+ * @return {Float32Array} - The audio samples
3270
3495
  * @memberof Audio */
3271
- 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): any[];
3496
+ 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;
3272
3497
  /**
3273
3498
  * LittleJS Object System
3274
3499
  * - EngineObject is the base class for all game objects
@@ -3950,6 +4175,13 @@ declare module "littlejsengine" {
3950
4175
  localSpace: boolean;
3951
4176
  /** @property {number} - If non zero the particle is drawn as a trail, stretched in the direction of velocity */
3952
4177
  trailScale: number;
4178
+ /** @property {number} - Grows the whole effect as each particle is born: the spawn area, the particles' sizes,
4179
+ * speed and fall, so it looks the same only bigger; 1 is as made, and a particle keeps the scale it was born
4180
+ * with, so a change never moves the ones already out */
4181
+ scale: number;
4182
+ /** @property {number} - The effect's own fall, added to each particle's velocity y every frame, on top of the
4183
+ * world's gravity times gravityScale; an effect that sets its own looks the same in any game */
4184
+ gravity: number;
3953
4185
  /** @property {ParticleCallback|undefined} - Callback when particle is created
3954
4186
  * @type {ParticleCallback|undefined} */
3955
4187
  particleCreateCallback: ParticleCallback | undefined;
@@ -4000,6 +4232,8 @@ declare module "littlejsengine" {
4000
4232
  constructor(emitter: ParticleEmitter, pos: Vector2, angle: number, colorStart: Color, colorEnd: Color, lifeTime: number, sizeStart: number, sizeEnd: number, velocity?: Vector2, angleVelocity?: number);
4001
4233
  /** @property {ParticleEmitter} - The emitter this particle came from */
4002
4234
  emitter: ParticleEmitter;
4235
+ /** @property {number} - The emitter's scale when it was made, which grows its fall */
4236
+ scale: number;
4003
4237
  /** @property {Vector2} - Position, world space or local to the emitter when localSpace is set */
4004
4238
  pos: Vector2;
4005
4239
  /** @property {number} - Angle in radians */
@@ -4318,6 +4552,8 @@ declare module "littlejsengine" {
4318
4552
  * new PostProcessPlugin(shaderCode);
4319
4553
  */
4320
4554
  constructor(shaderCode?: string, includeMainCanvas?: boolean, feedbackTexture?: boolean);
4555
+ /** @property {string} - The shadertoy style mainImage code it shades with, see setShaderCode */
4556
+ shaderCode: string;
4321
4557
  /** @property {WebGLProgram|undefined} - Shader for post processing
4322
4558
  * @type {WebGLProgram|undefined} */
4323
4559
  shader: WebGLProgram | undefined;
@@ -4330,6 +4566,10 @@ declare module "littlejsengine" {
4330
4566
  /** @property {WebGLVertexArrayObject|undefined} - Vertex array object
4331
4567
  * @type {WebGLVertexArrayObject|undefined} */
4332
4568
  vao: WebGLVertexArrayObject | undefined;
4569
+ /** Shade with new code from the next frame on, to switch effects while the game runs; the shader is made again
4570
+ * @param {string} [shaderCode] - Shadertoy style mainImage code, postProcessEffects builds it; none passes the
4571
+ * frame through */
4572
+ setShaderCode(shaderCode?: string): void;
4333
4573
  }
4334
4574
  /**
4335
4575
  * Set up post processing with a bloom effect, so bright colors and lights glow
@@ -4354,6 +4594,98 @@ declare module "littlejsengine" {
4354
4594
  * @memberof PostProcess
4355
4595
  */
4356
4596
  export function postProcessBloomShader(threshold?: number, strength?: number, size?: number): string;
4597
+ /**
4598
+ * Join effects into one post process shader, in the order given, for PostProcessPlugin or setShaderCode
4599
+ * - Each effect is a piece of shader code on c, the pixel's color, and uv, where it is on the screen from 0 to 1;
4600
+ * your own code is a piece too, a line of GLSL or many, dropped in where you put it
4601
+ * - Put the ones that bend the picture or sample it first: postProcessCurve, postProcessChromatic, postProcessGlow
4602
+ * @param {...string} effects - The pieces, from the effect functions or your own code
4603
+ * @return {string} - Shadertoy style mainImage code
4604
+ * @example
4605
+ * new PostProcessPlugin(postProcessEffects(
4606
+ * postProcessScanlines(.5), postProcessVignette(), 'c.rgb *= vec3(1, .9, .8);'));
4607
+ * @memberof PostProcess
4608
+ */
4609
+ export function postProcessEffects(...effects: string[]): string;
4610
+ /**
4611
+ * Bright parts glow, the bloom as an effect to join with others; postProcessBloom sets up bloom on its own
4612
+ * @param {number} [threshold] - Brightness where the glow starts, 0 is everything and 1 is only pure white
4613
+ * @param {number} [strength] - How much glow to add
4614
+ * @param {number} [size] - How far the glow spreads in pixels, which also sets how many samples it takes
4615
+ * @return {string}
4616
+ * @memberof PostProcess
4617
+ */
4618
+ export function postProcessGlow(threshold?: number, strength?: number, size?: number): string;
4619
+ /**
4620
+ * Scan lines across the screen, like an old TV
4621
+ * @param {number} [strength] - How dark the lines are, and how bright between them
4622
+ * @param {number} [spacing] - Pixels from one line to the next
4623
+ * @return {string}
4624
+ * @memberof PostProcess
4625
+ */
4626
+ export function postProcessScanlines(strength?: number, spacing?: number): string;
4627
+ /**
4628
+ * Static noise over the picture, changing every frame
4629
+ * @param {number} [strength] - How bright the static is
4630
+ * @param {number} [size] - Size of a speck in pixels
4631
+ * @return {string}
4632
+ * @memberof PostProcess
4633
+ */
4634
+ export function postProcessNoise(strength?: number, size?: number): string;
4635
+ /**
4636
+ * Darken toward the edges and corners
4637
+ * @param {number} [strength] - How dark the corners get, 1 is black
4638
+ * @param {number} [falloff] - How far in it reaches, low darkens most of the screen, high only the corners
4639
+ * @return {string}
4640
+ * @memberof PostProcess
4641
+ */
4642
+ export function postProcessVignette(strength?: number, falloff?: number): string;
4643
+ /**
4644
+ * Bend the picture like the bulged glass of an old TV, black past the corners; put it first
4645
+ * @param {number} [strength] - How much it bends
4646
+ * @return {string}
4647
+ * @memberof PostProcess
4648
+ */
4649
+ export function postProcessCurve(strength?: number): string;
4650
+ /**
4651
+ * Split red and blue apart toward the edges, like a cheap lens; put it before what shades the picture
4652
+ * @param {number} [strength] - How far apart at the edge, as a part of the screen
4653
+ * @return {string}
4654
+ * @memberof PostProcess
4655
+ */
4656
+ export function postProcessChromatic(strength?: number): string;
4657
+ /**
4658
+ * Draw lines where the 3D depth jumps, around objects and along their creases; needs render3D.depthTexture on
4659
+ * @param {Color} [color] - The lines' color, its alpha how strong they are
4660
+ * @param {number} [thickness] - How wide the lines are in pixels
4661
+ * @param {number} [threshold] - How big a jump makes a line, as a part of the distance, lower draws more
4662
+ * @return {string}
4663
+ * @memberof PostProcess
4664
+ */
4665
+ export function postProcessOutline(color?: Color, thickness?: number, threshold?: number): string;
4666
+ /**
4667
+ * The look of an old TV, as one effect to use alone or join with others: static noise, scan lines, a soft glow and
4668
+ * a vignette, and a bulged screen when curve is set; any setting at 0 leaves that part out
4669
+ * @param {Object} [settings]
4670
+ * @param {number} [settings.noise] - Static noise strength
4671
+ * @param {number} [settings.scanlines] - Scan line strength
4672
+ * @param {number} [settings.scanlineSpacing] - Pixels from one scan line to the next
4673
+ * @param {number} [settings.glow] - Soft glow strength
4674
+ * @param {number} [settings.vignette] - Vignette strength
4675
+ * @param {number} [settings.curve] - How much the screen bulges, 0 by default for flat
4676
+ * @return {string}
4677
+ * @example
4678
+ * new PostProcessPlugin(postProcessEffects(postProcessTV({scanlines: .4, curve: .1})));
4679
+ * @memberof PostProcess
4680
+ */
4681
+ export function postProcessTV({ noise, scanlines, scanlineSpacing, glow, vignette, curve }?: {
4682
+ noise?: number;
4683
+ scanlines?: number;
4684
+ scanlineSpacing?: number;
4685
+ glow?: number;
4686
+ vignette?: number;
4687
+ curve?: number;
4688
+ }): string;
4357
4689
  /**
4358
4690
  * LittleJS Light System Plugin
4359
4691
  * - Adds 2D dynamic lighting to the scene
@@ -4376,6 +4708,8 @@ declare module "littlejsengine" {
4376
4708
  * shadow map through renderShadow(), which calls render() by default; obj.castShadow = false keeps it
4377
4709
  * out (a floor TileLayer, a background), a draw's alpha sets how much light it blocks, and
4378
4710
  * setShadowTransparent lets its color tint the light
4711
+ * - 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
4712
+ * lightmap, so it shows in the dark and sits in front of everything there
4379
4713
  * - Must be constructed BEFORE PostProcessPlugin so post-process sees lit pixels
4380
4714
  * @namespace LightSystem
4381
4715
  */
@@ -4473,6 +4807,9 @@ declare module "littlejsengine" {
4473
4807
  shadowMapWorldSize: number;
4474
4808
  shadowMapSizeAllocated: number;
4475
4809
  shadowTextureSizeAllocated: number;
4810
+ /** Bring the sizes of the textures it makes down to what the device can make: shadowMapSize, shadowTextureSize
4811
+ * and a textureSize given by hand; called before they are made, so a size too big falls back instead of failing */
4812
+ clampTextureSizes(): void;
4476
4813
  /** Draw a single Light's falloff blob into the currently bound lightmap.
4477
4814
  * Called by Light.renderLight() during the plugin's render pass.
4478
4815
  * @param {Light} light */
@@ -4520,6 +4857,17 @@ declare module "littlejsengine" {
4520
4857
  * or torch that holds it, or the player carrying it, does not block it; it has to reach past that object's
4521
4858
  * corners, about half its diagonal and a little more, or dark rays run out from them */
4522
4859
  shadowCore: number;
4860
+ /** @property {number} - Size across of a soft hazy glow drawn over the light, like a lamp at night, 0 for
4861
+ * none; it is added over the lit scene, in front of everything there */
4862
+ glow: number;
4863
+ /** @property {number} - How fast the glow fades from its middle: 1 by default, .5 a wide haze, 2 a tight
4864
+ * bright core */
4865
+ glowFalloff: number;
4866
+ /** @type {TileInfo|undefined} */
4867
+ glowTileInfo: TileInfo | undefined;
4868
+ /** Draw this light's glow, soft and round, its glow size across and in its color, added over the lit scene;
4869
+ * called by LightSystemPlugin after the lightmap is applied */
4870
+ renderGlow(): void;
4523
4871
  }
4524
4872
  /**
4525
4873
  * LittleJS ZzFXM Plugin
@@ -6788,6 +7136,16 @@ declare module "littlejsengine" {
6788
7136
  function PIECEWISE(...fns: ((arg0: number) => number)[]): (arg0: number) => number;
6789
7137
  function BEZIER(x1: number, y1: number, x2: number, y2: number): (arg0: number) => number;
6790
7138
  }
7139
+ /** Leave the current scene, destroy every object that is not persistent, and enter the next scene
7140
+ * - Setting the current scene again restarts it, and no scene leaves the game with none
7141
+ * - The switch happens at once, it can be called from anywhere but a scene's leave
7142
+ * @param {Scene} [scene] - The scene to enter
7143
+ * @memberof SceneSystem */
7144
+ export function setScene(scene?: Scene): void;
7145
+ /** Get the current scene
7146
+ * @return {Scene|undefined}
7147
+ * @memberof SceneSystem */
7148
+ export function getScene(): Scene | undefined;
6791
7149
  /** Grid pathfinder using A* with two optional smoothing passes.
6792
7150
  * @memberof PathFinding
6793
7151
  * @example
@@ -7363,24 +7721,27 @@ declare module "littlejsengine" {
7363
7721
  */
7364
7722
  export function buildMatrix(pos?: Vector3, rotation?: Vector3, scale?: Vector3, matrix?: Matrix4): Matrix4;
7365
7723
  /**
7366
- * Check if a point is inside an axis aligned box, boundary is inclusive
7724
+ * Check if a point is inside a box, boundary is inclusive
7367
7725
  * @param {Vector3} point
7368
7726
  * @param {Vector3} pos - Center of the box
7369
7727
  * @param {Vector3} size - Full size of the box
7728
+ * @param {Vector3} [rotation] - How the box is turned, upright when left out
7370
7729
  * @return {boolean}
7371
7730
  * @memberof Math3D
7372
7731
  */
7373
- export function isPointInBox3D(point: Vector3, pos: Vector3, size: Vector3): boolean;
7732
+ export function isPointInBox3D(point: Vector3, pos: Vector3, size: Vector3, rotation?: Vector3): boolean;
7374
7733
  /**
7375
- * Check if two axis aligned boxes are overlapping, touching edges do not overlap
7734
+ * Check if two boxes are overlapping, touching edges do not overlap
7376
7735
  * @param {Vector3} posA
7377
7736
  * @param {Vector3} sizeA - Full size of box A
7378
7737
  * @param {Vector3} posB
7379
7738
  * @param {Vector3} [sizeB] - Full size of box B, zero for a point
7739
+ * @param {Vector3} [rotationA] - How box A is turned, upright when left out
7740
+ * @param {Vector3} [rotationB] - How box B is turned
7380
7741
  * @return {boolean}
7381
7742
  * @memberof Math3D
7382
7743
  */
7383
- export function isOverlapping3D(posA: Vector3, sizeA: Vector3, posB: Vector3, sizeB?: Vector3): boolean;
7744
+ export function isOverlapping3D(posA: Vector3, sizeA: Vector3, posB: Vector3, sizeB?: Vector3, rotationA?: Vector3, rotationB?: Vector3): boolean;
7384
7745
  /**
7385
7746
  * Returns the vector to move sphere A by so it no longer overlaps sphere B, or undefined
7386
7747
  * @param {Vector3} posA
@@ -7392,15 +7753,16 @@ declare module "littlejsengine" {
7392
7753
  */
7393
7754
  export function collideSphereSphere(posA: Vector3, radiusA: number, posB: Vector3, radiusB: number): Vector3 | undefined;
7394
7755
  /**
7395
- * Returns the vector to move a sphere out of an axis aligned box, or undefined
7756
+ * Returns the vector to move a sphere out of a box, or undefined
7396
7757
  * @param {Vector3} pos - Sphere center
7397
7758
  * @param {number} radius
7398
7759
  * @param {Vector3} boxPos
7399
7760
  * @param {Vector3} boxSize - Full size of the box
7761
+ * @param {Vector3} [boxRotation] - How the box is turned, upright when left out
7400
7762
  * @return {Vector3|undefined}
7401
7763
  * @memberof Math3D
7402
7764
  */
7403
- export function collideSphereBox(pos: Vector3, radius: number, boxPos: Vector3, boxSize: Vector3): Vector3 | undefined;
7765
+ export function collideSphereBox(pos: Vector3, radius: number, boxPos: Vector3, boxSize: Vector3, boxRotation?: Vector3): Vector3 | undefined;
7404
7766
  /**
7405
7767
  * Returns the vector to move a sphere back inside an axis aligned box, or undefined when it is all inside
7406
7768
  * - The inside out twin of collideSphereBox, for keeping things in a room or an arena
@@ -7427,14 +7789,17 @@ declare module "littlejsengine" {
7427
7789
  /**
7428
7790
  * Returns the vector to move box A by so it no longer overlaps box B, the shortest way out, or undefined
7429
7791
  * - The 3D twin of collideBoxBox
7792
+ * - Turned boxes are tested by the separating axis test, the push is along the direction they overlap least on
7430
7793
  * @param {Vector3} posA
7431
7794
  * @param {Vector3} sizeA - Full size of box A
7432
7795
  * @param {Vector3} posB
7433
7796
  * @param {Vector3} sizeB - Full size of box B
7797
+ * @param {Vector3} [rotationA] - How box A is turned, upright when left out
7798
+ * @param {Vector3} [rotationB] - How box B is turned
7434
7799
  * @return {Vector3|undefined}
7435
7800
  * @memberof Math3D
7436
7801
  */
7437
- export function collideBoxBox3D(posA: Vector3, sizeA: Vector3, posB: Vector3, sizeB: Vector3): Vector3 | undefined;
7802
+ export function collideBoxBox3D(posA: Vector3, sizeA: Vector3, posB: Vector3, sizeB: Vector3, rotationA?: Vector3, rotationB?: Vector3): Vector3 | undefined;
7438
7803
  /**
7439
7804
  * Returns the distance along the ray to the first intersection with a sphere, or undefined
7440
7805
  * - The hit is ray.getPosition(distance), a direction that is not unit length scales the distance
@@ -7457,16 +7822,17 @@ declare module "littlejsengine" {
7457
7822
  */
7458
7823
  export function raycastPlane(ray: Ray3D, planePos: Vector3, planeNormal: Vector3): number | undefined;
7459
7824
  /**
7460
- * Returns the distance along the ray to the first intersection with an axis aligned box, or undefined
7825
+ * Returns the distance along the ray to the first intersection with a box, or undefined
7461
7826
  * - The hit is ray.getPosition(distance), a direction that is not unit length scales the distance
7462
7827
  * - A ray starting inside the box is already there, so it gets back 0
7463
7828
  * @param {Ray3D} ray
7464
7829
  * @param {Vector3} pos - Center of the box
7465
7830
  * @param {Vector3} size - Full size of the box
7831
+ * @param {Vector3} [rotation] - How the box is turned, upright when left out
7466
7832
  * @return {number|undefined}
7467
7833
  * @memberof Math3D
7468
7834
  */
7469
- export function raycastBox(ray: Ray3D, pos: Vector3, size: Vector3): number | undefined;
7835
+ export function raycastBox(ray: Ray3D, pos: Vector3, size: Vector3, rotation?: Vector3): number | undefined;
7470
7836
  /**
7471
7837
  * LittleJS 3D Rendering Plugin
7472
7838
  * - Adds a 3D scene that draws into the same WebGL canvas as the 2D game
@@ -7499,6 +7865,10 @@ declare module "littlejsengine" {
7499
7865
  * new EngineObject3D(vec3(), buildBox());
7500
7866
  */
7501
7867
  export class Render3DPlugin {
7868
+ /** @type {Render3DDrawState} */
7869
+ drawState: Render3DDrawState;
7870
+ /** @property {number} - Goes up when a draw state field changes, so a batch sees at a glance that none did */
7871
+ stateVersion: number;
7502
7872
  /** @property {Camera3D} - The camera */
7503
7873
  camera: Camera3D;
7504
7874
  /** @property {Vector3} - Direction toward the sun, where its light comes from, like a directional Light3D;
@@ -7531,10 +7901,22 @@ declare module "littlejsengine" {
7531
7901
  /** @property {boolean} - Default for every builder's smooth argument: true for smooth vertex normals, false for
7532
7902
  * flat faces */
7533
7903
  smoothShading: boolean;
7904
+ /** @property {boolean} - Draw the camera's depth into a texture each frame for post processing:
7905
+ * PostProcessPlugin hands it to its shader as iChannel2, read with sceneDepth(uv); off by default and free
7906
+ * when off, on it draws the solid objects of the default layer once more, depth only */
7907
+ depthTexture: boolean;
7534
7908
  /** @property {boolean} - Cast real shadows from the sun, off by default and free when off */
7535
7909
  shadows: boolean;
7910
+ /** @property {number} - How far a sound played with playSound is heard when it was made with no range of
7911
+ * its own, in world units; further than the 2D soundDefaultRange, a 3D world is bigger */
7912
+ soundDefaultRange: number;
7536
7913
  /** @property {number} - Size of the shadow map in pixels, bigger is sharper and slower */
7537
7914
  shadowMapSize: number;
7915
+ /** @property {Light3D|undefined} - A spotlight, a Light3D with a coneAngle, to cast the shadows in place
7916
+ * of the sun, a flashlight in the dark: the shadow map looks down its cone, as far as its radius, and the
7917
+ * sun still lights the scene but casts none; undefined for the sun, as is a light that is off or has no cone
7918
+ * @type {Light3D|undefined} */
7919
+ shadowLight: Light3D | undefined;
7538
7920
  /** @property {number} - World size the shadow map covers around shadowCenter, smaller is sharper; it is a
7539
7921
  * square facing the light, so it turns as the light does, and about 1.5 times an area's width covers it from
7540
7922
  * any angle */
@@ -7546,31 +7928,6 @@ declare module "littlejsengine" {
7546
7928
  shadowBias: number;
7547
7929
  /** @property {number} - How much to blur the shadow edges */
7548
7930
  shadowSoftness: number;
7549
- /** @property {boolean} - Apply lighting, when false draws plain vertex color times texture and casts no shadow;
7550
- * off for billboards, lines, ribbons and soft discs, an object sets emissive instead */
7551
- lighting: boolean;
7552
- /** @property {number} - How much a surface lights itself, set per object by its emissive */
7553
- emissive: number;
7554
- /** @property {boolean} - Additive blending instead of alpha, in the transparent stage */
7555
- additive: boolean;
7556
- /** @property {boolean} - Test against the depth buffer, reset to true before each object and callback; a draw
7557
- * with it off goes over what was drawn before it and under what is drawn after, by render order, which
7558
- * ends the batch of meshes before it, so one per object costs a draw per object */
7559
- depthTest: boolean;
7560
- /** @property {boolean} - Write to the depth buffer, owned by the stages: on for opaque, off for transparent */
7561
- depthWrite: boolean;
7562
- cullBackFaces: boolean;
7563
- mirrored: boolean;
7564
- /** @property {number} - Strength of the highlight where the sun and the Light3D objects reflect, 0 is none and
7565
- * 1 adds a light's full color at its brightest; its size is fixed */
7566
- specular: number;
7567
- /** @property {Shader|undefined} - Custom Shader for the next draws, set from each object's shader; undefined
7568
- * draws with the plugin's own
7569
- * @type {Shader|undefined} */
7570
- shader: Shader | undefined;
7571
- /** @property {boolean} - Darken by the shadow map when shadows are on, turn it off for things that should stay
7572
- * lit inside a shadow */
7573
- receiveShadow: boolean;
7574
7931
  /** @property {Function|undefined} - Draw solid world here, it runs again for shadows so only draw in it
7575
7932
  * @type {Function|undefined} */
7576
7933
  onRenderOpaque: Function | undefined;
@@ -7592,9 +7949,6 @@ declare module "littlejsengine" {
7592
7949
  /** @property {boolean} - Sample textures through mipmaps so they do not shimmer in the distance, false uses
7593
7950
  * each texture's own filtering like 2D */
7594
7951
  mipmaps: boolean;
7595
- /** @property {boolean} - Draw state: keep texture pixels hard edged, no mipmaps and no blending between them,
7596
- * set per object by pixelated */
7597
- pixelated: boolean;
7598
7952
  /** @property {number} - Anisotropic filtering for textures seen at an angle, 1 to 16, 1 is off; needs mipmaps */
7599
7953
  anisotropy: number;
7600
7954
  /** @property {Mesh} - A box of size 1 that drawBox uses, for any object that is a box; set the object's scale3D
@@ -7629,7 +7983,6 @@ declare module "littlejsengine" {
7629
7983
  /** @property {Vector3} - Camera forward axis this frame */
7630
7984
  cameraForward: Vector3;
7631
7985
  cameraBack: Vector3;
7632
- blend: boolean;
7633
7986
  /** @type {Array<Array<number>>} */
7634
7987
  frustumPlanes: Array<Array<number>>;
7635
7988
  /** @type {Array<Array<number>>} */
@@ -7654,6 +8007,13 @@ declare module "littlejsengine" {
7654
8007
  /** @type {WebGLFramebuffer|undefined} */
7655
8008
  shadowFramebuffer: WebGLFramebuffer | undefined;
7656
8009
  shadowTextureSize: number;
8010
+ /** @type {WebGLTexture|undefined} */
8011
+ cameraDepthTexture: WebGLTexture | undefined;
8012
+ /** @type {WebGLFramebuffer|undefined} */
8013
+ cameraDepthFramebuffer: WebGLFramebuffer | undefined;
8014
+ cameraDepthWidth: number;
8015
+ cameraDepthHeight: number;
8016
+ depthPass: boolean;
7657
8017
  contextGeneration: number;
7658
8018
  uniforms: Map<any, any>;
7659
8019
  /** @type {Object<string, Array<number>>} */
@@ -7664,6 +8024,9 @@ declare module "littlejsengine" {
7664
8024
  passIsDefault: boolean;
7665
8025
  lightPositions: Float32Array;
7666
8026
  lightColors: Float32Array;
8027
+ lightCones: Float32Array;
8028
+ shadowLightIndex: number;
8029
+ shadowDepthBias: number;
7667
8030
  /** @type {WebGLBuffer|undefined} */
7668
8031
  streamBuffer: WebGLBuffer | undefined;
7669
8032
  /** @type {Array<WebGLBuffer>} */
@@ -7688,6 +8051,89 @@ declare module "littlejsengine" {
7688
8051
  state: any;
7689
8052
  draw: () => void;
7690
8053
  }> | undefined;
8054
+ set lighting(arg: boolean);
8055
+ /** Apply lighting, when false draws plain vertex color times texture and casts no shadow;
8056
+ * off for billboards, lines, ribbons and soft discs, an object sets emissive instead
8057
+ * @return {boolean} */
8058
+ get lighting(): boolean;
8059
+ set emissive(arg: number);
8060
+ /** How much a surface lights itself, set per object by its emissive
8061
+ * @return {number} */
8062
+ get emissive(): number;
8063
+ set additive(arg: boolean);
8064
+ /** Additive blending instead of alpha, in the transparent stage
8065
+ * @return {boolean} */
8066
+ get additive(): boolean;
8067
+ set depthTest(arg: boolean);
8068
+ /** Test against the depth buffer, reset to true before each object and callback; a draw
8069
+ * with it off goes over what was drawn before it and under what is drawn after, by render order, which
8070
+ * ends the batch of meshes before it, so one per object costs a draw per object
8071
+ * @return {boolean} */
8072
+ get depthTest(): boolean;
8073
+ set depthWrite(arg: boolean);
8074
+ /** Write to the depth buffer, owned by the stages: on for opaque, off for transparent
8075
+ * @return {boolean} */
8076
+ get depthWrite(): boolean;
8077
+ set cullBackFaces(arg: boolean);
8078
+ /** Skip back faces, set by drawMesh from each mesh: off for strips so they show from
8079
+ * both sides
8080
+ * @return {boolean} */
8081
+ get cullBackFaces(): boolean;
8082
+ set mirrored(arg: boolean);
8083
+ /** The transform mirrors the draw, so the other winding is the front, set by drawMesh
8084
+ * from each transform
8085
+ * @return {boolean} */
8086
+ get mirrored(): boolean;
8087
+ set specular(arg: number);
8088
+ /** Strength of the highlight where the sun and the Light3D objects reflect, 0 is none and
8089
+ * 1 adds a light's full color at its brightest; shininess sets its size
8090
+ * @return {number} */
8091
+ get specular(): number;
8092
+ set shininess(arg: number);
8093
+ /** The highlight's exponent, how small and sharp it is: 4 is broad like rubber, 100 sharp
8094
+ * like polished metal; set from each object's shininess
8095
+ * @return {number} */
8096
+ get shininess(): number;
8097
+ set normalMap(arg: TextureInfo);
8098
+ /** Normal map for the next draws, set from each object's normalMap
8099
+ * @return {TextureInfo|undefined} */
8100
+ get normalMap(): TextureInfo;
8101
+ set normalScale(arg: number);
8102
+ /** How strongly the normal map bends the surface, set from each object's normalScale
8103
+ * @return {number} */
8104
+ get normalScale(): number;
8105
+ set reflectivity(arg: number);
8106
+ /** How much the surface reflects the sky, 0 to 1, set from each object's reflectivity
8107
+ * @return {number} */
8108
+ get reflectivity(): number;
8109
+ set emissiveMap(arg: TextureInfo);
8110
+ /** Emissive map for the next draws, set from each object's emissiveMap
8111
+ * @return {TextureInfo|undefined} */
8112
+ get emissiveMap(): TextureInfo;
8113
+ set emissiveMapColor(arg: Color);
8114
+ /** Multiplies the emissive map, set from each object's emissiveMapColor; compared by its rgb, so a Color
8115
+ * changed in place is seen when it is set again, and undefined is white
8116
+ * @return {Color} */
8117
+ get emissiveMapColor(): Color;
8118
+ set shader(arg: Shader);
8119
+ /** Custom Shader for the next draws, set from each object's shader; undefined draws
8120
+ * with the plugin's own
8121
+ * @return {Shader|undefined} */
8122
+ get shader(): Shader;
8123
+ set receiveShadow(arg: boolean);
8124
+ /** Darken by the shadow map when shadows are on, turn it off for things that should
8125
+ * stay lit inside a shadow
8126
+ * @return {boolean} */
8127
+ get receiveShadow(): boolean;
8128
+ set pixelated(arg: boolean);
8129
+ /** Keep texture pixels hard edged, no mipmaps and no blending between them, set per
8130
+ * object by pixelated
8131
+ * @return {boolean} */
8132
+ get pixelated(): boolean;
8133
+ set blend(arg: boolean);
8134
+ /** Blending on, set by the stages
8135
+ * @return {boolean} */
8136
+ get blend(): boolean;
7691
8137
  /** Rebuild the view and projection matrices from the camera, called automatically each frame
7692
8138
  * @param {number} [aspect] - Width over height, defaults to the main canvas */
7693
8139
  updateMatrices(aspect?: number): void;
@@ -7728,7 +8174,8 @@ declare module "littlejsengine" {
7728
8174
  distance: number;
7729
8175
  } | undefined;
7730
8176
  /** Play a sound at a 3D position, quieter with distance from the camera and panned by its side, like Sound.play
7731
- * with a 2D position
8177
+ * with a 2D position; a sound made with no range of its own is heard to soundDefaultRange, 100, and one given
8178
+ * a range keeps it
7732
8179
  * @param {Sound} sound
7733
8180
  * @param {Vector3} pos3D
7734
8181
  * @param {number} [volume]
@@ -7953,17 +8400,17 @@ declare module "littlejsengine" {
7953
8400
  * EngineObject3D - An EngineObject with a 3D transform and a mesh
7954
8401
  * - Set pos3D, rotation3D and scale3D instead of the 2D pos, size and angle
7955
8402
  * - Gets update, children, timers, destroy and renderOrder from EngineObject
7956
- * - velocity3D is added to pos3D each frame, along with render3D.gravity and damping once it has a mass
8403
+ * - velocity3D is added to pos3D each frame, slowed by damping, and render3D.gravity pulls it once it has a mass
7957
8404
  * - Objects face -Z, the same way the camera does, so lookAt turns them to face a point
7958
8405
  * - The 2D pos and velocity are still there but nothing draws them
7959
- * - These inherited fields are 2D only and do nothing here: angle, angleVelocity, angleDamping,
7960
- * additiveColor, drawSize, mirror, clampSpeed, friction and groundObject
8406
+ * - These inherited fields are 2D only and do nothing here: angle, angleVelocity, additiveColor, drawSize and mirror;
8407
+ * damping, angleDamping, clampSpeed, friction and groundObject work as in 2D, on velocity3D and angleVelocity3D
7961
8408
  * - The inherited shader works here as in 2D, and with emissive at 1 its snippet does its own lighting
7962
8409
  * - Set sync2D for a 2D game with 3D looks, pos and angle then drive pos3D and rotation3D,
7963
8410
  * which is the one way those 2D fields reach a 3D object
7964
8411
  * - setCollision takes the same flags as in 2D, but the solid collision happens in 3D against size3D
7965
- * - The solid box is axis aligned in the world, rotation3D is ignored like angle is in 2D, so give a turned wall a
7966
- * size3D along the world axes
8412
+ * - The solid box turns with rotation3D, so a turned wall or a ramp collides as it looks; resting on one no steeper
8413
+ * than groundAngle stands there
7967
8414
  * - Its tile and raycast halves are 2D only so they default off here, and a child sits solid collision out
7968
8415
  * - A sync2D object collides in 2D instead, which needs the 2D size set as well as size3D
7969
8416
  * - setMesh swaps the mesh and frees the old one, for text and terrain that get built again
@@ -7997,7 +8444,7 @@ declare module "littlejsengine" {
7997
8444
  /** @property {Vector3} - Added to pos3D each frame by the engine before update, like the 2D velocity, no super
7998
8445
  * call needed; damping and render3D.gravity act on it once the object has a mass */
7999
8446
  velocity3D: Vector3;
8000
- /** @property {Vector3} - Added to rotation3D each frame by the engine before update, angleDamping is 2D only */
8447
+ /** @property {Vector3} - Added to rotation3D each frame by the engine before update, slowed by angleDamping */
8001
8448
  angleVelocity3D: Vector3;
8002
8449
  /** @property {Mesh|undefined} - Mesh to draw
8003
8450
  * @type {Mesh|undefined} */
@@ -8019,11 +8466,33 @@ declare module "littlejsengine" {
8019
8466
  /** @property {boolean} - Additive blending, in the transparent stage */
8020
8467
  additive: boolean;
8021
8468
  /** @property {number} - Strength of the highlight where the sun and the Light3D objects reflect, 0 is none and
8022
- * 1 adds a light's full color at its brightest; its size is fixed */
8469
+ * 1 adds a light's full color at its brightest; shininess sets its size */
8023
8470
  specular: number;
8471
+ /** @property {number} - The highlight's exponent, how small and sharp it is: 4 is broad like rubber, 16 the
8472
+ * default, 100 sharp like polished metal; shows only with specular above 0 */
8473
+ shininess: number;
8474
+ /** @property {TextureInfo|undefined} - A normal map that bends the surface at each texel so it catches the
8475
+ * light like bumps and grooves, green pointing up the image as OpenGL and glTF have it; read at the color
8476
+ * texture's coordinates, see normalMapFromHeight to make one in code
8477
+ * @type {TextureInfo|undefined} */
8478
+ normalMap: TextureInfo | undefined;
8479
+ /** @property {number} - How strongly the normal map bends the surface, 0 turns it off, as glTF's scale */
8480
+ normalScale: number;
8481
+ /** @property {number} - How much it reflects the sky, 0 none and 1 a mirror of it; the edges seen at a
8482
+ * glancing angle reflect more either way, as water and glass do */
8483
+ reflectivity: number;
8484
+ /** @property {TextureInfo|undefined} - A texture of where it glows, added on top of the lit surface so it
8485
+ * shows in the dark, like lit windows; read at the color texture's coordinates
8486
+ * @type {TextureInfo|undefined} */
8487
+ emissiveMap: TextureInfo | undefined;
8488
+ /** @property {Color} - Multiplies the emissive map, as glTF's emissiveFactor */
8489
+ emissiveMapColor: Color;
8024
8490
  /** @property {boolean} - Collide as the sphere that fits size3D instead of as the size3D box, so it rolls
8025
8491
  * around corners */
8026
8492
  collideAsSphere3D: boolean;
8493
+ /** @property {number} - The steepest slope it stands on, in radians from level, PI/4 by default: resting on
8494
+ * a solid within this of flat sets groundObject and holds it still, steeper it slides down */
8495
+ groundAngle: number;
8027
8496
  /** @property {boolean} - Darkened by the shadow map when render3D.shadows is on */
8028
8497
  receiveShadow: boolean;
8029
8498
  /** @property {boolean|undefined} - Draw this object over the 2D scene, undefined uses render3D.renderAfter2D
@@ -8297,20 +8766,24 @@ declare module "littlejsengine" {
8297
8766
  * InstancedMesh3D - Many copies of one mesh drawn as one call, with their transforms kept on the GPU
8298
8767
  * - For big sets that mostly stay put: an instance costs nothing per frame until it changes, so a hundred thousand
8299
8768
  * trees cost what one tree does; objects and drawMesh batch by themselves too, but rebuild their batch every frame
8300
- * - setMatrixAt and setColorAt change one instance, and only the changed range uploads before the next draw
8769
+ * - setTransformAt, setMatrixAt and setColorAt change one instance, and only the changed range uploads before the
8770
+ * next draw; the matrices and the colors are kept apart, so moving instances uploads 64 bytes each
8771
+ * - For many instances moving every frame, setTransforms places a run of them from arrays of positions, rotations
8772
+ * and scales in one loop, the fastest way; or write matrixData directly and call markDirtyRange
8301
8773
  * - The instances are in world space; the object's own pos3D, rotation3D and scale3D do not move them
8302
- * - The whole set is culled by one bounding sphere around the origin, and casts and receives shadows like any object
8774
+ * - The whole set is culled by one bounding sphere around the origin, worked out when culling reads it, or set by hand
8775
+ * with radius; it casts and receives shadows like any object
8303
8776
  * - The object's flags cover the whole set, one emissive, one tileInfo, one shader; only the colors are per instance
8304
8777
  * - A mirrored instance, one with a negative scale, shows its inside unless the mesh is doubleSided
8305
8778
  * - A transparent set draws in one go in the transparent stage, its instances are not sorted against each other;
8306
8779
  * the set sorts against other transparent draws by the object's position, so put pos3D at its middle
8307
- * - pick, the raycast and the collect helpers do not see the instances, test them yourself from instanceData
8780
+ * - pick, the raycast and the collect helpers do not see the instances, test them yourself from matrixData
8308
8781
  * @extends EngineObject3D
8309
8782
  * @memberof Render3D
8310
8783
  * @example
8311
8784
  * const forest = new InstancedMesh3D(treeMesh, 1000);
8312
8785
  * for (let i = 0; i < 1000; ++i)
8313
- * forest.setMatrixAt(i, buildMatrix(randomGroundPos(), vec3(0, rand(2*PI), 0)));
8786
+ * forest.setTransformAt(i, randomGroundPos(), vec3(0, rand(2*PI), 0));
8314
8787
  */
8315
8788
  export class InstancedMesh3D extends EngineObject3D {
8316
8789
  /** Create a set of instances of a mesh, each at the origin in the object's color until it is set
@@ -8323,21 +8796,53 @@ declare module "littlejsengine" {
8323
8796
  count: number;
8324
8797
  /** @property {number} - How many instances it was made with */
8325
8798
  maxCount: number;
8326
- /** @property {Float32Array} - The per instance values the shader reads, 24 floats each: the matrix, the color
8327
- * and the uv rect; edit it directly and call markDirty for the instances changed */
8328
- instanceData: Float32Array;
8329
- /** @property {number} - Radius of the sphere around the origin that holds every instance set so far, for
8330
- * culling; from the farthest instance and the largest scale, and the mesh's size when it draws */
8331
- radius: number;
8332
- reach: number;
8333
- maxScale: number;
8334
- /** @property {number} - First instance to upload before the next draw */
8799
+ /** @property {Float32Array} - Each instance's matrix, 16 floats, what moving them uploads; edit it directly and
8800
+ * call markDirty for the instances changed */
8801
+ matrixData: Float32Array;
8802
+ /** @property {Float32Array} - Each instance's color and uv rect, 8 floats, uploaded only when they change; edit
8803
+ * it directly and call markColorDirty for the instances changed */
8804
+ colorData: Float32Array;
8805
+ /** @property {number} - First instance whose matrix uploads before the next draw */
8335
8806
  dirtyStart: number;
8336
- /** @property {number} - One past the last instance to upload, so nothing uploads when it is not past dirtyStart */
8807
+ /** @property {number} - One past the last instance whose matrix uploads, nothing when it is not past dirtyStart */
8337
8808
  dirtyEnd: number;
8809
+ /** @property {number} - First instance whose color uploads before the next draw */
8810
+ colorDirtyStart: number;
8811
+ /** @property {number} - One past the last instance whose color uploads */
8812
+ colorDirtyEnd: number;
8813
+ reachSquared: number;
8814
+ scaleSquared: number;
8815
+ boundsStart: number;
8816
+ boundsEnd: number;
8817
+ /** @type {number|undefined} */
8818
+ fixedRadius: number | undefined;
8338
8819
  buffer: WebGLBuffer;
8820
+ /** @type {WebGLBuffer|undefined} */
8821
+ colorBuffer: WebGLBuffer | undefined;
8339
8822
  bufferGeneration: number;
8340
8823
  uvTileInfo: TileInfo | TextureInfo;
8824
+ /** Place an instance by its position, rotation and scale, what buildMatrix takes, written straight in with no
8825
+ * matrix made; in world space
8826
+ * @param {number} i
8827
+ * @param {Vector3} [pos]
8828
+ * @param {Vector3} [rotation] - Euler angles in radians
8829
+ * @param {Vector3} [scale] */
8830
+ setTransformAt(i: number, pos?: Vector3, rotation?: Vector3, scale?: Vector3): void;
8831
+ /** Place a run of instances from arrays indexed by instance, plain or typed, as a game keeps them: each is placed
8832
+ * as setTransformAt places it, all in one loop with nothing made, the fastest way to move many every frame;
8833
+ * in world space
8834
+ * @param {number} start - First instance
8835
+ * @param {number} count - How many
8836
+ * @param {ArrayLike<number>} x - Positions
8837
+ * @param {ArrayLike<number>} y
8838
+ * @param {ArrayLike<number>} z
8839
+ * @param {ArrayLike<number>} [rx] - Euler angles in radians, all three or none for upright
8840
+ * @param {ArrayLike<number>} [ry]
8841
+ * @param {ArrayLike<number>} [rz]
8842
+ * @param {ArrayLike<number>} [sx] - Scales, all three or none for 1
8843
+ * @param {ArrayLike<number>} [sy]
8844
+ * @param {ArrayLike<number>} [sz] */
8845
+ setTransforms(start: number, count: number, x: ArrayLike<number>, y: ArrayLike<number>, z: ArrayLike<number>, rx?: ArrayLike<number>, ry?: ArrayLike<number>, rz?: ArrayLike<number>, sx?: ArrayLike<number>, sy?: ArrayLike<number>, sz?: ArrayLike<number>): void;
8341
8846
  /** Place an instance, in world space
8342
8847
  * @param {number} i
8343
8848
  * @param {Matrix4} matrix */
@@ -8350,10 +8855,26 @@ declare module "littlejsengine" {
8350
8855
  * @param {number} i
8351
8856
  * @param {Color} color */
8352
8857
  setColorAt(i: number, color: Color): void;
8353
- /** Note that an instance changed, so it uploads before the next draw and the bounds hold it; setMatrixAt and
8354
- * setColorAt call this, and so must an edit made straight to instanceData
8858
+ /** Note that an instance's matrix changed, so it uploads before the next draw and the bounds take it in when
8859
+ * they are read; setTransformAt and setMatrixAt call this, and so must an edit made straight to matrixData
8355
8860
  * @param {number} i */
8356
8861
  markDirty(i: number): void;
8862
+ /** Note that a run of instances' matrices changed, for code that writes matrixData directly, the lowest level
8863
+ * way to move many: they upload before the next draw and the bounds take them in when they are read
8864
+ * @param {number} start - First instance
8865
+ * @param {number} end - One past the last */
8866
+ markDirtyRange(start: number, end: number): void;
8867
+ /** Note that an instance's color changed, so it uploads before the next draw; setColorAt calls this, and so must
8868
+ * an edit made straight to colorData
8869
+ * @param {number} i */
8870
+ markColorDirty(i: number): void;
8871
+ set radius(arg: number);
8872
+ /** Radius of the sphere around the origin that holds every instance set so far, for culling: the farthest
8873
+ * instance, and the mesh's size at the largest scale; it only grows, and takes in the instances set since it
8874
+ * was last read, so with frustum culling off it is never worked out. Set it to fix the sphere, which a big set
8875
+ * that is culled can use to skip that work, and set it to undefined to go back to the bounds
8876
+ * @return {number} */
8877
+ get radius(): number;
8357
8878
  }
8358
8879
  /**
8359
8880
  * Spin a flat outline around the Y axis to make a round shape, like a vase or a wheel
@@ -8499,6 +9020,15 @@ declare module "littlejsengine" {
8499
9020
  * @memberof Render3D
8500
9021
  */
8501
9022
  export function buildSky(topColor?: Color, horizonColor?: Color, bottomColor?: Color, sides?: number, rings?: number): Mesh;
9023
+ /** Make a normal map from a height at each pixel, for bumps and grooves with no image file: the slope at each pixel
9024
+ * from its neighbors' heights, taken around the edges so the map tiles; set it as an object's normalMap
9025
+ * @param {Vector2} size - In pixels
9026
+ * @param {function(number, number): number} heightFunction - The height 0 to 1 at a pixel, x across and y down
9027
+ * @param {number} [strength] - How steep the slopes are: a height change of 1 over one pixel leans the normal
9028
+ * by strength
9029
+ * @return {TextureInfo} - Wraps; headless it has no image
9030
+ * @memberof Render3D */
9031
+ export function normalMapFromHeight(size: Vector2, heightFunction: (arg0: number, arg1: number) => number, strength?: number): TextureInfo;
8502
9032
  /**
8503
9033
  * Turn a sprite into a 3D block model by giving its pixels thickness
8504
9034
  * - A pixel counts as solid when it is more than half opaque
@@ -8607,6 +9137,16 @@ declare module "littlejsengine" {
8607
9137
  * @return {number|undefined}
8608
9138
  * @ignore */
8609
9139
  levelRaycast3D(ray: Ray3D): number | undefined;
9140
+ /** Where a short move goes under the surface, for a particle's move in one frame: the part of the move made
9141
+ * before it, 0 to 1, and the surface normal there; undefined when it stays above, starts under, or is off the map
9142
+ * @param {Vector3} from
9143
+ * @param {Vector3} to
9144
+ * @return {{distance: number, normal: Vector3}|undefined}
9145
+ * @ignore */
9146
+ levelSegment3D(from: Vector3, to: Vector3): {
9147
+ distance: number;
9148
+ normal: Vector3;
9149
+ };
8610
9150
  /** Keep an object above the ground, called by the engine for each object with collideLevel
8611
9151
  * @param {EngineObject3D} o
8612
9152
  * @param {Vector3} oldPos - Where it was before it moved
@@ -8752,6 +9292,16 @@ declare module "littlejsengine" {
8752
9292
  * @return {number|undefined}
8753
9293
  * @ignore */
8754
9294
  levelRaycast3D(ray: Ray3D): number | undefined;
9295
+ /** Where a short move goes into a block, for a particle's move in one frame: the part of the move made before it,
9296
+ * 0 to 1, and the normal of the face it comes in through; undefined when it hits none, or starts inside one
9297
+ * @param {Vector3} from
9298
+ * @param {Vector3} to
9299
+ * @return {{distance: number, normal: Vector3}|undefined}
9300
+ * @ignore */
9301
+ levelSegment3D(from: Vector3, to: Vector3): {
9302
+ distance: number;
9303
+ normal: Vector3;
9304
+ } | undefined;
8755
9305
  /** Draw the chunks, each at its center, with the whole texture so each face shows its own tile
8756
9306
  * @param {boolean} transparent
8757
9307
  * @ignore */
@@ -8760,7 +9310,10 @@ declare module "littlejsengine" {
8760
9310
  /**
8761
9311
  * Light3D - A light that is an EngineObject3D, so it can move, follow a parent or be destroyed like anything else
8762
9312
  * - A point light: it lights what is near it and fades out by its radius, DirectionalLight3D shines from far away
8763
- * - Only the sun, render3D.sunDirection, casts shadows; these light and make highlights without one
9313
+ * - A coneAngle makes it a spotlight: it shines along its own forward, turned by rotation3D or by what it is
9314
+ * attached to, inside the cone, fading over the part of it coneSoftness says
9315
+ * - The sun, render3D.sunDirection, casts the shadows; a spotlight can cast them in its place, see
9316
+ * render3D.shadowLight; the other lights light and make highlights without one
8764
9317
  * - Only the 8 lights nearest the camera are used each frame
8765
9318
  * - radius is where the light fades out, and it fades fast, so a small radius wants a higher intensity
8766
9319
  * - intensity multiplies the color, above 1 for a light brighter than white
@@ -8786,6 +9339,18 @@ declare module "littlejsengine" {
8786
9339
  /** @property {boolean} - Shine from far away, from its position toward the origin, instead of out from its
8787
9340
  * position with a falloff; DirectionalLight3D sets it */
8788
9341
  directional: boolean;
9342
+ /** @property {number} - Makes it a spotlight: the angle in radians from its forward out to the edge of its
9343
+ * cone, so the beam is twice this across; 0 for a light that shines every way */
9344
+ coneAngle: number;
9345
+ /** @property {number} - How much of the cone is its fading edge: 0 a hard edge, .2 by default, the outer
9346
+ * fifth, 1 fading all the way from the middle of the beam */
9347
+ coneSoftness: number;
9348
+ /** @property {number} - Size of a soft hazy glow drawn over the light, like a lamp at night, 0 for none; it
9349
+ * is added onto what is behind it, and what is in front of the light hides it */
9350
+ glow: number;
9351
+ /** @property {number} - How fast the glow fades from its middle: 1 by default, .5 a wide haze, 2 a tight
9352
+ * bright core */
9353
+ glowFalloff: number;
8789
9354
  }
8790
9355
  /**
8791
9356
  * DirectionalLight3D - A Light3D that shines from far away with no falloff, like sunlight
@@ -8881,13 +9446,41 @@ declare module "littlejsengine" {
8881
9446
  /** @property {boolean} - Capture the mouse on a click, so looking needs no button held */
8882
9447
  lockPointer: boolean;
8883
9448
  /** @property {number} - Speed of a jump in world units a frame, 0 for none; Space or gamepad button 0 jumps
8884
- * while it stands on something, a height map or voxel map it collides with, see collideLevel */
9449
+ * while it stands on something, a height map, a voxel map or a solid, see groundObject */
8885
9450
  jumpSpeed: number;
8886
9451
  /** @property {number} - How far above its position the eye is, in its own space, so with a size3D the eye can
8887
9452
  * sit toward the top of the body instead of its middle; keep it under half the body's height, or the eye is
8888
9453
  * outside the body and sees through a ceiling it stands under */
8889
9454
  eyeHeight: number;
8890
9455
  }
9456
+ /**
9457
+ * A particle as a ParticleEmitter3D's callbacks see it: one object the emitter reuses, set from the particle for each
9458
+ * call and written back after it, so copy what you keep
9459
+ * @typedef {Object} Particle3D
9460
+ * @property {ParticleEmitter3D} emitter - The emitter it is in
9461
+ * @property {Vector3} pos - Where it is, change it to move it
9462
+ * @property {Vector3} velocity - How far it moves each frame
9463
+ * @property {number} age - Seconds it has lived
9464
+ * @property {number} lifeTime - Seconds it lives
9465
+ * @property {number} scale - How much the emitter grows its effect, from its scale3D and its parents', as the 2D
9466
+ * particle's scale
9467
+ * @property {boolean} destroyed - Set by destroy
9468
+ * @property {function(): void} destroy - End it this update, the destroy callback gets it
9469
+ * @memberof Render3D
9470
+ */
9471
+ /**
9472
+ * @callback Particle3DCallback - A function a ParticleEmitter3D calls with one of its particles
9473
+ * @param {Particle3D} particle
9474
+ * @memberof Render3D
9475
+ */
9476
+ /**
9477
+ * @callback Particle3DCollideCallback - Decides whether a particle stops where it hits the level, a filter as in 2D
9478
+ * @param {Particle3D} particle
9479
+ * @param {EngineObject3D} level - The HeightMap or VoxelMap it hit
9480
+ * @param {Vector3} pos - Where it hit
9481
+ * @return {boolean|void} - true to stop it there; a callback that returns nothing lets it pass through
9482
+ * @memberof Render3D
9483
+ */
8891
9484
  /**
8892
9485
  * ParticleEmitter3D - Spawns camera facing particles, the 3D twin of ParticleEmitter
8893
9486
  * - Each particle is a flat square facing the camera, with a soft round dot when no tile is given
@@ -8897,9 +9490,14 @@ declare module "littlejsengine" {
8897
9490
  * - emitConeAngle spreads them, PI sprays in every direction
8898
9491
  * - Speeds are per frame and sizes are world units, the same as the 2D emitter
8899
9492
  * - scale3D, its own or a parent's, grows the whole effect: the spawn area, the sizes, the speed and the fall
8900
- * - gravity here is its own number added to velocity y each frame: it is neither the engine's 2D
8901
- * gravity nor render3D.gravity, so an effect keeps its own fall wherever it is used
9493
+ * - gravity here is its own number added to velocity y each frame, so an effect keeps its own fall wherever it is
9494
+ * used, the same as the 2D emitter's gravity; gravityScale adds a share of render3D.gravity on top, as the 2D
9495
+ * emitter's gravityScale adds the engine's gravity
8902
9496
  * - An emitter with an emitTime destroys itself once its last particle is gone, like the 2D emitter
9497
+ * - Callbacks as the 2D emitter's: particleCreateCallback, particleUpdateCallback, particleCollideCallback and
9498
+ * particleDestroyCallback, each given a Particle3D, one object the emitter reuses for every particle and call
9499
+ * - collideLevel, off by default, has particles hit the height maps and voxel maps, bouncing by restitution and
9500
+ * sliding by friction
8903
9501
  * @extends EngineObject3D
8904
9502
  * @memberof Render3D
8905
9503
  * @example
@@ -8923,14 +9521,17 @@ declare module "littlejsengine" {
8923
9521
  * @param {number} [sizeEnd] - Particle size at end of life
8924
9522
  * @param {number} [speed] - Spawn speed in world units per frame
8925
9523
  * @param {number} [damping] - Per frame velocity multiplier, 1 is none
8926
- * @param {number} [gravity] - Per frame change to velocity y, negative pulls down; its own number,
8927
- * not render3D.gravity, so the 2D emitter's gravityScale has no equivalent here
9524
+ * @param {number} [gravity] - Per frame change to velocity y, negative pulls down; its own number, and
9525
+ * gravityScale adds a share of render3D.gravity on top
8928
9526
  * @param {number} [fadeRate] - Fraction of life spent fading, half in and half out
8929
9527
  * @param {number} [randomness] - Extra randomness applied to speed, size and life
8930
9528
  * @param {boolean} [additive] - Additive blending */
8931
9529
  constructor(pos3D?: Vector3, emitSize?: number | Vector3, emitTime?: number, emitRate?: number, emitConeAngle?: number, tileInfo?: TileInfo | TextureInfo, colorStartA?: Color, colorStartB?: Color, colorEndA?: Color, colorEndB?: Color, particleTime?: number, sizeStart?: number, sizeEnd?: number, speed?: number, damping?: number, gravity?: number, fadeRate?: number, randomness?: number, additive?: boolean);
8932
9530
  /** @property {number|Vector3} - Spawn area, a number for a sphere diameter or a vec3 for a box */
8933
9531
  emitSize: number | Vector3;
9532
+ /** @property {boolean} - Flatten the spawn area across the way it emits, its own up: a sphere becomes a disc
9533
+ * and a box a flat rectangle, for rain from a sheet of sky or flames from a patch of ground */
9534
+ emitFlat: boolean;
8934
9535
  /** @property {number} - How long to keep emitting, 0 is forever */
8935
9536
  emitTime: number;
8936
9537
  /** @property {number} - Particles per second, 0 does not emit */
@@ -8959,7 +9560,8 @@ declare module "littlejsengine" {
8959
9560
  fadeRate: number;
8960
9561
  /** @property {number} - Extra randomness applied to speed, size and life */
8961
9562
  randomness: number;
8962
- /** @property {number} - Seconds of each particle's path to draw as a ribbon behind it, 0 draws billboards */
9563
+ /** @property {number} - Seconds of each particle's path to draw as a ribbon behind it, 0 draws billboards;
9564
+ * with engineVariableStep it keeps trailTime * frameRate updates of path */
8963
9565
  trailTime: number;
8964
9566
  /** @property {number} - Radians per frame each particle turns in the camera plane, either way; 0 is no spin */
8965
9567
  angleSpeed: number;
@@ -8973,12 +9575,30 @@ declare module "littlejsengine" {
8973
9575
  trailData: Float32Array | undefined;
8974
9576
  /** @property {number} - Trail points kept per particle, from trailTime */
8975
9577
  trailMax: number;
9578
+ /** @property {Particle3DCallback|undefined} - Called with each particle as it is made
9579
+ * @type {Particle3DCallback|undefined} */
9580
+ particleCreateCallback: Particle3DCallback | undefined;
9581
+ /** @property {Particle3DCallback|undefined} - Called with each particle each update, after it moves
9582
+ * @type {Particle3DCallback|undefined} */
9583
+ particleUpdateCallback: Particle3DCallback | undefined;
9584
+ /** @property {Particle3DCollideCallback|undefined} - Decides if a particle stops where it hits the level,
9585
+ * with collideLevel on; a callback that returns nothing lets it through
9586
+ * @type {Particle3DCollideCallback|undefined} */
9587
+ particleCollideCallback: Particle3DCollideCallback | undefined;
9588
+ /** @property {Particle3DCallback|undefined} - Called with each particle as it goes, its life over or destroyed
9589
+ * @type {Particle3DCallback|undefined} */
9590
+ particleDestroyCallback: Particle3DCallback | undefined;
9591
+ /** @property {Particle3D} - The particle the callbacks get, one object for every particle and call
9592
+ * @type {Particle3D} */
9593
+ particleView: Particle3D;
8976
9594
  /** @property {Vector3|undefined} - Where the emitter was at its last update, for when its parent is destroyed
8977
9595
  * @type {Vector3|undefined} */
8978
9596
  worldPos3D: Vector3 | undefined;
8979
9597
  emitTimeBuffer: number;
8980
9598
  /** Spawn one particle now */
8981
9599
  emitParticle(): void;
9600
+ particleCall(callback: any, k: any, level: any, pos: any): any;
9601
+ particleCollide(k: any, x: any, y: any, z: any): void;
8982
9602
  }
8983
9603
  /**
8984
9604
  * Trail3D - A ribbon through where the object has been, thinning and fading with age
@@ -9023,10 +9643,95 @@ declare module "littlejsengine" {
9023
9643
  clear(): void;
9024
9644
  worldPos3D: Vector3;
9025
9645
  }
9646
+ /**
9647
+ * LensFlare3D - The sun's lens flare, the old kind: a glow at the sun and a row of discs and rings of different
9648
+ * sizes along the line from the sun through the middle of the screen
9649
+ * - Make one and it shows, over the 3D scene and under what the game draws after, a HUD; destroy it to take it away
9650
+ * - It follows render3D.sunDirection, and fades out as the sun leaves the screen or goes behind something
9651
+ * - flareSize, count, intensity and saturation set its look, seed picks another arrangement, and its color tints it,
9652
+ * with the sun's own color; or give it elements of your own
9653
+ * - visible is how much of the sun shows, 0 to 1, eased over fadeTime, there for a game to read
9654
+ * - What hides the sun is found with a ray from the camera, against the level and every object that is not see
9655
+ * through, each as the box around its mesh, see render3D.pick; turn it off with occlusion
9656
+ * - It needs WebGL, and it draws nothing in the shadow of renderAfter2D
9657
+ * @extends EngineObject3D
9658
+ * @memberof Render3D
9659
+ * @example
9660
+ * new LensFlare3D; // the sun flares
9661
+ * new LensFlare3D(1.5, 10, .7, 0); // bigger, 10 ghosts, dimmer, all one color
9662
+ */
9663
+ export class LensFlare3D extends EngineObject3D {
9664
+ /** Create the sun's lens flare
9665
+ * @param {number} [size] - Scales every part of it, 1 by default
9666
+ * @param {number} [count] - How many ghosts there are along the line, besides the glow at the sun
9667
+ * @param {number} [intensity] - How bright it is
9668
+ * @param {number} [saturation] - How colorful the ghosts are, 0 for all the flare's own color, 1 a rainbow
9669
+ * @param {Color} [color] - Tints the whole flare, with the sun's color */
9670
+ constructor(size?: number, count?: number, intensity?: number, saturation?: number, color?: Color);
9671
+ /** @property {number} - Scales every part of the flare */
9672
+ flareSize: number;
9673
+ /** @property {number} - How many ghosts there are along the line, besides the glow at the sun */
9674
+ count: number;
9675
+ /** @property {number} - How bright it is */
9676
+ intensity: number;
9677
+ /** @property {number} - How colorful the ghosts are, 0 for all the flare's own color, 1 a rainbow */
9678
+ saturation: number;
9679
+ /** @property {number} - Picks the arrangement of the ghosts, another seed is another flare */
9680
+ seed: number;
9681
+ /** @property {Array<{at: number, size: number, color: Color, shape: string}>|undefined} - The parts of the
9682
+ * flare, to set your own in place of the ones made from count, seed and saturation: at is where along the
9683
+ * line, 0 the sun, 1 the middle of the screen, 2 as far past it; size is across, as a part of the screen's
9684
+ * height; shape is glow, disc or ring
9685
+ * @type {Array<{at: number, size: number, color: Color, shape: string}>|undefined} */
9686
+ elements: {
9687
+ at: number;
9688
+ size: number;
9689
+ color: Color;
9690
+ shape: string;
9691
+ }[];
9692
+ /** @property {boolean} - Fade out when something is between the camera and the sun */
9693
+ occlusion: boolean;
9694
+ /** @property {number} - Seconds the flare takes to fade out or in when the sun is hidden or shows again */
9695
+ fadeTime: number;
9696
+ /** @property {number} - How much of the sun shows, 0 hidden or behind the camera to 1 in plain view, eased */
9697
+ visible: number;
9698
+ madeKey: string;
9699
+ /** @type {Array<{at: number, size: number, color: Color, shape: string}>} */
9700
+ made: {
9701
+ at: number;
9702
+ size: number;
9703
+ color: Color;
9704
+ shape: string;
9705
+ }[];
9706
+ /** The parts of the flare: the elements set by hand, or the ones made from count, seed and saturation, a glow
9707
+ * and a core at the sun and the ghosts, made again when one of those changes
9708
+ * @return {Array<{at: number, size: number, color: Color, shape: string}>} */
9709
+ getElements(): Array<{
9710
+ at: number;
9711
+ size: number;
9712
+ color: Color;
9713
+ shape: string;
9714
+ }>;
9715
+ /** Where the sun is on the screen, in pixels like mousePosScreen, undefined when it is behind the camera
9716
+ * @return {Vector2|undefined} */
9717
+ getSunScreenPos(): Vector2 | undefined;
9718
+ /** The parts of the flare as they are drawn now: each one's place on the screen, its size in pixels and its
9719
+ * color, dimmed by how much of the sun shows; empty when there is nothing to draw
9720
+ * @return {Array<{pos: Vector2, size: number, color: Color, shape: string}>} */
9721
+ getScreenElements(): Array<{
9722
+ pos: Vector2;
9723
+ size: number;
9724
+ color: Color;
9725
+ shape: string;
9726
+ }>;
9727
+ /** Is something between the camera and the sun: the level, or an object that is not see through
9728
+ * @return {boolean} */
9729
+ isSunHidden(): boolean;
9730
+ }
9026
9731
  /**
9027
9732
  * Collect the EngineObject3D objects whose boxes overlap a sphere or a box, the 3D twin of engineObjectsCollect
9028
- * - Boxes are axis aligned around the world position, rotation3D is ignored; lights, emitters and trails have no size
9029
- * and are never collected
9733
+ * - Each object is its size3D box at its world position, turned as it is turned; lights, emitters and trails have no
9734
+ * size and are never collected
9030
9735
  * @param {Vector3} pos - Center of the area
9031
9736
  * @param {Vector3|number} size - Diameter of a sphere if a number, 0 for a point, full size of a box if a Vector3
9032
9737
  * @param {Array<EngineObject>} [objects] - Defaults to every object
@@ -9154,6 +9859,8 @@ declare module "littlejsengine" {
9154
9859
  * GLTFObject that createObject makes; a skinned character's walk is not read
9155
9860
  * - Materials give a base color and texture and whether they blend; glass made with KHR_materials_transmission blends too,
9156
9861
  * and a KHR_materials_unlit material comes in emissive, its own color with no shading
9862
+ * - A material's normal map and emissive map load too, with its normal scale and emissive factor, read at the base
9863
+ * color texture's uvs; roughness, metalness and occlusion maps are not loaded
9157
9864
  * - The base color texture reads the uv set its texCoord names, moved by KHR_texture_transform as gltfpack and
9158
9865
  * Blender write it
9159
9866
  * - An OPAQUE material, the default, ignores its texture's alpha as the format says: a texture only such materials
@@ -9196,6 +9903,17 @@ declare module "littlejsengine" {
9196
9903
  /** @property {boolean} - The material is unlit (KHR_materials_unlit), its own color with no shading; the object
9197
9904
  * createObject makes draws it with emissive 1 */
9198
9905
  unlit: boolean;
9906
+ /** @property {TextureInfo|undefined} - The material's normal map, drawn with the base color texture's uvs
9907
+ * @type {TextureInfo|undefined} */
9908
+ normalMap: TextureInfo | undefined;
9909
+ /** @property {number} - The normal map's strength, its scale in the file */
9910
+ normalScale: number;
9911
+ /** @property {TextureInfo|undefined} - The material's emissive map, or a white texture when it has an
9912
+ * emissiveFactor and no texture, so it glows all over
9913
+ * @type {TextureInfo|undefined} */
9914
+ emissiveMap: TextureInfo | undefined;
9915
+ /** @property {Color} - The emissiveFactor, which multiplies the emissive map */
9916
+ emissiveMapColor: Color;
9199
9917
  }
9200
9918
  /**
9201
9919
  * GLTFObject - A model as an object with a child per part, which plays the model's animations
@@ -9301,6 +10019,69 @@ declare module "littlejsengine" {
9301
10019
  * @param {number} [size] - Length of the cross
9302
10020
  * @memberof Render3D */
9303
10021
  export function debugPoint3D(pos: Vector3, color?: Color, time?: number, size?: number): void;
10022
+ /** Add a type of object, so level3DLoad makes one wherever a level has an object of that type
10023
+ * - The name is a string because minified builds rename classes
10024
+ * - A class, or any function with a prototype, is made with new make(pos3D, properties); an arrow function is
10025
+ * called as make(pos3D, properties), for what is not an object, like a player start
10026
+ * - properties is the defaults with the object's own values over them, and each of the type's own is also set on
10027
+ * what was made; a property the type has no default for is in properties and is not set
10028
+ * - Give a class a constructor of its own that takes the position: one that hands every argument on to
10029
+ * EngineObject3D would hand it the properties as its mesh
10030
+ * - An EngineObject3D then gets the object's rotation, and its scale times the scale it was made with
10031
+ * - Adding a name again replaces it, Box, Sphere, Cylinder and Light too
10032
+ * @param {string} name - The type the objects have in the level
10033
+ * @param {Function} make - A class made at each object's position, or a function called with it
10034
+ * @param {Object} [defaults] - Properties of each one made, the level editor shows inputs for them
10035
+ * @param {TileInfo} [tileInfo] - An icon for the level editor
10036
+ * @memberof Level3D
10037
+ * @example
10038
+ * level3DAddType('Crate', Crate, {health: 3});
10039
+ * level3DAddType('PlayerStart', (pos)=> playerStart = pos); */
10040
+ export function level3DAddType(name: string, make: Function, defaults?: any, tileInfo?: TileInfo): void;
10041
+ /** Add a type that is a mesh and nothing more, a static prop with no class to write, for a built mesh or a model
10042
+ * - Each object has a color and a solid property, solid collides as the box around the mesh
10043
+ * @param {string} name - The type the objects have in the level
10044
+ * @param {Mesh} mesh - Shared by every object of the type
10045
+ * @param {TileInfo} [tileInfo] - Its texture
10046
+ * @param {Color} [color] - Its color, an object's own color property goes over it
10047
+ * @memberof Level3D
10048
+ * @example
10049
+ * level3DAddMesh('Tree', treeMesh, tile(4)); */
10050
+ export function level3DAddMesh(name: string, mesh: Mesh, tileInfo?: TileInfo, color?: Color): void;
10051
+ /** Make the objects of a level, each from the type added for its name
10052
+ * - The level is an object: {littlejs3D: 1, objects: [{id, type, pos: [x, y, z]}, ...]}, and {} is a new one
10053
+ * - rotation is pitch, yaw and roll in degrees, scale is a number for each axis, both left out when they are
10054
+ * the default, and properties holds what differs from the type's defaults
10055
+ * - A Color property is a #rrggbb or #rrggbbaa string, a Vector2 or Vector3 an array, as the default says
10056
+ * - An object whose type was not added is skipped, with a warning in debug builds
10057
+ * - What a file written by hand gets wrong uses the default: a value that is not of its default's type
10058
+ * - An object its type can not make is skipped with an error in debug builds, where asserts throw, and the rest
10059
+ * of the level is made
10060
+ * - A level may hold a map of blocks, in a voxels block: pos, its corner, size, its cells along x, y and z, and
10061
+ * blocks, runs of a count and a type along x, then y, then z; it is made a VoxelMap, the first of what is
10062
+ * returned, see level3DVoxelSetup for its sheet
10063
+ * - A level may hold a terrain, in a terrain block: pos, its center, size, its size in the world along x and z,
10064
+ * height, how tall a full height is, color, and heights, rows of 0 to 1 from -z to +z, each from -x to +x; it
10065
+ * is made a HeightMap, returned with what else was made
10066
+ * - A level may set the scene too, in a scene block beside its objects: sky, three colors for straight up, the
10067
+ * horizon and straight down, ambient, how much of them lights the scene, .5 when not given, sunDirection and
10068
+ * sunColor, fog, its start and end, fogColor, the horizon color when not given, and shadows; what the block
10069
+ * leaves out stays as the game set it, and a level with no block changes nothing
10070
+ * @param {Object} level - The level, the level editor edits this same object
10071
+ * @return {Array<any>} - What each object's type made, a function that made nothing is left out
10072
+ * @memberof Level3D */
10073
+ export function level3DLoad(level: any): Array<any>;
10074
+ /** How a level's block map is made: the sheet its blocks show tiles of, and a function to set it up
10075
+ * - A level's voxels block makes a VoxelMap when the level loads, with texture 0 and the default tile size unless
10076
+ * a sheet is given here; a block's type shows that tile of the sheet on every face
10077
+ * - setup is called with each map a level makes, to give block types their own faces or make them see-through
10078
+ * - Call it before level3DLoad; with no arguments the defaults are back
10079
+ * @param {TileInfo} [tileInfo] - The sheet's first tile, as for a VoxelMap
10080
+ * @param {function(VoxelMap): void} [setup]
10081
+ * @example
10082
+ * level3DVoxelSetup(tile(0, 16, 1), (map)=> map.setBlockType(1, {top: 0, side: 1, bottom: 2})); // grass
10083
+ * @memberof Level3D */
10084
+ export function level3DVoxelSetup(tileInfo?: TileInfo, setup?: (arg0: VoxelMap) => void): void;
9304
10085
  /**
9305
10086
  * LittleJS Three.js Plugin
9306
10087
  * - Renders a three.js scene on a canvas behind the LittleJS canvases
@@ -9501,6 +10282,177 @@ declare module "littlejsengine" {
9501
10282
  * }
9502
10283
  * @memberof TextureSheets */
9503
10284
  export function spritesReady(): Promise<any>;
10285
+ /**
10286
+ * LittleJS Particle Effects Plugin
10287
+ * - Ready made particle effects in one line, particleEffect('fire', pos), and particleEffect3D for 3D
10288
+ * - Every built-in effect is tuned around a one unit emitter; options.scale grows it to fit, options.hue and
10289
+ * options.saturation recolor it
10290
+ * - Effects are plain data, {name, settings, behaviors}, the format the particle designer saves: load a library the
10291
+ * designer saved with particleEffectsLoad and play its effects by name
10292
+ * - The built-in effects draw with a sheet of shapes the plugin draws itself, so they need no image
10293
+ * @namespace ParticleEffects
10294
+ */
10295
+ /** The groups the settings are in, in order
10296
+ * @type {Array<string>}
10297
+ * @memberof ParticleEffects */
10298
+ export const particleEffectGroups: Array<string>;
10299
+ /** Every setting an effect has: its name, kind (number, checkbox, color or shape), default, the range the designer's
10300
+ * slider covers (min, max, step), the hard limits a typed value is clamped to, and whether it is set after the
10301
+ * emitter is made rather than passed to its constructor (extra)
10302
+ * @type {Array<{group:string, name:string, kind:string, value:any, min:number, max:number, step:number,
10303
+ * description:string, hardMin:number, hardMax:number, extra:boolean}>}
10304
+ * @memberof ParticleEffects */
10305
+ export const particleEffectSettings: Array<{
10306
+ group: string;
10307
+ name: string;
10308
+ kind: string;
10309
+ value: any;
10310
+ min: number;
10311
+ max: number;
10312
+ step: number;
10313
+ description: string;
10314
+ hardMin: number;
10315
+ hardMax: number;
10316
+ extra: boolean;
10317
+ }>;
10318
+ /** The behaviors an effect can use, each a push applied to every particle every update, with a 2D and a 3D version
10319
+ * @type {Array<{name:string, update:(Function|undefined), update3D:(Function|undefined), min:number, max:number,
10320
+ * value:number, description:string}>}
10321
+ * @memberof ParticleEffects */
10322
+ export const particleEffectBehaviors: Array<{
10323
+ name: string;
10324
+ update: (Function | undefined);
10325
+ update3D: (Function | undefined);
10326
+ min: number;
10327
+ max: number;
10328
+ value: number;
10329
+ description: string;
10330
+ }>;
10331
+ /** Names of the shapes the plugin draws, for an effect's shape setting
10332
+ * @type {Array<string>}
10333
+ * @memberof ParticleEffects */
10334
+ export const particleEffectShapes: Array<string>;
10335
+ /** Any input into a whole effect: missing fields take their defaults, bad ones are dropped or clamped
10336
+ * @param {Object} [raw] - {name, settings, behaviors}, from a library file, the designer or code
10337
+ * @return {{name:string, settings:Object, behaviors:Array<{name:string, strength:number}>}}
10338
+ * @memberof ParticleEffects */
10339
+ export function particleEffectSanitize(raw?: any): {
10340
+ name: string;
10341
+ settings: any;
10342
+ behaviors: {
10343
+ name: string;
10344
+ strength: number;
10345
+ }[];
10346
+ };
10347
+ /** A copy of an effect with its four colors turned around the color wheel and their saturation scaled; lightness and
10348
+ * alpha stay, and grey and white have no hue to turn
10349
+ * @param {Object} effect
10350
+ * @param {number} [hue] - How far around the wheel, 1 is all the way
10351
+ * @param {number} [saturation] - Multiplies the saturation, 0 is grey, clamped to 1
10352
+ * @return {Object}
10353
+ * @memberof ParticleEffects */
10354
+ export function particleEffectRecolor(effect: any, hue?: number, saturation?: number): any;
10355
+ /** Add effects to play by name, sanitized; one with the name of an effect already there replaces it
10356
+ * @param {Array<Object>|Object} effects
10357
+ * @memberof ParticleEffects */
10358
+ export function particleEffectsAdd(effects: Array<any> | any): void;
10359
+ /** The effect with a name, any case, undefined if there is none
10360
+ * @param {string} name
10361
+ * @return {Object|undefined}
10362
+ * @memberof ParticleEffects */
10363
+ export function particleEffectsGet(name: string): any | undefined;
10364
+ /** A library file, or one effect, into sanitized effects; throws on bad input
10365
+ * @param {string} text
10366
+ * @return {Array<Object>}
10367
+ * @memberof ParticleEffects */
10368
+ export function particleEffectsParse(text: string): Array<any>;
10369
+ /** The text of a library file with these effects, what particleEffectsLoad and the designer read
10370
+ * @param {Array<Object>} effects
10371
+ * @return {string}
10372
+ * @memberof ParticleEffects */
10373
+ export function particleEffectsText(effects: Array<any>): string;
10374
+ /** Load a library file the particle designer saved and add its effects
10375
+ * @param {string} url
10376
+ * @return {Promise<Array<Object>>} - The effects it had
10377
+ * @memberof ParticleEffects */
10378
+ export function particleEffectsLoad(url: string): Promise<Array<any>>;
10379
+ /** The tile of a built-in shape, on a sheet the plugin draws once; undefined headless, without a canvas or without
10380
+ * WebGL, where an effect draws untextured squares
10381
+ * @param {string} name - One of particleEffectShapes
10382
+ * @return {TileInfo|undefined}
10383
+ * @memberof ParticleEffects */
10384
+ export function particleEffectShapeTile(name: string): TileInfo | undefined;
10385
+ /** Play an effect: a 2D emitter set to it, placed, scaled and recolored
10386
+ * - A continuous effect (fire, a torch) goes until destroyed or given an emitTime, a one-shot ends itself
10387
+ * - Any setting in the options replaces the effect's own for this play: {emitTime: .5} for a burst of a continuous
10388
+ * effect, {emitTime: 0, emitRate: 30} to keep a one-shot going, or speed, particleTime and the rest
10389
+ * - Attach it to an object with addChild to follow it
10390
+ * @param {string|Object} nameOrEffect - A built-in or added effect's name, or an effect
10391
+ * @param {Vector2} [pos]
10392
+ * @param {Object} [options]
10393
+ * @param {number} [options.scale] - Grows the whole effect, the built-ins fit a one unit object at 1
10394
+ * @param {number} [options.hue] - Turns its colors around the color wheel, 1 is all the way
10395
+ * @param {number} [options.saturation] - Multiplies its saturation, 0 is grey
10396
+ * @param {number} [options.angle] - Direction, 0 is up; the effect's own angle when not given
10397
+ * @param {TileInfo|TextureInfo} [options.tileInfo] - The game's own art to draw with in place of the effect's shape,
10398
+ * tinted by its colors; a whole texture draws as one tile
10399
+ * @param {*} [options.settings] - Any effect setting by its name, emitTime, emitRate, speed and the rest, replacing
10400
+ * the effect's own for this play
10401
+ * @return {ParticleEmitter|undefined} - undefined when there is no such effect
10402
+ * @memberof ParticleEffects */
10403
+ export function particleEffect(nameOrEffect: string | any, pos?: Vector2, options?: {
10404
+ scale?: number;
10405
+ hue?: number;
10406
+ saturation?: number;
10407
+ angle?: number;
10408
+ tileInfo?: TileInfo | TextureInfo;
10409
+ settings?: any;
10410
+ }): ParticleEmitter | undefined;
10411
+ /** Play an effect in 3D: a ParticleEmitter3D set to it, placed, scaled and recolored
10412
+ * - The same effect data as particleEffect, so the look carries across: a circle spawn area becomes a sphere and a
10413
+ * rectangle a box as deep as it is wide, both flat across the way it emits with options.flatten, a disc or a
10414
+ * sheet; a trail becomes a streak of the same length, and the settings the 3D emitter lacks (particleConeAngle,
10415
+ * randomColorLinear, velocityInheritance, localSpace) are left out; the stick behavior becomes the friction a
10416
+ * particle lands with
10417
+ * @param {string|Object} nameOrEffect - A built-in or added effect's name, or an effect
10418
+ * @param {Vector3} [pos3D]
10419
+ * @param {Object} [options] - scale, hue, saturation, angle, tileInfo and any setting as particleEffect; angle turns it
10420
+ * about z, so 0 is up; flatten makes the spawn area flat across the way it emits
10421
+ * @return {ParticleEmitter3D|undefined} - undefined when there is no such effect
10422
+ * @memberof ParticleEffects */
10423
+ export function particleEffect3D(nameOrEffect: string | any, pos3D?: Vector3, options?: any): ParticleEmitter3D | undefined;
10424
+ /** The names of the built-in effects, in the order a gallery shows them
10425
+ * @type {Array<string>}
10426
+ * @memberof ParticleEffects */
10427
+ export const particleEffectsBuiltIn: Array<string>;
10428
+ /** Set a 2D emitter to an effect, live, so a running one keeps its particles
10429
+ * @param {ParticleEmitter} emitter
10430
+ * @param {Object} effect
10431
+ * @memberof ParticleEffects */
10432
+ export function particleEffectApply(emitter: ParticleEmitter, effect: any): void;
10433
+ /** Set a 3D emitter to an effect, live, so a running one keeps its particles; its place, scale and flatten stay
10434
+ * @param {ParticleEmitter3D} emitter
10435
+ * @param {Object} effect
10436
+ * @memberof ParticleEffects */
10437
+ export function particleEffectApply3D(emitter: ParticleEmitter3D, effect: any): void;
10438
+ /** An effect with a 2D emitter's settings, to save, build again, or build in 3D with particleEffect3D; its tile is
10439
+ * left out, since a hand made emitter's tile is its own texture and not one an effect can name, and so is its
10440
+ * scale, which an effect does not keep: pass it again with options.scale
10441
+ * @param {ParticleEmitter} emitter
10442
+ * @param {string} [name]
10443
+ * @return {Object}
10444
+ * @memberof ParticleEffects */
10445
+ export function particleEffectFromEmitter(emitter: ParticleEmitter, name?: string): any;
10446
+ /** Add a behavior effects can use by name, or replace one
10447
+ * @param {string} name
10448
+ * @param {function(Particle, number): void} update - Pushes a 2D particle, given the strength
10449
+ * @param {function(Particle3D, number): void} [update3D] - The same for a 3D particle, none leaves 3D alone
10450
+ * @param {number} [min] - Strength range the designer offers
10451
+ * @param {number} [max]
10452
+ * @param {number} [value] - Strength when first added
10453
+ * @param {string} [description]
10454
+ * @memberof ParticleEffects */
10455
+ export function particleEffectsAddBehavior(name: string, update: (arg0: Particle, arg1: number) => void, update3D?: (arg0: Particle3D, arg1: number) => void, min?: number, max?: number, value?: number, description?: string): void;
9504
10456
  /**
9505
10457
  * LittleJS Level Editor
9506
10458
  * - Paint the game's tile layers while it is paused, then keep playing with the changes
@@ -9548,6 +10500,14 @@ declare module "littlejsengine" {
9548
10500
  * section has Play from mouse, which starts play there, Escape at the mouse and Play at the view center
9549
10501
  * @type {EditorPlayFromCallback|undefined} */
9550
10502
  onPlayFrom: EditorPlayFromCallback | undefined;
10503
+ /** @property {Array<number>|undefined} - The tiles the palette shows, in its order, for a sheet that also holds
10504
+ * sprites and art that are not level tiles; undefined shows every tile of the sheet
10505
+ * @type {Array<number>|undefined} */
10506
+ paletteTiles: Array<number> | undefined;
10507
+ /** @property {boolean|undefined} - Which level editor opens: true the 3D one, false the 2D one, undefined the
10508
+ * 3D one when a level was loaded with level3DLoad and there is a Render3DPlugin
10509
+ * @type {boolean|undefined} */
10510
+ use3D: boolean | undefined;
9551
10511
  /** True while the editor is open, the game is paused under it
9552
10512
  * @return {boolean} */
9553
10513
  get isOpen(): boolean;