littlejsengine 1.2.3 → 1.2.9
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/build.bat +1 -1
- package/engine/engine.all.js +115 -50
- package/engine/engine.all.min.js +1 -1
- package/engine/engine.all.release.js +106 -36
- package/engine/engine.js +3 -3
- package/engine/engineDebug.js +9 -14
- package/engine/engineDraw.js +30 -12
- package/engine/engineMedals.js +4 -1
- package/engine/engineObject.js +17 -1
- package/engine/engineParticles.js +1 -1
- package/engine/engineTileLayer.js +11 -10
- package/engine/engineUtilities.js +38 -6
- package/engine/engineWebGL.js +2 -2
- package/engine/index.d.ts +41 -14
- package/examples/breakout/index.html +3 -3
- package/examples/particles/index.html +366 -0
- package/examples/particles/tiles.png +0 -0
- package/examples/platformer/gameEffects.js +6 -6
- package/examples/platformer/index.html +6 -6
- package/examples/puzzle/game.js +1 -1
- package/examples/puzzle/index.html +2 -2
- package/examples/stress/index.html +1 -1
- package/index.html +13 -13
- package/package.json +8 -1
- package/engine/engineBuildSetup.bat +0 -7
|
@@ -344,7 +344,13 @@ class Vector2
|
|
|
344
344
|
/** Returns true if this vector is within the bounds of an array size passed in
|
|
345
345
|
* @param {Vector2} arraySize
|
|
346
346
|
* @return {Boolean} */
|
|
347
|
-
arrayCheck(arraySize) { return this.x >= 0 && this.y >= 0 && this.x < arraySize.x && this.y < arraySize.y; }
|
|
347
|
+
arrayCheck(arraySize) { return this.x >= 0 && this.y >= 0 && this.x < arraySize.x && this.y < arraySize.y; }
|
|
348
|
+
|
|
349
|
+
/** Returns this vector expressed as a string
|
|
350
|
+
* @param {float} digits - precision to display
|
|
351
|
+
* @return {String} */
|
|
352
|
+
toString(digits=3)
|
|
353
|
+
{ return `(${(this.x<0?'':' ') + this.x.toFixed(digits)},${(this.y<0?'':' ') + this.y.toFixed(digits)} )`; }
|
|
348
354
|
}
|
|
349
355
|
|
|
350
356
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -415,7 +421,7 @@ class Color
|
|
|
415
421
|
* @return {Color} */
|
|
416
422
|
lerp(c, p) { return this.add(c.subtract(this).scale(clamp(p))); }
|
|
417
423
|
|
|
418
|
-
/** Sets this color given a hue, saturation, lightness
|
|
424
|
+
/** Sets this color given a hue, saturation, lightness, and alpha
|
|
419
425
|
* @param {Number} [hue=0]
|
|
420
426
|
* @param {Number} [saturation=0]
|
|
421
427
|
* @param {Number} [lightness=1]
|
|
@@ -451,21 +457,43 @@ class Color
|
|
|
451
457
|
).clamp();
|
|
452
458
|
}
|
|
453
459
|
|
|
454
|
-
/** Returns this color expressed as an
|
|
460
|
+
/** Returns this color expressed as an CSS color value
|
|
455
461
|
* @return {String} */
|
|
456
|
-
|
|
462
|
+
toString()
|
|
457
463
|
{
|
|
458
464
|
ASSERT(this.r>=0 && this.r<=1 && this.g>=0 && this.g<=1 && this.b>=0 && this.b<=1 && this.a>=0 && this.a<=1);
|
|
459
465
|
return `rgb(${this.r*255|0},${this.g*255|0},${this.b*255|0},${this.a})`;
|
|
460
466
|
}
|
|
461
467
|
|
|
462
|
-
/** Returns this color expressed as 32 bit integer value
|
|
468
|
+
/** Returns this color expressed as 32 bit integer RGBA value
|
|
463
469
|
* @return {Number} */
|
|
464
470
|
rgbaInt()
|
|
465
471
|
{
|
|
466
472
|
ASSERT(this.r>=0 && this.r<=1 && this.g>=0 && this.g<=1 && this.b>=0 && this.b<=1 && this.a>=0 && this.a<=1);
|
|
467
473
|
return (this.r*255|0) + (this.g*255<<8) + (this.b*255<<16) + (this.a*255<<24);
|
|
468
474
|
}
|
|
475
|
+
|
|
476
|
+
/** Returns this color expressed as a hex code
|
|
477
|
+
* @return {String} */
|
|
478
|
+
hex()
|
|
479
|
+
{
|
|
480
|
+
const toHex = (c)=> ((c=c*255|0)<16 ? '0' : '') + c.toString(16);
|
|
481
|
+
return '#' + toHex(this.r) + toHex(this.g) + toHex(this.b);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/** Set this color from a hex code
|
|
485
|
+
* @param {String} hex - html hex code
|
|
486
|
+
* @return {Color} */
|
|
487
|
+
setHex(hex)
|
|
488
|
+
{
|
|
489
|
+
const fromHex = (a)=> parseInt(hex.slice(a,a+2), 16)/255;
|
|
490
|
+
this.r = fromHex(1);
|
|
491
|
+
this.g = fromHex(3),
|
|
492
|
+
this.b = fromHex(5);
|
|
493
|
+
this.a = 1;
|
|
494
|
+
ASSERT(this.r>=0 && this.r<=1 && this.g>=0 && this.g<=1 && this.b>=0 && this.b<=1);
|
|
495
|
+
return this;
|
|
496
|
+
}
|
|
469
497
|
}
|
|
470
498
|
|
|
471
499
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -502,7 +530,7 @@ class Timer
|
|
|
502
530
|
|
|
503
531
|
/** Returns true if set and elapsed
|
|
504
532
|
* @return {Boolean} */
|
|
505
|
-
elapsed() { return time >
|
|
533
|
+
elapsed() { return time > this.time; }
|
|
506
534
|
|
|
507
535
|
/** Get how long since elapsed, returns 0 if not set (returns negative if currently active)
|
|
508
536
|
* @return {Number} */
|
|
@@ -511,6 +539,10 @@ class Timer
|
|
|
511
539
|
/** Get percentage elapsed based on time it was set to, returns 0 if not set
|
|
512
540
|
* @return {Number} */
|
|
513
541
|
getPercent() { return this.isSet()? percent(this.time - time, this.setTime, 0) : 0; }
|
|
542
|
+
|
|
543
|
+
/** Returns this timer expressed as a string
|
|
544
|
+
* @return {String} */
|
|
545
|
+
toString() { return this.unset() ? 'unset' : Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ); }
|
|
514
546
|
}
|
|
515
547
|
/**
|
|
516
548
|
* LittleJS Engine Settings
|
|
@@ -753,7 +785,7 @@ let medalDisplayIconSize = 50;
|
|
|
753
785
|
const engineName = 'LittleJS';
|
|
754
786
|
|
|
755
787
|
/** Version of engine */
|
|
756
|
-
const engineVersion = '1.2.
|
|
788
|
+
const engineVersion = '1.2.8';
|
|
757
789
|
|
|
758
790
|
/** Frames per second to update objects
|
|
759
791
|
* @default */
|
|
@@ -834,8 +866,6 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
834
866
|
// main update loop
|
|
835
867
|
const engineUpdate = (frameTimeMS=0)=>
|
|
836
868
|
{
|
|
837
|
-
requestAnimationFrame(engineUpdate);
|
|
838
|
-
|
|
839
869
|
// update time keeping
|
|
840
870
|
let frameTimeDeltaMS = frameTimeMS - frameTimeLastMS;
|
|
841
871
|
frameTimeLastMS = frameTimeMS;
|
|
@@ -934,6 +964,8 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
934
964
|
overlayContext.fillText(text, mainCanvas.width-2, 2);
|
|
935
965
|
drawCount = 0;
|
|
936
966
|
}
|
|
967
|
+
|
|
968
|
+
requestAnimationFrame(engineUpdate);
|
|
937
969
|
}
|
|
938
970
|
|
|
939
971
|
// set tile image source to load the image and start the engine
|
|
@@ -1051,7 +1083,7 @@ class EngineObject
|
|
|
1051
1083
|
* @param {Vector2} [size=objectDefaultSize] - World space size of the object
|
|
1052
1084
|
* @param {Number} [tileIndex=-1] - Tile to use to render object, untextured if -1
|
|
1053
1085
|
* @param {Vector2} [tileSize=tileSizeDefault] - Size of tile in source pixels
|
|
1054
|
-
* @param {Number} [angle=0] - Angle
|
|
1086
|
+
* @param {Number} [angle=0] - Angle the object is rotated by
|
|
1055
1087
|
* @param {Color} [color] - Color to apply to tile when rendered
|
|
1056
1088
|
* @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
|
|
1057
1089
|
*/
|
|
@@ -1367,6 +1399,22 @@ class EngineObject
|
|
|
1367
1399
|
this.isSolid = isSolid;
|
|
1368
1400
|
this.collideTiles = collideTiles;
|
|
1369
1401
|
}
|
|
1402
|
+
|
|
1403
|
+
toString()
|
|
1404
|
+
{
|
|
1405
|
+
let text = 'type = ' + this.constructor.name;
|
|
1406
|
+
if (this.pos.x || this.pos.y)
|
|
1407
|
+
text += '\npos = ' + this.pos;
|
|
1408
|
+
if (this.velocity.x || this.velocity.y)
|
|
1409
|
+
text += '\nvelocity = ' + this.velocity;
|
|
1410
|
+
if (this.size.x || this.size.y)
|
|
1411
|
+
text += '\nsize = ' + this.size;
|
|
1412
|
+
if (this.angle)
|
|
1413
|
+
text += '\nangle = ' + this.angle.toFixed(3);
|
|
1414
|
+
if (this.color)
|
|
1415
|
+
text += '\ncolor = ' + this.color;
|
|
1416
|
+
return text;
|
|
1417
|
+
}
|
|
1370
1418
|
}
|
|
1371
1419
|
/**
|
|
1372
1420
|
* LittleJS Drawing System
|
|
@@ -1480,7 +1528,7 @@ function drawTile(pos, size=vec2(1), tileIndex=-1, tileSize=tileSizeDefault, col
|
|
|
1480
1528
|
if (tileIndex < 0)
|
|
1481
1529
|
{
|
|
1482
1530
|
// if negative tile index, force untextured
|
|
1483
|
-
context.fillStyle = color
|
|
1531
|
+
context.fillStyle = color;
|
|
1484
1532
|
context.fillRect(-.5, -.5, 1, 1);
|
|
1485
1533
|
}
|
|
1486
1534
|
else
|
|
@@ -1585,7 +1633,8 @@ function setBlendMode(additive, useWebGL=glEnable)
|
|
|
1585
1633
|
mainContext.globalCompositeOperation = additive ? 'lighter' : 'source-over';
|
|
1586
1634
|
}
|
|
1587
1635
|
|
|
1588
|
-
/** Draw text on overlay canvas in
|
|
1636
|
+
/** Draw text on overlay canvas in screen space
|
|
1637
|
+
* Automatically splits new lines into rows
|
|
1589
1638
|
* @param {String} text
|
|
1590
1639
|
* @param {Vector2} pos
|
|
1591
1640
|
* @param {Number} [size=1]
|
|
@@ -1594,20 +1643,37 @@ function setBlendMode(additive, useWebGL=glEnable)
|
|
|
1594
1643
|
* @param {Color} [lineColor=new Color(0,0,0)]
|
|
1595
1644
|
* @param {String} [textAlign='center']
|
|
1596
1645
|
* @memberof Draw */
|
|
1597
|
-
function
|
|
1646
|
+
function drawTextScreen(text, pos, size=1, color=new Color, lineWidth=0, lineColor=new Color(0,0,0), textAlign='center', font=fontDefault)
|
|
1598
1647
|
{
|
|
1599
|
-
|
|
1600
|
-
overlayContext.
|
|
1648
|
+
overlayContext.fillStyle = color;
|
|
1649
|
+
overlayContext.lineWidth = lineWidth *= cameraScale;
|
|
1650
|
+
overlayContext.strokeStyle = lineColor;
|
|
1601
1651
|
overlayContext.textAlign = textAlign;
|
|
1652
|
+
overlayContext.font = size + 'px '+ font;
|
|
1602
1653
|
overlayContext.textBaseline = 'middle';
|
|
1603
|
-
|
|
1654
|
+
|
|
1655
|
+
pos = pos.copy();
|
|
1656
|
+
text.split('\n').forEach(line=>
|
|
1604
1657
|
{
|
|
1605
|
-
overlayContext.
|
|
1606
|
-
overlayContext.
|
|
1607
|
-
|
|
1608
|
-
}
|
|
1609
|
-
|
|
1610
|
-
|
|
1658
|
+
lineWidth && overlayContext.strokeText(line, pos.x, pos.y);
|
|
1659
|
+
overlayContext.fillText(line, pos.x, pos.y);
|
|
1660
|
+
pos.y += size;
|
|
1661
|
+
});
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
/** Draw text on overlay canvas in world space
|
|
1665
|
+
* Automatically splits new lines into rows
|
|
1666
|
+
* @param {String} text
|
|
1667
|
+
* @param {Vector2} pos
|
|
1668
|
+
* @param {Number} [size=1]
|
|
1669
|
+
* @param {Color} [color=new Color(1,1,1)]
|
|
1670
|
+
* @param {Number} [lineWidth=0]
|
|
1671
|
+
* @param {Color} [lineColor=new Color(0,0,0)]
|
|
1672
|
+
* @param {String} [textAlign='center']
|
|
1673
|
+
* @memberof Draw */
|
|
1674
|
+
function drawText(text, pos, size=1, color, lineWidth, lineColor, textAlign, font)
|
|
1675
|
+
{
|
|
1676
|
+
drawTextScreen(text, worldToScreen(pos), size*cameraScale, color, lineWidth, lineColor, textAlign, font);
|
|
1611
1677
|
}
|
|
1612
1678
|
|
|
1613
1679
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -2762,14 +2828,14 @@ class TileLayerData
|
|
|
2762
2828
|
*/
|
|
2763
2829
|
class TileLayer extends EngineObject
|
|
2764
2830
|
{
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2831
|
+
/** Create a tile layer object
|
|
2832
|
+
* @param {Vector2} [position=new Vector2()] - World space position
|
|
2833
|
+
* @param {Vector2} [size=tileCollisionSize] - World space size
|
|
2834
|
+
* @param {Vector2} [tileSize=tileSizeDefault] - Size of tiles in source pixels
|
|
2835
|
+
* @param {Vector2} [scale=new Vector2(1,1)] - How much to scale this layer when rendered
|
|
2836
|
+
* @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
|
|
2837
|
+
*/
|
|
2838
|
+
constructor(pos, size=tileCollisionSize, tileSize=tileSizeDefault, scale=vec2(1), renderOrder=0)
|
|
2773
2839
|
{
|
|
2774
2840
|
super(pos, size, -1, tileSize, 0, undefined, renderOrder);
|
|
2775
2841
|
|
|
@@ -2929,7 +2995,7 @@ class TileLayer extends EngineObject
|
|
|
2929
2995
|
if (tileIndex < 0)
|
|
2930
2996
|
{
|
|
2931
2997
|
// untextured
|
|
2932
|
-
context.fillStyle = color
|
|
2998
|
+
context.fillStyle = color;
|
|
2933
2999
|
context.fillRect(-.5, -.5, 1, 1);
|
|
2934
3000
|
}
|
|
2935
3001
|
else
|
|
@@ -2948,7 +3014,8 @@ class TileLayer extends EngineObject
|
|
|
2948
3014
|
* @param {Vector2} [size=new Vector2(1,1)]
|
|
2949
3015
|
* @param {Color} [color=new Color(1,1,1)]
|
|
2950
3016
|
* @param {Number} [angle=0] */
|
|
2951
|
-
drawRect(pos, size, color, angle)
|
|
3017
|
+
drawRect(pos, size, color, angle)
|
|
3018
|
+
{ this.drawTile(pos, size, -1, 0, color, angle); }
|
|
2952
3019
|
}
|
|
2953
3020
|
/*
|
|
2954
3021
|
LittleJS Particle System
|
|
@@ -2980,7 +3047,7 @@ class ParticleEmitter extends EngineObject
|
|
|
2980
3047
|
{
|
|
2981
3048
|
/** Create a particle system with the given settings
|
|
2982
3049
|
* @param {Vector2} position - World space position of the emitter
|
|
2983
|
-
* @param {Number} [angle=0] - Angle to
|
|
3050
|
+
* @param {Number} [angle=0] - Angle to emit the particles
|
|
2984
3051
|
* @param {Number} [emitSize=0] - World space size of the emitter (float for circle diameter, vec2 for rect)
|
|
2985
3052
|
* @param {Number} [emitTime=0] - How long to stay alive (0 is forever)
|
|
2986
3053
|
* @param {Number} [emitRate=100] - How many particles per second to spawn, does not emit if 0
|
|
@@ -3271,7 +3338,7 @@ function medalsInit(saveName)
|
|
|
3271
3338
|
{
|
|
3272
3339
|
// check if medals are unlocked
|
|
3273
3340
|
medalsSaveName = saveName;
|
|
3274
|
-
debugMedals || medals.forEach(medal=>
|
|
3341
|
+
debugMedals || medals.forEach(medal=> localStorage[medal.storageKey()]);
|
|
3275
3342
|
}
|
|
3276
3343
|
|
|
3277
3344
|
/**
|
|
@@ -3460,6 +3527,9 @@ class Newgrounds
|
|
|
3460
3527
|
const scoreboardResult = this.call('ScoreBoard.getBoards');
|
|
3461
3528
|
this.scoreboards = scoreboardResult ? scoreboardResult.result.data.scoreboards : [];
|
|
3462
3529
|
debugMedals && console.log(this.scoreboards);
|
|
3530
|
+
|
|
3531
|
+
const keepAliveMS = 5 * 60 * 1e3;
|
|
3532
|
+
setInterval(()=>this.call('Gateway.ping', 0, 1), keepAliveMS);
|
|
3463
3533
|
}
|
|
3464
3534
|
|
|
3465
3535
|
/** Send message to unlock a medal by id
|
|
@@ -3581,7 +3651,7 @@ function glInit()
|
|
|
3581
3651
|
|
|
3582
3652
|
// setup vertex and fragment shaders
|
|
3583
3653
|
glShader = glCreateProgram(
|
|
3584
|
-
'precision highp float;'+ // use highp for better accuracy
|
|
3654
|
+
'precision highp float;'+ // use highp for better accuracy
|
|
3585
3655
|
'uniform mat4 m;'+ // transform matrix
|
|
3586
3656
|
'attribute vec2 p,t;'+ // position, uv
|
|
3587
3657
|
'attribute vec4 c,a;'+ // color, additiveColor
|
|
@@ -3592,7 +3662,7 @@ function glInit()
|
|
|
3592
3662
|
'v=t;d=c;e=a;'+ // pass stuff to fragment shader
|
|
3593
3663
|
'}' // end of shader
|
|
3594
3664
|
,
|
|
3595
|
-
'precision highp float;'+ // use highp for better accuracy
|
|
3665
|
+
'precision highp float;'+ // use highp for better accuracy
|
|
3596
3666
|
'varying vec2 v;'+ // uv
|
|
3597
3667
|
'varying vec4 d,e;'+ // color, additiveColor
|
|
3598
3668
|
'uniform sampler2D s;'+ // texture
|
package/engine/engine.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
const engineName = 'LittleJS';
|
|
23
23
|
|
|
24
24
|
/** Version of engine */
|
|
25
|
-
const engineVersion = '1.2.
|
|
25
|
+
const engineVersion = '1.2.9';
|
|
26
26
|
|
|
27
27
|
/** Frames per second to update objects
|
|
28
28
|
* @default */
|
|
@@ -103,8 +103,6 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
103
103
|
// main update loop
|
|
104
104
|
const engineUpdate = (frameTimeMS=0)=>
|
|
105
105
|
{
|
|
106
|
-
requestAnimationFrame(engineUpdate);
|
|
107
|
-
|
|
108
106
|
// update time keeping
|
|
109
107
|
let frameTimeDeltaMS = frameTimeMS - frameTimeLastMS;
|
|
110
108
|
frameTimeLastMS = frameTimeMS;
|
|
@@ -203,6 +201,8 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
203
201
|
overlayContext.fillText(text, mainCanvas.width-2, 2);
|
|
204
202
|
drawCount = 0;
|
|
205
203
|
}
|
|
204
|
+
|
|
205
|
+
requestAnimationFrame(engineUpdate);
|
|
206
206
|
}
|
|
207
207
|
|
|
208
208
|
// set tile image source to load the image and start the engine
|
package/engine/engineDebug.js
CHANGED
|
@@ -273,17 +273,11 @@ const debugRender = ()=>
|
|
|
273
273
|
drawRect(mousePos.floor().add(vec2(.5)), vec2(1), new Color(0,0,1,.5));
|
|
274
274
|
drawLine(mousePos, bestObject.pos, .1, !raycastHitPos ? new Color(0,1,0,.5) : new Color(1,0,0,.5));
|
|
275
275
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
+ (bestObject.angle>0?' ':' ') + (bestObject.angle*180/PI).toFixed(1) + '°',
|
|
282
|
-
pos = pos.add(height), ...args);
|
|
283
|
-
drawText('vel = ' + printVec2(bestObject.velocity), pos = pos.add(height), ...args);
|
|
284
|
-
drawText('size = ' + printVec2(bestObject.size), pos = pos.add(height), ...args);
|
|
285
|
-
drawText('type = ' + ( bestObject.constructor.name), pos = mousePos.subtract(height), ...args);
|
|
286
|
-
drawText('collision = ' + getTileCollisionData(mousePos), pos = mousePos.subtract(height.scale(2)), ...args);
|
|
276
|
+
const debugText = 'mouse pos = ' + mousePos +
|
|
277
|
+
'\nmouse collision = ' + getTileCollisionData(mousePos) +
|
|
278
|
+
'\n\n--- object info ---\n' +
|
|
279
|
+
bestObject.toString();
|
|
280
|
+
drawTextScreen(debugText, mousePosScreen, 24, new Color, .05, undefined, undefined, 'monospace');
|
|
287
281
|
mainContext = saveContext;
|
|
288
282
|
}
|
|
289
283
|
|
|
@@ -292,11 +286,12 @@ const debugRender = ()=>
|
|
|
292
286
|
|
|
293
287
|
{
|
|
294
288
|
// draw debug primitives
|
|
295
|
-
overlayContext.save();
|
|
296
289
|
overlayContext.lineWidth = 2;
|
|
297
290
|
const pointSize = debugPointSize * cameraScale;
|
|
298
291
|
debugPrimitives.forEach(p=>
|
|
299
292
|
{
|
|
293
|
+
overlayContext.save();
|
|
294
|
+
|
|
300
295
|
// create canvas transform from world space to screen space
|
|
301
296
|
const pos = worldToScreen(p.pos);
|
|
302
297
|
|
|
@@ -332,12 +327,12 @@ const debugRender = ()=>
|
|
|
332
327
|
p.fill && overlayContext.fill();
|
|
333
328
|
overlayContext.stroke();
|
|
334
329
|
}
|
|
330
|
+
|
|
331
|
+
overlayContext.restore();
|
|
335
332
|
});
|
|
336
333
|
|
|
337
334
|
// remove expired pritives
|
|
338
335
|
debugPrimitives = debugPrimitives.filter(r=>r.time.get()<0);
|
|
339
|
-
|
|
340
|
-
overlayContext.restore();
|
|
341
336
|
}
|
|
342
337
|
|
|
343
338
|
{
|
package/engine/engineDraw.js
CHANGED
|
@@ -110,7 +110,7 @@ function drawTile(pos, size=vec2(1), tileIndex=-1, tileSize=tileSizeDefault, col
|
|
|
110
110
|
if (tileIndex < 0)
|
|
111
111
|
{
|
|
112
112
|
// if negative tile index, force untextured
|
|
113
|
-
context.fillStyle = color
|
|
113
|
+
context.fillStyle = color;
|
|
114
114
|
context.fillRect(-.5, -.5, 1, 1);
|
|
115
115
|
}
|
|
116
116
|
else
|
|
@@ -215,7 +215,8 @@ function setBlendMode(additive, useWebGL=glEnable)
|
|
|
215
215
|
mainContext.globalCompositeOperation = additive ? 'lighter' : 'source-over';
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
-
/** Draw text on overlay canvas in
|
|
218
|
+
/** Draw text on overlay canvas in screen space
|
|
219
|
+
* Automatically splits new lines into rows
|
|
219
220
|
* @param {String} text
|
|
220
221
|
* @param {Vector2} pos
|
|
221
222
|
* @param {Number} [size=1]
|
|
@@ -224,20 +225,37 @@ function setBlendMode(additive, useWebGL=glEnable)
|
|
|
224
225
|
* @param {Color} [lineColor=new Color(0,0,0)]
|
|
225
226
|
* @param {String} [textAlign='center']
|
|
226
227
|
* @memberof Draw */
|
|
227
|
-
function
|
|
228
|
+
function drawTextScreen(text, pos, size=1, color=new Color, lineWidth=0, lineColor=new Color(0,0,0), textAlign='center', font=fontDefault)
|
|
228
229
|
{
|
|
229
|
-
|
|
230
|
-
overlayContext.
|
|
230
|
+
overlayContext.fillStyle = color;
|
|
231
|
+
overlayContext.lineWidth = lineWidth *= cameraScale;
|
|
232
|
+
overlayContext.strokeStyle = lineColor;
|
|
231
233
|
overlayContext.textAlign = textAlign;
|
|
234
|
+
overlayContext.font = size + 'px '+ font;
|
|
232
235
|
overlayContext.textBaseline = 'middle';
|
|
233
|
-
|
|
236
|
+
|
|
237
|
+
pos = pos.copy();
|
|
238
|
+
text.split('\n').forEach(line=>
|
|
234
239
|
{
|
|
235
|
-
overlayContext.
|
|
236
|
-
overlayContext.
|
|
237
|
-
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
|
|
240
|
+
lineWidth && overlayContext.strokeText(line, pos.x, pos.y);
|
|
241
|
+
overlayContext.fillText(line, pos.x, pos.y);
|
|
242
|
+
pos.y += size;
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/** Draw text on overlay canvas in world space
|
|
247
|
+
* Automatically splits new lines into rows
|
|
248
|
+
* @param {String} text
|
|
249
|
+
* @param {Vector2} pos
|
|
250
|
+
* @param {Number} [size=1]
|
|
251
|
+
* @param {Color} [color=new Color(1,1,1)]
|
|
252
|
+
* @param {Number} [lineWidth=0]
|
|
253
|
+
* @param {Color} [lineColor=new Color(0,0,0)]
|
|
254
|
+
* @param {String} [textAlign='center']
|
|
255
|
+
* @memberof Draw */
|
|
256
|
+
function drawText(text, pos, size=1, color, lineWidth, lineColor, textAlign, font)
|
|
257
|
+
{
|
|
258
|
+
drawTextScreen(text, worldToScreen(pos), size*cameraScale, color, lineWidth, lineColor, textAlign, font);
|
|
241
259
|
}
|
|
242
260
|
|
|
243
261
|
///////////////////////////////////////////////////////////////////////////////
|
package/engine/engineMedals.js
CHANGED
|
@@ -35,7 +35,7 @@ function medalsInit(saveName)
|
|
|
35
35
|
{
|
|
36
36
|
// check if medals are unlocked
|
|
37
37
|
medalsSaveName = saveName;
|
|
38
|
-
debugMedals || medals.forEach(medal=>
|
|
38
|
+
debugMedals || medals.forEach(medal=> localStorage[medal.storageKey()]);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/**
|
|
@@ -224,6 +224,9 @@ class Newgrounds
|
|
|
224
224
|
const scoreboardResult = this.call('ScoreBoard.getBoards');
|
|
225
225
|
this.scoreboards = scoreboardResult ? scoreboardResult.result.data.scoreboards : [];
|
|
226
226
|
debugMedals && console.log(this.scoreboards);
|
|
227
|
+
|
|
228
|
+
const keepAliveMS = 5 * 60 * 1e3;
|
|
229
|
+
setInterval(()=>this.call('Gateway.ping', 0, 1), keepAliveMS);
|
|
227
230
|
}
|
|
228
231
|
|
|
229
232
|
/** Send message to unlock a medal by id
|
package/engine/engineObject.js
CHANGED
|
@@ -36,7 +36,7 @@ class EngineObject
|
|
|
36
36
|
* @param {Vector2} [size=objectDefaultSize] - World space size of the object
|
|
37
37
|
* @param {Number} [tileIndex=-1] - Tile to use to render object, untextured if -1
|
|
38
38
|
* @param {Vector2} [tileSize=tileSizeDefault] - Size of tile in source pixels
|
|
39
|
-
* @param {Number} [angle=0] - Angle
|
|
39
|
+
* @param {Number} [angle=0] - Angle the object is rotated by
|
|
40
40
|
* @param {Color} [color] - Color to apply to tile when rendered
|
|
41
41
|
* @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
|
|
42
42
|
*/
|
|
@@ -352,4 +352,20 @@ class EngineObject
|
|
|
352
352
|
this.isSolid = isSolid;
|
|
353
353
|
this.collideTiles = collideTiles;
|
|
354
354
|
}
|
|
355
|
+
|
|
356
|
+
toString()
|
|
357
|
+
{
|
|
358
|
+
let text = 'type = ' + this.constructor.name;
|
|
359
|
+
if (this.pos.x || this.pos.y)
|
|
360
|
+
text += '\npos = ' + this.pos;
|
|
361
|
+
if (this.velocity.x || this.velocity.y)
|
|
362
|
+
text += '\nvelocity = ' + this.velocity;
|
|
363
|
+
if (this.size.x || this.size.y)
|
|
364
|
+
text += '\nsize = ' + this.size;
|
|
365
|
+
if (this.angle)
|
|
366
|
+
text += '\nangle = ' + this.angle.toFixed(3);
|
|
367
|
+
if (this.color)
|
|
368
|
+
text += '\ncolor = ' + this.color;
|
|
369
|
+
return text;
|
|
370
|
+
}
|
|
355
371
|
}
|
|
@@ -28,7 +28,7 @@ class ParticleEmitter extends EngineObject
|
|
|
28
28
|
{
|
|
29
29
|
/** Create a particle system with the given settings
|
|
30
30
|
* @param {Vector2} position - World space position of the emitter
|
|
31
|
-
* @param {Number} [angle=0] - Angle to
|
|
31
|
+
* @param {Number} [angle=0] - Angle to emit the particles
|
|
32
32
|
* @param {Number} [emitSize=0] - World space size of the emitter (float for circle diameter, vec2 for rect)
|
|
33
33
|
* @param {Number} [emitTime=0] - How long to stay alive (0 is forever)
|
|
34
34
|
* @param {Number} [emitRate=100] - How many particles per second to spawn, does not emit if 0
|
|
@@ -153,14 +153,14 @@ class TileLayerData
|
|
|
153
153
|
*/
|
|
154
154
|
class TileLayer extends EngineObject
|
|
155
155
|
{
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
156
|
+
/** Create a tile layer object
|
|
157
|
+
* @param {Vector2} [position=new Vector2()] - World space position
|
|
158
|
+
* @param {Vector2} [size=tileCollisionSize] - World space size
|
|
159
|
+
* @param {Vector2} [tileSize=tileSizeDefault] - Size of tiles in source pixels
|
|
160
|
+
* @param {Vector2} [scale=new Vector2(1,1)] - How much to scale this layer when rendered
|
|
161
|
+
* @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
|
|
162
|
+
*/
|
|
163
|
+
constructor(pos, size=tileCollisionSize, tileSize=tileSizeDefault, scale=vec2(1), renderOrder=0)
|
|
164
164
|
{
|
|
165
165
|
super(pos, size, -1, tileSize, 0, undefined, renderOrder);
|
|
166
166
|
|
|
@@ -320,7 +320,7 @@ class TileLayer extends EngineObject
|
|
|
320
320
|
if (tileIndex < 0)
|
|
321
321
|
{
|
|
322
322
|
// untextured
|
|
323
|
-
context.fillStyle = color
|
|
323
|
+
context.fillStyle = color;
|
|
324
324
|
context.fillRect(-.5, -.5, 1, 1);
|
|
325
325
|
}
|
|
326
326
|
else
|
|
@@ -339,5 +339,6 @@ class TileLayer extends EngineObject
|
|
|
339
339
|
* @param {Vector2} [size=new Vector2(1,1)]
|
|
340
340
|
* @param {Color} [color=new Color(1,1,1)]
|
|
341
341
|
* @param {Number} [angle=0] */
|
|
342
|
-
drawRect(pos, size, color, angle)
|
|
342
|
+
drawRect(pos, size, color, angle)
|
|
343
|
+
{ this.drawTile(pos, size, -1, 0, color, angle); }
|
|
343
344
|
}
|
|
@@ -311,7 +311,13 @@ class Vector2
|
|
|
311
311
|
/** Returns true if this vector is within the bounds of an array size passed in
|
|
312
312
|
* @param {Vector2} arraySize
|
|
313
313
|
* @return {Boolean} */
|
|
314
|
-
arrayCheck(arraySize) { return this.x >= 0 && this.y >= 0 && this.x < arraySize.x && this.y < arraySize.y; }
|
|
314
|
+
arrayCheck(arraySize) { return this.x >= 0 && this.y >= 0 && this.x < arraySize.x && this.y < arraySize.y; }
|
|
315
|
+
|
|
316
|
+
/** Returns this vector expressed as a string
|
|
317
|
+
* @param {float} digits - precision to display
|
|
318
|
+
* @return {String} */
|
|
319
|
+
toString(digits=3)
|
|
320
|
+
{ return `(${(this.x<0?'':' ') + this.x.toFixed(digits)},${(this.y<0?'':' ') + this.y.toFixed(digits)} )`; }
|
|
315
321
|
}
|
|
316
322
|
|
|
317
323
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -382,7 +388,7 @@ class Color
|
|
|
382
388
|
* @return {Color} */
|
|
383
389
|
lerp(c, p) { return this.add(c.subtract(this).scale(clamp(p))); }
|
|
384
390
|
|
|
385
|
-
/** Sets this color given a hue, saturation, lightness
|
|
391
|
+
/** Sets this color given a hue, saturation, lightness, and alpha
|
|
386
392
|
* @param {Number} [hue=0]
|
|
387
393
|
* @param {Number} [saturation=0]
|
|
388
394
|
* @param {Number} [lightness=1]
|
|
@@ -418,21 +424,43 @@ class Color
|
|
|
418
424
|
).clamp();
|
|
419
425
|
}
|
|
420
426
|
|
|
421
|
-
/** Returns this color expressed as an
|
|
427
|
+
/** Returns this color expressed as an CSS color value
|
|
422
428
|
* @return {String} */
|
|
423
|
-
|
|
429
|
+
toString()
|
|
424
430
|
{
|
|
425
431
|
ASSERT(this.r>=0 && this.r<=1 && this.g>=0 && this.g<=1 && this.b>=0 && this.b<=1 && this.a>=0 && this.a<=1);
|
|
426
432
|
return `rgb(${this.r*255|0},${this.g*255|0},${this.b*255|0},${this.a})`;
|
|
427
433
|
}
|
|
428
434
|
|
|
429
|
-
/** Returns this color expressed as 32 bit integer value
|
|
435
|
+
/** Returns this color expressed as 32 bit integer RGBA value
|
|
430
436
|
* @return {Number} */
|
|
431
437
|
rgbaInt()
|
|
432
438
|
{
|
|
433
439
|
ASSERT(this.r>=0 && this.r<=1 && this.g>=0 && this.g<=1 && this.b>=0 && this.b<=1 && this.a>=0 && this.a<=1);
|
|
434
440
|
return (this.r*255|0) + (this.g*255<<8) + (this.b*255<<16) + (this.a*255<<24);
|
|
435
441
|
}
|
|
442
|
+
|
|
443
|
+
/** Returns this color expressed as a hex code
|
|
444
|
+
* @return {String} */
|
|
445
|
+
hex()
|
|
446
|
+
{
|
|
447
|
+
const toHex = (c)=> ((c=c*255|0)<16 ? '0' : '') + c.toString(16);
|
|
448
|
+
return '#' + toHex(this.r) + toHex(this.g) + toHex(this.b);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/** Set this color from a hex code
|
|
452
|
+
* @param {String} hex - html hex code
|
|
453
|
+
* @return {Color} */
|
|
454
|
+
setHex(hex)
|
|
455
|
+
{
|
|
456
|
+
const fromHex = (a)=> parseInt(hex.slice(a,a+2), 16)/255;
|
|
457
|
+
this.r = fromHex(1);
|
|
458
|
+
this.g = fromHex(3),
|
|
459
|
+
this.b = fromHex(5);
|
|
460
|
+
this.a = 1;
|
|
461
|
+
ASSERT(this.r>=0 && this.r<=1 && this.g>=0 && this.g<=1 && this.b>=0 && this.b<=1);
|
|
462
|
+
return this;
|
|
463
|
+
}
|
|
436
464
|
}
|
|
437
465
|
|
|
438
466
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -469,7 +497,7 @@ class Timer
|
|
|
469
497
|
|
|
470
498
|
/** Returns true if set and elapsed
|
|
471
499
|
* @return {Boolean} */
|
|
472
|
-
elapsed() { return time >
|
|
500
|
+
elapsed() { return time > this.time; }
|
|
473
501
|
|
|
474
502
|
/** Get how long since elapsed, returns 0 if not set (returns negative if currently active)
|
|
475
503
|
* @return {Number} */
|
|
@@ -478,4 +506,8 @@ class Timer
|
|
|
478
506
|
/** Get percentage elapsed based on time it was set to, returns 0 if not set
|
|
479
507
|
* @return {Number} */
|
|
480
508
|
getPercent() { return this.isSet()? percent(this.time - time, this.setTime, 0) : 0; }
|
|
509
|
+
|
|
510
|
+
/** Returns this timer expressed as a string
|
|
511
|
+
* @return {String} */
|
|
512
|
+
toString() { return this.unset() ? 'unset' : Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ); }
|
|
481
513
|
}
|
package/engine/engineWebGL.js
CHANGED
|
@@ -47,7 +47,7 @@ function glInit()
|
|
|
47
47
|
|
|
48
48
|
// setup vertex and fragment shaders
|
|
49
49
|
glShader = glCreateProgram(
|
|
50
|
-
'precision highp float;'+ // use highp for better accuracy
|
|
50
|
+
'precision highp float;'+ // use highp for better accuracy
|
|
51
51
|
'uniform mat4 m;'+ // transform matrix
|
|
52
52
|
'attribute vec2 p,t;'+ // position, uv
|
|
53
53
|
'attribute vec4 c,a;'+ // color, additiveColor
|
|
@@ -58,7 +58,7 @@ function glInit()
|
|
|
58
58
|
'v=t;d=c;e=a;'+ // pass stuff to fragment shader
|
|
59
59
|
'}' // end of shader
|
|
60
60
|
,
|
|
61
|
-
'precision highp float;'+ // use highp for better accuracy
|
|
61
|
+
'precision highp float;'+ // use highp for better accuracy
|
|
62
62
|
'varying vec2 v;'+ // uv
|
|
63
63
|
'varying vec4 d,e;'+ // color, additiveColor
|
|
64
64
|
'uniform sampler2D s;'+ // texture
|