littlejsengine 1.14.19 → 1.14.23
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/dist/littlejs.d.ts +118 -18
- package/dist/littlejs.esm.js +506 -199
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +493 -199
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +468 -200
- package/examples/electron/game.js +1 -41
- package/examples/electron/index.html +2 -2
- package/examples/htmlMenu/game.js +1 -1
- package/examples/index.html +12 -6
- package/examples/module/game.js +5 -7
- package/examples/particles/index.html +6 -9
- package/examples/platformer/gameCharacter.js +1 -1
- package/examples/platformer/gameEffects.js +7 -2
- package/examples/platformer/gameObjects.js +3 -3
- package/examples/shorts/animation.js +2 -2
- package/examples/shorts/base.html +4 -1
- package/examples/shorts/cameraDrag.js +22 -0
- package/examples/shorts/debugDraw.js +38 -0
- package/examples/shorts/fps.js +90 -0
- package/examples/shorts/helloWorld.js +1 -1
- package/examples/shorts/hillGlideGame.js +1 -1
- package/examples/shorts/landerGame.js +1 -1
- package/examples/shorts/postProcess.js +1 -1
- package/examples/shorts/sequencer.js +3 -3
- package/examples/shorts/spaceGame.js +1 -1
- package/examples/shorts/spriteAtlas.js +6 -6
- package/examples/shorts/starfield.js +1 -1
- package/examples/shorts/tileRaycast.js +39 -0
- package/examples/shorts/tiles.png +0 -0
- package/examples/shorts/tiltedView.js +1 -1
- package/examples/starter/game.js +5 -7
- package/examples/starter/index.html +2 -2
- package/examples/typescript/game.js +3 -2
- package/examples/typescript/game.ts +5 -7
- package/examples/uiSystem/game.js +2 -2
- package/package.json +1 -1
- package/src/engine.js +3 -3
- package/src/engineAudio.js +13 -13
- package/src/engineDebug.js +27 -0
- package/src/engineDraw.js +68 -20
- package/src/engineExport.js +13 -0
- package/src/engineInput.js +14 -16
- package/src/engineObject.js +31 -6
- package/src/engineParticles.js +36 -15
- package/src/engineRelease.js +2 -1
- package/src/engineSettings.js +20 -1
- package/src/engineTileLayer.js +62 -59
- package/src/engineUtilities.js +206 -58
- package/src/engineWebGL.js +13 -8
- package/examples/shorts/raycasting.js +0 -79
package/src/engineParticles.js
CHANGED
|
@@ -152,6 +152,12 @@ class ParticleEmitter extends EngineObject
|
|
|
152
152
|
this.particleCreateCallback = undefined;
|
|
153
153
|
/** @property {number} - Track particle emit time */
|
|
154
154
|
this.emitTimeBuffer = 0;
|
|
155
|
+
/** @property {number} - Percentage of velocity to pass to particles (0-1) */
|
|
156
|
+
this.velocityInheritance = 0;
|
|
157
|
+
|
|
158
|
+
// track previous position and angle
|
|
159
|
+
this.previousAngle = this.angle;
|
|
160
|
+
this.previousPos = this.pos.copy();
|
|
155
161
|
}
|
|
156
162
|
|
|
157
163
|
/** Update the emitter to spawn particles, called automatically by engine once each frame */
|
|
@@ -160,6 +166,18 @@ class ParticleEmitter extends EngineObject
|
|
|
160
166
|
// only do default update to apply parent transforms
|
|
161
167
|
this.parent && super.update();
|
|
162
168
|
|
|
169
|
+
if (this.velocityInheritance)
|
|
170
|
+
{
|
|
171
|
+
// pass emitter velocity to particles
|
|
172
|
+
const p = this.velocityInheritance;
|
|
173
|
+
this.velocity.x = p * (this.pos.x - this.previousPos.x);
|
|
174
|
+
this.velocity.y = p * (this.pos.y - this.previousPos.y);
|
|
175
|
+
this.angleVelocity = p * (this.angle - this.previousAngle);
|
|
176
|
+
this.previousAngle = this.angle;
|
|
177
|
+
this.previousPos.x = this.pos.x;
|
|
178
|
+
this.previousPos.y = this.pos.y;
|
|
179
|
+
}
|
|
180
|
+
|
|
163
181
|
// update emitter
|
|
164
182
|
if (!this.emitTime || this.getAliveTime() <= this.emitTime)
|
|
165
183
|
{
|
|
@@ -217,7 +235,7 @@ class ParticleEmitter extends EngineObject
|
|
|
217
235
|
const particle = new Particle(pos, this.tileInfo, angle, colorStart, colorEnd, particleTime, sizeStart, sizeEnd, this.fadeRate, this.additive, this.trailScale, this.localSpace && this, this.particleDestroyCallback);
|
|
218
236
|
particle.velocity = vec2().setAngle(velocityAngle, speed);
|
|
219
237
|
particle.angleVelocity = angleSpeed;
|
|
220
|
-
if (!this.localSpace)
|
|
238
|
+
if (!this.localSpace && this.velocityInheritance > 0)
|
|
221
239
|
{
|
|
222
240
|
// apply emitter velocity to particle
|
|
223
241
|
particle.velocity.x += this.velocity.x;
|
|
@@ -315,6 +333,16 @@ class Particle extends EngineObject
|
|
|
315
333
|
this.velocity.y *= s;
|
|
316
334
|
}
|
|
317
335
|
}
|
|
336
|
+
|
|
337
|
+
if (this.lifeTime > 0 && time - this.spawnTime > this.lifeTime)
|
|
338
|
+
{
|
|
339
|
+
// destroy particle when its time runs out
|
|
340
|
+
const c = this.colorEnd;
|
|
341
|
+
this.color.set(c.r, c.g, c.b, c.a);
|
|
342
|
+
this.size.set(this.sizeEnd, this.sizeEnd);
|
|
343
|
+
this.destroyCallback && this.destroyCallback(this);
|
|
344
|
+
this.destroyed = 1;
|
|
345
|
+
}
|
|
318
346
|
}
|
|
319
347
|
|
|
320
348
|
/** Render the particle, automatically called each frame, sorted by renderOrder */
|
|
@@ -323,7 +351,7 @@ class Particle extends EngineObject
|
|
|
323
351
|
// lerp color and size
|
|
324
352
|
const p1 = this.lifeTime > 0 ? min((time - this.spawnTime) / this.lifeTime, 1) : 1, p2 = 1-p1;
|
|
325
353
|
const radius = p2 * this.sizeStart + p1 * this.sizeEnd;
|
|
326
|
-
|
|
354
|
+
const size = vec2(radius);
|
|
327
355
|
this.color.r = p2 * this.colorStart.r + p1 * this.colorEnd.r;
|
|
328
356
|
this.color.g = p2 * this.colorStart.g + p1 * this.colorEnd.g;
|
|
329
357
|
this.color.b = p2 * this.colorStart.b + p1 * this.colorEnd.b;
|
|
@@ -343,7 +371,7 @@ class Particle extends EngineObject
|
|
|
343
371
|
{
|
|
344
372
|
// in local space of emitter
|
|
345
373
|
const a = this.localSpaceEmitter.angle;
|
|
346
|
-
const c =
|
|
374
|
+
const c = cos(a), s = sin(a);
|
|
347
375
|
pos = this.localSpaceEmitter.pos.add(
|
|
348
376
|
new Vector2(pos.x*c - pos.y*s, pos.x*s + pos.y*c));
|
|
349
377
|
angle += this.localSpaceEmitter.angle;
|
|
@@ -359,21 +387,14 @@ class Particle extends EngineObject
|
|
|
359
387
|
{
|
|
360
388
|
// stretch in direction of motion
|
|
361
389
|
const trailLength = speed * this.trailScale;
|
|
362
|
-
|
|
363
|
-
angle =
|
|
364
|
-
drawTile(pos,
|
|
390
|
+
size.y = max(size.x, trailLength);
|
|
391
|
+
angle = atan2(direction.x, direction.y);
|
|
392
|
+
drawTile(pos, size, this.tileInfo, this.color, angle, this.mirror);
|
|
365
393
|
}
|
|
366
394
|
}
|
|
367
395
|
else
|
|
368
|
-
drawTile(pos,
|
|
396
|
+
drawTile(pos, size, this.tileInfo, this.color, angle, this.mirror);
|
|
369
397
|
this.additive && setBlendMode();
|
|
370
|
-
debugParticles && debugRect(pos,
|
|
371
|
-
|
|
372
|
-
if (p1 === 1)
|
|
373
|
-
{
|
|
374
|
-
// destroy particle when its time runs out
|
|
375
|
-
this.destroyCallback && this.destroyCallback(this);
|
|
376
|
-
this.destroyed = 1;
|
|
377
|
-
}
|
|
398
|
+
debugParticles && debugRect(pos, size, '#f005', 0, angle);
|
|
378
399
|
}
|
|
379
400
|
}
|
package/src/engineRelease.js
CHANGED
|
@@ -38,4 +38,5 @@ function debugShowErrors(){}
|
|
|
38
38
|
function debugVideoCaptureIsActive(){ return false; }
|
|
39
39
|
function debugVideoCaptureStart (){}
|
|
40
40
|
function debugVideoCaptureStop (){}
|
|
41
|
-
function debugVideoCaptureUpdate(){}
|
|
41
|
+
function debugVideoCaptureUpdate(){}
|
|
42
|
+
function debugProtectConstant(o){ return o; }
|
package/src/engineSettings.js
CHANGED
|
@@ -216,6 +216,14 @@ let touchInputEnable = true;
|
|
|
216
216
|
* @memberof Settings */
|
|
217
217
|
let touchGamepadEnable = false;
|
|
218
218
|
|
|
219
|
+
/** True if touch gamepad should have start button in the center
|
|
220
|
+
* - When the game is paused, any touch will press the button
|
|
221
|
+
* - This can function as a way to pause/unpause the game
|
|
222
|
+
* @type {boolean}
|
|
223
|
+
* @default
|
|
224
|
+
* @memberof Settings */
|
|
225
|
+
let touchGamepadCenterButton = true;
|
|
226
|
+
|
|
219
227
|
/** True if touch gamepad should be analog stick or false to use if 8 way dpad
|
|
220
228
|
* @type {boolean}
|
|
221
229
|
* @default
|
|
@@ -391,9 +399,14 @@ function setHeadlessMode(headless) { headlessMode = headless; }
|
|
|
391
399
|
* @memberof Settings */
|
|
392
400
|
function setGLEnable(enable)
|
|
393
401
|
{
|
|
402
|
+
if (enable && !glCanBeEnabled)
|
|
403
|
+
{
|
|
404
|
+
console.warn('Can not enable WebGL if it was disabled on start.');
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
394
407
|
glEnable = enable;
|
|
395
408
|
if (glCanvas) // hide glCanvas if WebGL is disabled
|
|
396
|
-
glCanvas.style.
|
|
409
|
+
glCanvas.style.display = enable ? '' : 'none';
|
|
397
410
|
}
|
|
398
411
|
|
|
399
412
|
/** Set how many sided polygons to use when drawing circles and ellipses with WebGL
|
|
@@ -481,6 +494,12 @@ function setTouchInputEnable(enable) { touchInputEnable = enable; }
|
|
|
481
494
|
* @memberof Settings */
|
|
482
495
|
function setTouchGamepadEnable(enable) { touchGamepadEnable = enable; }
|
|
483
496
|
|
|
497
|
+
/** True if touch gamepad should have start button in the center
|
|
498
|
+
* - This can function as a way to pause/unpause the game
|
|
499
|
+
* @param {boolean} enable
|
|
500
|
+
* @memberof Settings */
|
|
501
|
+
function setTouchGamepadCenterButton(enable) { touchGamepadCenterButton = enable; }
|
|
502
|
+
|
|
484
503
|
/** Set if touch gamepad should be analog stick or 8 way dpad
|
|
485
504
|
* @param {boolean} analog
|
|
486
505
|
* @memberof Settings */
|
package/src/engineTileLayer.js
CHANGED
|
@@ -47,23 +47,22 @@ function tileCollisionTest(pos, size=vec2(), object, solidOnly=true)
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
/** Return the
|
|
51
|
-
* This does not return the exact intersection, but the center of the tile hit.
|
|
50
|
+
/** Return the exact position of the boudnary of first tile hit, undefined if nothing was hit.
|
|
52
51
|
* @param {Vector2} posStart
|
|
53
52
|
* @param {Vector2} posEnd
|
|
54
53
|
* @param {EngineObject} [object] - An object or undefined for generic test
|
|
54
|
+
* @param {Vector2} [normal] - Optional normal of the surface hit
|
|
55
55
|
* @param {boolean} [solidOnly=true] - Only check solid layers if true
|
|
56
|
-
* @return {Vector2}
|
|
56
|
+
* @return {Vector2|undefined} - position of the center of the tile hit or undefined if no hit
|
|
57
57
|
* @memberof TileLayers */
|
|
58
|
-
function tileCollisionRaycast(posStart, posEnd, object, solidOnly=true)
|
|
58
|
+
function tileCollisionRaycast(posStart, posEnd, object, normal, solidOnly=true)
|
|
59
59
|
{
|
|
60
60
|
for (const layer of tileCollisionLayers)
|
|
61
61
|
{
|
|
62
62
|
if (!solidOnly || layer.isSolid)
|
|
63
63
|
{
|
|
64
|
-
const hitPos = layer.collisionRaycast(posStart, posEnd, object)
|
|
65
|
-
if (hitPos)
|
|
66
|
-
return hitPos;
|
|
64
|
+
const hitPos = layer.collisionRaycast(posStart, posEnd, object, normal)
|
|
65
|
+
if (hitPos) return hitPos;
|
|
67
66
|
}
|
|
68
67
|
}
|
|
69
68
|
}
|
|
@@ -201,6 +200,8 @@ class CanvasLayer extends EngineObject
|
|
|
201
200
|
/** @property {TextureInfo} - Texture info to use for this object rendering */
|
|
202
201
|
const useWebGL = false; // do not use webgl by default
|
|
203
202
|
this.textureInfo = new TextureInfo(this.canvas, useWebGL);
|
|
203
|
+
/** @property {boolean} - True if WebGL texture needs to be refreshed */
|
|
204
|
+
this.refreshWebGL = false;
|
|
204
205
|
|
|
205
206
|
// disable physics by default
|
|
206
207
|
this.mass = this.gravityScale = this.friction = this.restitution = 0;
|
|
@@ -234,8 +235,15 @@ class CanvasLayer extends EngineObject
|
|
|
234
235
|
* @memberof Draw */
|
|
235
236
|
draw(pos, size, angle=0, color=WHITE, mirror=false, additiveColor, screenSpace=false, context)
|
|
236
237
|
{
|
|
237
|
-
// draw the canvas layer as a single tile that uses the whole texture
|
|
238
238
|
const useWebGL = glEnable && this.textureInfo.hasWebGL();
|
|
239
|
+
if (useWebGL && this.refreshWebGL)
|
|
240
|
+
{
|
|
241
|
+
// update the WebGL texture
|
|
242
|
+
this.textureInfo.createWebGLTexture();
|
|
243
|
+
this.refreshWebGL = false;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// draw the canvas layer as a single tile that uses the whole texture
|
|
239
247
|
const tileInfo = new TileInfo().setFullImage(this.textureInfo);
|
|
240
248
|
drawTile(pos, size, tileInfo, color, angle, mirror, additiveColor, useWebGL, screenSpace, context);
|
|
241
249
|
}
|
|
@@ -305,9 +313,18 @@ class CanvasLayer extends EngineObject
|
|
|
305
313
|
{ this.drawTile(pos, size, undefined, color, angle); }
|
|
306
314
|
|
|
307
315
|
/** Create or update the WebGL texture for this layer
|
|
308
|
-
* @param {boolean} [enable] - enable WebGL rendering and update the texture
|
|
309
|
-
|
|
316
|
+
* @param {boolean} [enable] - enable WebGL rendering and update the texture
|
|
317
|
+
* @param {boolean} [immediate] - shoulkd the texture be updated immediately
|
|
318
|
+
*/
|
|
319
|
+
useWebGL(enable=true, immediate=false)
|
|
310
320
|
{
|
|
321
|
+
if (!immediate && enable && this.textureInfo.hasWebGL())
|
|
322
|
+
{
|
|
323
|
+
// refresh the texture when needed
|
|
324
|
+
this.refreshWebGL = true;
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
|
|
311
328
|
if (enable)
|
|
312
329
|
this.textureInfo.createWebGLTexture();
|
|
313
330
|
else
|
|
@@ -338,7 +355,7 @@ class TileLayer extends CanvasLayer
|
|
|
338
355
|
*/
|
|
339
356
|
constructor(position, size, tileInfo=tile(), renderOrder=0)
|
|
340
357
|
{
|
|
341
|
-
const canvasSize = size.multiply(tileInfo.size);
|
|
358
|
+
const canvasSize = tileInfo ? size.multiply(tileInfo.size) : size;
|
|
342
359
|
super(position, size, 0, renderOrder, canvasSize);
|
|
343
360
|
|
|
344
361
|
// set tile info
|
|
@@ -391,6 +408,13 @@ class TileLayer extends CanvasLayer
|
|
|
391
408
|
{
|
|
392
409
|
ASSERT(drawContext !== this.context, 'must call redrawEnd() after drawing tiles!');
|
|
393
410
|
|
|
411
|
+
if (this.refreshWebGL)
|
|
412
|
+
{
|
|
413
|
+
// update the WebGL texture
|
|
414
|
+
this.textureInfo.createWebGLTexture();
|
|
415
|
+
this.refreshWebGL = false;
|
|
416
|
+
}
|
|
417
|
+
|
|
394
418
|
// draw the tile layer as a single tile
|
|
395
419
|
const tileInfo = new TileInfo().setFullImage(this.textureInfo);
|
|
396
420
|
const size = this.drawSize || this.size;
|
|
@@ -427,8 +451,9 @@ class TileLayer extends CanvasLayer
|
|
|
427
451
|
drawCanvas = this.canvas;
|
|
428
452
|
drawContext = this.context;
|
|
429
453
|
cameraPos = this.size.scale(.5);
|
|
430
|
-
|
|
431
|
-
|
|
454
|
+
const tileSize = this.tileInfo ? this.tileInfo.size : vec2(1);
|
|
455
|
+
cameraScale = tileSize.x;
|
|
456
|
+
mainCanvasSize = this.size.multiply(tileSize);
|
|
432
457
|
if (clear)
|
|
433
458
|
{
|
|
434
459
|
// clear and set size
|
|
@@ -588,65 +613,43 @@ class TileCollisionLayer extends TileLayer
|
|
|
588
613
|
// check if the object should collide with this tile
|
|
589
614
|
const tileData = this.collisionData[y*this.size.x+x];
|
|
590
615
|
if (tileData)
|
|
591
|
-
if (!object || object.collideWithTile(tileData,
|
|
616
|
+
if (!object || object.collideWithTile(tileData,
|
|
617
|
+
hitPos.set(x + this.pos.x, y + this.pos.y)))
|
|
592
618
|
return true;
|
|
593
619
|
}
|
|
594
620
|
return false;
|
|
595
621
|
}
|
|
596
622
|
|
|
597
|
-
/** Return the
|
|
598
|
-
* This does not return the exact intersection, but the center of the tile hit.
|
|
623
|
+
/** Return the exact position of the boudnary of first tile hit, undefined if nothing was hit.
|
|
599
624
|
* @param {Vector2} posStart
|
|
600
625
|
* @param {Vector2} posEnd
|
|
601
|
-
* @param {EngineObject} [object]
|
|
602
|
-
* @
|
|
603
|
-
|
|
626
|
+
* @param {EngineObject} [object] - An object or undefined for generic test
|
|
627
|
+
* @param {Vector2} [normal] - Optional normal of the surface hit
|
|
628
|
+
* @return {Vector2|undefined} */
|
|
629
|
+
collisionRaycast(posStart, posEnd, object, normal)
|
|
604
630
|
{
|
|
605
631
|
ASSERT(isVector2(posStart) && isVector2(posEnd), 'positions must be Vector2s');
|
|
606
632
|
ASSERT(!object || object instanceof EngineObject, 'object must be an EngineObject');
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
const
|
|
610
|
-
const posStartY = posStart.y - this.pos.y;
|
|
611
|
-
const posEndX = posEnd.x - this.pos.x;
|
|
612
|
-
const posEndY = posEnd.y - this.pos.y;
|
|
613
|
-
|
|
614
|
-
// test if a ray collides with tiles from start to end
|
|
615
|
-
const deltaX = posEndX - posStartX;
|
|
616
|
-
const deltaY = posEndY - posStartY;
|
|
617
|
-
const totalLength = (deltaX**2 + deltaY**2)**.5;
|
|
618
|
-
const unitX = abs(totalLength/deltaX);
|
|
619
|
-
const unitY = abs(totalLength/deltaY);
|
|
620
|
-
|
|
621
|
-
// setup iteration variables
|
|
622
|
-
const pos = posStart.floor(), signDeltaX = sign(deltaX), signDeltaY = sign(deltaY);
|
|
623
|
-
let xi = unitX * (deltaX < 0 ? posStart.x - pos.x : pos.x - posStart.x + 1) || 0;
|
|
624
|
-
let yi = unitY * (deltaY < 0 ? posStart.y - pos.y : pos.y - posStart.y + 1) || 0;
|
|
625
|
-
|
|
626
|
-
// use line drawing algorithm to test for collisions
|
|
627
|
-
while (true)
|
|
633
|
+
|
|
634
|
+
const localPos = new Vector2;
|
|
635
|
+
const collisionTest = (pos)=>
|
|
628
636
|
{
|
|
629
637
|
// check for tile collision
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
pos.x += .5; pos.y += .5;
|
|
634
|
-
debugRaycast && debugLine(posStart, posEnd, '#f00', .02);
|
|
635
|
-
debugRaycast && debugPoint(pos, '#ff0');
|
|
636
|
-
return pos;
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
// check if past the end
|
|
640
|
-
if (xi >= totalLength && yi >= totalLength)
|
|
641
|
-
break;
|
|
642
|
-
|
|
643
|
-
// get coordinates of next tile to check
|
|
644
|
-
if (xi > yi)
|
|
645
|
-
pos.y += signDeltaY, yi += unitY;
|
|
646
|
-
else
|
|
647
|
-
pos.x += signDeltaX, xi += unitX;
|
|
638
|
+
localPos.set(pos.x - this.pos.x, pos.y - this.pos.y);
|
|
639
|
+
const tileData = this.getCollisionData(localPos);
|
|
640
|
+
return tileData && (!object || object.collideWithTile(tileData, pos));
|
|
648
641
|
}
|
|
649
|
-
|
|
650
642
|
debugRaycast && debugLine(posStart, posEnd, '#00f', .02);
|
|
643
|
+
const hitPos = lineTest(posStart, posEnd, collisionTest, normal);
|
|
644
|
+
if (hitPos)
|
|
645
|
+
{
|
|
646
|
+
const tilePos = hitPos.floor().add(vec2(.5));
|
|
647
|
+
debugRaycast && debugRect(tilePos, vec2(1), '#f008');
|
|
648
|
+
debugRaycast && debugLine(posStart, hitPos, '#f00', .02);
|
|
649
|
+
debugRaycast && debugPoint(hitPos, '#0f0');
|
|
650
|
+
debugRaycast && normal &&
|
|
651
|
+
debugLine(hitPos, hitPos.add(normal), '#ff0', .02);
|
|
652
|
+
return hitPos;
|
|
653
|
+
}
|
|
651
654
|
}
|
|
652
655
|
}
|