littlejsengine 1.9.3 → 1.9.5

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.
@@ -156,16 +156,57 @@ function smoothStep(percent) { return percent * percent * (3 - 2 * percent); }
156
156
  function nearestPowerOfTwo(value) { return 2**Math.ceil(Math.log2(value)); }
157
157
 
158
158
  /** Returns true if two axis aligned bounding boxes are overlapping
159
- * @param {Vector2} pointA - Center of box A
160
- * @param {Vector2} sizeA - Size of box A
161
- * @param {Vector2} pointB - Center of box B
162
- * @param {Vector2} [sizeB=(0,0)] - Size of box B, a point if undefined
163
- * @return {Boolean} - True if overlapping
159
+ * @param {Vector2} posA - Center of box A
160
+ * @param {Vector2} sizeA - Size of box A
161
+ * @param {Vector2} posB - Center of box B
162
+ * @param {Vector2} [sizeB=(0,0)] - Size of box B, a point if undefined
163
+ * @return {Boolean} - True if overlapping
164
164
  * @memberof Utilities */
165
- function isOverlapping(pointA, sizeA, pointB, sizeB=vec2())
165
+ function isOverlapping(posA, sizeA, posB, sizeB=vec2())
166
166
  {
167
- return abs(pointA.x - pointB.x)*2 < sizeA.x + sizeB.x
168
- && abs(pointA.y - pointB.y)*2 < sizeA.y + sizeB.y;
167
+ return abs(posA.x - posB.x)*2 < sizeA.x + sizeB.x
168
+ && abs(posA.y - posB.y)*2 < sizeA.y + sizeB.y;
169
+ }
170
+
171
+ /** Returns true if a line segment is intersecting an axis aligned box
172
+ * @param {Vector2} start - Start of raycast
173
+ * @param {Vector2} end - End of raycast
174
+ * @param {Vector2} pos - Center of box
175
+ * @param {Vector2} size - Size of box
176
+ * @return {Boolean} - True if intersecting
177
+ * @memberof Utilities */
178
+ function isIntersecting(start, end, pos, size)
179
+ {
180
+ // Liang-Barsky algorithm
181
+ const boxMin = pos.subtract(size.scale(.5));
182
+ const boxMax = boxMin.add(size);
183
+ const delta = end.subtract(start);
184
+ const a = start.subtract(boxMin);
185
+ const b = start.subtract(boxMax);
186
+ const p = [-delta.x, delta.x, -delta.y, delta.y];
187
+ const q = [a.x, -b.x, a.y, -b.y];
188
+ let tMin = 0, tMax = 1;
189
+ for (let i = 4; i--;)
190
+ {
191
+ if (p[i])
192
+ {
193
+ const t = q[i] / p[i];
194
+ if (p[i] < 0)
195
+ {
196
+ if (t > tMax) return false;
197
+ tMin = max(t, tMin);
198
+ }
199
+ else
200
+ {
201
+ if (t < tMin) return false;
202
+ tMax = min(t, tMax);
203
+ }
204
+ }
205
+ else if (q[i] < 0)
206
+ return false;
207
+ }
208
+
209
+ return true;
169
210
  }
170
211
 
171
212
  /** Returns an oscillating wave between 0 and amplitude with frequency of 1 Hz by default
@@ -665,7 +706,7 @@ class Color
665
706
 
666
707
  /** Returns this color expressed in hsla format
667
708
  * @return {Array} */
668
- getHSLA()
709
+ HSLA()
669
710
  {
670
711
  const r = clamp(this.r);
671
712
  const g = clamp(this.g);
@@ -1349,6 +1390,8 @@ class EngineObject
1349
1390
  this.collideSolidObjects = false;
1350
1391
  /** @property {Boolean} - Object collides with and blocks other objects */
1351
1392
  this.isSolid = false;
1393
+ /** @property {Boolean} - Object collides with raycasts */
1394
+ this.collideRaycast = false;
1352
1395
 
1353
1396
  // add to list of objects
1354
1397
  engineObjects.push(this);
@@ -1553,13 +1596,7 @@ class EngineObject
1553
1596
  * @param {Number} tileData - the value of the tile at the position
1554
1597
  * @param {Vector2} pos - tile where the collision occured
1555
1598
  * @return {Boolean} - true if the collision should be resolved */
1556
- collideWithTile(tileData, pos) { return tileData > 0; }
1557
-
1558
- /** Called to check if a tile raycast hit
1559
- * @param {Number} tileData - the value of the tile at the position
1560
- * @param {Vector2} pos - tile where the raycast is
1561
- * @return {Boolean} - true if the raycast should hit */
1562
- collideWithTileRaycast(tileData, pos) { return tileData > 0; }
1599
+ collideWithTile(tileData, pos) { return tileData > 0; }
1563
1600
 
1564
1601
  /** Called to check if a object collision should be resolved
1565
1602
  * @param {EngineObject} object - the object to test against
@@ -1606,16 +1643,18 @@ class EngineObject
1606
1643
  }
1607
1644
 
1608
1645
  /** Set how this object collides
1609
- * @param {Boolean} [collideSolidObjects] - Does it collide with solid objects
1610
- * @param {Boolean} [isSolid] - Does it collide with and block other objects (expensive in large numbers)
1611
- * @param {Boolean} [collideTiles] - Does it collide with the tile collision */
1612
- setCollision(collideSolidObjects=true, isSolid=true, collideTiles=true)
1646
+ * @param {Boolean} [collideSolidObjects] - Does it collide with solid objects?
1647
+ * @param {Boolean} [isSolid] - Does it collide with and block other objects? (expensive in large numbers)
1648
+ * @param {Boolean} [collideTiles] - Does it collide with the tile collision?
1649
+ * @param {Boolean} [collideRaycast] - Does it collide with raycasts? */
1650
+ setCollision(collideSolidObjects=true, isSolid=true, collideTiles=true, collideRaycast=true)
1613
1651
  {
1614
1652
  ASSERT(collideSolidObjects || !isSolid, 'solid objects must be set to collide');
1615
1653
 
1616
1654
  this.collideSolidObjects = collideSolidObjects;
1617
1655
  this.isSolid = isSolid;
1618
1656
  this.collideTiles = collideTiles;
1657
+ this.collideRaycast = collideRaycast;
1619
1658
  }
1620
1659
 
1621
1660
  /** Returns string containg info about this object for debugging
@@ -1755,13 +1794,23 @@ class TileInfo
1755
1794
  this.textureIndex = textureIndex;
1756
1795
  }
1757
1796
 
1758
- /** Returns an offset copy of this tile, useful for animation
1797
+ /** Returns a copy of this tile offset by a vector
1759
1798
  * @param {Vector2} offset - Offset to apply in pixels
1760
1799
  * @return {TileInfo}
1761
1800
  */
1762
1801
  offset(offset)
1763
1802
  { return new TileInfo(this.pos.add(offset), this.size, this.textureIndex); }
1764
1803
 
1804
+ /** Returns a copy of this tile offset by a number of animation frames
1805
+ * @param {Number} frame - Offset to apply in animation frames
1806
+ * @return {TileInfo}
1807
+ */
1808
+ frame(frame)
1809
+ {
1810
+ ASSERT(typeof frame == 'number');
1811
+ return this.offset(vec2(frame*this.size.x, 0));
1812
+ }
1813
+
1765
1814
  /** Returns the texture info for this tile
1766
1815
  * @return {TextureInfo}
1767
1816
  */
@@ -1912,21 +1961,6 @@ function drawRect(pos, size, color, angle, useWebGL, screenSpace, context)
1912
1961
  drawTile(pos, size, undefined, color, angle, false, undefined, useWebGL, screenSpace, context);
1913
1962
  }
1914
1963
 
1915
- /** Draw colored polygon using passed in points
1916
- * @param {Array} points - Array of Vector2 points
1917
- * @param {Color} [color=(1,1,1,1)]
1918
- * @param {Boolean} [screenSpace=false]
1919
- * @param {CanvasRenderingContext2D} [context=mainContext]
1920
- * @memberof Draw */
1921
- function drawPoly(points, color=new Color, screenSpace, context=mainContext)
1922
- {
1923
- context.fillStyle = color.toString();
1924
- context.beginPath();
1925
- for (const point of screenSpace ? points : points.map(worldToScreen))
1926
- context.lineTo(point.x, point.y);
1927
- context.fill();
1928
- }
1929
-
1930
1964
  /** Draw colored line between two points
1931
1965
  * @param {Vector2} posA
1932
1966
  * @param {Vector2} posB
@@ -2353,9 +2387,21 @@ function mouseToScreen(mousePos)
2353
2387
  ///////////////////////////////////////////////////////////////////////////////
2354
2388
  // Gamepad input
2355
2389
 
2390
+ // gamepad internal variables
2356
2391
  const stickData = [];
2392
+
2393
+ // gamepads are updated by engine every frame automatically
2357
2394
  function gamepadsUpdate()
2358
2395
  {
2396
+ const applyDeadZones = (v)=>
2397
+ {
2398
+ const min=.3, max=.8;
2399
+ const deadZone = (v)=>
2400
+ v > min ? percent( v, min, max) :
2401
+ v < -min ? -percent(-v, min, max) : 0;
2402
+ return vec2(deadZone(v.x), deadZone(-v.y)).clampLength();
2403
+ }
2404
+
2359
2405
  // update touch gamepad if enabled
2360
2406
  if (touchGamepadEnable && isTouchDevice)
2361
2407
  {
@@ -2367,7 +2413,16 @@ function gamepadsUpdate()
2367
2413
  {
2368
2414
  // read virtual analog stick
2369
2415
  const sticks = stickData[0] || (stickData[0] = []);
2370
- sticks[0] = vec2(touchGamepadStick.x, -touchGamepadStick.y); // flip vertical
2416
+ sticks[0] = vec2();
2417
+ if (touchGamepadAnalog)
2418
+ sticks[0] = applyDeadZones(touchGamepadStick);
2419
+ else if (touchGamepadStick.lengthSquared() > .3)
2420
+ {
2421
+ // convert to 8 way dpad
2422
+ sticks[0].x = Math.round(touchGamepadStick.x);
2423
+ sticks[0].y = -Math.round(touchGamepadStick.y);
2424
+ sticks[0] = sticks[0].clampLength();
2425
+ }
2371
2426
 
2372
2427
  // read virtual gamepad buttons
2373
2428
  const data = inputData[1] || (inputData[1] = []);
@@ -2379,7 +2434,12 @@ function gamepadsUpdate()
2379
2434
  }
2380
2435
  }
2381
2436
 
2382
- if (!gamepadsEnable || !navigator || !navigator.getGamepads || !document.hasFocus() && !debug)
2437
+ // return if gamepads are disabled or not supported
2438
+ if (!gamepadsEnable || !navigator || !navigator.getGamepads)
2439
+ return;
2440
+
2441
+ // only poll gamepads when focused or in debug mode
2442
+ if (!debug && !document.hasFocus())
2383
2443
  return;
2384
2444
 
2385
2445
  // poll gamepads
@@ -2393,14 +2453,9 @@ function gamepadsUpdate()
2393
2453
 
2394
2454
  if (gamepad)
2395
2455
  {
2396
- // read clamp dead zone of analog sticks
2397
- const deadZone = .3, deadZoneMax = .8, applyDeadZone = (v)=>
2398
- v > deadZone ? percent( v, deadZone, deadZoneMax) :
2399
- v < -deadZone ? -percent(-v, deadZone, deadZoneMax) : 0;
2400
-
2401
2456
  // read analog sticks
2402
2457
  for (let j = 0; j < gamepad.axes.length-1; j+=2)
2403
- sticks[j>>1] = vec2(applyDeadZone(gamepad.axes[j]), applyDeadZone(-gamepad.axes[j+1])).clampLength();
2458
+ sticks[j>>1] = applyDeadZones(vec2(gamepad.axes[j],gamepad.axes[j+1]));
2404
2459
 
2405
2460
  // read buttons
2406
2461
  for (let j = gamepad.buttons.length; j--;)
@@ -2529,14 +2584,7 @@ function createTouchGamepad()
2529
2584
  if (touchPos.distance(stickCenter) < touchGamepadSize)
2530
2585
  {
2531
2586
  // virtual analog stick
2532
- if (touchGamepadAnalog)
2533
- touchGamepadStick = touchPos.subtract(stickCenter).scale(2/touchGamepadSize).clampLength();
2534
- else
2535
- {
2536
- // 8 way dpad
2537
- const angle = touchPos.subtract(stickCenter).angle();
2538
- touchGamepadStick.setAngle((angle * 4 / PI + 8.5 | 0) * PI / 4);
2539
- }
2587
+ touchGamepadStick = touchPos.subtract(stickCenter).scale(2/touchGamepadSize).clampLength();
2540
2588
  }
2541
2589
  else if (touchPos.distance(buttonCenter) < touchGamepadSize)
2542
2590
  {
@@ -2795,7 +2843,7 @@ class SoundWave extends Sound
2795
2843
  * 1, 0, 9, 1 // channel notes
2796
2844
  * ],
2797
2845
  * [ // channel 1
2798
- * 0, 1, // instrument 1, right speaker
2846
+ * 0, 1, // instrument 0, right speaker
2799
2847
  * 0, 12, 17, -1 // channel notes
2800
2848
  * ]
2801
2849
  * ],
@@ -3259,7 +3307,7 @@ function tileCollisionTest(pos, size=vec2(), object)
3259
3307
  }
3260
3308
  }
3261
3309
 
3262
- /** Return the center of tile if any that is hit (does not return the exact intersection)
3310
+ /** Return the center of first tile hit (does not return the exact intersection)
3263
3311
  * @param {Vector2} posStart
3264
3312
  * @param {Vector2} posEnd
3265
3313
  * @param {EngineObject} [object]
@@ -3455,8 +3503,11 @@ class TileLayer extends EngineObject
3455
3503
  mainCanvas.height = mainCanvasSize.y;
3456
3504
  }
3457
3505
 
3458
- // begin a new render for the tile canvas
3459
- enginePreRender();
3506
+ // disable smoothing for pixel art
3507
+ this.context.imageSmoothingEnabled = !canvasPixelated;
3508
+
3509
+ // setup gl rendering if enabled
3510
+ glEnable && glPreRender();
3460
3511
  }
3461
3512
 
3462
3513
  /** Call to end the redraw process */
@@ -4605,7 +4656,7 @@ const engineName = 'LittleJS';
4605
4656
  * @type {String}
4606
4657
  * @default
4607
4658
  * @memberof Engine */
4608
- const engineVersion = '1.9.3';
4659
+ const engineVersion = '1.9.5';
4609
4660
 
4610
4661
  /** Frames per second to update
4611
4662
  * @type {Number}
@@ -4672,6 +4723,19 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
4672
4723
  {
4673
4724
  ASSERT(Array.isArray(imageSources), 'pass in images as array');
4674
4725
 
4726
+ // Called automatically by engine to setup render system
4727
+ function enginePreRender()
4728
+ {
4729
+ // save canvas size
4730
+ mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
4731
+
4732
+ // disable smoothing for pixel art
4733
+ mainContext.imageSmoothingEnabled = !canvasPixelated;
4734
+
4735
+ // setup gl rendering if enabled
4736
+ glEnable && glPreRender();
4737
+ }
4738
+
4675
4739
  // internal update loop for engine
4676
4740
  function engineUpdate(frameTimeMS=0)
4677
4741
  {
@@ -4687,7 +4751,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
4687
4751
  timeReal += frameTimeDeltaMS / 1e3;
4688
4752
  frameTimeBufferMS += paused ? 0 : frameTimeDeltaMS;
4689
4753
  if (!debugSpeedUp)
4690
- frameTimeBufferMS = min(frameTimeBufferMS, 50); // clamp incase of slow framerate
4754
+ frameTimeBufferMS = min(frameTimeBufferMS, 50); // clamp in case of slow framerate
4691
4755
  updateCanvas();
4692
4756
 
4693
4757
  if (paused)
@@ -4829,7 +4893,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
4829
4893
  }
4830
4894
  image.src = src;
4831
4895
  })
4832
- )
4896
+ );
4833
4897
 
4834
4898
  // draw splash screen
4835
4899
  showSplashScreen && promises.push(new Promise(resolve =>
@@ -4854,19 +4918,6 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
4854
4918
  });
4855
4919
  }
4856
4920
 
4857
- // Called automatically by engine to setup render system
4858
- function enginePreRender()
4859
- {
4860
- // save canvas size
4861
- mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
4862
-
4863
- // disable smoothing for pixel art
4864
- mainContext.imageSmoothingEnabled = !canvasPixelated;
4865
-
4866
- // setup gl rendering if enabled
4867
- glEnable && glPreRender();
4868
- }
4869
-
4870
4921
  /** Update each engine object, remove destroyed objects, and update time
4871
4922
  * @memberof Engine */
4872
4923
  function engineObjectsUpdate()
@@ -4900,30 +4951,63 @@ function engineObjectsDestroy()
4900
4951
  engineObjects = engineObjects.filter(o=>!o.destroyed);
4901
4952
  }
4902
4953
 
4903
- /** Triggers a callback for each object within a given area
4904
- * @param {Vector2} [pos] - Center of test area
4954
+ /** Collects all object within a given area
4955
+ * @param {Vector2} [pos] - Center of test area, or undefined for all objects
4905
4956
  * @param {Number|Vector2} [size] - Radius of circle if float, rectangle size if Vector2
4906
- * @param {Function} [callbackFunction] - Calls this function on every object that passes the test
4907
4957
  * @param {Array} [objects=engineObjects] - List of objects to check
4958
+ * @return {Array} - List of collected objects
4908
4959
  * @memberof Engine */
4909
- function engineObjectsCallback(pos, size, callbackFunction, objects=engineObjects)
4960
+ function engineObjectsCollect(pos, size, objects=engineObjects)
4910
4961
  {
4962
+ const collectedObjects = [];
4911
4963
  if (!pos) // all objects
4912
4964
  {
4913
4965
  for (const o of objects)
4914
- callbackFunction(o);
4966
+ collectedObjects.push(o);
4915
4967
  }
4916
- else if (typeof size === 'object') // bounding box test
4968
+ else if (size instanceof Vector2) // bounding box test
4917
4969
  {
4918
4970
  for (const o of objects)
4919
- isOverlapping(pos, size, o.pos, o.size) && callbackFunction(o);
4971
+ isOverlapping(pos, size, o.pos, o.size) && collectedObjects.push(o);
4920
4972
  }
4921
4973
  else // circle test
4922
4974
  {
4923
4975
  const sizeSquared = size*size;
4924
4976
  for (const o of objects)
4925
- pos.distanceSquared(o.pos) < sizeSquared && callbackFunction(o);
4977
+ pos.distanceSquared(o.pos) < sizeSquared && collectedObjects.push(o);
4926
4978
  }
4979
+ return collectedObjects;
4980
+ }
4981
+
4982
+ /** Triggers a callback for each object within a given area
4983
+ * @param {Vector2} [pos] - Center of test area, or undefined for all objects
4984
+ * @param {Number|Vector2} [size] - Radius of circle if float, rectangle size if Vector2
4985
+ * @param {Function} [callbackFunction] - Calls this function on every object that passes the test
4986
+ * @param {Array} [objects=engineObjects] - List of objects to check
4987
+ * @memberof Engine */
4988
+ function engineObjectsCallback(pos, size, callbackFunction, objects=engineObjects)
4989
+ { engineObjectsCollect(pos, size, objects).forEach(o => callbackFunction(o)); }
4990
+
4991
+ /** Return a list of objects intersecting a ray
4992
+ * @param {Vector2} start
4993
+ * @param {Vector2} end
4994
+ * @param {Array} [objects=engineObjects] - List of objects to check
4995
+ * @return {Array} - List of objects hit
4996
+ * @memberof Engine */
4997
+ function engineObjectsRaycast(start, end, objects=engineObjects)
4998
+ {
4999
+ const hitObjects = [];
5000
+ for (const o of objects)
5001
+ {
5002
+ if (o.collideRaycast && isIntersecting(start, end, o.pos, o.size))
5003
+ {
5004
+ debugRaycast && debugRect(o.pos, o.size, '#f00');
5005
+ hitObjects.push(o);
5006
+ }
5007
+ }
5008
+
5009
+ debugRaycast && debugLine(start, end, hitObjects.length ? '#f00' : '#00f', .02);
5010
+ return hitObjects;
4927
5011
  }
4928
5012
 
4929
5013
  ///////////////////////////////////////////////////////////////////////////////
@@ -5011,16 +5095,16 @@ function drawEngineSplashScreen(t)
5011
5095
  rect(37,14,9,6);
5012
5096
 
5013
5097
  // big stack
5014
- rect(50,20,10,-10,color(0,1));
5015
- rect(50,20,6.5,-10,color(0,2));
5016
- rect(50,20,3.5,-10,color(0,3));
5017
- rect(50,20,10,-10);
5018
- circle(55,2,11.4,.5,PI-.5,color(3,3));
5019
- circle(55,2,11.4,.5,PI/2,color(3,2),1);
5020
- circle(55,2,11.4,.5,PI-.5);
5021
- rect(45,7,20,-7,color(0,2));
5022
- rect(45,0,20,3,color(0,3));
5023
- rect(45,0,20,7);
5098
+ rect(50,20,10,-8,color(0,1))
5099
+ rect(50,20,6.5,-8,color(0,2))
5100
+ rect(50,20,3.5,-8,color(0,3))
5101
+ rect(50,20,10,-8)
5102
+ circle(55,2,11.4,.5,PI-.5,color(3,3))
5103
+ circle(55,2,11.4,.5,PI/2,color(3,2),1)
5104
+ circle(55,2,11.4,.5,PI-.5)
5105
+ rect(45,7,20,-7,color(0,2))
5106
+ rect(45,-1,20,4,color(0,3))
5107
+ rect(45,-1,20,8)
5024
5108
 
5025
5109
  // engine
5026
5110
  for (let i=5; i--;)
@@ -8,7 +8,7 @@
8
8
 
9
9
  // import module
10
10
  import * as LittleJS from '../../dist/littlejs.esm.js';
11
- const {Vector2, Color, Timer, tile, vec2, hsl, rgb} = LittleJS;
11
+ const {tile, vec2, hsl} = LittleJS;
12
12
 
13
13
  // show the LittleJS splash screen
14
14
  LittleJS.setShowSplashScreen(true);
@@ -218,8 +218,7 @@ class Character extends GameObject
218
218
  const animationFrame = this.isDead() ? 0 :
219
219
  this.climbingLadder || this.groundTimer.active() ?
220
220
  2*this.walkCyclePercent|0 : 1;
221
- const playerTile = spriteAtlas.player;
222
- this.tileInfo.pos.x = playerTile.pos.x + playerTile.size.x*animationFrame;
221
+ this.tileInfo = spriteAtlas.player.frame(animationFrame);
223
222
 
224
223
  let bodyPos = this.pos;
225
224
  if (!this.isDead())
@@ -130,14 +130,13 @@ function destroyTile(pos, makeSound = 1, cleanNeighbors = 1)
130
130
 
131
131
  // destroy tile
132
132
  const tileType = getTileCollisionData(pos);
133
-
134
- if (!tileType || tileType == tileType_solid)
133
+ if (!tileType)
135
134
  return 1;
136
135
 
137
136
  const tileLayer = tileLayers[foregroundLayerIndex];
138
137
  const centerPos = pos.add(vec2(.5));
139
138
  const layerData = tileLayer.getData(pos);
140
- if (!layerData)
139
+ if (!layerData || tileType == tileType_solid)
141
140
  return;
142
141
 
143
142
  // create effects
@@ -108,7 +108,6 @@ function loadLevel()
108
108
  new Enemy(objectPos);
109
109
  if (tile == tileLookup.coin)
110
110
  new Coin(objectPos);
111
- setTileData(pos, layer, 0);
112
111
  continue;
113
112
  }
114
113
 
@@ -6,7 +6,7 @@
6
6
  'use strict';
7
7
  // import module
8
8
  import * as LittleJS from '../../dist/littlejs.esm.js';
9
- const { Vector2, Color, Timer, tile, vec2, hsl, rgb } = LittleJS;
9
+ const { tile, vec2, hsl } = LittleJS;
10
10
  // show the LittleJS splash screen
11
11
  LittleJS.setShowSplashScreen(true);
12
12
  // sound effects
@@ -8,7 +8,7 @@
8
8
 
9
9
  // import module
10
10
  import * as LittleJS from '../../dist/littlejs.esm.js';
11
- const {Vector2, Color, Timer, tile, vec2, hsl, rgb} = LittleJS;
11
+ const {tile, vec2, hsl} = LittleJS;
12
12
 
13
13
  // show the LittleJS splash screen
14
14
  LittleJS.setShowSplashScreen(true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "littlejsengine",
3
- "version": "1.9.3",
3
+ "version": "1.9.5",
4
4
  "description": "LittleJS - Tiny and Fast HTML5 Game Engine",
5
5
  "main": "dist/littlejs.esm.js",
6
6
  "types": "dist/littlejs.d.ts",
package/reference.md CHANGED
@@ -13,13 +13,7 @@ To start LittleJS, you need to create a few functions and pass them to engineIni
13
13
 
14
14
  ```javascript
15
15
  // Start up LittleJS engine with your callback functions
16
- engineInit(init, update, updatePost, render, renderPost, imageSources=['tiles.png'])
17
-
18
- // Destroy and remove all objects
19
- engineObjectsDestroy()
20
-
21
- // Trigger a callback for each object within a given area
22
- engineObjectsCallback(pos, size, callbackFunction, objects=engineObjects)
16
+ engineInit(init, update, updatePost, render, renderPost, imageSources=['tiles.png']);
23
17
  ```
24
18
 
25
19
  ## LittleJS Utilities Classes and Functions
@@ -53,6 +47,7 @@ lerpAngle(percent, angleA, angleB) // Linearly interpolates with wrap
53
47
  smoothStep(percent) // Applies smoothstep function
54
48
  nearestPowerOfTwo(value) // Returns the nearest power of two
55
49
  isOverlapping(pointA, sizeA, pointB, sizeB) // Checks if bounding boxes overlap
50
+ isIntersecting(start, end, pos, size) // Checks if ray intersects box
56
51
  wave(frequency=1, amplitude=1, t=time) // Returns oscillating wave
57
52
  formatTime(t) // Formats seconds for display
58
53
 
@@ -103,7 +98,7 @@ Color.scale(scale, alphaScale=scale) // Scale by a float
103
98
  Color.clamp() // Clamp this color
104
99
  Color.lerp(c, percent) // Interpolate between colors
105
100
  Color.setHSLA(h=0, s=0, l=1, a=1) // Set the color from HSLA values
106
- Color.getHSLA() // Get the color in HSLA format
101
+ Color.HSLA() // Get the color in HSLA format
107
102
  Color.mutate(amount=.05, alphaAmount=0) // Randomly diverge from this color
108
103
  Color.setHex(hex) // Set this color from a hex code
109
104
  Color.rgbaInt() // Get this color as 32 bit RGBA value
@@ -138,7 +133,6 @@ Timer.valueOf() // Get how long since elapsed, 0 if not set
138
133
  // Drawing functions
139
134
  drawTile(pos, size=(1,1), tileInfo, color, angle=0, mirror, additiveColor)
140
135
  drawRect(pos, size=(1,1), color=(1,1,1,1), angle=0)
141
- drawPoly(points, color=(1,1,1,1))
142
136
  drawLine(posA, posB, thickness=.1, color=(1,1,1,1))
143
137
  drawCanvas2D(pos, size, angle, mirror, drawFunction)
144
138
  drawText(text, pos, size=1, color=(1,1,1,1), lineWidth, lineColor)
@@ -153,6 +147,7 @@ TileInfo.pos // Top left corner of tile in pixels
153
147
  TileInfo.size // Size of tile in pixels
154
148
  TileInfo.textureIndex // Texture index to use
155
149
  TileInfo.offset(offset) // Offset this tile by a certain amount in pixels
150
+ TileInfo.frame(frame) // Offset this tile by a number of animation frames
156
151
  TileInfo.getTextureInfo() // Returns texture info for this tile
157
152
 
158
153
  // Texture Info Object
@@ -285,7 +280,6 @@ EngineObject.update() // Update object, called auto
285
280
  EngineObject.render() // Render object, called automatically
286
281
  EngineObject.destroy() // Destroy this object and children
287
282
  EngineObject.collideWithTile(tileData, pos) // Tile collision resolve check
288
- EngineObject.collideWithTileRaycast(tileData, pos) // Check if raycast hit
289
283
  EngineObject.collideWithObject(object) // Object collision resolve check
290
284
  EngineObject.getAliveTime(object) // How long since object was created
291
285
  EngineObject.applyAcceleration(acceleration) // Apply acceleration
@@ -314,7 +308,7 @@ EngineObject.renderOrder // Objects are sorted by render order
314
308
  EngineObject.velocity // Velocity of the object
315
309
  EngineObject.angleVelocity // Angular velocity of the object
316
310
 
317
- // Object settings
311
+ // Engine Object settings
318
312
  enablePhysicsSolver = true // Enable collisions between objects?
319
313
  objectDefaultMass = 1 // Default object mass for collisions
320
314
  objectDefaultDamping = 1 // How much to slow velocity by each frame (0-1)
@@ -323,6 +317,12 @@ objectDefaultElasticity = 0 // How much to bounce when a collision occurs (0-1
323
317
  objectDefaultFriction = .8 // How much to slow when touching (0-1)
324
318
  objectMaxSpeed = 1 // Clamp max speed to avoid fast objects missing collisions
325
319
  gravity = 0 // How much gravity to apply to objects
320
+
321
+ // Engine Object functions
322
+ engineObjectsCollect(pos, size, objects=engineObjects)k
323
+ engineObjectsCallback(pos, size, callbackFunction, objects=engineObjects)
324
+ engineObjectsRaycast(start, end, objects=engineObjects)
325
+ engineObjectsDestroy()
326
326
  ```
327
327
 
328
328
  ## LittleJS Tile Layer System