littlejsengine 1.14.11 → 1.14.19
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 +303 -137
- package/dist/littlejs.esm.js +936 -463
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +934 -462
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +859 -417
- package/examples/box2d/game.js +3 -2
- package/examples/box2d/gameObjects.js +2 -2
- package/examples/box2d/tiles.png +0 -0
- package/examples/breakout/game.js +5 -5
- 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 +4 -4
- package/examples/electron/index.html +2 -2
- package/examples/electron/package.json +1 -8
- package/examples/index.html +67 -56
- package/examples/module/game.js +4 -4
- package/examples/platformer/gameEffects.js +5 -5
- 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 +135 -0
- package/examples/shorts/nineSlice.js +34 -15
- package/examples/shorts/parallax.js +5 -4
- 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/shader.js +29 -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 +24 -5
- 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 +4 -4
- package/examples/starter/index.html +2 -2
- package/examples/style.css +1 -0
- package/examples/typescript/game.js +4 -4
- package/examples/typescript/game.ts +4 -4
- package/examples/uiSystem/game.js +4 -3
- package/package.json +4 -2
- package/plugins/box2d.js +17 -2
- package/plugins/newgrounds.js +7 -5
- package/plugins/postProcess.js +76 -53
- package/plugins/uiSystem.js +192 -53
- package/plugins/zzfxm.js +5 -1
- package/reference.md +1 -1
- package/src/engine.js +60 -23
- package/src/engineAudio.js +44 -17
- package/src/engineDebug.js +75 -45
- package/src/engineDraw.js +94 -59
- package/src/engineExport.js +2 -1
- package/src/engineMedals.js +10 -2
- package/src/engineObject.js +14 -10
- package/src/engineParticles.js +60 -47
- package/src/engineSettings.js +7 -7
- package/src/engineTileLayer.js +73 -56
- package/src/engineUtilities.js +67 -20
- package/src/engineWebGL.js +134 -63
package/src/engineDraw.js
CHANGED
|
@@ -83,7 +83,7 @@ let drawCount;
|
|
|
83
83
|
* Create a tile info object using a grid based system
|
|
84
84
|
* - This can take vecs or floats for easier use and conversion
|
|
85
85
|
* - If an index is passed in, the tile size and index will determine the position
|
|
86
|
-
* @param {Vector2|number} [pos=0] -
|
|
86
|
+
* @param {Vector2|number} [pos=0] - Position of the tile in pixels, or tile index
|
|
87
87
|
* @param {Vector2|number} [size=tileSizeDefault] - Size of tile in pixels
|
|
88
88
|
* @param {number} [textureIndex] - Texture index to use
|
|
89
89
|
* @param {number} [padding] - How many pixels padding around tiles
|
|
@@ -128,6 +128,7 @@ function tile(pos=new Vector2, size=tileSizeDefault, textureIndex=0, padding=0)
|
|
|
128
128
|
|
|
129
129
|
/**
|
|
130
130
|
* Tile Info - Stores info about how to draw a tile
|
|
131
|
+
* @memberof Draw
|
|
131
132
|
*/
|
|
132
133
|
class TileInfo
|
|
133
134
|
{
|
|
@@ -172,48 +173,54 @@ class TileInfo
|
|
|
172
173
|
}
|
|
173
174
|
|
|
174
175
|
/**
|
|
175
|
-
* Set this tile to use a full image
|
|
176
|
-
* @param {
|
|
177
|
-
* @param {WebGLTexture} [glTexture] - WebGL texture
|
|
176
|
+
* Set this tile to use a full image in a texture info
|
|
177
|
+
* @param {TextureInfo} textureInfo
|
|
178
178
|
* @return {TileInfo}
|
|
179
179
|
*/
|
|
180
|
-
setFullImage(
|
|
180
|
+
setFullImage(textureInfo)
|
|
181
181
|
{
|
|
182
182
|
this.pos = new Vector2;
|
|
183
|
-
this.size =
|
|
184
|
-
this.textureInfo =
|
|
183
|
+
this.size = textureInfo.size.copy();
|
|
184
|
+
this.textureInfo = textureInfo;
|
|
185
185
|
// do not use padding or bleed
|
|
186
186
|
this.bleedScale = this.padding = 0;
|
|
187
187
|
return this;
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
/**
|
|
191
|
+
/**
|
|
192
|
+
* Tile Info - Stores info about each texture
|
|
193
|
+
* @memberof Draw
|
|
194
|
+
*/
|
|
192
195
|
class TextureInfo
|
|
193
196
|
{
|
|
194
197
|
/**
|
|
195
198
|
* Create a TextureInfo, called automatically by the engine
|
|
196
199
|
* @param {HTMLImageElement|OffscreenCanvas} image
|
|
197
|
-
* @param {
|
|
200
|
+
* @param {boolean} [useWebGL] - Should use WebGL if available?
|
|
198
201
|
*/
|
|
199
|
-
constructor(image,
|
|
202
|
+
constructor(image, useWebGL=true)
|
|
200
203
|
{
|
|
201
|
-
/** @property {HTMLImageElement} - image source */
|
|
204
|
+
/** @property {HTMLImageElement|OffscreenCanvas} - image source */
|
|
202
205
|
this.image = image;
|
|
203
206
|
/** @property {Vector2} - size of the image */
|
|
204
|
-
this.size = vec2(image.width, image.height);
|
|
207
|
+
this.size = image ? vec2(image.width, image.height) : vec2();
|
|
205
208
|
/** @property {Vector2} - inverse of the size, cached for rendering */
|
|
206
|
-
this.sizeInverse = vec2(1/image.width, 1/image.height);
|
|
209
|
+
this.sizeInverse = image ? vec2(1/image.width, 1/image.height) : vec2();
|
|
207
210
|
/** @property {WebGLTexture} - WebGL texture */
|
|
208
|
-
this.glTexture =
|
|
211
|
+
this.glTexture = undefined;
|
|
212
|
+
useWebGL && this.createWebGLTexture();
|
|
209
213
|
}
|
|
210
214
|
|
|
211
|
-
|
|
212
|
-
{
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
215
|
+
/** Creates the WebGL texture, updates if already created */
|
|
216
|
+
createWebGLTexture() { glRegisterTextureInfo(this); }
|
|
217
|
+
|
|
218
|
+
/** Destroys the WebGL texture */
|
|
219
|
+
destroyWebGLTexture() { glUnregisterTextureInfo(this); }
|
|
220
|
+
|
|
221
|
+
/** Check if the texture is webgl enabled
|
|
222
|
+
* @return {boolean} */
|
|
223
|
+
hasWebGL() { return !!this.glTexture; }
|
|
217
224
|
}
|
|
218
225
|
|
|
219
226
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -234,10 +241,11 @@ class TextureInfo
|
|
|
234
241
|
function drawTile(pos, size=new Vector2(1), tileInfo, color=WHITE,
|
|
235
242
|
angle=0, mirror, additiveColor, useWebGL=glEnable, screenSpace, context)
|
|
236
243
|
{
|
|
237
|
-
ASSERT(isVector2(pos), '
|
|
238
|
-
ASSERT(isVector2(size), '
|
|
239
|
-
ASSERT(isColor(color)
|
|
240
|
-
ASSERT(isNumber(angle), '
|
|
244
|
+
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
245
|
+
ASSERT(isVector2(size), 'size must be a vec2');
|
|
246
|
+
ASSERT(isColor(color), 'color is invalid');
|
|
247
|
+
ASSERT(isNumber(angle), 'angle must be a number');
|
|
248
|
+
ASSERT(!additiveColor || isColor(additiveColor), 'additiveColor must be a color');
|
|
241
249
|
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
242
250
|
|
|
243
251
|
const textureInfo = tileInfo && tileInfo.textureInfo;
|
|
@@ -332,10 +340,10 @@ function drawRect(pos, size, color, angle, useWebGL, screenSpace, context)
|
|
|
332
340
|
* @memberof Draw */
|
|
333
341
|
function drawRectGradient(pos, size, colorTop=WHITE, colorBottom=BLACK, angle=0, useWebGL=glEnable, screenSpace=false, context)
|
|
334
342
|
{
|
|
335
|
-
ASSERT(isVector2(pos), '
|
|
336
|
-
ASSERT(isVector2(size), '
|
|
337
|
-
ASSERT(isColor(colorTop) && isColor(colorBottom), '
|
|
338
|
-
ASSERT(isNumber(angle), '
|
|
343
|
+
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
344
|
+
ASSERT(isVector2(size), 'size must be a vec2');
|
|
345
|
+
ASSERT(isColor(colorTop) && isColor(colorBottom), 'color is invalid');
|
|
346
|
+
ASSERT(isNumber(angle), 'angle must be a number');
|
|
339
347
|
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
340
348
|
if (useWebGL)
|
|
341
349
|
{
|
|
@@ -393,11 +401,11 @@ function drawRectGradient(pos, size, colorTop=WHITE, colorBottom=BLACK, angle=0,
|
|
|
393
401
|
* @memberof Draw */
|
|
394
402
|
function drawLineList(points, width=.1, color, wrap=false, pos=vec2(), angle=0, useWebGL=glEnable, screenSpace, context)
|
|
395
403
|
{
|
|
396
|
-
ASSERT(Array.isArray(points), '
|
|
397
|
-
ASSERT(isNumber(width), '
|
|
398
|
-
ASSERT(isColor(color), '
|
|
399
|
-
ASSERT(isVector2(pos), '
|
|
400
|
-
ASSERT(isNumber(angle), '
|
|
404
|
+
ASSERT(Array.isArray(points), 'points must be an array');
|
|
405
|
+
ASSERT(isNumber(width), 'width must be a number');
|
|
406
|
+
ASSERT(isColor(color), 'color is invalid');
|
|
407
|
+
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
408
|
+
ASSERT(isNumber(angle), 'angle must be a number');
|
|
401
409
|
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
402
410
|
if (useWebGL)
|
|
403
411
|
{
|
|
@@ -468,8 +476,8 @@ function drawLine(posA, posB, width=.1, color, pos=vec2(), angle=0, useWebGL, sc
|
|
|
468
476
|
* @memberof Draw */
|
|
469
477
|
function drawRegularPoly(pos, size=vec2(1), sides=3, color=WHITE, lineWidth=0, lineColor=BLACK, angle=0, useWebGL=glEnable, screenSpace=false, context)
|
|
470
478
|
{
|
|
471
|
-
ASSERT(isVector2(size), '
|
|
472
|
-
ASSERT(isNumber(sides), '
|
|
479
|
+
ASSERT(isVector2(size), 'size must be a vec2');
|
|
480
|
+
ASSERT(isNumber(sides), 'sides must be a number');
|
|
473
481
|
|
|
474
482
|
// build regular polygon points
|
|
475
483
|
const points = [];
|
|
@@ -495,12 +503,13 @@ function drawRegularPoly(pos, size=vec2(1), sides=3, color=WHITE, lineWidth=0, l
|
|
|
495
503
|
* @memberof Draw */
|
|
496
504
|
function drawPoly(points, color=WHITE, lineWidth=0, lineColor=BLACK, pos=vec2(), angle=0, useWebGL=glEnable, screenSpace=false, context=undefined)
|
|
497
505
|
{
|
|
498
|
-
ASSERT(isVector2(pos), '
|
|
499
|
-
ASSERT(Array.isArray(points), '
|
|
500
|
-
ASSERT(isColor(color) && isColor(lineColor), '
|
|
501
|
-
ASSERT(isNumber(lineWidth), '
|
|
502
|
-
ASSERT(isNumber(angle), '
|
|
506
|
+
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
507
|
+
ASSERT(Array.isArray(points), 'points must be an array');
|
|
508
|
+
ASSERT(isColor(color) && isColor(lineColor), 'color is invalid');
|
|
509
|
+
ASSERT(isNumber(lineWidth), 'lineWidth must be a number');
|
|
510
|
+
ASSERT(isNumber(angle), 'angle must be a number');
|
|
503
511
|
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
512
|
+
|
|
504
513
|
if (useWebGL)
|
|
505
514
|
{
|
|
506
515
|
let scale = 1;
|
|
@@ -547,13 +556,14 @@ function drawPoly(points, color=WHITE, lineWidth=0, lineColor=BLACK, pos=vec2(),
|
|
|
547
556
|
* @memberof Draw */
|
|
548
557
|
function drawEllipse(pos, size=vec2(1), color=WHITE, angle=0, lineWidth=0, lineColor=BLACK, useWebGL=glEnable, screenSpace=false, context)
|
|
549
558
|
{
|
|
550
|
-
ASSERT(isVector2(pos), '
|
|
551
|
-
ASSERT(isVector2(size), '
|
|
552
|
-
ASSERT(isColor(color) && isColor(lineColor), '
|
|
553
|
-
ASSERT(isNumber(angle), '
|
|
554
|
-
ASSERT(isNumber(lineWidth), '
|
|
555
|
-
ASSERT(lineWidth >= 0 && lineWidth < size.x && lineWidth < size.y, '
|
|
559
|
+
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
560
|
+
ASSERT(isVector2(size), 'size must be a vec2');
|
|
561
|
+
ASSERT(isColor(color) && isColor(lineColor), 'color is invalid');
|
|
562
|
+
ASSERT(isNumber(angle), 'angle must be a number');
|
|
563
|
+
ASSERT(isNumber(lineWidth), 'lineWidth must be a number');
|
|
564
|
+
ASSERT(lineWidth >= 0 && lineWidth < size.x && lineWidth < size.y, 'invalid lineWidth');
|
|
556
565
|
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
566
|
+
|
|
557
567
|
if (useWebGL)
|
|
558
568
|
{
|
|
559
569
|
// draw as a regular polygon
|
|
@@ -590,21 +600,32 @@ function drawEllipse(pos, size=vec2(1), color=WHITE, angle=0, lineWidth=0, lineC
|
|
|
590
600
|
* @memberof Draw */
|
|
591
601
|
function drawCircle(pos, size=1, color=WHITE, lineWidth=0, lineColor=BLACK, useWebGL=glEnable, screenSpace=false, context)
|
|
592
602
|
{
|
|
593
|
-
ASSERT(isNumber(size), '
|
|
603
|
+
ASSERT(isNumber(size), 'size must be a number');
|
|
594
604
|
drawEllipse(pos, vec2(size), color, 0, lineWidth, lineColor, useWebGL, screenSpace, context);
|
|
595
605
|
}
|
|
596
606
|
|
|
607
|
+
/**
|
|
608
|
+
* @callback Canvas2DDrawFunction - A function that draws to a 2D canvas context
|
|
609
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} context
|
|
610
|
+
* @memberof Draw
|
|
611
|
+
*/
|
|
612
|
+
|
|
597
613
|
/** Draw directly to a 2d canvas context in world space
|
|
598
614
|
* @param {Vector2} pos
|
|
599
615
|
* @param {Vector2} size
|
|
600
616
|
* @param {number} angle
|
|
601
617
|
* @param {boolean} [mirror]
|
|
602
|
-
* @param {
|
|
618
|
+
* @param {Canvas2DDrawFunction} [drawFunction]
|
|
603
619
|
* @param {boolean} [screenSpace=false]
|
|
604
620
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=drawContext]
|
|
605
621
|
* @memberof Draw */
|
|
606
622
|
function drawCanvas2D(pos, size, angle=0, mirror=false, drawFunction, screenSpace=false, context=drawContext)
|
|
607
623
|
{
|
|
624
|
+
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
625
|
+
ASSERT(isVector2(size), 'size must be a vec2');
|
|
626
|
+
ASSERT(isNumber(angle), 'angle must be a number');
|
|
627
|
+
ASSERT(typeof drawFunction === 'function', 'drawFunction must be a function');
|
|
628
|
+
|
|
608
629
|
if (!screenSpace)
|
|
609
630
|
{
|
|
610
631
|
// transform from world space to screen space
|
|
@@ -632,12 +653,13 @@ function drawCanvas2D(pos, size, angle=0, mirror=false, drawFunction, screenSpac
|
|
|
632
653
|
* @param {Color} [lineColor=(0,0,0,1)]
|
|
633
654
|
* @param {CanvasTextAlign} [textAlign='center']
|
|
634
655
|
* @param {string} [font=fontDefault]
|
|
656
|
+
* @param {string} [fontStyle]
|
|
635
657
|
* @param {number} [maxWidth]
|
|
636
658
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=drawContext]
|
|
637
659
|
* @memberof Draw */
|
|
638
|
-
function drawText(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, font, maxWidth, context=drawContext)
|
|
660
|
+
function drawText(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, font, fontStyle, maxWidth, context=drawContext)
|
|
639
661
|
{
|
|
640
|
-
drawTextScreen(text, worldToScreen(pos), size*cameraScale, color, lineWidth*cameraScale, lineColor, textAlign, font, maxWidth, context);
|
|
662
|
+
drawTextScreen(text, worldToScreen(pos), size*cameraScale, color, lineWidth*cameraScale, lineColor, textAlign, font, fontStyle, maxWidth, context);
|
|
641
663
|
}
|
|
642
664
|
|
|
643
665
|
/** Draw text on overlay canvas in world space
|
|
@@ -650,11 +672,12 @@ function drawText(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, f
|
|
|
650
672
|
* @param {Color} [lineColor=(0,0,0,1)]
|
|
651
673
|
* @param {CanvasTextAlign} [textAlign='center']
|
|
652
674
|
* @param {string} [font=fontDefault]
|
|
675
|
+
* @param {string} [fontStyle]
|
|
653
676
|
* @param {number} [maxWidth]
|
|
654
677
|
* @memberof Draw */
|
|
655
|
-
function drawTextOverlay(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, font, maxWidth)
|
|
678
|
+
function drawTextOverlay(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, font, fontStyle, maxWidth)
|
|
656
679
|
{
|
|
657
|
-
drawText(text, pos, size, color, lineWidth, lineColor, textAlign, font, maxWidth, overlayContext);
|
|
680
|
+
drawText(text, pos, size, color, lineWidth, lineColor, textAlign, font, fontStyle, maxWidth, overlayContext);
|
|
658
681
|
}
|
|
659
682
|
|
|
660
683
|
/** Draw text on overlay canvas in screen space
|
|
@@ -667,16 +690,27 @@ function drawTextOverlay(text, pos, size=1, color, lineWidth=0, lineColor, textA
|
|
|
667
690
|
* @param {Color} [lineColor=(0,0,0,1)]
|
|
668
691
|
* @param {CanvasTextAlign} [textAlign]
|
|
669
692
|
* @param {string} [font=fontDefault]
|
|
693
|
+
* @param {string} [fontStyle]
|
|
670
694
|
* @param {number} [maxWidth]
|
|
671
695
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=overlayContext]
|
|
672
696
|
* @memberof Draw */
|
|
673
|
-
function drawTextScreen(text, pos, size=1, color=WHITE, lineWidth=0, lineColor=BLACK, textAlign='center', font=fontDefault, maxWidth, context=overlayContext)
|
|
697
|
+
function drawTextScreen(text, pos, size=1, color=WHITE, lineWidth=0, lineColor=BLACK, textAlign='center', font=fontDefault, fontStyle='', maxWidth, context=overlayContext)
|
|
674
698
|
{
|
|
699
|
+
ASSERT(isString(text), 'text must be a string');
|
|
700
|
+
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
701
|
+
ASSERT(isNumber(size), 'size must be a number');
|
|
702
|
+
ASSERT(isColor(color), 'color must be a color');
|
|
703
|
+
ASSERT(isNumber(lineWidth), 'lineWidth must be a number');
|
|
704
|
+
ASSERT(isColor(lineColor), 'lineColor must be a color');
|
|
705
|
+
ASSERT(['left','center','right'].includes(textAlign), 'align must be left, center, or right');
|
|
706
|
+
ASSERT(isString(font), 'font must be a string');
|
|
707
|
+
ASSERT(isString(fontStyle), 'fontStyle must be a string');
|
|
708
|
+
|
|
675
709
|
context.fillStyle = color.toString();
|
|
676
710
|
context.strokeStyle = lineColor.toString();
|
|
677
711
|
context.lineWidth = lineWidth;
|
|
678
712
|
context.textAlign = textAlign;
|
|
679
|
-
context.font = size + 'px '+ font;
|
|
713
|
+
context.font = fontStyle + ' ' + size + 'px '+ font;
|
|
680
714
|
context.textBaseline = 'middle';
|
|
681
715
|
|
|
682
716
|
const lines = (text+'').split('\n');
|
|
@@ -873,6 +907,7 @@ let engineFontImage;
|
|
|
873
907
|
* - 96 characters (from space to tilde) are stored in an image
|
|
874
908
|
* - Uses a default 8x8 font if none is supplied
|
|
875
909
|
* - You can also use fonts from the main tile sheet
|
|
910
|
+
* @memberof Draw
|
|
876
911
|
* @example
|
|
877
912
|
* // use built in font
|
|
878
913
|
* const font = new FontImage;
|
|
@@ -883,11 +918,11 @@ let engineFontImage;
|
|
|
883
918
|
class FontImage
|
|
884
919
|
{
|
|
885
920
|
/** Create an image font
|
|
886
|
-
* @param {HTMLImageElement} [image]
|
|
887
|
-
* @param {Vector2} [tileSize=(8,8)]
|
|
888
|
-
* @param {Vector2} [paddingSize=(0,1)] - How much
|
|
921
|
+
* @param {HTMLImageElement} [image] - Image for the font, default if undefined
|
|
922
|
+
* @param {Vector2} [tileSize=(8,8)] - Size of the font source tiles
|
|
923
|
+
* @param {Vector2} [paddingSize=(0,1)] - How much space between characters
|
|
889
924
|
*/
|
|
890
|
-
constructor(image, tileSize=vec2(8), paddingSize=vec2(0,1)
|
|
925
|
+
constructor(image, tileSize=vec2(8), paddingSize=vec2(0,1))
|
|
891
926
|
{
|
|
892
927
|
// load default font image
|
|
893
928
|
if (!engineFontImage)
|
|
@@ -929,7 +964,7 @@ class FontImage
|
|
|
929
964
|
* @param {boolean} [center]
|
|
930
965
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=drawContext]
|
|
931
966
|
*/
|
|
932
|
-
drawTextScreen(text, pos, scale=4, center, context=overlayContext)
|
|
967
|
+
drawTextScreen(text, pos, scale=4, center=true, context=overlayContext)
|
|
933
968
|
{
|
|
934
969
|
context.save();
|
|
935
970
|
const size = this.tileSize;
|
package/src/engineExport.js
CHANGED
|
@@ -178,6 +178,7 @@ export
|
|
|
178
178
|
isColor,
|
|
179
179
|
isVector2,
|
|
180
180
|
isNumber,
|
|
181
|
+
isString,
|
|
181
182
|
|
|
182
183
|
// Default Colors
|
|
183
184
|
WHITE,
|
|
@@ -313,7 +314,7 @@ export
|
|
|
313
314
|
tileCollisionGetData,
|
|
314
315
|
tileCollisionTest,
|
|
315
316
|
tileCollisionRaycast,
|
|
316
|
-
|
|
317
|
+
tileLayersLoad,
|
|
317
318
|
TileLayerData,
|
|
318
319
|
CanvasLayer,
|
|
319
320
|
TileLayer,
|
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);
|
|
@@ -16,7 +23,7 @@
|
|
|
16
23
|
* tile(0, 16), // tileInfo
|
|
17
24
|
* rgb(1,1,1,1), rgb(0,0,0,1), // colorStartA, colorStartB
|
|
18
25
|
* rgb(1,1,1,0), rgb(0,0,0,0), // colorEndA, colorEndB
|
|
19
|
-
*
|
|
26
|
+
* 1, .2, .2, .1, .05, // particleTime, sizeStart, sizeEnd, particleSpeed, particleAngleSpeed
|
|
20
27
|
* .99, 1, 1, PI, .05, // damping, angleDamping, gravityScale, particleCone, fadeRate,
|
|
21
28
|
* .5, 1 // randomness, collide, additive, randomColorLinear, renderOrder
|
|
22
29
|
* );
|
|
@@ -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
|
}
|