littlejsengine 1.14.11 → 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 +252 -109
- package/dist/littlejs.esm.js +559 -252
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +557 -251
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +482 -206
- 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 +10 -7
- package/examples/module/game.js +3 -3
- package/examples/platformer/gameEffects.js +4 -4
- package/examples/platformer/gameLevel.js +1 -1
- package/examples/platformer/gameObjects.js +4 -4
- 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 +11 -8
- package/examples/shorts/medals.js +4 -4
- package/examples/shorts/music.js +29 -56
- 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 +15 -15
- package/examples/shorts/piano.js +15 -21
- package/examples/shorts/pongGame.js +6 -4
- package/examples/shorts/raycasting.js +9 -4
- package/examples/shorts/sequencer.js +122 -0
- package/examples/shorts/shapes.js +7 -4
- package/examples/shorts/slidingPuzzle.js +4 -2
- 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 +3 -3
- package/package.json +4 -2
- package/plugins/box2d.js +17 -2
- package/plugins/newgrounds.js +7 -5
- package/plugins/postProcess.js +5 -2
- package/plugins/uiSystem.js +120 -34
- package/plugins/zzfxm.js +5 -1
- package/reference.md +1 -1
- package/src/engine.js +35 -12
- package/src/engineAudio.js +31 -14
- package/src/engineDebug.js +75 -45
- package/src/engineDraw.js +60 -31
- package/src/engineExport.js +2 -1
- package/src/engineMedals.js +10 -2
- package/src/engineObject.js +14 -10
- package/src/engineParticles.js +59 -46
- package/src/engineSettings.js +7 -7
- package/src/engineTileLayer.js +45 -20
- package/src/engineUtilities.js +67 -20
package/src/engineMedals.js
CHANGED
|
@@ -59,8 +59,14 @@ function medalsInit(saveName)
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
/**
|
|
63
|
+
* @callback MedalCallbackFunction - Function that processes a medal
|
|
64
|
+
* @param {Medal} medal
|
|
65
|
+
* @memberof Medals
|
|
66
|
+
*/
|
|
67
|
+
|
|
62
68
|
/** Calls a function for each medal
|
|
63
|
-
* @param {
|
|
69
|
+
* @param {MedalCallbackFunction} callback
|
|
64
70
|
* @memberof Medals */
|
|
65
71
|
function medalsForEach(callback)
|
|
66
72
|
{ Object.values(medals).forEach(medal=>callback(medal)); }
|
|
@@ -69,6 +75,7 @@ function medalsForEach(callback)
|
|
|
69
75
|
|
|
70
76
|
/**
|
|
71
77
|
* Medal - Tracks an unlockable medal
|
|
78
|
+
* @memberof Medals
|
|
72
79
|
* @example
|
|
73
80
|
* // create a medal
|
|
74
81
|
* const medal_example = new Medal(0, 'Example Medal', 'More info about the medal goes here.', '🎖️');
|
|
@@ -137,11 +144,12 @@ class Medal
|
|
|
137
144
|
const height = medalDisplaySize.y;
|
|
138
145
|
const x = overlayCanvas.width - width;
|
|
139
146
|
const y = -height*hidePercent;
|
|
147
|
+
const backgroundColor = hsl(0,0,.9);
|
|
140
148
|
|
|
141
149
|
// draw containing rect and clip to that region
|
|
142
150
|
context.save();
|
|
143
151
|
context.beginPath();
|
|
144
|
-
context.fillStyle =
|
|
152
|
+
context.fillStyle = backgroundColor.toString();
|
|
145
153
|
context.strokeStyle = BLACK.toString();
|
|
146
154
|
context.lineWidth = 3;
|
|
147
155
|
context.rect(x, y, width, height);
|
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/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
|
{
|
|
@@ -109,9 +109,9 @@ function tileCollisionLoad(tileMapData, tileInfo=tile(), renderOrder=0, collisio
|
|
|
109
109
|
tileLayers[layerIndex] = tileLayer;
|
|
110
110
|
|
|
111
111
|
// apply layer color
|
|
112
|
-
const layerColor = dataLayer.
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
const layerColor = dataLayer.tintcolor ?
|
|
113
|
+
new Color().setHex(dataLayer.tintcolor) :
|
|
114
|
+
dataLayer.color || WHITE;
|
|
115
115
|
ASSERT(isColor(layerColor), 'layer color is not a color');
|
|
116
116
|
|
|
117
117
|
for (let x=levelSize.x; x--;)
|
|
@@ -138,6 +138,7 @@ function tileCollisionLoad(tileMapData, tileInfo=tile(), renderOrder=0, collisio
|
|
|
138
138
|
///////////////////////////////////////////////////////////////////////////////
|
|
139
139
|
/**
|
|
140
140
|
* Tile layer data object stores info about how to draw a tile
|
|
141
|
+
* @memberof TileLayers
|
|
141
142
|
* @example
|
|
142
143
|
* // create tile layer data with tile index 0 and random orientation and color
|
|
143
144
|
* const tileIndex = 0;
|
|
@@ -175,6 +176,7 @@ class TileLayerData
|
|
|
175
176
|
* - Contains an offscreen canvas that can be rendered to
|
|
176
177
|
* - WebGL rendering is optional, call useWebGL to enable
|
|
177
178
|
* @extends EngineObject
|
|
179
|
+
* @memberof TileLayers
|
|
178
180
|
* @example
|
|
179
181
|
* const canvasLayer = new CanvasLayer(vec2(), vec2(200,100));
|
|
180
182
|
*/
|
|
@@ -189,6 +191,7 @@ class CanvasLayer extends EngineObject
|
|
|
189
191
|
*/
|
|
190
192
|
constructor(position, size, angle=0, renderOrder=0, canvasSize=vec2(512))
|
|
191
193
|
{
|
|
194
|
+
ASSERT(isVector2(canvasSize), 'canvasSize must be a Vector2');
|
|
192
195
|
super(position, size, undefined, angle, WHITE, renderOrder);
|
|
193
196
|
|
|
194
197
|
/** @property {HTMLCanvasElement} - The canvas used by this layer */
|
|
@@ -236,12 +239,18 @@ class CanvasLayer extends EngineObject
|
|
|
236
239
|
drawTile(pos, size, tileInfo, color, angle, mirror, additiveColor, useWebGL, screenSpace, context);
|
|
237
240
|
}
|
|
238
241
|
|
|
242
|
+
/**
|
|
243
|
+
* @callback Canvas2DDrawCallback - Function that draws to a canvas 2D context
|
|
244
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} context
|
|
245
|
+
* @memberof TileLayers
|
|
246
|
+
*/
|
|
247
|
+
|
|
239
248
|
/** Draw onto the layer canvas in world space (bypass WebGL)
|
|
240
249
|
* @param {Vector2} pos
|
|
241
250
|
* @param {Vector2} size
|
|
242
251
|
* @param {number} angle
|
|
243
252
|
* @param {boolean} mirror
|
|
244
|
-
* @param {
|
|
253
|
+
* @param {Canvas2DDrawCallback} drawFunction */
|
|
245
254
|
drawCanvas2D(pos, size, angle, mirror, drawFunction)
|
|
246
255
|
{
|
|
247
256
|
const context = this.context;
|
|
@@ -278,7 +287,7 @@ class CanvasLayer extends EngineObject
|
|
|
278
287
|
else
|
|
279
288
|
{
|
|
280
289
|
// untextured
|
|
281
|
-
context.fillStyle = color;
|
|
290
|
+
context.fillStyle = color.toString();
|
|
282
291
|
context.fillRect(-.5, -.5, 1, 1);
|
|
283
292
|
}
|
|
284
293
|
});
|
|
@@ -315,7 +324,9 @@ class CanvasLayer extends EngineObject
|
|
|
315
324
|
* - To allow dynamic modifications, layers are rendered using canvas 2d
|
|
316
325
|
* - Some devices like mobile phones are limited to 4k texture resolution
|
|
317
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)
|
|
318
328
|
* @extends CanvasLayer
|
|
329
|
+
* @memberof TileLayers
|
|
319
330
|
* @example
|
|
320
331
|
* const tileLayer = new TileLayer(vec2(), vec2(200,100));
|
|
321
332
|
*/
|
|
@@ -325,15 +336,14 @@ class TileLayer extends CanvasLayer
|
|
|
325
336
|
* @param {Vector2} position - World space position
|
|
326
337
|
* @param {Vector2} size - World space size
|
|
327
338
|
* @param {TileInfo} [tileInfo] - Default tile info for layer (used for size and texture)
|
|
328
|
-
* @param {Vector2} [scale=(1,1)] - How much to scale this layer when rendered
|
|
329
339
|
* @param {number} [renderOrder] - Objects are sorted by renderOrder
|
|
330
340
|
* @param {boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering
|
|
331
341
|
*/
|
|
332
|
-
constructor(position, size, tileInfo=tile(),
|
|
342
|
+
constructor(position, size, tileInfo=tile(), renderOrder=0, useWebGL=glEnable)
|
|
333
343
|
{
|
|
334
344
|
super(position, size, 0, renderOrder, size);
|
|
345
|
+
|
|
335
346
|
this.tileInfo = tileInfo;
|
|
336
|
-
|
|
337
347
|
const canvasSize = size.multiply(tileInfo.size);
|
|
338
348
|
/** @property {HTMLCanvasElement} - The canvas used by this tile layer */
|
|
339
349
|
this.canvas = new OffscreenCanvas(canvasSize.x, canvasSize.y);
|
|
@@ -370,6 +380,8 @@ class TileLayer extends CanvasLayer
|
|
|
370
380
|
* @param {boolean} [redraw] - Force the tile to redraw if true */
|
|
371
381
|
setData(layerPos, data, redraw=false)
|
|
372
382
|
{
|
|
383
|
+
ASSERT(isVector2(layerPos), 'layerPos must be a Vector2');
|
|
384
|
+
ASSERT(data instanceof TileLayerData, 'data must be a TileLayerData');
|
|
373
385
|
if (layerPos.arrayCheck(this.size))
|
|
374
386
|
{
|
|
375
387
|
this.data[(layerPos.y|0)*this.size.x+layerPos.x|0] = data;
|
|
@@ -381,7 +393,10 @@ class TileLayer extends CanvasLayer
|
|
|
381
393
|
* @param {Vector2} layerPos - Local position in array
|
|
382
394
|
* @return {TileLayerData} */
|
|
383
395
|
getData(layerPos)
|
|
384
|
-
{
|
|
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
|
+
}
|
|
385
400
|
|
|
386
401
|
// Render the tile layer, called automatically by the engine
|
|
387
402
|
render()
|
|
@@ -390,9 +405,10 @@ class TileLayer extends CanvasLayer
|
|
|
390
405
|
|
|
391
406
|
// draw the tile layer as a single tile
|
|
392
407
|
const tileInfo = new TileInfo().setFullImage(this.canvas, this.glTexture);
|
|
393
|
-
const
|
|
408
|
+
const size = this.drawSize || this.size;
|
|
409
|
+
const pos = this.pos.add(size.scale(.5));
|
|
394
410
|
const useWebGL = glEnable && this.glTexture !== undefined;
|
|
395
|
-
drawTile(pos,
|
|
411
|
+
drawTile(pos, size, tileInfo, WHITE, 0, false, CLEAR_BLACK, useWebGL);
|
|
396
412
|
}
|
|
397
413
|
|
|
398
414
|
/** Draw all the tile data to an offscreen canvas
|
|
@@ -484,6 +500,7 @@ class TileLayer extends CanvasLayer
|
|
|
484
500
|
* - there can be multiple tile collision layers
|
|
485
501
|
* - tile collision layers should not overlap each other
|
|
486
502
|
* @extends TileLayer
|
|
503
|
+
* @memberof TileLayers
|
|
487
504
|
*/
|
|
488
505
|
class TileCollisionLayer extends TileLayer
|
|
489
506
|
{
|
|
@@ -496,8 +513,7 @@ class TileCollisionLayer extends TileLayer
|
|
|
496
513
|
*/
|
|
497
514
|
constructor(position, size, tileInfo=tile(), renderOrder=0, useWebGL=glEnable)
|
|
498
515
|
{
|
|
499
|
-
|
|
500
|
-
super(position, size.floor(), tileInfo, scale, renderOrder, useWebGL);
|
|
516
|
+
super(position, size.floor(), tileInfo, renderOrder, useWebGL);
|
|
501
517
|
|
|
502
518
|
/** @property {Array<number>} - The tile collision grid */
|
|
503
519
|
this.collisionData = [];
|
|
@@ -527,6 +543,7 @@ class TileCollisionLayer extends TileLayer
|
|
|
527
543
|
* @param {Vector2} size - width and height of tile collision 2d grid */
|
|
528
544
|
initCollision(size)
|
|
529
545
|
{
|
|
546
|
+
ASSERT(isVector2(size), 'size must be a Vector2');
|
|
530
547
|
this.size = size.floor();
|
|
531
548
|
this.collisionData = [];
|
|
532
549
|
this.collisionData.length = size.area();
|
|
@@ -538,6 +555,7 @@ class TileCollisionLayer extends TileLayer
|
|
|
538
555
|
* @param {number} [data] */
|
|
539
556
|
setCollisionData(gridPos, data=1)
|
|
540
557
|
{
|
|
558
|
+
ASSERT(isVector2(gridPos), 'gridPos must be a Vector2');
|
|
541
559
|
const i = (gridPos.y|0)*this.size.x + gridPos.x|0;
|
|
542
560
|
gridPos.arrayCheck(this.size) && (this.collisionData[i] = data);
|
|
543
561
|
}
|
|
@@ -547,6 +565,7 @@ class TileCollisionLayer extends TileLayer
|
|
|
547
565
|
* @return {number} */
|
|
548
566
|
getCollisionData(gridPos)
|
|
549
567
|
{
|
|
568
|
+
ASSERT(isVector2(gridPos), 'gridPos must be a Vector2');
|
|
550
569
|
const i = (gridPos.y|0)*this.size.x + gridPos.x|0;
|
|
551
570
|
return gridPos.arrayCheck(this.size) ? this.collisionData[i] : 0;
|
|
552
571
|
}
|
|
@@ -558,6 +577,9 @@ class TileCollisionLayer extends TileLayer
|
|
|
558
577
|
* @return {boolean} */
|
|
559
578
|
collisionTest(pos, size=new Vector2, object)
|
|
560
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
|
+
|
|
561
583
|
// transform to local layer space
|
|
562
584
|
const posX = pos.x - this.pos.x;
|
|
563
585
|
const posY = pos.y - this.pos.y;
|
|
@@ -588,6 +610,9 @@ class TileCollisionLayer extends TileLayer
|
|
|
588
610
|
* @return {Vector2} */
|
|
589
611
|
collisionRaycast(posStart, posEnd, object)
|
|
590
612
|
{
|
|
613
|
+
ASSERT(isVector2(posStart) && isVector2(posEnd), 'positions must be Vector2s');
|
|
614
|
+
ASSERT(!object || object instanceof EngineObject, 'object must be an EngineObject');
|
|
615
|
+
|
|
591
616
|
// transform to local layer space
|
|
592
617
|
const posStartX = posStart.x - this.pos.x;
|
|
593
618
|
const posStartY = posStart.y - this.pos.y;
|