littlejsengine 1.6.6 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +76 -53
  2. package/build/littlejs.d.ts +154 -136
  3. package/build/littlejs.esm.js +461 -305
  4. package/build/littlejs.esm.min.js +1 -1
  5. package/build/littlejs.js +452 -291
  6. package/build/littlejs.min.js +1 -1
  7. package/build/littlejs.release.js +2317 -2168
  8. package/examples/breakout/game.js +5 -1
  9. package/examples/breakout/index.html +5 -5
  10. package/examples/breakoutTutorial/README.md +6 -6
  11. package/examples/breakoutTutorial/game.js +3 -0
  12. package/examples/breakoutTutorial/index.html +3 -3
  13. package/examples/electron/build.js +105 -0
  14. package/examples/electron/game.js +4 -2
  15. package/examples/electron/index.html +13 -2
  16. package/examples/electron/package.json +5 -3
  17. package/examples/empty/game.js +3 -1
  18. package/examples/empty/index.html +1 -1
  19. package/examples/js13k/build.bat +2 -0
  20. package/examples/js13k/build.js +110 -0
  21. package/examples/js13k/game.js +109 -0
  22. package/examples/js13k/index.html +18 -0
  23. package/examples/js13k/tiles.png +0 -0
  24. package/examples/module/game.js +9 -3
  25. package/examples/module/index.html +2 -2
  26. package/examples/particles/index.html +7 -13
  27. package/examples/platformer/game.js +5 -2
  28. package/examples/platformer/gameEffects.js +12 -12
  29. package/examples/platformer/gamePlayer.js +2 -2
  30. package/examples/platformer/index.html +8 -8
  31. package/examples/puzzle/game.js +5 -3
  32. package/examples/puzzle/index.html +4 -4
  33. package/examples/starter/build.bat +2 -78
  34. package/examples/starter/build.js +109 -0
  35. package/examples/starter/game.js +4 -1
  36. package/examples/starter/index.html +15 -18
  37. package/examples/stress/index.html +5 -7
  38. package/examples/typescript/build.bat +2 -14
  39. package/examples/typescript/build.js +31 -0
  40. package/examples/typescript/game.js +94 -89
  41. package/examples/typescript/game.ts +9 -3
  42. package/examples/typescript/index.html +2 -2
  43. package/package.json +2 -2
  44. package/src/engine.js +3 -3
  45. package/src/engineAudio.js +44 -16
  46. package/src/engineBuild.bat +2 -132
  47. package/src/engineBuild.js +156 -0
  48. package/src/engineDebug.js +25 -15
  49. package/src/engineDraw.js +62 -53
  50. package/src/engineExport.js +7 -12
  51. package/src/engineInput.js +27 -35
  52. package/src/engineObject.js +15 -13
  53. package/src/engineParticles.js +6 -6
  54. package/src/engineRelease.js +1 -3
  55. package/src/engineSettings.js +1 -0
  56. package/src/engineTileLayer.js +31 -18
  57. package/src/engineUtilities.js +161 -93
  58. package/src/engineWebGL.js +63 -27
  59. package/examples/electron/build.bat +0 -52
@@ -6,12 +6,12 @@
6
6
 
7
7
  /**
8
8
  * LittleJS Object Base Object Class
9
- * - Base object class used by the engine
9
+ * - Top level object class used by the engine
10
10
  * - Automatically adds self to object list
11
11
  * - Will be updated and rendered each frame
12
12
  * - Renders as a sprite from a tilesheet by default
13
13
  * - Can have color and addtive color applied
14
- * - 2d Physics and collision system
14
+ * - 2D Physics and collision system
15
15
  * - Sorted by renderOrder
16
16
  * - Objects can have children attached
17
17
  * - Parents are updated before children, and set child transform
@@ -78,7 +78,7 @@ class EngineObject
78
78
  /** @property {Number} [renderOrder=0] - Objects are sorted by render order */
79
79
  this.renderOrder = renderOrder;
80
80
  /** @property {Vector2} [velocity=Vector2()] - Velocity of the object */
81
- this.velocity = new Vector2();
81
+ this.velocity = vec2();
82
82
  /** @property {Number} [angleVelocity=0] - Angular velocity of the object */
83
83
  this.angleVelocity = 0;
84
84
 
@@ -138,15 +138,17 @@ class EngineObject
138
138
  for (const o of engineObjectsCollide)
139
139
  {
140
140
  // non solid objects don't collide with eachother
141
- if (!this.isSolid & !o.isSolid || o.destroyed || o.parent || o == this)
141
+ if (!this.isSolid && !o.isSolid || o.destroyed || o.parent || o == this)
142
142
  continue;
143
143
 
144
144
  // check collision
145
145
  if (!isOverlapping(this.pos, this.size, o.pos, o.size))
146
146
  continue;
147
147
 
148
- // pass collision to objects
149
- if (!this.collideWithObject(o) | !o.collideWithObject(this))
148
+ // notify objects of collision and check if should be resolved
149
+ const collide1 = this.collideWithObject(o);
150
+ const collide2 = o.collideWithObject(this);
151
+ if (!collide1 || !collide2)
150
152
  continue;
151
153
 
152
154
  if (isOverlapping(oldPos, this.size, o.pos, o.size))
@@ -171,7 +173,7 @@ class EngineObject
171
173
  const isBlockedY = abs(oldPos.x - o.pos.x)*2 < sizeBoth.x;
172
174
  const elasticity = max(this.elasticity, o.elasticity);
173
175
 
174
- if (smallStepUp | isBlockedY | !isBlockedX) // resolve y collision
176
+ if (smallStepUp || isBlockedY || !isBlockedX) // resolve y collision
175
177
  {
176
178
  // push outside object collision
177
179
  this.pos.y = o.pos.y + (sizeBoth.y/2 + epsilon) * sign(oldPos.y - o.pos.y);
@@ -200,7 +202,7 @@ class EngineObject
200
202
  o.velocity.y = lerp(elasticity, inelastic, elastic1);
201
203
  }
202
204
  }
203
- if (!smallStepUp & isBlockedX) // resolve x collision
205
+ if (!smallStepUp && isBlockedX) // resolve x collision
204
206
  {
205
207
  // push outside collision
206
208
  this.pos.x = o.pos.x + (sizeBoth.x/2 + epsilon) * sign(oldPos.x - o.pos.x);
@@ -235,9 +237,9 @@ class EngineObject
235
237
  if (!tileCollisionTest(oldPos, this.size, this))
236
238
  {
237
239
  // test which side we bounced off (or both if a corner)
238
- const isBlockedY = tileCollisionTest(new Vector2(oldPos.x, this.pos.y), this.size, this);
239
- const isBlockedX = tileCollisionTest(new Vector2(this.pos.x, oldPos.y), this.size, this);
240
- if (isBlockedY | !isBlockedX)
240
+ const isBlockedY = tileCollisionTest(vec2(oldPos.x, this.pos.y), this.size, this);
241
+ const isBlockedX = tileCollisionTest(vec2(this.pos.x, oldPos.y), this.size, this);
242
+ if (isBlockedY || !isBlockedX)
241
243
  {
242
244
  // set if landed on ground
243
245
  this.groundObject = wasMovingDown;
@@ -300,7 +302,7 @@ class EngineObject
300
302
  * @param {EngineObject} object - the object to test against
301
303
  * @return {Boolean} - true if the collision should be resolved
302
304
  */
303
- collideWithObject(o) { return 1; }
305
+ collideWithObject(object) { return 1; }
304
306
 
305
307
  /** How long since the object was created
306
308
  * @return {Number} */
@@ -308,7 +310,7 @@ class EngineObject
308
310
 
309
311
  /** Apply acceleration to this object (adjust velocity, not affected by mass)
310
312
  * @param {Vector2} acceleration */
311
- applyAcceleration(a) { if (this.mass) this.velocity = this.velocity.add(a); }
313
+ applyAcceleration(acceleration) { if (this.mass) this.velocity = this.velocity.add(acceleration); }
312
314
 
313
315
  /** Apply force to this object (adjust velocity, affected by mass)
314
316
  * @param {Vector2} force */
@@ -85,7 +85,7 @@ class ParticleEmitter extends EngineObject
85
85
  localSpace
86
86
  )
87
87
  {
88
- super(pos, new Vector2, tileIndex, tileSize, angle, undefined, renderOrder);
88
+ super(pos, vec2(), tileIndex, tileSize, angle, undefined, renderOrder);
89
89
 
90
90
  // emitter settings
91
91
  /** @property {Number} - World space size of the emitter (float for circle diameter, vec2 for rect) */
@@ -152,7 +152,7 @@ class ParticleEmitter extends EngineObject
152
152
  this.parent && super.update();
153
153
 
154
154
  // update emitter
155
- if (!this.emitTime | this.getAliveTime() <= this.emitTime)
155
+ if (!this.emitTime || this.getAliveTime() <= this.emitTime)
156
156
  {
157
157
  // emit particles
158
158
  if (this.emitRate * particleEmitRateScale)
@@ -174,7 +174,7 @@ class ParticleEmitter extends EngineObject
174
174
  {
175
175
  // spawn a particle
176
176
  let pos = this.emitSize.x != undefined ? // check if vec2 was used for size
177
- (new Vector2(rand(-.5,.5), rand(-.5,.5)))
177
+ vec2(rand(-.5,.5), rand(-.5,.5))
178
178
  .multiply(this.emitSize).rotate(this.angle) // box emitter
179
179
  : randInCircle(this.emitSize/2); // circle emitter
180
180
  let angle = rand(this.particleConeAngle, -this.particleConeAngle);
@@ -204,7 +204,7 @@ class ParticleEmitter extends EngineObject
204
204
  // build particle settings
205
205
  particle.colorStart = colorStart;
206
206
  particle.colorEndDelta = colorEnd.subtract(colorStart);
207
- particle.velocity = (new Vector2).setAngle(velocityAngle, speed);
207
+ particle.velocity = vec2().setAngle(velocityAngle, speed);
208
208
  particle.angleVelocity = angleSpeed;
209
209
  particle.lifeTime = particleTime;
210
210
  particle.sizeStart = sizeStart;
@@ -249,7 +249,7 @@ class Particle extends EngineObject
249
249
  * @param {Number} [angle=0] - Angle to rotate the particle
250
250
  */
251
251
  constructor(pos, tileIndex, tileSize, angle)
252
- { super(pos, new Vector2, tileIndex, tileSize, angle); }
252
+ { super(pos, vec2(), tileIndex, tileSize, angle); }
253
253
 
254
254
  /** Render the particle, automatically called each frame, sorted by renderOrder */
255
255
  render()
@@ -257,7 +257,7 @@ class Particle extends EngineObject
257
257
  // modulate size and color
258
258
  const p = min((time - this.spawnTime) / this.lifeTime, 1);
259
259
  const radius = this.sizeStart + p * this.sizeEndDelta;
260
- const size = new Vector2(radius, radius);
260
+ const size = vec2(radius);
261
261
  const fadeRate = this.fadeRate/2;
262
262
  const color = new Color(
263
263
  this.colorStart.r + p * this.colorEndDelta.r,
@@ -1,6 +1,5 @@
1
1
  /**
2
- * LittleJS - Release Build
3
- * MIT License - Copyright 2021 Frank Force
2
+ * LittleJS - Release Mode
4
3
  * - This file is used for release builds in place of engineDebug.js
5
4
  * - Debug functionality is disabled to reduce size and increase performance
6
5
  */
@@ -8,7 +7,6 @@
8
7
  'use strict';
9
8
 
10
9
  let showWatermark = 0;
11
- let godMode = 0;
12
10
  let debugKeyCode = 0;
13
11
  const debug = 0;
14
12
  const debugOverlay = 0;
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * LittleJS Engine Settings
3
+ * - All settings for the engine are here
3
4
  * @namespace Settings
4
5
  */
5
6
 
@@ -67,12 +67,12 @@ function tileCollisionTest(pos, size=vec2(), object)
67
67
  for (let x = minX; x < maxX; ++x)
68
68
  {
69
69
  const tileData = tileCollision[y*tileCollisionSize.x+x];
70
- if (tileData && (!object || object.collideWithTile(tileData, new Vector2(x, y))))
70
+ if (tileData && (!object || object.collideWithTile(tileData, vec2(x, y))))
71
71
  return 1;
72
72
  }
73
73
  }
74
74
 
75
- /** Return the center of tile if any that is hit (this does not return the exact hit point)
75
+ /** Return the center of tile if any that is hit (does not return the exact intersection)
76
76
  * @param {Vector2} posStart
77
77
  * @param {Vector2} posEnd
78
78
  * @param {EngineObject} [object]
@@ -81,28 +81,41 @@ function tileCollisionTest(pos, size=vec2(), object)
81
81
  function tileCollisionRaycast(posStart, posEnd, object)
82
82
  {
83
83
  // test if a ray collides with tiles from start to end
84
- // todo: a way to get the exact hit point, it must still register as inside the hit tile
85
- const posDelta = (posEnd = posEnd.floor()).subtract(posStart = posStart.floor());
86
- const dx = abs(posDelta.x), dy = -abs(posDelta.y);
87
- const sx = sign(posDelta.x), sy = sign(posDelta.y);
84
+ // todo: a way to get the exact hit point, it must still be inside the hit tile
85
+ const delta = posEnd.subtract(posStart);
86
+ const totalLength = delta.length();
87
+ const normalizedDelta = delta.normalize();
88
+ const unit = vec2(abs(1/normalizedDelta.x), abs(1/normalizedDelta.y));
89
+ const flooredPosStart = posStart.floor();
88
90
 
89
- for (let x = posStart.x, y = posStart.y, e = dx + dy;;)
91
+ // setup iteration variables
92
+ let pos = flooredPosStart;
93
+ let xi = unit.x * (delta.x < 0 ? posStart.x - pos.x : pos.x - posStart.x + 1);
94
+ let yi = unit.y * (delta.y < 0 ? posStart.y - pos.y : pos.y - posStart.y + 1);
95
+
96
+ while (1)
90
97
  {
91
- const tileData = getTileCollisionData(vec2(x,y));
92
- if (tileData && (object ? object.collideWithTileRaycast(tileData, new Vector2(x, y)) : tileData > 0))
98
+ // check for tile collision
99
+ const tileData = getTileCollisionData(pos);
100
+ if (tileData && (!object || object.collideWithTile(tileData, pos)))
93
101
  {
94
- debugRaycast && debugLine(posStart, posEnd, '#f00',.02, 1);
95
- debugRaycast && debugPoint(new Vector2(x+.5, y+.5), '#ff0', 1);
96
- return new Vector2(x+.5, y+.5);
102
+ debugRaycast && debugLine(posStart, posEnd, '#f00', .02);
103
+ debugRaycast && debugPoint(pos.add(vec2(.5)), '#ff0');
104
+ return pos.add(vec2(.5));
97
105
  }
98
106
 
99
- // update Bresenham line drawing algorithm
100
- if (x == posEnd.x & y == posEnd.y) break;
101
- const e2 = 2*e;
102
- if (e2 >= dy) e += dy, x += sx;
103
- if (e2 <= dx) e += dx, y += sy;
107
+ // check if past the end
108
+ if (xi > totalLength && yi > totalLength)
109
+ break;
110
+
111
+ // get coordinates of the next tile to check
112
+ if (xi > yi)
113
+ pos.y += sign(delta.y), yi += unit.y;
114
+ else
115
+ pos.x += sign(delta.x), xi += unit.x;
104
116
  }
105
- debugRaycast && debugLine(posStart, posEnd, '#00f',.02, 1);
117
+
118
+ debugRaycast && debugLine(posStart, posEnd, '#00f', .02);
106
119
  }
107
120
 
108
121
  ///////////////////////////////////////////////////////////////////////////////