littlejsengine 1.3.5 → 1.4.0
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/README.md +7 -4
- package/engine/engine.all.js +112 -74
- package/engine/engine.all.min.js +1 -1
- package/engine/engine.all.release.js +113 -75
- package/engine/engine.js +30 -27
- package/engine/engineDebug.js +1 -1
- package/engine/engineDraw.js +13 -5
- package/engine/engineInput.js +2 -2
- package/engine/engineRelease.js +2 -2
- package/engine/engineSettings.js +2 -1
- package/engine/engineTileLayer.js +1 -1
- package/engine/engineUtilities.js +62 -36
- package/engine/engineWebGL.js +1 -1
- package/engine/index.d.ts +34 -8
- package/examples/breakout/index.html +3 -3
- package/examples/particles/index.html +14 -14
- package/examples/platformer/game.js +1 -1
- package/examples/platformer/gameObjects.js +2 -2
- package/examples/platformer/index.html +5 -5
- package/examples/puzzle/index.html +2 -2
- package/examples/stress/index.html +1 -1
- package/game.js +1 -1
- package/index.html +13 -13
- package/package.json +1 -1
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
11
|
+
let showWatermark = 0;
|
|
12
|
+
let godMode = 0;
|
|
11
13
|
const debug = 0;
|
|
12
|
-
const showWatermark = 0;
|
|
13
|
-
const godMode = 0;
|
|
14
14
|
const debugOverlay = 0;
|
|
15
15
|
const debugPhysics = 0;
|
|
16
16
|
const debugParticles = 0;
|
|
@@ -355,6 +355,28 @@ class Vector2
|
|
|
355
355
|
|
|
356
356
|
///////////////////////////////////////////////////////////////////////////////
|
|
357
357
|
|
|
358
|
+
/**
|
|
359
|
+
* Create a color object with RGBA values
|
|
360
|
+
* @param {Number} [r=1]
|
|
361
|
+
* @param {Number} [g=1]
|
|
362
|
+
* @param {Number} [b=1]
|
|
363
|
+
* @param {Number} [a=1]
|
|
364
|
+
* @return {Color}
|
|
365
|
+
* @memberof Utilities
|
|
366
|
+
*/
|
|
367
|
+
const colorRGBA = (r, g, b, a)=> new Color(r, g, b, a);
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Create a color object with HSLA values
|
|
371
|
+
* @param {Number} [h=0]
|
|
372
|
+
* @param {Number} [s=0]
|
|
373
|
+
* @param {Number} [l=1]
|
|
374
|
+
* @param {Number} [a=1]
|
|
375
|
+
* @return {Color}
|
|
376
|
+
* @memberof Utilities
|
|
377
|
+
*/
|
|
378
|
+
const colorHSLA = (h, s, l, a)=> new Color().setHSLA(h, s, l, a);
|
|
379
|
+
|
|
358
380
|
/**
|
|
359
381
|
* Color object (red, green, blue, alpha) with some helpful functions
|
|
360
382
|
* @example
|
|
@@ -442,6 +464,34 @@ class Color
|
|
|
442
464
|
return this;
|
|
443
465
|
}
|
|
444
466
|
|
|
467
|
+
/** Returns this color expressed in hsla format
|
|
468
|
+
* @return {Array} */
|
|
469
|
+
getHSLA()
|
|
470
|
+
{
|
|
471
|
+
const r = this.r;
|
|
472
|
+
const g = this.g;
|
|
473
|
+
const b = this.b;
|
|
474
|
+
const a = this.a;
|
|
475
|
+
const max = Math.max(r, g, b);
|
|
476
|
+
const min = Math.min(r, g, b);
|
|
477
|
+
const l = (max + min) / 2;
|
|
478
|
+
|
|
479
|
+
let h = 0, s = 0;
|
|
480
|
+
if (max != min)
|
|
481
|
+
{
|
|
482
|
+
let d = max - min;
|
|
483
|
+
s = l > .5 ? d / (2 - max - min) : d / (max + min);
|
|
484
|
+
if (r == max)
|
|
485
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
486
|
+
else if (g == max)
|
|
487
|
+
h = (b - r) / d + 2;
|
|
488
|
+
else if (b == max)
|
|
489
|
+
h = (r - g) / d + 4;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
return [h / 6, s, l, a];
|
|
493
|
+
}
|
|
494
|
+
|
|
445
495
|
/** Returns a new color that has each component randomly adjusted
|
|
446
496
|
* @param {Number} [amount=.05]
|
|
447
497
|
* @param {Number} [alphaAmount=0]
|
|
@@ -473,42 +523,6 @@ class Color
|
|
|
473
523
|
return (this.r*255|0) + (this.g*255<<8) + (this.b*255<<16) + (this.a*255<<24);
|
|
474
524
|
}
|
|
475
525
|
|
|
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
|
-
/** Returns this color expressed in hsla format
|
|
485
|
-
* @return {Array} */
|
|
486
|
-
getHSLA()
|
|
487
|
-
{
|
|
488
|
-
const r = this.r;
|
|
489
|
-
const g = this.g;
|
|
490
|
-
const b = this.b;
|
|
491
|
-
const a = this.a;
|
|
492
|
-
const max = Math.max(r, g, b);
|
|
493
|
-
const min = Math.min(r, g, b);
|
|
494
|
-
const l = (max + min) / 2;
|
|
495
|
-
|
|
496
|
-
let h = 0, s = 0;
|
|
497
|
-
if (max != min)
|
|
498
|
-
{
|
|
499
|
-
let d = max - min;
|
|
500
|
-
s = l > .5 ? d / (2 - max - min) : d / (max + min);
|
|
501
|
-
if (r == max)
|
|
502
|
-
h = (g - b) / d + (g < b ? 6 : 0);
|
|
503
|
-
else if (g == max)
|
|
504
|
-
h = (b - r) / d + 2;
|
|
505
|
-
else if (b == max)
|
|
506
|
-
h = (r - g) / d + 4;
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
return [h / 6, s, l, a];
|
|
510
|
-
}
|
|
511
|
-
|
|
512
526
|
/** Set this color from a hex code
|
|
513
527
|
* @param {String} hex - html hex code
|
|
514
528
|
* @return {Color} */
|
|
@@ -522,6 +536,14 @@ class Color
|
|
|
522
536
|
ASSERT(this.r>=0 && this.r<=1 && this.g>=0 && this.g<=1 && this.b>=0 && this.b<=1);
|
|
523
537
|
return this;
|
|
524
538
|
}
|
|
539
|
+
|
|
540
|
+
/** Returns this color expressed as a hex code
|
|
541
|
+
* @return {String} */
|
|
542
|
+
getHex()
|
|
543
|
+
{
|
|
544
|
+
const toHex = (c)=> ((c=c*255|0)<16 ? '0' : '') + c.toString(16);
|
|
545
|
+
return '#' + toHex(this.r) + toHex(this.g) + toHex(this.b);
|
|
546
|
+
}
|
|
525
547
|
}
|
|
526
548
|
|
|
527
549
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -571,6 +593,10 @@ class Timer
|
|
|
571
593
|
/** Returns this timer expressed as a string
|
|
572
594
|
* @return {String} */
|
|
573
595
|
toString() { if (debug) { return this.unset() ? 'unset' : Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ); } }
|
|
596
|
+
|
|
597
|
+
/** Get how long since elapsed, returns 0 if not set (returns negative if currently active)
|
|
598
|
+
* @return {Number} */
|
|
599
|
+
valueOf() { return this.get(); }
|
|
574
600
|
}
|
|
575
601
|
/**
|
|
576
602
|
* LittleJS Engine Settings
|
|
@@ -588,7 +614,8 @@ class Timer
|
|
|
588
614
|
* @memberof Settings */
|
|
589
615
|
let canvasMaxSize = vec2(1920, 1200);
|
|
590
616
|
|
|
591
|
-
/** Fixed size of the canvas, if enabled
|
|
617
|
+
/** Fixed size of the canvas, if enabled canvas size never changes
|
|
618
|
+
* - you may also need to set mainCanvasSize if using screen space coords in startup
|
|
592
619
|
* @type {Vector2}
|
|
593
620
|
* @default
|
|
594
621
|
* @memberof Settings */
|
|
@@ -818,7 +845,7 @@ let medalDisplayIconSize = 50;
|
|
|
818
845
|
const engineName = 'LittleJS';
|
|
819
846
|
|
|
820
847
|
/** Version of engine */
|
|
821
|
-
const engineVersion = '1.
|
|
848
|
+
const engineVersion = '1.4.0';
|
|
822
849
|
|
|
823
850
|
/** Frames per second to update objects
|
|
824
851
|
* @default */
|
|
@@ -909,6 +936,33 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
909
936
|
timeReal += frameTimeDeltaMS / 1e3;
|
|
910
937
|
frameTimeBufferMS = min(frameTimeBufferMS + !paused * frameTimeDeltaMS, 50); // clamp incase of slow framerate
|
|
911
938
|
|
|
939
|
+
if (canvasFixedSize.x)
|
|
940
|
+
{
|
|
941
|
+
// clear set fixed size
|
|
942
|
+
overlayCanvas.width = mainCanvas.width = canvasFixedSize.x;
|
|
943
|
+
overlayCanvas.height = mainCanvas.height = canvasFixedSize.y;
|
|
944
|
+
|
|
945
|
+
// fit to window by adding space on top or bottom if necessary
|
|
946
|
+
const aspect = innerWidth / innerHeight;
|
|
947
|
+
const fixedAspect = mainCanvas.width / mainCanvas.height;
|
|
948
|
+
mainCanvas.style.width = overlayCanvas.style.width = aspect < fixedAspect ? '100%' : '';
|
|
949
|
+
mainCanvas.style.height = overlayCanvas.style.height = aspect < fixedAspect ? '' : '100%';
|
|
950
|
+
if (glCanvas)
|
|
951
|
+
{
|
|
952
|
+
glCanvas.style.width = mainCanvas.style.width;
|
|
953
|
+
glCanvas.style.height = mainCanvas.style.height;
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
else
|
|
957
|
+
{
|
|
958
|
+
// clear and set size to same as window
|
|
959
|
+
overlayCanvas.width = mainCanvas.width = min(innerWidth, canvasMaxSize.x);
|
|
960
|
+
overlayCanvas.height = mainCanvas.height = min(innerHeight, canvasMaxSize.y);
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
// save canvas size
|
|
964
|
+
mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
|
|
965
|
+
|
|
912
966
|
if (paused)
|
|
913
967
|
{
|
|
914
968
|
// do post update even when paused
|
|
@@ -945,30 +999,6 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
945
999
|
// add the time smoothing back in
|
|
946
1000
|
frameTimeBufferMS += deltaSmooth;
|
|
947
1001
|
}
|
|
948
|
-
|
|
949
|
-
if (canvasFixedSize.x)
|
|
950
|
-
{
|
|
951
|
-
// clear set fixed size
|
|
952
|
-
mainCanvas.width = canvasFixedSize.x;
|
|
953
|
-
mainCanvas.height = canvasFixedSize.y;
|
|
954
|
-
|
|
955
|
-
// fit to window by adding space on top or bottom if necessary
|
|
956
|
-
const aspect = innerWidth / innerHeight;
|
|
957
|
-
const fixedAspect = mainCanvas.width / mainCanvas.height;
|
|
958
|
-
mainCanvas.style.width = overlayCanvas.style.width = aspect < fixedAspect ? '100%' : '';
|
|
959
|
-
mainCanvas.style.height = overlayCanvas.style.height = aspect < fixedAspect ? '' : '100%';
|
|
960
|
-
if (glCanvas)
|
|
961
|
-
{
|
|
962
|
-
glCanvas.style.width = mainCanvas.style.width;
|
|
963
|
-
glCanvas.style.height = mainCanvas.style.height;
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
else
|
|
967
|
-
{
|
|
968
|
-
// clear and set size to same as window
|
|
969
|
-
mainCanvas.width = min(innerWidth, canvasMaxSize.x);
|
|
970
|
-
mainCanvas.height = min(innerHeight, canvasMaxSize.y);
|
|
971
|
-
}
|
|
972
1002
|
|
|
973
1003
|
// render sort then render while removing destroyed objects
|
|
974
1004
|
enginePreRender();
|
|
@@ -1008,8 +1038,8 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
1008
1038
|
// called by engine to setup render system
|
|
1009
1039
|
function enginePreRender()
|
|
1010
1040
|
{
|
|
1011
|
-
// save canvas size
|
|
1012
|
-
mainCanvasSize = vec2(
|
|
1041
|
+
// save canvas size
|
|
1042
|
+
mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
|
|
1013
1043
|
|
|
1014
1044
|
// disable smoothing for pixel art
|
|
1015
1045
|
mainContext.imageSmoothingEnabled = !cavasPixelated;
|
|
@@ -1507,18 +1537,26 @@ let overlayContext;
|
|
|
1507
1537
|
let mainCanvasSize = vec2();
|
|
1508
1538
|
|
|
1509
1539
|
/** Convert from screen to world space coordinates
|
|
1540
|
+
* - if calling outside of render, you may need to manually set mainCanvasSize
|
|
1510
1541
|
* @param {Vector2} screenPos
|
|
1511
1542
|
* @return {Vector2}
|
|
1512
1543
|
* @memberof Draw */
|
|
1513
1544
|
const screenToWorld = (screenPos)=>
|
|
1514
|
-
|
|
1545
|
+
{
|
|
1546
|
+
ASSERT(mainCanvasSize.x && mainCanvasSize.y, 'mainCanvasSize is invalid');
|
|
1547
|
+
return screenPos.add(vec2(.5)).subtract(mainCanvasSize.scale(.5)).multiply(vec2(1/cameraScale,-1/cameraScale)).add(cameraPos);
|
|
1548
|
+
}
|
|
1515
1549
|
|
|
1516
1550
|
/** Convert from world to screen space coordinates
|
|
1551
|
+
* - if calling outside of render, you may need to manually set mainCanvasSize
|
|
1517
1552
|
* @param {Vector2} worldPos
|
|
1518
1553
|
* @return {Vector2}
|
|
1519
1554
|
* @memberof Draw */
|
|
1520
1555
|
const worldToScreen = (worldPos)=>
|
|
1521
|
-
|
|
1556
|
+
{
|
|
1557
|
+
ASSERT(mainCanvasSize.x && mainCanvasSize.y, 'mainCanvasSize is invalid');
|
|
1558
|
+
return worldPos.subtract(cameraPos).multiply(vec2(cameraScale,-cameraScale)).add(mainCanvasSize.scale(.5)).subtract(vec2(.5));
|
|
1559
|
+
}
|
|
1522
1560
|
|
|
1523
1561
|
/** Draw textured tile centered in world space, with color applied if using WebGL
|
|
1524
1562
|
* @param {Vector2} pos - Center of the tile in world space
|
|
@@ -1633,7 +1671,7 @@ function drawLine(posA, posB, thickness=.1, color, useWebGL)
|
|
|
1633
1671
|
{
|
|
1634
1672
|
const halfDelta = vec2((posB.x - posA.x)/2, (posB.y - posA.y)/2);
|
|
1635
1673
|
const size = vec2(thickness, halfDelta.length()*2);
|
|
1636
|
-
drawRect(posA.add(halfDelta), size, color, halfDelta.angle(),
|
|
1674
|
+
drawRect(posA.add(halfDelta), size, color, halfDelta.angle(), useWebGL);
|
|
1637
1675
|
}
|
|
1638
1676
|
|
|
1639
1677
|
/** Draw directly to a 2d canvas context in world space
|
|
@@ -1650,7 +1688,7 @@ function drawCanvas2D(pos, size, angle, mirror, drawFunction, context = mainCont
|
|
|
1650
1688
|
pos = worldToScreen(pos);
|
|
1651
1689
|
size = size.scale(cameraScale);
|
|
1652
1690
|
context.save();
|
|
1653
|
-
context.translate(pos.x+.5|0, pos.y
|
|
1691
|
+
context.translate(pos.x+.5|0, pos.y+.5|0);
|
|
1654
1692
|
context.rotate(angle);
|
|
1655
1693
|
context.scale(mirror ? -size.x : size.x, size.y);
|
|
1656
1694
|
drawFunction(context);
|
|
@@ -1770,7 +1808,7 @@ class FontImage
|
|
|
1770
1808
|
const size = this.tileSize;
|
|
1771
1809
|
const drawSize = size.add(this.paddingSize).scale(scale);
|
|
1772
1810
|
const cols = this.image.width / this.tileSize.x |0;
|
|
1773
|
-
text.split('\n').forEach((line, i)=>
|
|
1811
|
+
(text+'').split('\n').forEach((line, i)=>
|
|
1774
1812
|
{
|
|
1775
1813
|
const centerOffset = center ? line.length * size.x * scale / 2 |0 : 0;
|
|
1776
1814
|
for(let j=line.length; j--;)
|
|
@@ -1996,7 +2034,7 @@ const mouseToScreen = (mousePos)=>
|
|
|
1996
2034
|
return vec2(); // fix bug that can occur if user clicks before page loads
|
|
1997
2035
|
|
|
1998
2036
|
const rect = mainCanvas.getBoundingClientRect();
|
|
1999
|
-
return
|
|
2037
|
+
return vec2(mainCanvas.width, mainCanvas.height).multiply(
|
|
2000
2038
|
vec2(percent(mousePos.x, rect.left, rect.right), percent(mousePos.y, rect.top, rect.bottom)));
|
|
2001
2039
|
}
|
|
2002
2040
|
|
|
@@ -2196,7 +2234,7 @@ function touchGamepadRender()
|
|
|
2196
2234
|
return;
|
|
2197
2235
|
|
|
2198
2236
|
// fade off when not touching or paused
|
|
2199
|
-
const alpha = percent(touchGamepadTimer
|
|
2237
|
+
const alpha = percent(touchGamepadTimer, 4, 3);
|
|
2200
2238
|
if (!alpha || paused)
|
|
2201
2239
|
return;
|
|
2202
2240
|
|
|
@@ -3042,7 +3080,7 @@ constructor(pos, size=tileCollisionSize, tileSize=tileSizeDefault, scale=vec2(1)
|
|
|
3042
3080
|
const cols = tileImage.width/tileSize.x;
|
|
3043
3081
|
context.globalAlpha = color.a; // only alpha, no color, is supported in this mode
|
|
3044
3082
|
context.drawImage(tileImage,
|
|
3045
|
-
(tileIndex%cols)*tileSize.x, (tileIndex/cols|0)*tileSize.
|
|
3083
|
+
(tileIndex%cols)*tileSize.x, (tileIndex/cols|0)*tileSize.y,
|
|
3046
3084
|
tileSize.x, tileSize.y, -.5, -.5, 1, 1);
|
|
3047
3085
|
}
|
|
3048
3086
|
});
|
|
@@ -3887,7 +3925,7 @@ function glFlush()
|
|
|
3887
3925
|
* @memberof WebGL */
|
|
3888
3926
|
function glCopyToContext(context, forceDraw)
|
|
3889
3927
|
{
|
|
3890
|
-
if (
|
|
3928
|
+
if (!glEnable || !glBatchCount && !forceDraw) return;
|
|
3891
3929
|
|
|
3892
3930
|
glFlush();
|
|
3893
3931
|
|
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.
|
|
25
|
+
const engineVersion = '1.4.0';
|
|
26
26
|
|
|
27
27
|
/** Frames per second to update objects
|
|
28
28
|
* @default */
|
|
@@ -113,6 +113,33 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
113
113
|
timeReal += frameTimeDeltaMS / 1e3;
|
|
114
114
|
frameTimeBufferMS = min(frameTimeBufferMS + !paused * frameTimeDeltaMS, 50); // clamp incase of slow framerate
|
|
115
115
|
|
|
116
|
+
if (canvasFixedSize.x)
|
|
117
|
+
{
|
|
118
|
+
// clear set fixed size
|
|
119
|
+
overlayCanvas.width = mainCanvas.width = canvasFixedSize.x;
|
|
120
|
+
overlayCanvas.height = mainCanvas.height = canvasFixedSize.y;
|
|
121
|
+
|
|
122
|
+
// fit to window by adding space on top or bottom if necessary
|
|
123
|
+
const aspect = innerWidth / innerHeight;
|
|
124
|
+
const fixedAspect = mainCanvas.width / mainCanvas.height;
|
|
125
|
+
mainCanvas.style.width = overlayCanvas.style.width = aspect < fixedAspect ? '100%' : '';
|
|
126
|
+
mainCanvas.style.height = overlayCanvas.style.height = aspect < fixedAspect ? '' : '100%';
|
|
127
|
+
if (glCanvas)
|
|
128
|
+
{
|
|
129
|
+
glCanvas.style.width = mainCanvas.style.width;
|
|
130
|
+
glCanvas.style.height = mainCanvas.style.height;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else
|
|
134
|
+
{
|
|
135
|
+
// clear and set size to same as window
|
|
136
|
+
overlayCanvas.width = mainCanvas.width = min(innerWidth, canvasMaxSize.x);
|
|
137
|
+
overlayCanvas.height = mainCanvas.height = min(innerHeight, canvasMaxSize.y);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// save canvas size
|
|
141
|
+
mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
|
|
142
|
+
|
|
116
143
|
if (paused)
|
|
117
144
|
{
|
|
118
145
|
// do post update even when paused
|
|
@@ -149,30 +176,6 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
149
176
|
// add the time smoothing back in
|
|
150
177
|
frameTimeBufferMS += deltaSmooth;
|
|
151
178
|
}
|
|
152
|
-
|
|
153
|
-
if (canvasFixedSize.x)
|
|
154
|
-
{
|
|
155
|
-
// clear set fixed size
|
|
156
|
-
mainCanvas.width = canvasFixedSize.x;
|
|
157
|
-
mainCanvas.height = canvasFixedSize.y;
|
|
158
|
-
|
|
159
|
-
// fit to window by adding space on top or bottom if necessary
|
|
160
|
-
const aspect = innerWidth / innerHeight;
|
|
161
|
-
const fixedAspect = mainCanvas.width / mainCanvas.height;
|
|
162
|
-
mainCanvas.style.width = overlayCanvas.style.width = aspect < fixedAspect ? '100%' : '';
|
|
163
|
-
mainCanvas.style.height = overlayCanvas.style.height = aspect < fixedAspect ? '' : '100%';
|
|
164
|
-
if (glCanvas)
|
|
165
|
-
{
|
|
166
|
-
glCanvas.style.width = mainCanvas.style.width;
|
|
167
|
-
glCanvas.style.height = mainCanvas.style.height;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
else
|
|
171
|
-
{
|
|
172
|
-
// clear and set size to same as window
|
|
173
|
-
mainCanvas.width = min(innerWidth, canvasMaxSize.x);
|
|
174
|
-
mainCanvas.height = min(innerHeight, canvasMaxSize.y);
|
|
175
|
-
}
|
|
176
179
|
|
|
177
180
|
// render sort then render while removing destroyed objects
|
|
178
181
|
enginePreRender();
|
|
@@ -212,8 +215,8 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
212
215
|
// called by engine to setup render system
|
|
213
216
|
function enginePreRender()
|
|
214
217
|
{
|
|
215
|
-
// save canvas size
|
|
216
|
-
mainCanvasSize = vec2(
|
|
218
|
+
// save canvas size
|
|
219
|
+
mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
|
|
217
220
|
|
|
218
221
|
// disable smoothing for pixel art
|
|
219
222
|
mainContext.imageSmoothingEnabled = !cavasPixelated;
|
package/engine/engineDebug.js
CHANGED
package/engine/engineDraw.js
CHANGED
|
@@ -53,18 +53,26 @@ let overlayContext;
|
|
|
53
53
|
let mainCanvasSize = vec2();
|
|
54
54
|
|
|
55
55
|
/** Convert from screen to world space coordinates
|
|
56
|
+
* - if calling outside of render, you may need to manually set mainCanvasSize
|
|
56
57
|
* @param {Vector2} screenPos
|
|
57
58
|
* @return {Vector2}
|
|
58
59
|
* @memberof Draw */
|
|
59
60
|
const screenToWorld = (screenPos)=>
|
|
60
|
-
|
|
61
|
+
{
|
|
62
|
+
ASSERT(mainCanvasSize.x && mainCanvasSize.y, 'mainCanvasSize is invalid');
|
|
63
|
+
return screenPos.add(vec2(.5)).subtract(mainCanvasSize.scale(.5)).multiply(vec2(1/cameraScale,-1/cameraScale)).add(cameraPos);
|
|
64
|
+
}
|
|
61
65
|
|
|
62
66
|
/** Convert from world to screen space coordinates
|
|
67
|
+
* - if calling outside of render, you may need to manually set mainCanvasSize
|
|
63
68
|
* @param {Vector2} worldPos
|
|
64
69
|
* @return {Vector2}
|
|
65
70
|
* @memberof Draw */
|
|
66
71
|
const worldToScreen = (worldPos)=>
|
|
67
|
-
|
|
72
|
+
{
|
|
73
|
+
ASSERT(mainCanvasSize.x && mainCanvasSize.y, 'mainCanvasSize is invalid');
|
|
74
|
+
return worldPos.subtract(cameraPos).multiply(vec2(cameraScale,-cameraScale)).add(mainCanvasSize.scale(.5)).subtract(vec2(.5));
|
|
75
|
+
}
|
|
68
76
|
|
|
69
77
|
/** Draw textured tile centered in world space, with color applied if using WebGL
|
|
70
78
|
* @param {Vector2} pos - Center of the tile in world space
|
|
@@ -179,7 +187,7 @@ function drawLine(posA, posB, thickness=.1, color, useWebGL)
|
|
|
179
187
|
{
|
|
180
188
|
const halfDelta = vec2((posB.x - posA.x)/2, (posB.y - posA.y)/2);
|
|
181
189
|
const size = vec2(thickness, halfDelta.length()*2);
|
|
182
|
-
drawRect(posA.add(halfDelta), size, color, halfDelta.angle(),
|
|
190
|
+
drawRect(posA.add(halfDelta), size, color, halfDelta.angle(), useWebGL);
|
|
183
191
|
}
|
|
184
192
|
|
|
185
193
|
/** Draw directly to a 2d canvas context in world space
|
|
@@ -196,7 +204,7 @@ function drawCanvas2D(pos, size, angle, mirror, drawFunction, context = mainCont
|
|
|
196
204
|
pos = worldToScreen(pos);
|
|
197
205
|
size = size.scale(cameraScale);
|
|
198
206
|
context.save();
|
|
199
|
-
context.translate(pos.x+.5|0, pos.y
|
|
207
|
+
context.translate(pos.x+.5|0, pos.y+.5|0);
|
|
200
208
|
context.rotate(angle);
|
|
201
209
|
context.scale(mirror ? -size.x : size.x, size.y);
|
|
202
210
|
drawFunction(context);
|
|
@@ -316,7 +324,7 @@ class FontImage
|
|
|
316
324
|
const size = this.tileSize;
|
|
317
325
|
const drawSize = size.add(this.paddingSize).scale(scale);
|
|
318
326
|
const cols = this.image.width / this.tileSize.x |0;
|
|
319
|
-
text.split('\n').forEach((line, i)=>
|
|
327
|
+
(text+'').split('\n').forEach((line, i)=>
|
|
320
328
|
{
|
|
321
329
|
const centerOffset = center ? line.length * size.x * scale / 2 |0 : 0;
|
|
322
330
|
for(let j=line.length; j--;)
|
package/engine/engineInput.js
CHANGED
|
@@ -162,7 +162,7 @@ const mouseToScreen = (mousePos)=>
|
|
|
162
162
|
return vec2(); // fix bug that can occur if user clicks before page loads
|
|
163
163
|
|
|
164
164
|
const rect = mainCanvas.getBoundingClientRect();
|
|
165
|
-
return
|
|
165
|
+
return vec2(mainCanvas.width, mainCanvas.height).multiply(
|
|
166
166
|
vec2(percent(mousePos.x, rect.left, rect.right), percent(mousePos.y, rect.top, rect.bottom)));
|
|
167
167
|
}
|
|
168
168
|
|
|
@@ -362,7 +362,7 @@ function touchGamepadRender()
|
|
|
362
362
|
return;
|
|
363
363
|
|
|
364
364
|
// fade off when not touching or paused
|
|
365
|
-
const alpha = percent(touchGamepadTimer
|
|
365
|
+
const alpha = percent(touchGamepadTimer, 4, 3);
|
|
366
366
|
if (!alpha || paused)
|
|
367
367
|
return;
|
|
368
368
|
|
package/engine/engineRelease.js
CHANGED
package/engine/engineSettings.js
CHANGED
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
* @memberof Settings */
|
|
15
15
|
let canvasMaxSize = vec2(1920, 1200);
|
|
16
16
|
|
|
17
|
-
/** Fixed size of the canvas, if enabled
|
|
17
|
+
/** Fixed size of the canvas, if enabled canvas size never changes
|
|
18
|
+
* - you may also need to set mainCanvasSize if using screen space coords in startup
|
|
18
19
|
* @type {Vector2}
|
|
19
20
|
* @default
|
|
20
21
|
* @memberof Settings */
|
|
@@ -328,7 +328,7 @@ constructor(pos, size=tileCollisionSize, tileSize=tileSizeDefault, scale=vec2(1)
|
|
|
328
328
|
const cols = tileImage.width/tileSize.x;
|
|
329
329
|
context.globalAlpha = color.a; // only alpha, no color, is supported in this mode
|
|
330
330
|
context.drawImage(tileImage,
|
|
331
|
-
(tileIndex%cols)*tileSize.x, (tileIndex/cols|0)*tileSize.
|
|
331
|
+
(tileIndex%cols)*tileSize.x, (tileIndex/cols|0)*tileSize.y,
|
|
332
332
|
tileSize.x, tileSize.y, -.5, -.5, 1, 1);
|
|
333
333
|
}
|
|
334
334
|
});
|
|
@@ -322,6 +322,28 @@ class Vector2
|
|
|
322
322
|
|
|
323
323
|
///////////////////////////////////////////////////////////////////////////////
|
|
324
324
|
|
|
325
|
+
/**
|
|
326
|
+
* Create a color object with RGBA values
|
|
327
|
+
* @param {Number} [r=1]
|
|
328
|
+
* @param {Number} [g=1]
|
|
329
|
+
* @param {Number} [b=1]
|
|
330
|
+
* @param {Number} [a=1]
|
|
331
|
+
* @return {Color}
|
|
332
|
+
* @memberof Utilities
|
|
333
|
+
*/
|
|
334
|
+
const colorRGBA = (r, g, b, a)=> new Color(r, g, b, a);
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Create a color object with HSLA values
|
|
338
|
+
* @param {Number} [h=0]
|
|
339
|
+
* @param {Number} [s=0]
|
|
340
|
+
* @param {Number} [l=1]
|
|
341
|
+
* @param {Number} [a=1]
|
|
342
|
+
* @return {Color}
|
|
343
|
+
* @memberof Utilities
|
|
344
|
+
*/
|
|
345
|
+
const colorHSLA = (h, s, l, a)=> new Color().setHSLA(h, s, l, a);
|
|
346
|
+
|
|
325
347
|
/**
|
|
326
348
|
* Color object (red, green, blue, alpha) with some helpful functions
|
|
327
349
|
* @example
|
|
@@ -409,6 +431,34 @@ class Color
|
|
|
409
431
|
return this;
|
|
410
432
|
}
|
|
411
433
|
|
|
434
|
+
/** Returns this color expressed in hsla format
|
|
435
|
+
* @return {Array} */
|
|
436
|
+
getHSLA()
|
|
437
|
+
{
|
|
438
|
+
const r = this.r;
|
|
439
|
+
const g = this.g;
|
|
440
|
+
const b = this.b;
|
|
441
|
+
const a = this.a;
|
|
442
|
+
const max = Math.max(r, g, b);
|
|
443
|
+
const min = Math.min(r, g, b);
|
|
444
|
+
const l = (max + min) / 2;
|
|
445
|
+
|
|
446
|
+
let h = 0, s = 0;
|
|
447
|
+
if (max != min)
|
|
448
|
+
{
|
|
449
|
+
let d = max - min;
|
|
450
|
+
s = l > .5 ? d / (2 - max - min) : d / (max + min);
|
|
451
|
+
if (r == max)
|
|
452
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
453
|
+
else if (g == max)
|
|
454
|
+
h = (b - r) / d + 2;
|
|
455
|
+
else if (b == max)
|
|
456
|
+
h = (r - g) / d + 4;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
return [h / 6, s, l, a];
|
|
460
|
+
}
|
|
461
|
+
|
|
412
462
|
/** Returns a new color that has each component randomly adjusted
|
|
413
463
|
* @param {Number} [amount=.05]
|
|
414
464
|
* @param {Number} [alphaAmount=0]
|
|
@@ -440,42 +490,6 @@ class Color
|
|
|
440
490
|
return (this.r*255|0) + (this.g*255<<8) + (this.b*255<<16) + (this.a*255<<24);
|
|
441
491
|
}
|
|
442
492
|
|
|
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
|
-
/** Returns this color expressed in hsla format
|
|
452
|
-
* @return {Array} */
|
|
453
|
-
getHSLA()
|
|
454
|
-
{
|
|
455
|
-
const r = this.r;
|
|
456
|
-
const g = this.g;
|
|
457
|
-
const b = this.b;
|
|
458
|
-
const a = this.a;
|
|
459
|
-
const max = Math.max(r, g, b);
|
|
460
|
-
const min = Math.min(r, g, b);
|
|
461
|
-
const l = (max + min) / 2;
|
|
462
|
-
|
|
463
|
-
let h = 0, s = 0;
|
|
464
|
-
if (max != min)
|
|
465
|
-
{
|
|
466
|
-
let d = max - min;
|
|
467
|
-
s = l > .5 ? d / (2 - max - min) : d / (max + min);
|
|
468
|
-
if (r == max)
|
|
469
|
-
h = (g - b) / d + (g < b ? 6 : 0);
|
|
470
|
-
else if (g == max)
|
|
471
|
-
h = (b - r) / d + 2;
|
|
472
|
-
else if (b == max)
|
|
473
|
-
h = (r - g) / d + 4;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
return [h / 6, s, l, a];
|
|
477
|
-
}
|
|
478
|
-
|
|
479
493
|
/** Set this color from a hex code
|
|
480
494
|
* @param {String} hex - html hex code
|
|
481
495
|
* @return {Color} */
|
|
@@ -489,6 +503,14 @@ class Color
|
|
|
489
503
|
ASSERT(this.r>=0 && this.r<=1 && this.g>=0 && this.g<=1 && this.b>=0 && this.b<=1);
|
|
490
504
|
return this;
|
|
491
505
|
}
|
|
506
|
+
|
|
507
|
+
/** Returns this color expressed as a hex code
|
|
508
|
+
* @return {String} */
|
|
509
|
+
getHex()
|
|
510
|
+
{
|
|
511
|
+
const toHex = (c)=> ((c=c*255|0)<16 ? '0' : '') + c.toString(16);
|
|
512
|
+
return '#' + toHex(this.r) + toHex(this.g) + toHex(this.b);
|
|
513
|
+
}
|
|
492
514
|
}
|
|
493
515
|
|
|
494
516
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -538,4 +560,8 @@ class Timer
|
|
|
538
560
|
/** Returns this timer expressed as a string
|
|
539
561
|
* @return {String} */
|
|
540
562
|
toString() { if (debug) { return this.unset() ? 'unset' : Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ); } }
|
|
563
|
+
|
|
564
|
+
/** Get how long since elapsed, returns 0 if not set (returns negative if currently active)
|
|
565
|
+
* @return {Number} */
|
|
566
|
+
valueOf() { return this.get(); }
|
|
541
567
|
}
|
package/engine/engineWebGL.js
CHANGED