littlejsengine 1.1.26 → 1.2.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.
@@ -32,7 +32,7 @@
32
32
  class EngineObject
33
33
  {
34
34
  /** Create an engine object and adds it to the list of objects
35
- * @param {Vector2} [position=new Vector2(0,0)] - World space position of the object
35
+ * @param {Vector2} [position=new Vector2()] - World space position of the object
36
36
  * @param {Vector2} [size=objectDefaultSize] - World space size of the object
37
37
  * @param {Number} [tileIndex=-1] - Tile to use to render object, untextured if -1
38
38
  * @param {Vector2} [tileSize=tileSizeDefault] - Size of tile in source pixels
@@ -77,12 +77,15 @@ class EngineObject
77
77
  this.gravityScale = 1;
78
78
  /** @property {Number} [renderOrder=0] - Objects are sorted by render order */
79
79
  this.renderOrder = renderOrder;
80
+ /** @property {Vector2} [velocity=new Vector2()] - Velocity of the object */
81
+ this.velocity = new Vector2();
82
+ /** @property {Number} [angleVelocity=0] - Angular velocity of the object */
83
+ this.angleVelocity = 0;
80
84
 
81
85
  // init other internal object stuff
82
86
  this.spawnTime = time;
83
- this.velocity = vec2(this.collideSolidObjects = this.angleVelocity = 0);
84
- this.collideTiles = 1;
85
87
  this.children = [];
88
+ this.collideTiles = 1;
86
89
 
87
90
  // add to list of objects
88
91
  engineObjects.push(this);
@@ -101,8 +104,8 @@ class EngineObject
101
104
  }
102
105
 
103
106
  // limit max speed to prevent missing collisions
104
- this.velocity.x = clamp(this.velocity.x, objectMaxSpeed, -objectMaxSpeed);
105
- this.velocity.y = clamp(this.velocity.y, objectMaxSpeed, -objectMaxSpeed);
107
+ this.velocity.x = clamp(this.velocity.x, -objectMaxSpeed, objectMaxSpeed);
108
+ this.velocity.y = clamp(this.velocity.y, -objectMaxSpeed, objectMaxSpeed);
106
109
 
107
110
  // apply physics
108
111
  const oldPos = this.pos.copy();
@@ -192,8 +195,8 @@ class EngineObject
192
195
 
193
196
  // lerp betwen elastic or inelastic based on elasticity
194
197
  const elasticity = max(this.elasticity, o.elasticity);
195
- this.velocity.y = lerp(elasticity, elastic0, inelastic);
196
- o.velocity.y = lerp(elasticity, elastic1, inelastic);
198
+ this.velocity.y = lerp(elasticity, inelastic, elastic0);
199
+ o.velocity.y = lerp(elasticity, inelastic, elastic1);
197
200
  }
198
201
  }
199
202
  if (!smallStepUp && (isBlockedX || !isBlockedY)) // resolve x collision
@@ -213,8 +216,8 @@ class EngineObject
213
216
 
214
217
  // lerp betwen elastic or inelastic based on elasticity
215
218
  const elasticity = max(this.elasticity, o.elasticity);
216
- this.velocity.x = lerp(elasticity, elastic0, inelastic);
217
- o.velocity.x = lerp(elasticity, elastic1, inelastic);
219
+ this.velocity.x = lerp(elasticity, inelastic, elastic0);
220
+ o.velocity.x = lerp(elasticity, inelastic, elastic1);
218
221
  }
219
222
  else // bounce if other object is fixed
220
223
  this.velocity.x *= -this.elasticity;
@@ -244,7 +247,7 @@ class EngineObject
244
247
 
245
248
  // adjust next velocity to settle on ground
246
249
  const o = (oldPos.y - this.size.y/2|0) - (oldPos.y - this.size.y/2);
247
- if (o < 0 && o > -1 && o > this.damping * this.velocity.y + gravity * this.gravityScale)
250
+ if (o < 0 && o > this.damping * this.velocity.y + gravity * this.gravityScale)
248
251
  this.velocity.y = this.damping ? (o - gravity * this.gravityScale) / this.damping : 0;
249
252
 
250
253
  // move to previous position
@@ -154,11 +154,11 @@ class TileLayerData
154
154
  class TileLayer extends EngineObject
155
155
  {
156
156
  /** Create a tile layer object
157
- * @param {Vector2} [position=new Vector2(0,0)] - World space position
158
- * @param {Vector2} [size=objectDefaultSize] - World space size
159
- * @param {Vector2} [tileSize=tileSizeDefault] - Size of tiles in source pixels
160
- * @param {Vector2} [scale=new Vector2(1,1)] - How much to scale this layer when rendered
161
- * @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
157
+ * @param {Vector2} [position=new Vector2()] - World space position
158
+ * @param {Vector2} [size=objectDefaultSize] - World space size
159
+ * @param {Vector2} [tileSize=tileSizeDefault] - Size of tiles in source pixels
160
+ * @param {Vector2} [scale=new Vector2(1,1)] - How much to scale this layer when rendered
161
+ * @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
162
162
  */
163
163
  constructor(pos, size=tileCollisionSize, tileSize=tileSizeDefault, scale=vec2(1), renderOrder=0)
164
164
  {
@@ -218,17 +218,19 @@ class TileLayer extends EngineObject
218
218
  );
219
219
  }
220
220
 
221
- /** Draw all the tile data to an offscreen canvas */
221
+ /** Draw all the tile data to an offscreen canvas
222
+ * - This may be slow in some browsers
223
+ */
222
224
  redraw()
223
225
  {
224
- this.redrawStart();
226
+ this.redrawStart(1);
225
227
  this.drawAllTileData();
226
228
  this.redrawEnd();
227
229
  }
228
230
 
229
231
  /** Call to start the redraw process
230
- * @param {Boolean} [clear=1] - Should it clear the canvas before drawing */
231
- redrawStart(clear = 1)
232
+ * @param {Boolean} [clear=0] - Should it clear the canvas before drawing */
233
+ redrawStart(clear = 0)
232
234
  {
233
235
  if (clear)
234
236
  {
@@ -49,27 +49,27 @@ const mod = (a, b=1)=> ((a % b) + b) % b;
49
49
 
50
50
  /** Clamps the value beween max and min
51
51
  * @param {Number} value
52
- * @param {Number} [max=1]
53
52
  * @param {Number} [min=0]
53
+ * @param {Number} [max=1]
54
54
  * @return {Number}
55
55
  * @memberof Utilities */
56
- const clamp = (v, max=1, min=0)=> (ASSERT(max > min), v < min ? min : v > max ? max : v);
56
+ const clamp = (v, min=0, max=1)=> v < min ? min : v > max ? max : v;
57
57
 
58
58
  /** Returns what percentage the value is between max and min
59
59
  * @param {Number} value
60
- * @param {Number} [max=1]
61
60
  * @param {Number} [min=0]
61
+ * @param {Number} [max=1]
62
62
  * @return {Number}
63
63
  * @memberof Utilities */
64
- const percent = (v, max=1, min=0)=> max-min ? clamp((v-min) / (max-min)) : 0;
64
+ const percent = (v, min=0, max=1)=> max-min ? clamp((v-min) / (max-min)) : 0;
65
65
 
66
66
  /** Linearly interpolates the percent value between max and min
67
67
  * @param {Number} percent
68
- * @param {Number} [max=1]
69
68
  * @param {Number} [min=0]
69
+ * @param {Number} [max=1]
70
70
  * @return {Number}
71
71
  * @memberof Utilities */
72
- const lerp = (p, max=1, min=0)=> min + clamp(p) * (max-min);
72
+ const lerp = (p, min=0, max=1)=> min + clamp(p) * (max-min);
73
73
 
74
74
  /** Applies smoothstep function to the percentage value
75
75
  * @param {Number} value
@@ -84,11 +84,11 @@ const smoothStep = (p)=> p * p * (3 - 2 * p);
84
84
  const nearestPowerOfTwo = (v)=> 2**Math.ceil(Math.log2(v));
85
85
 
86
86
  /** Returns true if two axis aligned bounding boxes are overlapping
87
- * @param {Vector2} pointA - Center of box A
88
- * @param {Vector2} sizeA - Size of box A
89
- * @param {Vector2} pointB - Center of box B
90
- * @param {Vector2} sizeB - Size of box B
91
- * @return {Boolean} - True if overlapping
87
+ * @param {Vector2} pointA - Center of box A
88
+ * @param {Vector2} sizeA - Size of box A
89
+ * @param {Vector2} pointB - Center of box B
90
+ * @param {Vector2} [sizeB] - Size of box B
91
+ * @return {Boolean} - True if overlapping
92
92
  * @memberof Utilities */
93
93
  const isOverlapping = (pA, sA, pB, sB)=> abs(pA.x - pB.x)*2 < sA.x + sB.x & abs(pA.y - pB.y)*2 < sA.y + sB.y;
94
94
 
@@ -477,5 +477,5 @@ class Timer
477
477
 
478
478
  /** Get percentage elapsed based on time it was set to, returns 0 if not set
479
479
  * @return {Number} */
480
- getPercent() { return this.isSet()? percent(this.time - time, 0, this.setTime) : 0; }
480
+ getPercent() { return this.isSet()? percent(this.time - time, this.setTime, 0) : 0; }
481
481
  }
@@ -38,8 +38,8 @@ function glInit()
38
38
 
39
39
  // create the canvas and tile texture
40
40
  glCanvas = document.createElement('canvas');
41
- glContext = glCanvas.getContext('webgl');
42
- glCanvas.style = canvaStyle;
41
+ glContext = glCanvas.getContext('webgl', {antialias: false});
42
+ glCanvas.style = styleCanvas;
43
43
  glTileTexture = glCreateTexture(tileImage);
44
44
 
45
45
  // some browsers are much faster without copying the gl buffer so we just overlay it instead
@@ -49,14 +49,13 @@ function glInit()
49
49
  glShader = glCreateProgram(
50
50
  'precision highp float;'+ // use highp for better accuracy, lowp for better perf
51
51
  'uniform mat4 m;'+ // transform matrix
52
- 'attribute float a;'+ // angle
53
- 'attribute vec2 p,s,t;'+ // position, size, uv
54
- 'attribute vec4 c,b;'+ // color, additiveColor
52
+ 'attribute vec2 p,t;'+ // position, uv
53
+ 'attribute vec4 c,a;'+ // color, additiveColor
55
54
  'varying vec2 v;'+ // return uv
56
55
  'varying vec4 d,e;'+ // return color, additiveColor
57
56
  'void main(){'+ // shader entry point
58
- 'gl_Position=m*vec4((s*cos(a)-vec2(-s.y,s)*sin(a))*.5+p,1,1);'+// transform position
59
- 'v=t;d=c;e=b;'+ // pass stuff to fragment shader
57
+ 'gl_Position=m*vec4(p,1,1);'+// transform position
58
+ 'v=t;d=c;e=a;'+ // pass stuff to fragment shader
60
59
  '}' // end of shader
61
60
  ,
62
61
  'precision highp float;'+ // use highp for better accuracy, lowp for better perf
@@ -83,12 +82,10 @@ function glInit()
83
82
  glContext.vertexAttribPointer(location, size, type, normalize, gl_VERTEX_BYTE_STRIDE, offset);
84
83
  offset += size*typeSize;
85
84
  }
86
- initVertexAttribArray('a', gl_FLOAT, 4, 1); // angle
87
85
  initVertexAttribArray('p', gl_FLOAT, 4, 2); // position
88
- initVertexAttribArray('s', gl_FLOAT, 4, 2); // size
89
86
  initVertexAttribArray('t', gl_FLOAT, 4, 2); // texture coords
90
87
  initVertexAttribArray('c', gl_UNSIGNED_BYTE, 1, 4, 1); // color
91
- initVertexAttribArray('b', gl_UNSIGNED_BYTE, 1, 4, 1); // additiveColor
88
+ initVertexAttribArray('a', gl_UNSIGNED_BYTE, 1, 4, 1); // additiveColor
92
89
  }
93
90
 
94
91
  /** Set the WebGl blend mode, normally you should call setBlendMode instead
@@ -203,6 +200,7 @@ function glPreRender(width, height, cameraX, cameraY, cameraScale)
203
200
 
204
201
  // clear and set to same size as main canvas
205
202
  glContext.viewport(0, 0, glCanvas.width = width, glCanvas.height = height);
203
+ glContext.clear(gl_COLOR_BUFFER_BIT);
206
204
 
207
205
  // set up the shader
208
206
  glContext.bindTexture(gl_TEXTURE_2D, glActiveTexture = glTileTexture);
@@ -249,12 +247,10 @@ function glCopyToContext(context, forceDraw)
249
247
  if (!glEnable || !glBatchCount) return;
250
248
 
251
249
  glFlush();
250
+
251
+ // do not draw in overlay mode because the canvas is visible
252
252
  if (!glOverlay || forceDraw)
253
- {
254
- // do not draw/clear in overlay mode because the canvas is visible
255
253
  context.drawImage(glCanvas, 0, 0);
256
- glContext.clear(gl_COLOR_BUFFER_BIT);
257
- }
258
254
  }
259
255
 
260
256
  /** Add a sprite to the gl draw list, used by all gl draw functions
@@ -277,51 +273,49 @@ function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba=0xffffff
277
273
  // flush if there is no room for more verts or if different blend mode
278
274
  if (glBatchCount == gl_MAX_BATCH || glBatchAdditive != glAdditive)
279
275
  glFlush();
276
+
277
+ // prepare to create the verts from size and angle
278
+ const c = Math.cos(angle)/2, s = Math.sin(angle)/2;
279
+ const cX = c*sizeX, cY = c*sizeY, sX = s*sizeX, sY = s*sizeY;
280
280
 
281
281
  // setup 2 triangles to form a quad
282
282
  let offset = glBatchCount++ * gl_VERTICES_PER_QUAD * gl_INDICIES_PER_VERT;
283
283
 
284
284
  // vertex 0
285
- glPositionData[offset++] = angle;
286
- glPositionData[offset++] = x; glPositionData[offset++] = y;
287
- glPositionData[offset++] = -sizeX; glPositionData[offset++] = -sizeY;
288
- glPositionData[offset++] = uv0X; glPositionData[offset++] = uv1Y;
289
- glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
285
+ glPositionData[offset++] = x - cX - sY;
286
+ glPositionData[offset++] = y - cY + sX;
287
+ glPositionData[offset++] = uv0X; glPositionData[offset++] = uv1Y;
288
+ glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
290
289
 
291
290
  // vertex 1
292
- glPositionData[offset++] = angle;
293
- glPositionData[offset++] = x; glPositionData[offset++] = y;
294
- glPositionData[offset++] = sizeX; glPositionData[offset++] = sizeY;
295
- glPositionData[offset++] = uv1X; glPositionData[offset++] = uv0Y;
296
- glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
291
+ glPositionData[offset++] = x + cX + sY;
292
+ glPositionData[offset++] = y + cY - sX;
293
+ glPositionData[offset++] = uv1X; glPositionData[offset++] = uv0Y;
294
+ glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
297
295
 
298
296
  // vertex 2
299
- glPositionData[offset++] = angle;
300
- glPositionData[offset++] = x; glPositionData[offset++] = y;
301
- glPositionData[offset++] = -sizeX; glPositionData[offset++] = sizeY;
302
- glPositionData[offset++] = uv0X; glPositionData[offset++] = uv0Y;
303
- glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
297
+ glPositionData[offset++] = x - cX + sY;
298
+ glPositionData[offset++] = y + cY + sX;
299
+ glPositionData[offset++] = uv0X; glPositionData[offset++] = uv0Y;
300
+ glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
304
301
 
305
302
  // vertex 0
306
- glPositionData[offset++] = angle;
307
- glPositionData[offset++] = x; glPositionData[offset++] = y;
308
- glPositionData[offset++] = -sizeX; glPositionData[offset++] = -sizeY;
309
- glPositionData[offset++] = uv0X; glPositionData[offset++] = uv1Y;
310
- glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
303
+ glPositionData[offset++] = x - cX - sY;
304
+ glPositionData[offset++] = y - cY + sX;
305
+ glPositionData[offset++] = uv0X; glPositionData[offset++] = uv1Y;
306
+ glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
311
307
 
312
308
  // vertex 3
313
- glPositionData[offset++] = angle;
314
- glPositionData[offset++] = x; glPositionData[offset++] = y;
315
- glPositionData[offset++] = sizeX; glPositionData[offset++] = -sizeY;
316
- glPositionData[offset++] = uv1X; glPositionData[offset++] = uv1Y;
317
- glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
309
+ glPositionData[offset++] = x + cX - sY;
310
+ glPositionData[offset++] = y - cY - sX;
311
+ glPositionData[offset++] = uv1X; glPositionData[offset++] = uv1Y;
312
+ glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
318
313
 
319
314
  // vertex 1
320
- glPositionData[offset++] = angle;
321
- glPositionData[offset++] = x; glPositionData[offset++] = y;
322
- glPositionData[offset++] = sizeX; glPositionData[offset++] = sizeY;
323
- glPositionData[offset++] = uv1X; glPositionData[offset++] = uv0Y;
324
- glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
315
+ glPositionData[offset++] = x + cX + sY;
316
+ glPositionData[offset++] = y + cY - sX;
317
+ glPositionData[offset++] = uv1X; glPositionData[offset++] = uv0Y;
318
+ glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
325
319
  }
326
320
 
327
321
  ///////////////////////////////////////////////////////////////////////////////
@@ -353,6 +347,6 @@ gl_LINK_STATUS = 35714,
353
347
 
354
348
  // constants for batch rendering
355
349
  gl_VERTICES_PER_QUAD = 6,
356
- gl_INDICIES_PER_VERT = 9,
350
+ gl_INDICIES_PER_VERT = 6,
357
351
  gl_MAX_BATCH = 1<<16,
358
- gl_VERTEX_BYTE_STRIDE = 4 + (4 * 2) * 3 + (4) * 2; // float + vec2 * 3 + (char * 4) * 2
352
+ gl_VERTEX_BYTE_STRIDE = (4 * 2) * 2 + (4) * 2; // vec2 * 2 + (char * 4) * 2