littlejsengine 1.21.0 → 1.23.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.
package/src/engineDraw.js CHANGED
@@ -259,8 +259,9 @@ class TextureInfo
259
259
  * @param {boolean} [useWebGL] - Should use WebGL if available?
260
260
  * @param {boolean|Array<number>} [wrap] - Should the texture wrap (REPEAT) or clamp (CLAMP_TO_EDGE)? Or the WebGL
261
261
  * modes across and down, like [gl.CLAMP_TO_EDGE, gl.MIRRORED_REPEAT], as a glTF sampler gives them
262
+ * @param {boolean} [pixelated] - Hard edged or smooth for this texture alone, undefined follows tilesPixelated
262
263
  */
263
- constructor(image, useWebGL=true, wrap=false)
264
+ constructor(image, useWebGL=true, wrap=false, pixelated)
264
265
  {
265
266
  /** @property {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas|ImageBitmap} - image source */
266
267
  this.image = image;
@@ -275,6 +276,10 @@ class TextureInfo
275
276
  * across and down
276
277
  * @type {boolean|Array<number>} */
277
278
  this.wrap = wrap;
279
+ /** @property {boolean|undefined} - Hard edged or smooth for this texture alone, a soft glow in a pixel art
280
+ * game or pixel art in a smooth one; undefined follows tilesPixelated
281
+ * @type {boolean|undefined} */
282
+ this.pixelated = pixelated;
278
283
  useWebGL && this.createWebGLTexture();
279
284
  }
280
285
 
@@ -305,6 +310,17 @@ class TextureInfo
305
310
  this.wrap = wrap;
306
311
  glSetTextureWrap(this.glTexture, wrap);
307
312
  }
313
+
314
+ /** Make this texture hard edged or smooth on its own, whatever tilesPixelated says for the rest; it is made again
315
+ * with the new filtering
316
+ * @param {boolean} [pixelated] - undefined follows tilesPixelated again */
317
+ setPixelated(pixelated)
318
+ {
319
+ this.pixelated = pixelated;
320
+ if (!this.glTexture) return;
321
+ this.destroyWebGLTexture();
322
+ this.createWebGLTexture();
323
+ }
308
324
  }
309
325
 
310
326
  ///////////////////////////////////////////////////////////////////////////////
@@ -480,17 +496,29 @@ class SpriteAnimator
480
496
  * @return {SpriteAnimation} */
481
497
  get clip() { return this.clips[this.name]; }
482
498
 
499
+ /** The clip showing now, once a clip that has ended has called its onEnd: the callback may switch clips, and a
500
+ * read gives the clip it switched to, not the one that ended
501
+ * @return {SpriteAnimation}
502
+ * @ignore */
503
+ get settledClip()
504
+ {
505
+ // each clip's own isDone calls its onEnd once; a few switches in a row at most
506
+ for (let i = 4, clip; i-- && clip !== this.clip;)
507
+ (clip = this.clip).isDone;
508
+ return this.clip;
509
+ }
510
+
483
511
  /** The tile of the frame showing now
484
512
  * @return {TileInfo} */
485
- get tileInfo() { return this.clip.tileInfo; }
513
+ get tileInfo() { return this.settledClip.tileInfo; }
486
514
 
487
515
  /** The frame of the clip showing now
488
516
  * @return {number} */
489
- get frame() { return this.clip.frame; }
517
+ get frame() { return this.settledClip.frame; }
490
518
 
491
519
  /** True once the clip showing now is a play that has ended
492
520
  * @return {boolean} */
493
- get isDone() { return this.clip.isDone; }
521
+ get isDone() { return this.settledClip.isDone; }
494
522
  }
495
523
 
496
524
  ///////////////////////////////////////////////////////////////////////////////
@@ -1848,6 +1876,33 @@ class ImageFont
1848
1876
  }
1849
1877
  }
1850
1878
 
1879
+ // how strong a light's glow is at a distance from its middle, 0 there to 1 at the edge: a bell, full in the middle
1880
+ // and nothing at the edge, fading faster the higher the falloff
1881
+ function engineGlowAlpha(r, falloff)
1882
+ {
1883
+ const k = 3.5 * falloff, edge = Math.exp(-k);
1884
+ return (Math.exp(-k * r * r) - edge) / (1 - edge);
1885
+ }
1886
+
1887
+ // the soft round glow of the 2D and 3D lights, one texture for each falloff, rounded to a tenth so a changing falloff
1888
+ // makes only a few, each made once from a canvas; undefined headless or without a canvas
1889
+ const engineGlowTextures = new Map;
1890
+ function engineGlowTexture(falloff=1)
1891
+ {
1892
+ ASSERT(isNumber(falloff) && falloff > 0, 'glowFalloff must be a number above 0');
1893
+ const key = max(round(falloff * 10), 1) / 10;
1894
+ let texture = engineGlowTextures.get(key);
1895
+ if (texture || !glContext || typeof OffscreenCanvas == 'undefined') return texture;
1896
+ const size = 64, context = createCanvasContext(size), steps = 16;
1897
+ const gradient = context.createRadialGradient(size / 2, size / 2, 0, size / 2, size / 2, size / 2);
1898
+ for (let i = 0; i <= steps; ++i)
1899
+ gradient.addColorStop(i / steps, 'rgba(255,255,255,' + engineGlowAlpha(i / steps, key).toFixed(4) + ')');
1900
+ context.fillStyle = gradient;
1901
+ context.fillRect(0, 0, size, size);
1902
+ engineGlowTextures.set(key, texture = new TextureInfo(context.canvas, true, false, false));
1903
+ return texture;
1904
+ }
1905
+
1851
1906
  // load engine font, called automatically on startup
1852
1907
  async function imageFontInit()
1853
1908
  {