littlejsengine 1.14.10 → 1.14.16
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 +264 -120
- package/dist/littlejs.esm.js +603 -288
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +600 -287
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +521 -232
- package/examples/box2d/gameObjects.js +2 -2
- package/examples/breakout/gameObjects.js +2 -2
- package/examples/breakoutTutorial/README.md +32 -32
- package/examples/breakoutTutorial/game.js +1 -1
- package/examples/electron/game.js +3 -3
- package/examples/electron/index.html +2 -2
- package/examples/electron/package.json +1 -8
- package/examples/index.html +59 -51
- package/examples/module/game.js +3 -3
- package/examples/platformer/gameCharacter.js +6 -2
- package/examples/platformer/gameEffects.js +4 -4
- package/examples/platformer/gameLevel.js +1 -1
- package/examples/platformer/gameObjects.js +11 -9
- package/examples/puzzle/game.js +1 -1
- package/examples/shorts/animation.js +1 -1
- package/examples/shorts/base.html +1 -1
- package/examples/shorts/blending.js +8 -14
- package/examples/shorts/box2d.js +7 -3
- package/examples/shorts/box2dCar.js +2 -1
- package/examples/shorts/empty.js +30 -0
- package/examples/shorts/helloWorld.js +1 -1
- package/examples/shorts/hillGlideGame.js +10 -4
- package/examples/shorts/landerGame.js +30 -3
- package/examples/shorts/medals.js +4 -4
- package/examples/shorts/music.js +29 -55
- package/examples/shorts/musicPlayer.js +134 -0
- package/examples/shorts/nineSlice.js +34 -15
- package/examples/shorts/parallax.js +4 -3
- package/examples/shorts/particles.js +16 -16
- package/examples/shorts/piano.js +15 -21
- package/examples/shorts/pongGame.js +6 -4
- package/examples/shorts/raycasting.js +13 -5
- package/examples/shorts/sequencer.js +122 -0
- package/examples/shorts/shapes.js +7 -4
- package/examples/shorts/slidingPuzzle.js +16 -6
- package/examples/shorts/sound.js +18 -9
- package/examples/shorts/spaceGame.js +12 -8
- package/examples/shorts/spriteAtlas.js +7 -7
- package/examples/shorts/starfield.js +1 -1
- package/examples/shorts/systemFont.js +2 -2
- package/examples/shorts/texture.js +2 -2
- package/examples/shorts/tileLayer.js +10 -10
- package/examples/shorts/tiltedView.js +14 -3
- package/examples/shorts/timers.js +10 -0
- package/examples/shorts/topDown.js +4 -1
- package/examples/shorts/uiSystem.js +8 -5
- package/examples/starter/game.js +3 -3
- package/examples/starter/index.html +2 -2
- package/examples/typescript/game.js +3 -3
- package/examples/typescript/game.ts +3 -3
- package/examples/uiSystem/game.js +6 -6
- package/package.json +4 -2
- package/plugins/box2d.js +18 -3
- package/plugins/newgrounds.js +11 -9
- package/plugins/postProcess.js +5 -2
- package/plugins/uiSystem.js +120 -34
- package/plugins/zzfxm.js +5 -1
- package/reference.md +1 -3
- package/src/engine.js +52 -21
- package/src/engineAudio.js +31 -14
- package/src/engineDebug.js +80 -55
- package/src/engineDraw.js +60 -31
- package/src/engineExport.js +3 -1
- package/src/engineMedals.js +10 -2
- package/src/engineObject.js +14 -10
- package/src/engineParticles.js +59 -46
- package/src/engineRelease.js +1 -0
- package/src/engineSettings.js +7 -7
- package/src/engineTileLayer.js +49 -18
- package/src/engineUtilities.js +79 -34
package/src/engineObject.js
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
* - Collision for objects can be set to be solid to block other objects
|
|
25
25
|
* - Objects may get pushed into overlapping other solid objects, if so they will push away
|
|
26
26
|
* - Solid objects are more performance intensive and should be used sparingly
|
|
27
|
+
* @memberof Engine
|
|
27
28
|
* @example
|
|
28
29
|
* // create an engine object, normally you would first extend the class with your own
|
|
29
30
|
* const pos = vec2(2,3);
|
|
@@ -32,18 +33,18 @@
|
|
|
32
33
|
class EngineObject
|
|
33
34
|
{
|
|
34
35
|
/** Create an engine object and adds it to the list of objects
|
|
35
|
-
* @param {Vector2} [pos=(0,0)]
|
|
36
|
-
* @param {Vector2} [size=(1,1)]
|
|
37
|
-
* @param {TileInfo} [tileInfo]
|
|
38
|
-
* @param {number} [angle]
|
|
39
|
-
* @param {Color} [color=
|
|
40
|
-
* @param {number} [renderOrder]
|
|
36
|
+
* @param {Vector2} [pos=(0,0)] - World space position of the object
|
|
37
|
+
* @param {Vector2} [size=(1,1)] - World space size of the object
|
|
38
|
+
* @param {TileInfo} [tileInfo] - Tile info to render object (undefined is untextured)
|
|
39
|
+
* @param {number} [angle] - Angle the object is rotated by
|
|
40
|
+
* @param {Color} [color=WHITE] - Color to apply to tile when rendered
|
|
41
|
+
* @param {number} [renderOrder] - Objects sorted by renderOrder before being rendered
|
|
41
42
|
*/
|
|
42
|
-
constructor(pos=vec2(), size=vec2(1), tileInfo, angle=0, color=
|
|
43
|
+
constructor(pos=vec2(), size=vec2(1), tileInfo, angle=0, color=WHITE, renderOrder=0)
|
|
43
44
|
{
|
|
44
45
|
// check passed in params
|
|
45
|
-
ASSERT(isVector2(pos), 'object pos
|
|
46
|
-
ASSERT(isVector2(size), 'object size
|
|
46
|
+
ASSERT(isVector2(pos), 'object pos must be a vec2');
|
|
47
|
+
ASSERT(isVector2(size), 'object size must be a vec2');
|
|
47
48
|
ASSERT(!tileInfo || tileInfo instanceof TileInfo, 'object tileInfo should be a TileInfo or undefined');
|
|
48
49
|
ASSERT(typeof angle === 'number' && isFinite(angle), 'object angle should be a number');
|
|
49
50
|
ASSERT(isColor(color), 'object color should be a valid rgba color');
|
|
@@ -328,7 +329,7 @@ class EngineObject
|
|
|
328
329
|
drawTile(this.pos, this.drawSize || this.size, this.tileInfo, this.color, this.angle, this.mirror, this.additiveColor);
|
|
329
330
|
}
|
|
330
331
|
|
|
331
|
-
/** Destroy this object, destroy its children, detach
|
|
332
|
+
/** Destroy this object, destroy its children, detach its parent, and mark it for removal */
|
|
332
333
|
destroy()
|
|
333
334
|
{
|
|
334
335
|
if (this.destroyed)
|
|
@@ -402,6 +403,8 @@ class EngineObject
|
|
|
402
403
|
addChild(child, localPos=vec2(), localAngle=0)
|
|
403
404
|
{
|
|
404
405
|
ASSERT(!child.parent && !this.children.includes(child));
|
|
406
|
+
ASSERT(child instanceof EngineObject, 'child must be an EngineObject');
|
|
407
|
+
ASSERT(child !== this, 'cannot add self as child');
|
|
405
408
|
this.children.push(child);
|
|
406
409
|
child.parent = this;
|
|
407
410
|
child.localPos = localPos.copy();
|
|
@@ -413,6 +416,7 @@ class EngineObject
|
|
|
413
416
|
removeChild(child)
|
|
414
417
|
{
|
|
415
418
|
ASSERT(child.parent === this && this.children.includes(child));
|
|
419
|
+
ASSERT(child instanceof EngineObject, 'child must be an EngineObject');
|
|
416
420
|
this.children.splice(this.children.indexOf(child), 1);
|
|
417
421
|
child.parent = 0;
|
|
418
422
|
}
|
package/src/engineParticles.js
CHANGED
|
@@ -4,9 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
'use strict';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* @callback ParticleCallbackFunction - Function that processes a particle
|
|
9
|
+
* @param {Particle} particle
|
|
10
|
+
* @memberof Engine
|
|
11
|
+
*/
|
|
12
|
+
|
|
7
13
|
/**
|
|
8
14
|
* Particle Emitter - Spawns particles with the given settings
|
|
9
15
|
* @extends EngineObject
|
|
16
|
+
* @memberof Engine
|
|
10
17
|
* @example
|
|
11
18
|
* // create a particle emitter
|
|
12
19
|
* let pos = vec2(2,3);
|
|
@@ -31,10 +38,10 @@ class ParticleEmitter extends EngineObject
|
|
|
31
38
|
* @param {number} [emitRate] - How many particles per second to spawn, does not emit if 0
|
|
32
39
|
* @param {number} [emitConeAngle=PI] - Local angle to apply velocity to particles from emitter
|
|
33
40
|
* @param {TileInfo} [tileInfo] - Tile info to render particles (undefined is untextured)
|
|
34
|
-
* @param {Color} [colorStartA=
|
|
35
|
-
* @param {Color} [colorStartB=
|
|
36
|
-
* @param {Color} [colorEndA=
|
|
37
|
-
* @param {Color} [colorEndB=
|
|
41
|
+
* @param {Color} [colorStartA=WHITE] - Color at start of life 1, randomized between start colors
|
|
42
|
+
* @param {Color} [colorStartB=WHITE] - Color at start of life 2, randomized between start colors
|
|
43
|
+
* @param {Color} [colorEndA=CLEAR_WHITE] - Color at end of life 1, randomized between end colors
|
|
44
|
+
* @param {Color} [colorEndB=CLEAR_WHITE] - Color at end of life 2, randomized between end colors
|
|
38
45
|
* @param {number} [particleTime] - How long particles live
|
|
39
46
|
* @param {number} [sizeStart] - How big are particles at start
|
|
40
47
|
* @param {number} [sizeEnd] - How big are particles at end
|
|
@@ -61,10 +68,10 @@ class ParticleEmitter extends EngineObject
|
|
|
61
68
|
emitRate = 100,
|
|
62
69
|
emitConeAngle = PI,
|
|
63
70
|
tileInfo,
|
|
64
|
-
colorStartA =
|
|
65
|
-
colorStartB =
|
|
66
|
-
colorEndA =
|
|
67
|
-
colorEndB =
|
|
71
|
+
colorStartA = WHITE,
|
|
72
|
+
colorStartB = WHITE,
|
|
73
|
+
colorEndA = CLEAR_WHITE,
|
|
74
|
+
colorEndB = CLEAR_WHITE,
|
|
68
75
|
particleTime = .5,
|
|
69
76
|
sizeStart = .1,
|
|
70
77
|
sizeEnd = 1,
|
|
@@ -87,7 +94,8 @@ class ParticleEmitter extends EngineObject
|
|
|
87
94
|
|
|
88
95
|
// emitter settings
|
|
89
96
|
/** @property {number|Vector2} - World space size of the emitter (float for circle diameter, vec2 for rect) */
|
|
90
|
-
this.emitSize = emitSize
|
|
97
|
+
this.emitSize = emitSize instanceof Vector2 ?
|
|
98
|
+
emitSize.copy() : emitSize;
|
|
91
99
|
/** @property {number} - How long to stay alive (0 is forever) */
|
|
92
100
|
this.emitTime = emitTime;
|
|
93
101
|
/** @property {number} - How many particles per second to spawn, does not emit if 0 */
|
|
@@ -97,13 +105,13 @@ class ParticleEmitter extends EngineObject
|
|
|
97
105
|
|
|
98
106
|
// color settings
|
|
99
107
|
/** @property {Color} - Color at start of life 1, randomized between start colors */
|
|
100
|
-
this.colorStartA = colorStartA;
|
|
108
|
+
this.colorStartA = colorStartA.copy();
|
|
101
109
|
/** @property {Color} - Color at start of life 2, randomized between start colors */
|
|
102
|
-
this.colorStartB = colorStartB;
|
|
110
|
+
this.colorStartB = colorStartB.copy();
|
|
103
111
|
/** @property {Color} - Color at end of life 1, randomized between end colors */
|
|
104
|
-
this.colorEndA = colorEndA;
|
|
112
|
+
this.colorEndA = colorEndA.copy();
|
|
105
113
|
/** @property {Color} - Color at end of life 2, randomized between end colors */
|
|
106
|
-
this.colorEndB = colorEndB;
|
|
114
|
+
this.colorEndB = colorEndB.copy();
|
|
107
115
|
/** @property {boolean} - Should color be randomized linearly or across each component */
|
|
108
116
|
this.randomColorLinear = randomColorLinear;
|
|
109
117
|
|
|
@@ -138,9 +146,9 @@ class ParticleEmitter extends EngineObject
|
|
|
138
146
|
this.localSpace = localSpace;
|
|
139
147
|
/** @property {number} - If non zero the particle is drawn as a trail, stretched in the direction of velocity */
|
|
140
148
|
this.trailScale = 0;
|
|
141
|
-
/** @property {
|
|
149
|
+
/** @property {ParticleCallbackFunction} - Callback when particle is destroyed */
|
|
142
150
|
this.particleDestroyCallback = undefined;
|
|
143
|
-
/** @property {
|
|
151
|
+
/** @property {ParticleCallbackFunction} - Callback when particle is created */
|
|
144
152
|
this.particleCreateCallback = undefined;
|
|
145
153
|
/** @property {number} - Track particle emit time */
|
|
146
154
|
this.emitTimeBuffer = 0;
|
|
@@ -241,6 +249,7 @@ class ParticleEmitter extends EngineObject
|
|
|
241
249
|
/**
|
|
242
250
|
* Particle Object - Created automatically by Particle Emitters
|
|
243
251
|
* @extends EngineObject
|
|
252
|
+
* @memberof Engine
|
|
244
253
|
*/
|
|
245
254
|
class Particle extends EngineObject
|
|
246
255
|
{
|
|
@@ -259,7 +268,7 @@ class Particle extends EngineObject
|
|
|
259
268
|
* @param {boolean} additive - Does it use additive blend mode
|
|
260
269
|
* @param {number} trailScale - If a trail, how long to make it
|
|
261
270
|
* @param {ParticleEmitter} [localSpaceEmitter] - Parent emitter if local space
|
|
262
|
-
* @param {
|
|
271
|
+
* @param {ParticleCallbackFunction} [destroyCallback] - Callback when particle dies
|
|
263
272
|
*/
|
|
264
273
|
constructor(position, tileInfo, angle, colorStart, colorEnd, lifeTime, sizeStart, sizeEnd, fadeRate, additive, trailScale, localSpaceEmitter, destroyCallback
|
|
265
274
|
)
|
|
@@ -268,14 +277,14 @@ class Particle extends EngineObject
|
|
|
268
277
|
|
|
269
278
|
/** @property {Color} - Color at start of life */
|
|
270
279
|
this.colorStart = colorStart;
|
|
271
|
-
/** @property {Color} -
|
|
272
|
-
this.
|
|
280
|
+
/** @property {Color} - Color at end of life */
|
|
281
|
+
this.colorEnd = colorEnd;
|
|
273
282
|
/** @property {number} - How long to live for */
|
|
274
283
|
this.lifeTime = lifeTime;
|
|
275
284
|
/** @property {number} - Size at start of life */
|
|
276
285
|
this.sizeStart = sizeStart;
|
|
277
|
-
/** @property {number} -
|
|
278
|
-
this.
|
|
286
|
+
/** @property {number} - Size at end of life */
|
|
287
|
+
this.sizeEnd = sizeEnd;
|
|
279
288
|
/** @property {number} - How quick to fade in/out */
|
|
280
289
|
this.fadeRate = fadeRate;
|
|
281
290
|
/** @property {boolean} - Is it additive */
|
|
@@ -284,7 +293,7 @@ class Particle extends EngineObject
|
|
|
284
293
|
this.trailScale = trailScale;
|
|
285
294
|
/** @property {ParticleEmitter} - Parent emitter if local space */
|
|
286
295
|
this.localSpaceEmitter = localSpaceEmitter;
|
|
287
|
-
/** @property {
|
|
296
|
+
/** @property {ParticleCallbackFunction} - Called when particle dies */
|
|
288
297
|
this.destroyCallback = destroyCallback;
|
|
289
298
|
// particles do not clamp speed by default
|
|
290
299
|
this.clampSpeed = false;
|
|
@@ -311,54 +320,58 @@ class Particle extends EngineObject
|
|
|
311
320
|
/** Render the particle, automatically called each frame, sorted by renderOrder */
|
|
312
321
|
render()
|
|
313
322
|
{
|
|
314
|
-
//
|
|
315
|
-
const
|
|
316
|
-
const radius = this.sizeStart +
|
|
317
|
-
|
|
323
|
+
// lerp color and size
|
|
324
|
+
const p1 = this.lifeTime > 0 ? min((time - this.spawnTime) / this.lifeTime, 1) : 1, p2 = 1-p1;
|
|
325
|
+
const radius = p2 * this.sizeStart + p1 * this.sizeEnd;
|
|
326
|
+
this.size.x = this.size.y = radius;
|
|
327
|
+
this.color.r = p2 * this.colorStart.r + p1 * this.colorEnd.r;
|
|
328
|
+
this.color.g = p2 * this.colorStart.g + p1 * this.colorEnd.g;
|
|
329
|
+
this.color.b = p2 * this.colorStart.b + p1 * this.colorEnd.b;
|
|
330
|
+
this.color.a = p2 * this.colorStart.a + p1 * this.colorEnd.a;
|
|
331
|
+
|
|
332
|
+
// fade alpha
|
|
318
333
|
const fadeRate = this.fadeRate/2;
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
this.colorStart.g + p * this.colorEndDelta.g,
|
|
322
|
-
this.colorStart.b + p * this.colorEndDelta.b,
|
|
323
|
-
(this.colorStart.a + p * this.colorEndDelta.a) *
|
|
324
|
-
(p < fadeRate ? p/fadeRate : p > 1-fadeRate ? (1-p)/fadeRate : 1)); // fade alpha
|
|
334
|
+
this.color.a *= p1 < fadeRate ? p1/fadeRate :
|
|
335
|
+
p1 > 1-fadeRate ? (1-p1)/fadeRate : 1;
|
|
325
336
|
|
|
326
337
|
// draw the particle
|
|
327
338
|
this.additive && setBlendMode(true);
|
|
328
339
|
|
|
340
|
+
// update the position and angle for drawing
|
|
329
341
|
let pos = this.pos, angle = this.angle;
|
|
330
342
|
if (this.localSpaceEmitter)
|
|
331
343
|
{
|
|
332
344
|
// in local space of emitter
|
|
333
|
-
|
|
345
|
+
const a = this.localSpaceEmitter.angle;
|
|
346
|
+
const c = Math.cos(a), s = Math.sin(a);
|
|
347
|
+
pos = this.localSpaceEmitter.pos.add(
|
|
348
|
+
new Vector2(pos.x*c - pos.y*s, pos.x*s + pos.y*c));
|
|
334
349
|
angle += this.localSpaceEmitter.angle;
|
|
335
350
|
}
|
|
336
351
|
if (this.trailScale)
|
|
337
352
|
{
|
|
338
353
|
// trail style particles
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
const speed =
|
|
354
|
+
const direction = this.localSpaceEmitter ?
|
|
355
|
+
this.velocity.rotate(-this.localSpaceEmitter.angle) :
|
|
356
|
+
this.velocity;
|
|
357
|
+
const speed = direction.length();
|
|
343
358
|
if (speed)
|
|
344
359
|
{
|
|
345
|
-
|
|
360
|
+
// stretch in direction of motion
|
|
346
361
|
const trailLength = speed * this.trailScale;
|
|
347
|
-
size.y = max(size.x, trailLength);
|
|
348
|
-
angle = direction.
|
|
349
|
-
drawTile(pos
|
|
362
|
+
this.size.y = max(this.size.x, trailLength);
|
|
363
|
+
angle = Math.atan2(direction.x, direction.y);
|
|
364
|
+
drawTile(pos, this.size, this.tileInfo, this.color, angle, this.mirror);
|
|
350
365
|
}
|
|
351
366
|
}
|
|
352
367
|
else
|
|
353
|
-
drawTile(pos, size, this.tileInfo, color, angle, this.mirror);
|
|
368
|
+
drawTile(pos, this.size, this.tileInfo, this.color, angle, this.mirror);
|
|
354
369
|
this.additive && setBlendMode();
|
|
355
|
-
debugParticles && debugRect(pos, size, '#f005', 0, angle);
|
|
370
|
+
debugParticles && debugRect(pos, this.size, '#f005', 0, angle);
|
|
356
371
|
|
|
357
|
-
if (
|
|
372
|
+
if (p1 === 1)
|
|
358
373
|
{
|
|
359
|
-
// destroy particle when
|
|
360
|
-
this.color = color;
|
|
361
|
-
this.size = size;
|
|
374
|
+
// destroy particle when its time runs out
|
|
362
375
|
this.destroyCallback && this.destroyCallback(this);
|
|
363
376
|
this.destroyed = 1;
|
|
364
377
|
}
|
package/src/engineRelease.js
CHANGED
package/src/engineSettings.js
CHANGED
|
@@ -306,7 +306,7 @@ let medalsPreventUnlock = false;
|
|
|
306
306
|
/** Set position of camera in world space
|
|
307
307
|
* @param {Vector2} pos
|
|
308
308
|
* @memberof Settings */
|
|
309
|
-
function setCameraPos(pos) { cameraPos = pos; }
|
|
309
|
+
function setCameraPos(pos) { cameraPos = pos.copy(); }
|
|
310
310
|
|
|
311
311
|
/** Set angle of camera in world space
|
|
312
312
|
* @param {number} angle
|
|
@@ -329,17 +329,17 @@ function setCanvasColorTiles(colorTiles) { canvasColorTiles = colorTiles; }
|
|
|
329
329
|
/** Set color to clear the canvas to before render
|
|
330
330
|
* @param {Color} color
|
|
331
331
|
* @memberof Settings */
|
|
332
|
-
function setCanvasClearColor(color) { canvasClearColor = color; }
|
|
332
|
+
function setCanvasClearColor(color) { canvasClearColor = color.copy(); }
|
|
333
333
|
|
|
334
334
|
/** Set max size of the canvas
|
|
335
335
|
* @param {Vector2} size
|
|
336
336
|
* @memberof Settings */
|
|
337
|
-
function setCanvasMaxSize(size) { canvasMaxSize = size; }
|
|
337
|
+
function setCanvasMaxSize(size) { canvasMaxSize = size.copy(); }
|
|
338
338
|
|
|
339
339
|
/** Set fixed size of the canvas
|
|
340
340
|
* @param {Vector2} size
|
|
341
341
|
* @memberof Settings */
|
|
342
|
-
function setCanvasFixedSize(size) { canvasFixedSize = size; }
|
|
342
|
+
function setCanvasFixedSize(size) { canvasFixedSize = size.copy(); }
|
|
343
343
|
|
|
344
344
|
/** Use nearest scaling algorithm for canvas for more pixelated look
|
|
345
345
|
* - If enabled sets css image-rendering:pixelated
|
|
@@ -404,7 +404,7 @@ function setGLCircleSides(sides) { glCircleSides = sides; }
|
|
|
404
404
|
/** Set default size of tiles in pixels
|
|
405
405
|
* @param {Vector2} size
|
|
406
406
|
* @memberof Settings */
|
|
407
|
-
function setTileSizeDefault(size) { tileSizeDefault = size; }
|
|
407
|
+
function setTileSizeDefault(size) { tileSizeDefault = size.copy(); }
|
|
408
408
|
|
|
409
409
|
/** Set to prevent tile bleeding from neighbors in pixels
|
|
410
410
|
* @param {number} scale
|
|
@@ -449,7 +449,7 @@ function setObjectMaxSpeed(speed) { objectMaxSpeed = speed; }
|
|
|
449
449
|
/** Set how much gravity to apply to objects
|
|
450
450
|
* @param {Vector2} newGravity
|
|
451
451
|
* @memberof Settings */
|
|
452
|
-
function setGravity(newGravity) { gravity = newGravity; }
|
|
452
|
+
function setGravity(newGravity) { gravity = newGravity.copy(); }
|
|
453
453
|
|
|
454
454
|
/** Set to scales emit rate of particles
|
|
455
455
|
* @param {number} scale
|
|
@@ -539,7 +539,7 @@ function setMedalDisplaySlideTime(time) { medalDisplaySlideTime = time; }
|
|
|
539
539
|
/** Set size of medal display
|
|
540
540
|
* @param {Vector2} size
|
|
541
541
|
* @memberof Settings */
|
|
542
|
-
function setMedalDisplaySize(size) { medalDisplaySize = size; }
|
|
542
|
+
function setMedalDisplaySize(size) { medalDisplaySize = size.copy(); }
|
|
543
543
|
|
|
544
544
|
/** Set to stop medals from being unlockable
|
|
545
545
|
* @param {boolean} preventUnlock
|
package/src/engineTileLayer.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* - Unlimited numbers of layers, allocates canvases as needed
|
|
5
5
|
* - Tile layers can be drawn to using their context with canvas2d
|
|
6
6
|
* - Tile layers can also have collision with EngineObjects
|
|
7
|
-
* @namespace
|
|
7
|
+
* @namespace TileLayers
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -14,13 +14,13 @@
|
|
|
14
14
|
|
|
15
15
|
/** Keep track of all tile layers with collision
|
|
16
16
|
* @type {Array<TileCollisionLayer>}
|
|
17
|
-
* @memberof
|
|
17
|
+
* @memberof TileLayers */
|
|
18
18
|
const tileCollisionLayers = [];
|
|
19
19
|
|
|
20
20
|
/** Get tile collision data for a given cell in the grid
|
|
21
21
|
* @param {Vector2} pos
|
|
22
22
|
* @return {number}
|
|
23
|
-
* @memberof
|
|
23
|
+
* @memberof TileLayers */
|
|
24
24
|
function tileCollisionGetData(pos)
|
|
25
25
|
{
|
|
26
26
|
// check all tile collision layers
|
|
@@ -36,7 +36,7 @@ function tileCollisionGetData(pos)
|
|
|
36
36
|
* @param {EngineObject} [object] - An object or undefined for generic test
|
|
37
37
|
* @param {boolean} [solidOnly] - Only check solid layers if true
|
|
38
38
|
* @return {TileCollisionLayer}
|
|
39
|
-
* @memberof
|
|
39
|
+
* @memberof TileLayers */
|
|
40
40
|
function tileCollisionTest(pos, size=vec2(), object, solidOnly=true)
|
|
41
41
|
{
|
|
42
42
|
for (const layer of tileCollisionLayers)
|
|
@@ -54,7 +54,7 @@ function tileCollisionTest(pos, size=vec2(), object, solidOnly=true)
|
|
|
54
54
|
* @param {EngineObject} [object] - An object or undefined for generic test
|
|
55
55
|
* @param {boolean} [solidOnly=true] - Only check solid layers if true
|
|
56
56
|
* @return {Vector2}
|
|
57
|
-
* @memberof
|
|
57
|
+
* @memberof TileLayers */
|
|
58
58
|
function tileCollisionRaycast(posStart, posEnd, object, solidOnly=true)
|
|
59
59
|
{
|
|
60
60
|
for (const layer of tileCollisionLayers)
|
|
@@ -77,8 +77,8 @@ function tileCollisionRaycast(posStart, posEnd, object, solidOnly=true)
|
|
|
77
77
|
* @param {number} [collisionLayer] - Layer to use for collision if any
|
|
78
78
|
* @param {boolean} [draw] - Should the layer be drawn automatically
|
|
79
79
|
* @return {Array<TileCollisionLayer>}
|
|
80
|
-
* @memberof
|
|
81
|
-
function
|
|
80
|
+
* @memberof TileLayers */
|
|
81
|
+
function tileLayersLoad(tileMapData, tileInfo=tile(), renderOrder=0, collisionLayer, draw=true)
|
|
82
82
|
{
|
|
83
83
|
if (!tileMapData)
|
|
84
84
|
{
|
|
@@ -108,6 +108,12 @@ function tileCollisionLoad(tileMapData, tileInfo=tile(), renderOrder=0, collisio
|
|
|
108
108
|
const tileLayer = new TileCollisionLayer(vec2(), levelSize, tileInfo, layerRenderOrder);
|
|
109
109
|
tileLayers[layerIndex] = tileLayer;
|
|
110
110
|
|
|
111
|
+
// apply layer color
|
|
112
|
+
const layerColor = dataLayer.tintcolor ?
|
|
113
|
+
new Color().setHex(dataLayer.tintcolor) :
|
|
114
|
+
dataLayer.color || WHITE;
|
|
115
|
+
ASSERT(isColor(layerColor), 'layer color is not a color');
|
|
116
|
+
|
|
111
117
|
for (let x=levelSize.x; x--;)
|
|
112
118
|
for (let y=levelSize.y; y--;)
|
|
113
119
|
{
|
|
@@ -115,7 +121,7 @@ function tileCollisionLoad(tileMapData, tileInfo=tile(), renderOrder=0, collisio
|
|
|
115
121
|
const data = dataLayer.data[x + y*levelSize.x];
|
|
116
122
|
if (data)
|
|
117
123
|
{
|
|
118
|
-
const layerData = new TileLayerData(data-1);
|
|
124
|
+
const layerData = new TileLayerData(data-1, 0, false, layerColor);
|
|
119
125
|
tileLayer.setData(pos, layerData);
|
|
120
126
|
|
|
121
127
|
// set collision for top layer
|
|
@@ -132,6 +138,7 @@ function tileCollisionLoad(tileMapData, tileInfo=tile(), renderOrder=0, collisio
|
|
|
132
138
|
///////////////////////////////////////////////////////////////////////////////
|
|
133
139
|
/**
|
|
134
140
|
* Tile layer data object stores info about how to draw a tile
|
|
141
|
+
* @memberof TileLayers
|
|
135
142
|
* @example
|
|
136
143
|
* // create tile layer data with tile index 0 and random orientation and color
|
|
137
144
|
* const tileIndex = 0;
|
|
@@ -169,6 +176,7 @@ class TileLayerData
|
|
|
169
176
|
* - Contains an offscreen canvas that can be rendered to
|
|
170
177
|
* - WebGL rendering is optional, call useWebGL to enable
|
|
171
178
|
* @extends EngineObject
|
|
179
|
+
* @memberof TileLayers
|
|
172
180
|
* @example
|
|
173
181
|
* const canvasLayer = new CanvasLayer(vec2(), vec2(200,100));
|
|
174
182
|
*/
|
|
@@ -183,6 +191,7 @@ class CanvasLayer extends EngineObject
|
|
|
183
191
|
*/
|
|
184
192
|
constructor(position, size, angle=0, renderOrder=0, canvasSize=vec2(512))
|
|
185
193
|
{
|
|
194
|
+
ASSERT(isVector2(canvasSize), 'canvasSize must be a Vector2');
|
|
186
195
|
super(position, size, undefined, angle, WHITE, renderOrder);
|
|
187
196
|
|
|
188
197
|
/** @property {HTMLCanvasElement} - The canvas used by this layer */
|
|
@@ -230,12 +239,18 @@ class CanvasLayer extends EngineObject
|
|
|
230
239
|
drawTile(pos, size, tileInfo, color, angle, mirror, additiveColor, useWebGL, screenSpace, context);
|
|
231
240
|
}
|
|
232
241
|
|
|
242
|
+
/**
|
|
243
|
+
* @callback Canvas2DDrawCallback - Function that draws to a canvas 2D context
|
|
244
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} context
|
|
245
|
+
* @memberof TileLayers
|
|
246
|
+
*/
|
|
247
|
+
|
|
233
248
|
/** Draw onto the layer canvas in world space (bypass WebGL)
|
|
234
249
|
* @param {Vector2} pos
|
|
235
250
|
* @param {Vector2} size
|
|
236
251
|
* @param {number} angle
|
|
237
252
|
* @param {boolean} mirror
|
|
238
|
-
* @param {
|
|
253
|
+
* @param {Canvas2DDrawCallback} drawFunction */
|
|
239
254
|
drawCanvas2D(pos, size, angle, mirror, drawFunction)
|
|
240
255
|
{
|
|
241
256
|
const context = this.context;
|
|
@@ -272,7 +287,7 @@ class CanvasLayer extends EngineObject
|
|
|
272
287
|
else
|
|
273
288
|
{
|
|
274
289
|
// untextured
|
|
275
|
-
context.fillStyle = color;
|
|
290
|
+
context.fillStyle = color.toString();
|
|
276
291
|
context.fillRect(-.5, -.5, 1, 1);
|
|
277
292
|
}
|
|
278
293
|
});
|
|
@@ -309,7 +324,9 @@ class CanvasLayer extends EngineObject
|
|
|
309
324
|
* - To allow dynamic modifications, layers are rendered using canvas 2d
|
|
310
325
|
* - Some devices like mobile phones are limited to 4k texture resolution
|
|
311
326
|
* - For with 16x16 tiles this limits layers to 256x256 on mobile devices
|
|
327
|
+
* - Tile layers are centered on their corner, so normal levels are at (0,0)
|
|
312
328
|
* @extends CanvasLayer
|
|
329
|
+
* @memberof TileLayers
|
|
313
330
|
* @example
|
|
314
331
|
* const tileLayer = new TileLayer(vec2(), vec2(200,100));
|
|
315
332
|
*/
|
|
@@ -319,15 +336,14 @@ class TileLayer extends CanvasLayer
|
|
|
319
336
|
* @param {Vector2} position - World space position
|
|
320
337
|
* @param {Vector2} size - World space size
|
|
321
338
|
* @param {TileInfo} [tileInfo] - Default tile info for layer (used for size and texture)
|
|
322
|
-
* @param {Vector2} [scale=(1,1)] - How much to scale this layer when rendered
|
|
323
339
|
* @param {number} [renderOrder] - Objects are sorted by renderOrder
|
|
324
340
|
* @param {boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering
|
|
325
341
|
*/
|
|
326
|
-
constructor(position, size, tileInfo=tile(),
|
|
342
|
+
constructor(position, size, tileInfo=tile(), renderOrder=0, useWebGL=glEnable)
|
|
327
343
|
{
|
|
328
344
|
super(position, size, 0, renderOrder, size);
|
|
345
|
+
|
|
329
346
|
this.tileInfo = tileInfo;
|
|
330
|
-
|
|
331
347
|
const canvasSize = size.multiply(tileInfo.size);
|
|
332
348
|
/** @property {HTMLCanvasElement} - The canvas used by this tile layer */
|
|
333
349
|
this.canvas = new OffscreenCanvas(canvasSize.x, canvasSize.y);
|
|
@@ -364,6 +380,8 @@ class TileLayer extends CanvasLayer
|
|
|
364
380
|
* @param {boolean} [redraw] - Force the tile to redraw if true */
|
|
365
381
|
setData(layerPos, data, redraw=false)
|
|
366
382
|
{
|
|
383
|
+
ASSERT(isVector2(layerPos), 'layerPos must be a Vector2');
|
|
384
|
+
ASSERT(data instanceof TileLayerData, 'data must be a TileLayerData');
|
|
367
385
|
if (layerPos.arrayCheck(this.size))
|
|
368
386
|
{
|
|
369
387
|
this.data[(layerPos.y|0)*this.size.x+layerPos.x|0] = data;
|
|
@@ -375,7 +393,10 @@ class TileLayer extends CanvasLayer
|
|
|
375
393
|
* @param {Vector2} layerPos - Local position in array
|
|
376
394
|
* @return {TileLayerData} */
|
|
377
395
|
getData(layerPos)
|
|
378
|
-
{
|
|
396
|
+
{
|
|
397
|
+
ASSERT(isVector2(layerPos), 'layerPos must be a Vector2');
|
|
398
|
+
return layerPos.arrayCheck(this.size) && this.data[(layerPos.y|0)*this.size.x+layerPos.x|0];
|
|
399
|
+
}
|
|
379
400
|
|
|
380
401
|
// Render the tile layer, called automatically by the engine
|
|
381
402
|
render()
|
|
@@ -384,9 +405,10 @@ class TileLayer extends CanvasLayer
|
|
|
384
405
|
|
|
385
406
|
// draw the tile layer as a single tile
|
|
386
407
|
const tileInfo = new TileInfo().setFullImage(this.canvas, this.glTexture);
|
|
387
|
-
const
|
|
408
|
+
const size = this.drawSize || this.size;
|
|
409
|
+
const pos = this.pos.add(size.scale(.5));
|
|
388
410
|
const useWebGL = glEnable && this.glTexture !== undefined;
|
|
389
|
-
drawTile(pos,
|
|
411
|
+
drawTile(pos, size, tileInfo, WHITE, 0, false, CLEAR_BLACK, useWebGL);
|
|
390
412
|
}
|
|
391
413
|
|
|
392
414
|
/** Draw all the tile data to an offscreen canvas
|
|
@@ -478,6 +500,7 @@ class TileLayer extends CanvasLayer
|
|
|
478
500
|
* - there can be multiple tile collision layers
|
|
479
501
|
* - tile collision layers should not overlap each other
|
|
480
502
|
* @extends TileLayer
|
|
503
|
+
* @memberof TileLayers
|
|
481
504
|
*/
|
|
482
505
|
class TileCollisionLayer extends TileLayer
|
|
483
506
|
{
|
|
@@ -490,8 +513,7 @@ class TileCollisionLayer extends TileLayer
|
|
|
490
513
|
*/
|
|
491
514
|
constructor(position, size, tileInfo=tile(), renderOrder=0, useWebGL=glEnable)
|
|
492
515
|
{
|
|
493
|
-
|
|
494
|
-
super(position, size.floor(), tileInfo, scale, renderOrder, useWebGL);
|
|
516
|
+
super(position, size.floor(), tileInfo, renderOrder, useWebGL);
|
|
495
517
|
|
|
496
518
|
/** @property {Array<number>} - The tile collision grid */
|
|
497
519
|
this.collisionData = [];
|
|
@@ -521,6 +543,7 @@ class TileCollisionLayer extends TileLayer
|
|
|
521
543
|
* @param {Vector2} size - width and height of tile collision 2d grid */
|
|
522
544
|
initCollision(size)
|
|
523
545
|
{
|
|
546
|
+
ASSERT(isVector2(size), 'size must be a Vector2');
|
|
524
547
|
this.size = size.floor();
|
|
525
548
|
this.collisionData = [];
|
|
526
549
|
this.collisionData.length = size.area();
|
|
@@ -532,6 +555,7 @@ class TileCollisionLayer extends TileLayer
|
|
|
532
555
|
* @param {number} [data] */
|
|
533
556
|
setCollisionData(gridPos, data=1)
|
|
534
557
|
{
|
|
558
|
+
ASSERT(isVector2(gridPos), 'gridPos must be a Vector2');
|
|
535
559
|
const i = (gridPos.y|0)*this.size.x + gridPos.x|0;
|
|
536
560
|
gridPos.arrayCheck(this.size) && (this.collisionData[i] = data);
|
|
537
561
|
}
|
|
@@ -541,6 +565,7 @@ class TileCollisionLayer extends TileLayer
|
|
|
541
565
|
* @return {number} */
|
|
542
566
|
getCollisionData(gridPos)
|
|
543
567
|
{
|
|
568
|
+
ASSERT(isVector2(gridPos), 'gridPos must be a Vector2');
|
|
544
569
|
const i = (gridPos.y|0)*this.size.x + gridPos.x|0;
|
|
545
570
|
return gridPos.arrayCheck(this.size) ? this.collisionData[i] : 0;
|
|
546
571
|
}
|
|
@@ -552,6 +577,9 @@ class TileCollisionLayer extends TileLayer
|
|
|
552
577
|
* @return {boolean} */
|
|
553
578
|
collisionTest(pos, size=new Vector2, object)
|
|
554
579
|
{
|
|
580
|
+
ASSERT(isVector2(pos) && isVector2(size), 'pos and size must be Vector2s');
|
|
581
|
+
ASSERT(!object || object instanceof EngineObject, 'object must be an EngineObject');
|
|
582
|
+
|
|
555
583
|
// transform to local layer space
|
|
556
584
|
const posX = pos.x - this.pos.x;
|
|
557
585
|
const posY = pos.y - this.pos.y;
|
|
@@ -582,6 +610,9 @@ class TileCollisionLayer extends TileLayer
|
|
|
582
610
|
* @return {Vector2} */
|
|
583
611
|
collisionRaycast(posStart, posEnd, object)
|
|
584
612
|
{
|
|
613
|
+
ASSERT(isVector2(posStart) && isVector2(posEnd), 'positions must be Vector2s');
|
|
614
|
+
ASSERT(!object || object instanceof EngineObject, 'object must be an EngineObject');
|
|
615
|
+
|
|
585
616
|
// transform to local layer space
|
|
586
617
|
const posStartX = posStart.x - this.pos.x;
|
|
587
618
|
const posStartY = posStart.y - this.pos.y;
|