littlejsengine 1.17.10 → 1.17.11

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.
@@ -1390,7 +1390,9 @@ declare module "littlejsengine" {
1390
1390
  * @memberof Math */
1391
1391
  export function isNumber(n: any): boolean;
1392
1392
  /**
1393
- * Check if object is a valid string or can be converted to one
1393
+ * Check if object can be converted to a string (has a toString method)
1394
+ * - Returns true for strings, numbers, and most objects
1395
+ * - Returns false for null and undefined
1394
1396
  * @param {any} s
1395
1397
  * @return {boolean}
1396
1398
  * @memberof Math */
@@ -1405,7 +1407,7 @@ declare module "littlejsengine" {
1405
1407
  * @type {Color}
1406
1408
  * @memberof Math */
1407
1409
  export const WHITE: Color;
1408
- /** Color - Clear White #757474ff with 0 alpha
1410
+ /** Color - Clear White #ffffff00 with 0 alpha
1409
1411
  * @type {Color}
1410
1412
  * @memberof Math */
1411
1413
  export const CLEAR_WHITE: Color;
@@ -1413,7 +1415,7 @@ declare module "littlejsengine" {
1413
1415
  * @type {Color}
1414
1416
  * @memberof Math */
1415
1417
  export const BLACK: Color;
1416
- /** Color - Clear Black #000000 with 0 alpha
1418
+ /** Color - Clear Black #00000000 with 0 alpha
1417
1419
  * @type {Color}
1418
1420
  * @memberof Math */
1419
1421
  export const CLEAR_BLACK: Color;
@@ -2235,8 +2237,8 @@ declare module "littlejsengine" {
2235
2237
  isLoaded(): boolean;
2236
2238
  /** Loads a sound from a URL and decodes it into sample data.
2237
2239
  * @param {string} filename
2238
- * @return {Promise<void>} */
2239
- loadSound(filename: string): Promise<void>;
2240
+ * @return {Promise} */
2241
+ loadSound(filename: string): Promise<any>;
2240
2242
  }
2241
2243
  /**
2242
2244
  * Sound Instance - Wraps an AudioBufferSourceNode for individual sound control
@@ -2250,7 +2252,7 @@ declare module "littlejsengine" {
2250
2252
  * // Control the individual instance
2251
2253
  * instance.setVolume(.5);
2252
2254
  * instance.pause();
2253
- * instance.unpause();
2255
+ * instance.resume();
2254
2256
  * instance.stop();
2255
2257
  */
2256
2258
  export class SoundInstance {
@@ -2292,14 +2294,14 @@ declare module "littlejsengine" {
2292
2294
  stop(fadeTime?: number): void;
2293
2295
  /** Pause this sound instance */
2294
2296
  pause(): void;
2295
- /** Unpauses this sound instance */
2297
+ /** Resume this sound instance */
2296
2298
  resume(): void;
2297
2299
  /** Check if this instance is currently playing
2298
2300
  * @return {boolean} - True if playing
2299
2301
  */
2300
2302
  isPlaying(): boolean;
2301
- /** Check if this instance is paused and was not stopped
2302
- * @return {boolean} - True if paused
2303
+ /** Check if this instance is paused or stopped (not currently playing)
2304
+ * @return {boolean} - True if not playing
2303
2305
  */
2304
2306
  isPaused(): boolean;
2305
2307
  /** Get the current playback time in seconds
@@ -4094,6 +4096,24 @@ declare module "littlejsengine" {
4094
4096
  * @param {number} [renderOrder] */
4095
4097
  constructor(pos?: Vector2, size?: Vector2, tileInfo?: TileInfo, angle?: number, color?: Color, renderOrder?: number);
4096
4098
  }
4099
+ /**
4100
+ * Box2d Tile Layer
4101
+ * - adds Box2d support to tile layers
4102
+ * - creates static box2d fixtures for solid tiles
4103
+ * @extends Box2dObject
4104
+ * @memberof Box2D
4105
+ */
4106
+ export class Box2dTileLayer extends Box2dObject {
4107
+ /** Create a Box2d tile layer object
4108
+ * @param {TileCollisionLayer} tileLayer - Tile layer for this object */
4109
+ constructor(tileLayer: TileCollisionLayer);
4110
+ /** @property {TileLayer} - The tile layer */
4111
+ tileLayer: TileCollisionLayer;
4112
+ /** Create box2d collision fixtures for solid tiles
4113
+ * @param {number} [friction]
4114
+ * @param {number} [restitution] */
4115
+ buildCollision(friction?: number, restitution?: number): void;
4116
+ }
4097
4117
  /**
4098
4118
  * Box2D Raycast Result
4099
4119
  * - Holds results from a box2d raycast queries
@@ -33,7 +33,7 @@ const engineName = 'LittleJS';
33
33
  * @type {string}
34
34
  * @default
35
35
  * @memberof Engine */
36
- const engineVersion = '1.17.10';
36
+ const engineVersion = '1.17.11';
37
37
 
38
38
  /** Frames per second to update
39
39
  * @type {number}
@@ -396,33 +396,11 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
396
396
  workReadContext = workReadCanvas.getContext('2d', { willReadFrequently: true });
397
397
 
398
398
  // create promises for loading images
399
- const promises = imageSources.map((src, textureIndex)=>
400
- new Promise(resolve =>
401
- {
402
- ASSERT(isString(src), 'imageSources must be an array of strings');
403
-
404
- const image = new Image;
405
- image.onerror = image.onload = ()=>
406
- {
407
- const textureInfo = new TextureInfo(image);
408
- textureInfos[textureIndex] = textureInfo;
409
- resolve();
410
- }
411
- image.crossOrigin = 'anonymous';
412
- image.src = src;
413
- })
414
- );
399
+ const promises = imageSources.map((src, i)=> loadTexture(i, src));
415
400
 
401
+ // no images to load
416
402
  if (!imageSources.length)
417
- {
418
- // no images to load
419
- promises.push(new Promise(resolve =>
420
- {
421
- const textureInfo = new TextureInfo(new Image);
422
- textureInfos[0] = textureInfo;
423
- resolve();
424
- }));
425
- }
403
+ promises.push(loadTexture(0));
426
404
 
427
405
  // load engine font image
428
406
  promises.push(fontImageInit());
@@ -649,7 +627,7 @@ function drawEngineLogo(t)
649
627
  x.lineWidth = .1+p*3.9;
650
628
  x.textAlign = 'center';
651
629
  x.textBaseline = 'top';
652
- rect(11,Y+2,59,8*p,-1);
630
+ rect(11,Y+1,59,8*p,-1);
653
631
  x.beginPath();
654
632
 
655
633
  let w2 = 0;
@@ -672,8 +650,8 @@ function drawEngineLogo(t)
672
650
  rect(25,15,8,25,-1); // cab front
673
651
  rect(10,40,15,-25,1); // cab back
674
652
  rect(14,21,7,9,2); // cab window
675
- rect(38,15,6,6,2); // little stack
676
-
653
+ rect(38,20,6,-6,2); // little stack
654
+
677
655
  // big stack
678
656
  rect(49,20,10,-6,0);
679
657
  const stackPoints = [vec2(44,8),vec2(64,8),vec2(59,8+6*p),vec2(49,8+6*p)];
@@ -681,8 +659,8 @@ function drawEngineLogo(t)
681
659
  rect(44,8,20,-7,0);
682
660
 
683
661
  // engine
684
- for (let i=5;i--;) circle(59-i*6,30,10,0,9,1,0);
685
- circle(59,30,4,0,9,2); // light
662
+ for (let i=5;i--;) circle(59-i*6*p,30,10,0,2*PI,1,0);
663
+ circle(59,30,4,0,7,2); // light
686
664
 
687
665
  // engine outline
688
666
  rect(35,20,24,0); // top
@@ -693,9 +671,7 @@ function drawEngineLogo(t)
693
671
  rect(17,40,43,14,-1); // bottom center
694
672
 
695
673
  // wheels
696
- for (let i=3;i--;)
697
- for (let j=2;j--;)
698
- circle(15*i+17,47,j?7:1,PI,3*PI,2);
674
+ for (let i=3;i--;) for (let j=2;j--;) circle(17+15*i,47,j?7:1,0,2*PI,2);
699
675
 
700
676
  // cowcatcher
701
677
  for (let i=2;i--;)
@@ -865,7 +841,7 @@ function debugPoint(pos, color, time, angle, screenSpace=false)
865
841
  function debugLine(posA, posB, color, width=.1, time, screenSpace=false)
866
842
  {
867
843
  ASSERT(isVector2(posA), 'posA must be a vec2');
868
- ASSERT(isVector2(posB), 'posB must be sa vec2');
844
+ ASSERT(isVector2(posB), 'posB must be a vec2');
869
845
  ASSERT(isNumber(width), 'width must be a number');
870
846
 
871
847
  const halfDelta = vec2((posB.x - posA.x)/2, (posB.y - posA.y)/2);
@@ -1693,7 +1669,9 @@ function wave(frequency=1, amplitude=1, t=time, offset=0)
1693
1669
  function isNumber(n) { return typeof n === 'number' && !isNaN(n); }
1694
1670
 
1695
1671
  /**
1696
- * Check if object is a valid string or can be converted to one
1672
+ * Check if object can be converted to a string (has a toString method)
1673
+ * - Returns true for strings, numbers, and most objects
1674
+ * - Returns false for null and undefined
1697
1675
  * @param {any} s
1698
1676
  * @return {boolean}
1699
1677
  * @memberof Math */
@@ -1770,7 +1748,7 @@ function lineTest(posStart, posEnd, testFunction, normal)
1770
1748
  if (stepX < 0)
1771
1749
  hitPos.x -= e;
1772
1750
  }
1773
- if (stepY < 0)
1751
+ else if (stepY < 0)
1774
1752
  hitPos.y -= e;
1775
1753
 
1776
1754
  // set normal
@@ -2477,7 +2455,7 @@ class Color
2477
2455
  * @memberof Math */
2478
2456
  const WHITE = debugProtectConstant(rgb());
2479
2457
 
2480
- /** Color - Clear White #757474ff with 0 alpha
2458
+ /** Color - Clear White #ffffff00 with 0 alpha
2481
2459
  * @type {Color}
2482
2460
  * @memberof Math */
2483
2461
  const CLEAR_WHITE = debugProtectConstant(rgb(1,1,1,0));
@@ -2487,7 +2465,7 @@ const CLEAR_WHITE = debugProtectConstant(rgb(1,1,1,0));
2487
2465
  * @memberof Math */
2488
2466
  const BLACK = debugProtectConstant(rgb(0,0,0));
2489
2467
 
2490
- /** Color - Clear Black #000000 with 0 alpha
2468
+ /** Color - Clear Black #00000000 with 0 alpha
2491
2469
  * @type {Color}
2492
2470
  * @memberof Math */
2493
2471
  const CLEAR_BLACK = debugProtectConstant(rgb(0,0,0,0));
@@ -4582,6 +4560,31 @@ function drawTextScreen(text, pos, size, color=WHITE, lineWidth=0, lineColor=BLA
4582
4560
  ///////////////////////////////////////////////////////////////////////////////
4583
4561
  // Drawing utilities
4584
4562
 
4563
+ /** Load a texture at a specific index
4564
+ * @param {number} textureIndex - Index to store the texture at
4565
+ * @param {string} [src] - Image source path
4566
+ * @return {Promise} Promise that resolves when texture is loaded
4567
+ * @memberof Draw */
4568
+ async function loadTexture(textureIndex, src)
4569
+ {
4570
+ ASSERT(isNumber(textureIndex), 'textureIndex must be a number');
4571
+ ASSERT(!textureInfos[textureIndex], 'textureIndex is already loaded!');
4572
+ ASSERT(!src || isString(src), 'image src must be a string');
4573
+
4574
+ const image = new Image;
4575
+ if (src)
4576
+ {
4577
+ await new Promise(resolve =>
4578
+ {
4579
+ image.onerror = image.onload = resolve;
4580
+ image.crossOrigin = 'anonymous';
4581
+ image.src = src;
4582
+ });
4583
+ }
4584
+
4585
+ textureInfos[textureIndex] = new TextureInfo(image);
4586
+ }
4587
+
4585
4588
  /** Convert from screen to world space coordinates
4586
4589
  * @param {Vector2} screenPos
4587
4590
  * @return {Vector2}
@@ -4962,23 +4965,20 @@ class FontImage
4962
4965
  }
4963
4966
 
4964
4967
  // load engine font, called automatically on startup
4965
- function fontImageInit()
4968
+ async function fontImageInit()
4966
4969
  {
4967
- return new Promise(resolve =>
4970
+ const image = new Image;
4971
+ await new Promise(resolve =>
4968
4972
  {
4969
- // create the engine font
4970
- const image = new Image;
4971
- image.onerror = image.onload = ()=>
4972
- {
4973
- const tilePos=vec2(), tileSize=vec2(8), padding=1, bleed=0;
4974
- const textureInfo = new TextureInfo(image);
4975
- const tileInfo = new TileInfo(tilePos, tileSize, textureInfo, padding, bleed);
4976
- engineFontImage = new FontImage(tileInfo);
4977
- resolve();
4978
- }
4973
+ image.onerror = image.onload = resolve;
4979
4974
  image.crossOrigin = 'anonymous';
4980
4975
  image.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAAeAQMAAABnrVXaAAAABlBMVEUAAAD///+l2Z/dAAAAAXRSTlMAQObYZgAAAjpJREFUOMu9kzFu2zAUhn+CAROgqrk+B2l0BWYxMjlXeYaAtFtbdA1sGgHqRQfI0CNkSG5AwYB0BQ8d5Bsomwah6CPVeGg6tEPzAxLwyI+P78cP4u9lNO9OoMKnLMOobG5020/yaj/MrRcCGh1gBbyiLTPJEYaIiom5KM9Jq7KgynMGtb6L4GL4MF2H4LQKCXTvDVw2I4MsgZT7QLExdiutH+D08VOP3INXRrWX1/mmpbkNgAPYRVANb4xpcegYvhiNbIXauQICEjBuYLfMakaakWQeXxiZ0VDtuJCKs3ztMV59QtsHJNcRxDzfdL21ty3PrfIcXTN+E+GFAv6T5nbT9jd50/WFxb5ksdAv49qS6ouymG66ji08UMT6moykYLAo+V0j23GN4m829ZySAD5K7QsBfQTvOG8eE+gTeGYRAmnNAubN3hf5Zv9tJWDHp/VTuaSm7SN4fyINQqaNO3RMVxvpSPXnOChnRNvFcGY0gnwiPswYwTKVPE0zVtX3mTEIOoFzaqLrGuJaV+Uqumb71fVk/VoOH3cdLNQP/FHi8hV0CQNoqBZsUPlLPMsdCJro9QAaQQ0woDy9BJm0eTxCFnO9srcYlhNVlfR2EyTrph1uUtbUtAJifwRgrKuYdXVHeb0YI3QpawohQHkloI3J5FuVwI5ORxC9k2Tuz9Ir1IjgeIPGMHYkAZe2RuYkmWFmt3gGbTPOmBUWVTmRmHtGrfpzG/yuQNOKa6gBB/WA9khitPgl6/GP+gl2Af6tCbvaygAAAABJRU5ErkJggg==';
4981
4976
  });
4977
+
4978
+ const tilePos=vec2(), tileSize=vec2(8), padding=1, bleed=0;
4979
+ const textureInfo = new TextureInfo(image);
4980
+ const tileInfo = new TileInfo(tilePos, tileSize, textureInfo, padding, bleed);
4981
+ engineFontImage = new FontImage(tileInfo);
4982
4982
  }
4983
4983
  /**
4984
4984
  * LittleJS Input System
@@ -5961,7 +5961,7 @@ class Sound
5961
5961
 
5962
5962
  /** Loads a sound from a URL and decodes it into sample data.
5963
5963
  * @param {string} filename
5964
- * @return {Promise<void>} */
5964
+ * @return {Promise} */
5965
5965
  async loadSound(filename)
5966
5966
  {
5967
5967
  const response = await fetch(filename);
@@ -6019,7 +6019,7 @@ class Sound
6019
6019
  * // Control the individual instance
6020
6020
  * instance.setVolume(.5);
6021
6021
  * instance.pause();
6022
- * instance.unpause();
6022
+ * instance.resume();
6023
6023
  * instance.stop();
6024
6024
  */
6025
6025
  class SoundInstance
@@ -6133,7 +6133,7 @@ class SoundInstance
6133
6133
  this.startTime = undefined;
6134
6134
  }
6135
6135
 
6136
- /** Unpauses this sound instance */
6136
+ /** Resume this sound instance */
6137
6137
  resume()
6138
6138
  {
6139
6139
  if (!this.isPaused()) return;
@@ -6147,8 +6147,8 @@ class SoundInstance
6147
6147
  */
6148
6148
  isPlaying() { return !!this.source; }
6149
6149
 
6150
- /** Check if this instance is paused and was not stopped
6151
- * @return {boolean} - True if paused
6150
+ /** Check if this instance is paused or stopped (not currently playing)
6151
+ * @return {boolean} - True if not playing
6152
6152
  */
6153
6153
  isPaused() { return !this.isPlaying(); }
6154
6154
 
@@ -7074,7 +7074,7 @@ class TileCollisionLayer extends TileLayer
7074
7074
  collisionTest(pos, size=new Vector2, callbackObject)
7075
7075
  {
7076
7076
  ASSERT(isVector2(pos) && isVector2(size), 'pos and size must be Vector2s');
7077
- ASSERT(!callbackObject || typeof callbackObject === 'function' || callbackObject instanceof EngineObject, 'callbackObject must be a funtion or EngineObject');
7077
+ ASSERT(!callbackObject || typeof callbackObject === 'function' || callbackObject instanceof EngineObject, 'callbackObject must be a function or EngineObject');
7078
7078
 
7079
7079
  // make function to check for collision
7080
7080
  const collisionTest = callbackObject ? typeof callbackObject === 'function' ?
@@ -7111,7 +7111,7 @@ class TileCollisionLayer extends TileLayer
7111
7111
  collisionRaycast(posStart, posEnd, callbackObject, normal)
7112
7112
  {
7113
7113
  ASSERT(isVector2(posStart) && isVector2(posEnd), 'positions must be Vector2s');
7114
- ASSERT(!callbackObject || typeof callbackObject === 'function' || callbackObject instanceof EngineObject, 'callbackObject must be a funtion or EngineObject');
7114
+ ASSERT(!callbackObject || typeof callbackObject === 'function' || callbackObject instanceof EngineObject, 'callbackObject must be a function or EngineObject');
7115
7115
 
7116
7116
  // make function to check for collision
7117
7117
  const collisionTest = callbackObject ? typeof callbackObject === 'function' ?
@@ -10442,7 +10442,7 @@ class UIScrollbar extends UIObject
10442
10442
  else
10443
10443
  {
10444
10444
  // draw the scrollbar handle
10445
- const value = isHorizontal ? this.value : 1 - this.value;
10445
+ const value = clamp(isHorizontal ? this.value : 1 - this.value);
10446
10446
  const p = (barWidth - handleWidth) * (value - .5);
10447
10447
  const pos = this.pos.add(isHorizontal ? vec2(p, 0) : vec2(0, p));
10448
10448
  const color = this.disabled ? this.disabledColor : this.handleColor;
@@ -10511,12 +10511,11 @@ class UIVideo extends UIObject
10511
10511
 
10512
10512
  /** Play or resume the video
10513
10513
  * @return {Promise} Promise that resolves when playback starts */
10514
- play()
10514
+ async play()
10515
10515
  {
10516
10516
  // try to play the video, catch any errors (autoplay may be blocked)
10517
- const promise = this.video.play();
10518
- promise?.catch(()=>{});
10519
- return promise;
10517
+ try { await this.video.play(); }
10518
+ catch(e) {}
10520
10519
  }
10521
10520
 
10522
10521
  /** Pause the video */
@@ -13155,6 +13154,7 @@ export
13155
13154
  Box2dObject,
13156
13155
  Box2dStaticObject,
13157
13156
  Box2dKinematicObject,
13157
+ Box2dTileLayer,
13158
13158
  Box2dRaycastResult,
13159
13159
  Box2dJoint,
13160
13160
  Box2dTargetJoint,