littlejsengine 1.6.92 → 1.7.1
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 +31 -24
- package/build/littlejs.d.ts +87 -60
- package/build/littlejs.esm.js +322 -189
- package/build/littlejs.esm.min.js +1 -1
- package/build/littlejs.js +316 -185
- package/build/littlejs.min.js +1 -1
- package/build/littlejs.release.js +296 -182
- package/examples/breakout/index.html +3 -3
- package/examples/breakoutTutorial/index.html +2 -2
- package/examples/electron/index.html +2 -2
- package/examples/js13k/index.html +13 -13
- package/examples/module/index.html +1 -1
- package/examples/particles/index.html +1 -1
- package/examples/platformer/gameEffects.js +11 -10
- package/examples/platformer/index.html +6 -6
- package/examples/puzzle/index.html +2 -2
- package/examples/starter/index.html +13 -13
- package/examples/stress/index.html +4 -4
- package/examples/typescript/index.html +1 -1
- package/package.json +1 -1
- package/src/engine.js +2 -2
- package/src/engineAudio.js +43 -15
- package/src/engineBuild.js +18 -5
- package/src/engineDebug.js +21 -5
- package/src/engineDraw.js +61 -60
- package/src/engineExport.js +6 -4
- package/src/engineInput.js +26 -34
- package/src/engineObject.js +2 -2
- package/src/engineRelease.js +1 -2
- package/src/engineSettings.js +1 -0
- package/src/engineUtilities.js +95 -40
- package/src/engineWebGL.js +63 -27
package/build/littlejs.esm.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
// LittleJS - MIT License - Copyright 2021 Frank Force
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* LittleJS Debug System
|
|
3
|
-
* - Press
|
|
5
|
+
* - Press Esc to show debug overlay with mouse pick
|
|
4
6
|
* - Number keys toggle debug functions
|
|
5
7
|
* - +/- apply time scale
|
|
6
8
|
* - Debug primitive rendering
|
|
7
|
-
* - Save a 2d canvas as
|
|
9
|
+
* - Save a 2d canvas as a png image
|
|
8
10
|
* @namespace Debug
|
|
9
11
|
*/
|
|
10
12
|
|
|
@@ -138,11 +140,27 @@ function debugClear() { debugPrimitives = []; }
|
|
|
138
140
|
/** Save a canvas to disk
|
|
139
141
|
* @param {HTMLCanvasElement} canvas
|
|
140
142
|
* @param {String} [filename]
|
|
143
|
+
* @param {String} [type='image/png']
|
|
144
|
+
* @memberof Debug */
|
|
145
|
+
function debugSaveCanvas(canvas, filename=engineName, type='image/png')
|
|
146
|
+
{ debugSaveDataURL(canvas.toDataURL(type), filename); }
|
|
147
|
+
|
|
148
|
+
/** Save a text file to disk
|
|
149
|
+
* @param {String} text
|
|
150
|
+
* @param {String} [filename]
|
|
151
|
+
* @param {String} [type='text/plain']
|
|
152
|
+
* @memberof Debug */
|
|
153
|
+
function debugSaveText(text, filename=engineName, type='text/plain')
|
|
154
|
+
{ debugSaveDataURL(URL.createObjectURL(new Blob([text], {'type':type})), filename); }
|
|
155
|
+
|
|
156
|
+
/** Save a data url to disk
|
|
157
|
+
* @param {String} dataURL
|
|
158
|
+
* @param {String} filename
|
|
141
159
|
* @memberof Debug */
|
|
142
|
-
function
|
|
160
|
+
function debugSaveDataURL(dataURL, filename)
|
|
143
161
|
{
|
|
144
|
-
downloadLink.download =
|
|
145
|
-
downloadLink.href =
|
|
162
|
+
downloadLink.download = filename;
|
|
163
|
+
downloadLink.href = dataURL;
|
|
146
164
|
downloadLink.click();
|
|
147
165
|
}
|
|
148
166
|
|
|
@@ -392,6 +410,7 @@ function debugRender()
|
|
|
392
410
|
* - Vector2 - fast, simple, easy 2D vector class
|
|
393
411
|
* - Color - holds a rgba color with some math functions
|
|
394
412
|
* - Timer - tracks time automatically
|
|
413
|
+
* - RandomGenerator - seeded random number generator
|
|
395
414
|
* @namespace Utilities
|
|
396
415
|
*/
|
|
397
416
|
|
|
@@ -442,25 +461,58 @@ function mod(dividend, divisor=1) { return ((dividend % divisor) + divisor) % di
|
|
|
442
461
|
* @param {Number} [max=1]
|
|
443
462
|
* @return {Number}
|
|
444
463
|
* @memberof Utilities */
|
|
445
|
-
function clamp(value, min=0, max=1)
|
|
446
|
-
{ return value < min ? min : value > max ? max : value; }
|
|
464
|
+
function clamp(value, min=0, max=1) { return value < min ? min : value > max ? max : value; }
|
|
447
465
|
|
|
448
|
-
/** Returns what percentage the value is between
|
|
466
|
+
/** Returns what percentage the value is between valueA and valueB
|
|
449
467
|
* @param {Number} value
|
|
450
|
-
* @param {Number}
|
|
451
|
-
* @param {Number}
|
|
468
|
+
* @param {Number} valueA
|
|
469
|
+
* @param {Number} valueB
|
|
452
470
|
* @return {Number}
|
|
453
471
|
* @memberof Utilities */
|
|
454
|
-
function percent(value,
|
|
455
|
-
{ return
|
|
472
|
+
function percent(value, valueA, valueB)
|
|
473
|
+
{ return valueB-valueA ? clamp((value-valueA) / (valueB-valueA)) : 0; }
|
|
456
474
|
|
|
457
|
-
/** Linearly interpolates
|
|
475
|
+
/** Linearly interpolates between values passed in using percent
|
|
458
476
|
* @param {Number} percent
|
|
459
|
-
* @param {Number}
|
|
460
|
-
* @param {Number}
|
|
477
|
+
* @param {Number} valueA
|
|
478
|
+
* @param {Number} valueB
|
|
461
479
|
* @return {Number}
|
|
462
480
|
* @memberof Utilities */
|
|
463
|
-
function lerp(percent,
|
|
481
|
+
function lerp(percent, valueA, valueB) { return valueA + clamp(percent) * (valueB-valueA); }
|
|
482
|
+
|
|
483
|
+
/** Returns signed wrapped distance between the two values passed in
|
|
484
|
+
* @param {Number} valueA
|
|
485
|
+
* @param {Number} valueB
|
|
486
|
+
* @param {Number} [wrapSize=1]
|
|
487
|
+
* @returns {Number}
|
|
488
|
+
* @memberof Utilities */
|
|
489
|
+
function distanceWrap(valueA, valueB, wrapSize=1)
|
|
490
|
+
{ const d = (valueA - valueB) % wrapSize; return d*2 % wrapSize - d; }
|
|
491
|
+
|
|
492
|
+
/** Linearly interpolates between values passed in with wrappping
|
|
493
|
+
* @param {Number} percent
|
|
494
|
+
* @param {Number} valueA
|
|
495
|
+
* @param {Number} valueB
|
|
496
|
+
* @param {Number} [wrapSize=1]
|
|
497
|
+
* @returns {Number}
|
|
498
|
+
* @memberof Utilities */
|
|
499
|
+
function lerpWrap(percent, valueA, valueB, wrapSize=1)
|
|
500
|
+
{ return valueB + clamp(percent) * distanceWrap(valueA, valueB, wrapSize); }
|
|
501
|
+
|
|
502
|
+
/** Returns signed wrapped distance between the two angles passed in
|
|
503
|
+
* @param {Number} angleA
|
|
504
|
+
* @param {Number} angleB
|
|
505
|
+
* @returns {Number}
|
|
506
|
+
* @memberof Utilities */
|
|
507
|
+
function distanceAngle(angleA, angleB) { distanceWrap(angleA, angleB, 2*PI); }
|
|
508
|
+
|
|
509
|
+
/** Linearly interpolates between the angles passed in with wrappping
|
|
510
|
+
* @param {Number} percent
|
|
511
|
+
* @param {Number} angleA
|
|
512
|
+
* @param {Number} angleB
|
|
513
|
+
* @returns {Number}
|
|
514
|
+
* @memberof Utilities */
|
|
515
|
+
function lerpAngle(percent, angleA, angleB) { return lerpWrap(percent, angleA, angleB, 2*PI); }
|
|
464
516
|
|
|
465
517
|
/** Applies smoothstep function to the percentage value
|
|
466
518
|
* @param {Number} percent
|
|
@@ -515,17 +567,23 @@ function formatTime(t) { return (t/60|0) + ':' + (t%60<10?'0':'') + (t%60|0); }
|
|
|
515
567
|
function rand(valueA=1, valueB=0) { return valueB + Math.random() * (valueA-valueB); }
|
|
516
568
|
|
|
517
569
|
/** Returns a floored random value the two values passed in
|
|
518
|
-
* @param {Number}
|
|
570
|
+
* @param {Number} valueA
|
|
519
571
|
* @param {Number} [valueB=0]
|
|
520
572
|
* @return {Number}
|
|
521
573
|
* @memberof Random */
|
|
522
|
-
function randInt(valueA
|
|
574
|
+
function randInt(valueA, valueB=0) { return Math.floor(rand(valueA,valueB)); }
|
|
523
575
|
|
|
524
576
|
/** Randomly returns either -1 or 1
|
|
525
577
|
* @return {Number}
|
|
526
578
|
* @memberof Random */
|
|
527
579
|
function randSign() { return randInt(2) * 2 - 1; }
|
|
528
580
|
|
|
581
|
+
/** Returns a random Vector2 with the passed in length
|
|
582
|
+
* @param {Number} [length=1]
|
|
583
|
+
* @return {Vector2}
|
|
584
|
+
* @memberof Random */
|
|
585
|
+
function randVector(length=1) { return new Vector2().setAngle(rand(2*PI), length); }
|
|
586
|
+
|
|
529
587
|
/** Returns a random Vector2 within a circular shape
|
|
530
588
|
* @param {Number} [radius=1]
|
|
531
589
|
* @param {Number} [minRadius=0]
|
|
@@ -534,12 +592,6 @@ function randSign() { return randInt(2) * 2 - 1; }
|
|
|
534
592
|
function randInCircle(radius=1, minRadius=0)
|
|
535
593
|
{ return radius > 0 ? randVector(radius * rand(minRadius / radius, 1)**.5) : new Vector2; }
|
|
536
594
|
|
|
537
|
-
/** Returns a random Vector2 with the passed in length
|
|
538
|
-
* @param {Number} [length=1]
|
|
539
|
-
* @return {Vector2}
|
|
540
|
-
* @memberof Random */
|
|
541
|
-
function randVector(length=1) { return new Vector2().setAngle(rand(2*PI), length); }
|
|
542
|
-
|
|
543
595
|
/** Returns a random color between the two passed in colors, combine components if linear
|
|
544
596
|
* @param {Color} [colorA=Color()]
|
|
545
597
|
* @param {Color} [colorB=Color(0,0,0,1)]
|
|
@@ -552,29 +604,50 @@ function randColor(colorA=new Color, colorB=new Color(0,0,0,1), linear)
|
|
|
552
604
|
new Color(rand(colorA.r,colorB.r), rand(colorA.g,colorB.g), rand(colorA.b,colorB.b), rand(colorA.a,colorB.a));
|
|
553
605
|
}
|
|
554
606
|
|
|
555
|
-
|
|
556
|
-
* @type {Number}
|
|
557
|
-
* @default
|
|
558
|
-
* @memberof Random */
|
|
559
|
-
let randSeed = 1;
|
|
560
|
-
|
|
561
|
-
/** Set seed used by the randSeeded function, should not be 0
|
|
562
|
-
* @param {Number} seed
|
|
563
|
-
* @memberof Random */
|
|
564
|
-
function setRandSeed(seed) { randSeed = seed; }
|
|
607
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
565
608
|
|
|
566
|
-
/**
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
570
|
-
*
|
|
571
|
-
|
|
609
|
+
/**
|
|
610
|
+
* Seeded random number generator
|
|
611
|
+
* - Can be used to create a deterministic random number sequence
|
|
612
|
+
* @example
|
|
613
|
+
* let r = new RandomGenerator(123); // random number generator with seed 123
|
|
614
|
+
* let a = r.rand(); // random value between 0 and 1
|
|
615
|
+
* let b = r.randInt(10); // random integer between 0 and 9
|
|
616
|
+
* r.seed = 123; // reset the seed
|
|
617
|
+
* let c = r.rand(); // the same value as a
|
|
618
|
+
*/
|
|
619
|
+
class RandomGenerator
|
|
572
620
|
{
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
621
|
+
/** Create a random number generator with the seed passed in
|
|
622
|
+
* @param {Number} seed - Starting seed */
|
|
623
|
+
constructor(seed)
|
|
624
|
+
{
|
|
625
|
+
/** @property {Number} - random seed */
|
|
626
|
+
this.seed = seed;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
/** Returns a seeded random value between the two values passed in
|
|
630
|
+
* @param {Number} [valueA=1]
|
|
631
|
+
* @param {Number} [valueB=0]
|
|
632
|
+
* @return {Number} */
|
|
633
|
+
float(valueA=1, valueB=0)
|
|
634
|
+
{
|
|
635
|
+
// xorshift algorithm
|
|
636
|
+
this.seed ^= this.seed << 13;
|
|
637
|
+
this.seed ^= this.seed >>> 17;
|
|
638
|
+
this.seed ^= this.seed << 5;
|
|
639
|
+
return valueB + (valueA - valueB) * abs(this.seed % 1e9) / 1e9;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/** Returns a floored seeded random value the two values passed in
|
|
643
|
+
* @param {Number} valueA
|
|
644
|
+
* @param {Number} [valueB=0]
|
|
645
|
+
* @return {Number} */
|
|
646
|
+
int(valueA, valueB=0) { return Math.floor(this.rand(valueA, valueB)); }
|
|
647
|
+
|
|
648
|
+
/** Randomly returns either -1 or 1 deterministically
|
|
649
|
+
* @return {Number} */
|
|
650
|
+
sign() { return this.randInt(2) * 2 - 1; }
|
|
578
651
|
}
|
|
579
652
|
|
|
580
653
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -992,6 +1065,7 @@ class Timer
|
|
|
992
1065
|
}
|
|
993
1066
|
/**
|
|
994
1067
|
* LittleJS Engine Settings
|
|
1068
|
+
* - All settings for the engine are here
|
|
995
1069
|
* @namespace Settings
|
|
996
1070
|
*/
|
|
997
1071
|
|
|
@@ -1247,12 +1321,12 @@ let medalsPreventUnlock;
|
|
|
1247
1321
|
|
|
1248
1322
|
/**
|
|
1249
1323
|
* LittleJS Object Base Object Class
|
|
1250
|
-
* -
|
|
1324
|
+
* - Top level object class used by the engine
|
|
1251
1325
|
* - Automatically adds self to object list
|
|
1252
1326
|
* - Will be updated and rendered each frame
|
|
1253
1327
|
* - Renders as a sprite from a tilesheet by default
|
|
1254
1328
|
* - Can have color and addtive color applied
|
|
1255
|
-
* -
|
|
1329
|
+
* - 2D Physics and collision system
|
|
1256
1330
|
* - Sorted by renderOrder
|
|
1257
1331
|
* - Objects can have children attached
|
|
1258
1332
|
* - Parents are updated before children, and set child transform
|
|
@@ -1619,9 +1693,10 @@ class EngineObject
|
|
|
1619
1693
|
}
|
|
1620
1694
|
/**
|
|
1621
1695
|
* LittleJS Drawing System
|
|
1622
|
-
* - Hybrid with both Canvas2D and WebGL available
|
|
1696
|
+
* - Hybrid system with both Canvas2D and WebGL available
|
|
1623
1697
|
* - Super fast tile sheet rendering with WebGL
|
|
1624
1698
|
* - Can apply rotation, mirror, color and additive color
|
|
1699
|
+
* - Font rendering system with built in engine font
|
|
1625
1700
|
* - Many useful utility functions
|
|
1626
1701
|
*
|
|
1627
1702
|
* LittleJS uses a hybrid rendering solution with the best of both Canvas2D and WebGL.
|
|
@@ -1631,7 +1706,6 @@ class EngineObject
|
|
|
1631
1706
|
* overlayCanvas - Another 2D canvas that appears on top of the other 2 canvases.
|
|
1632
1707
|
*
|
|
1633
1708
|
* The WebGL rendering system is very fast with some caveats...
|
|
1634
|
-
* - The default setup supports only 1 tile sheet, to support more call glCreateTexture and glSetTexture
|
|
1635
1709
|
* - Switching blend modes (additive) or textures causes another draw call which is expensive in excess
|
|
1636
1710
|
* - Group additive rendering together using renderOrder to mitigate this issue
|
|
1637
1711
|
*
|
|
@@ -1675,33 +1749,29 @@ const tileImage = new Image;
|
|
|
1675
1749
|
let tileImageSize, tileImageFixBleed, drawCount;
|
|
1676
1750
|
|
|
1677
1751
|
/** Convert from screen to world space coordinates
|
|
1678
|
-
* - if calling outside of render, you may need to manually set mainCanvasSize
|
|
1679
1752
|
* @param {Vector2} screenPos
|
|
1680
1753
|
* @return {Vector2}
|
|
1681
1754
|
* @memberof Draw */
|
|
1682
1755
|
function screenToWorld(screenPos)
|
|
1683
1756
|
{
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
.
|
|
1688
|
-
|
|
1689
|
-
.add(cameraPos);
|
|
1757
|
+
return new Vector2
|
|
1758
|
+
(
|
|
1759
|
+
(screenPos.x - mainCanvasSize.x/2 + .5) / cameraScale + cameraPos.x,
|
|
1760
|
+
(screenPos.y - mainCanvasSize.y/2 + .5) / -cameraScale + cameraPos.y
|
|
1761
|
+
);
|
|
1690
1762
|
}
|
|
1691
1763
|
|
|
1692
1764
|
/** Convert from world to screen space coordinates
|
|
1693
|
-
* - if calling outside of render, you may need to manually set mainCanvasSize
|
|
1694
1765
|
* @param {Vector2} worldPos
|
|
1695
1766
|
* @return {Vector2}
|
|
1696
1767
|
* @memberof Draw */
|
|
1697
1768
|
function worldToScreen(worldPos)
|
|
1698
1769
|
{
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
.
|
|
1702
|
-
.
|
|
1703
|
-
|
|
1704
|
-
.subtract(vec2(.5));
|
|
1770
|
+
return new Vector2
|
|
1771
|
+
(
|
|
1772
|
+
(worldPos.x - cameraPos.x) * cameraScale + mainCanvasSize.x/2 - .5,
|
|
1773
|
+
(worldPos.y - cameraPos.y) * -cameraScale + mainCanvasSize.y/2 - .5
|
|
1774
|
+
);
|
|
1705
1775
|
}
|
|
1706
1776
|
|
|
1707
1777
|
/** Draw textured tile centered in world space, with color applied if using WebGL
|
|
@@ -1714,13 +1784,21 @@ function worldToScreen(worldPos)
|
|
|
1714
1784
|
* @param {Boolean} [mirror=0] - If true image is flipped along the Y axis
|
|
1715
1785
|
* @param {Color} [additiveColor=Color(0,0,0,0)] - Additive color to be applied
|
|
1716
1786
|
* @param {Boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering
|
|
1787
|
+
* @param {Boolean} [screenSpace=0] - If true the pos and size are in screen space
|
|
1717
1788
|
* @memberof Draw */
|
|
1718
1789
|
function drawTile(pos, size=vec2(1), tileIndex=-1, tileSize=tileSizeDefault, color=new Color,
|
|
1719
|
-
angle=0, mirror, additiveColor=new Color(0,0,0,0), useWebGL=glEnable)
|
|
1790
|
+
angle=0, mirror, additiveColor=new Color(0,0,0,0), useWebGL=glEnable, screenSpace)
|
|
1720
1791
|
{
|
|
1721
1792
|
showWatermark && ++drawCount;
|
|
1793
|
+
|
|
1722
1794
|
if (glEnable && useWebGL)
|
|
1723
1795
|
{
|
|
1796
|
+
if (screenSpace)
|
|
1797
|
+
{
|
|
1798
|
+
// convert to world space
|
|
1799
|
+
pos = screenToWorld(pos);
|
|
1800
|
+
size = size.scale(1/cameraScale);
|
|
1801
|
+
}
|
|
1724
1802
|
if (tileIndex < 0 || !tileImage.width)
|
|
1725
1803
|
{
|
|
1726
1804
|
// if negative tile index or image not found, force untextured
|
|
@@ -1762,7 +1840,7 @@ function drawTile(pos, size=vec2(1), tileIndex=-1, tileSize=tileSizeDefault, col
|
|
|
1762
1840
|
context.globalAlpha = color.a; // only alpha is supported
|
|
1763
1841
|
context.drawImage(tileImage, sX, sY, sWidth, sHeight, -.5, -.5, 1, 1);
|
|
1764
1842
|
}
|
|
1765
|
-
});
|
|
1843
|
+
}, undefined, screenSpace);
|
|
1766
1844
|
}
|
|
1767
1845
|
}
|
|
1768
1846
|
|
|
@@ -1772,38 +1850,30 @@ function drawTile(pos, size=vec2(1), tileIndex=-1, tileSize=tileSizeDefault, col
|
|
|
1772
1850
|
* @param {Color} [color=Color()]
|
|
1773
1851
|
* @param {Number} [angle=0]
|
|
1774
1852
|
* @param {Boolean} [useWebGL=glEnable]
|
|
1853
|
+
* @param {Boolean} [screenSpace=0]
|
|
1775
1854
|
* @memberof Draw */
|
|
1776
|
-
function drawRect(pos, size, color, angle, useWebGL)
|
|
1777
|
-
{
|
|
1778
|
-
drawTile(pos, size, -1, tileSizeDefault, color, angle, 0, 0, useWebGL);
|
|
1779
|
-
}
|
|
1855
|
+
function drawRect(pos, size, color, angle, useWebGL, screenSpace)
|
|
1856
|
+
{ drawTile(pos, size, -1, tileSizeDefault, color, angle, 0, undefined, useWebGL, screenSpace); }
|
|
1780
1857
|
|
|
1781
|
-
/** Draw
|
|
1782
|
-
* @param {
|
|
1783
|
-
* @param {Vector2} [size=Vector2(1,1)] - Size of the tile
|
|
1784
|
-
* @param {Number} [tileIndex=-1] - Tile index to use, negative is untextured
|
|
1785
|
-
* @param {Vector2} [tileSize=tileSizeDefault] - Tile size in source pixels
|
|
1858
|
+
/** Draw colored polygon using passed in points
|
|
1859
|
+
* @param {Array} points - Array of Vector2 points
|
|
1786
1860
|
* @param {Color} [color=Color()]
|
|
1787
|
-
* @param {Number} [angle=0]
|
|
1788
|
-
* @param {Boolean} [mirror=0]
|
|
1789
|
-
* @param {Color} [additiveColor=Color(0,0,0,0)]
|
|
1790
1861
|
* @param {Boolean} [useWebGL=glEnable]
|
|
1862
|
+
* @param {Boolean} [screenSpace=0]
|
|
1791
1863
|
* @memberof Draw */
|
|
1792
|
-
function
|
|
1864
|
+
function drawPoly(points, color=new Color, useWebGL=glEnable, screenSpace)
|
|
1793
1865
|
{
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
{
|
|
1806
|
-
drawTileScreenSpace(pos, size, -1, tileSizeDefault, color, angle, 0, 0, useWebGL);
|
|
1866
|
+
if (useWebGL)
|
|
1867
|
+
glDrawPoints(screenSpace ? points.map(screenToWorld) : points, color.rgbaInt());
|
|
1868
|
+
else
|
|
1869
|
+
{
|
|
1870
|
+
// draw using canvas
|
|
1871
|
+
mainContext.fillStyle = color;
|
|
1872
|
+
mainContext.beginPath();
|
|
1873
|
+
for (const point of screenSpace ? points : points.map(worldToScreen))
|
|
1874
|
+
mainContext.lineTo(point.x, point.y);
|
|
1875
|
+
mainContext.fill();
|
|
1876
|
+
}
|
|
1807
1877
|
}
|
|
1808
1878
|
|
|
1809
1879
|
/** Draw colored line between two points
|
|
@@ -1812,12 +1882,13 @@ function drawRectScreenSpace(pos, size, color, angle, useWebGL)
|
|
|
1812
1882
|
* @param {Number} [thickness=.1]
|
|
1813
1883
|
* @param {Color} [color=Color()]
|
|
1814
1884
|
* @param {Boolean} [useWebGL=glEnable]
|
|
1885
|
+
* @param {Boolean} [screenSpace=0]
|
|
1815
1886
|
* @memberof Draw */
|
|
1816
1887
|
function drawLine(posA, posB, thickness=.1, color, useWebGL)
|
|
1817
1888
|
{
|
|
1818
1889
|
const halfDelta = vec2((posB.x - posA.x)/2, (posB.y - posA.y)/2);
|
|
1819
1890
|
const size = vec2(thickness, halfDelta.length()*2);
|
|
1820
|
-
drawRect(posA.add(halfDelta), size, color, halfDelta.angle(), useWebGL);
|
|
1891
|
+
drawRect(posA.add(halfDelta), size, color, halfDelta.angle(), useWebGL, screenSpace);
|
|
1821
1892
|
}
|
|
1822
1893
|
|
|
1823
1894
|
/** Draw directly to a 2d canvas context in world space
|
|
@@ -1827,12 +1898,16 @@ function drawLine(posA, posB, thickness=.1, color, useWebGL)
|
|
|
1827
1898
|
* @param {Boolean} mirror
|
|
1828
1899
|
* @param {Function} drawFunction
|
|
1829
1900
|
* @param {CanvasRenderingContext2D} [context=mainContext]
|
|
1901
|
+
* @param {Boolean} [screenSpace=0]
|
|
1830
1902
|
* @memberof Draw */
|
|
1831
|
-
function drawCanvas2D(pos, size, angle, mirror, drawFunction, context = mainContext)
|
|
1903
|
+
function drawCanvas2D(pos, size, angle, mirror, drawFunction, context = mainContext, screenSpace)
|
|
1832
1904
|
{
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1905
|
+
if (!screenSpace)
|
|
1906
|
+
{
|
|
1907
|
+
// create canvas transform from world space to screen space
|
|
1908
|
+
pos = worldToScreen(pos);
|
|
1909
|
+
size = size.scale(cameraScale);
|
|
1910
|
+
}
|
|
1836
1911
|
context.save();
|
|
1837
1912
|
context.translate(pos.x+.5|0, pos.y+.5|0);
|
|
1838
1913
|
context.rotate(angle);
|
|
@@ -1939,6 +2014,17 @@ class FontImage
|
|
|
1939
2014
|
this.context = context;
|
|
1940
2015
|
}
|
|
1941
2016
|
|
|
2017
|
+
/** Draw text in world space using the image font
|
|
2018
|
+
* @param {String} text
|
|
2019
|
+
* @param {Vector2} pos
|
|
2020
|
+
* @param {Number} [scale=.25]
|
|
2021
|
+
* @param {Boolean} [center]
|
|
2022
|
+
*/
|
|
2023
|
+
drawText(text, pos, scale=1, center)
|
|
2024
|
+
{
|
|
2025
|
+
this.drawTextScreen(text, worldToScreen(pos).floor(), scale*cameraScale|0, center);
|
|
2026
|
+
}
|
|
2027
|
+
|
|
1942
2028
|
/** Draw text in screen space using the image font
|
|
1943
2029
|
* @param {String} text
|
|
1944
2030
|
* @param {Vector2} pos
|
|
@@ -1976,17 +2062,6 @@ class FontImage
|
|
|
1976
2062
|
|
|
1977
2063
|
context.restore();
|
|
1978
2064
|
}
|
|
1979
|
-
|
|
1980
|
-
/** Draw text in world space using the image font
|
|
1981
|
-
* @param {String} text
|
|
1982
|
-
* @param {Vector2} pos
|
|
1983
|
-
* @param {Number} [scale=.25]
|
|
1984
|
-
* @param {Boolean} [center]
|
|
1985
|
-
*/
|
|
1986
|
-
drawText(text, pos, scale=1, center)
|
|
1987
|
-
{
|
|
1988
|
-
this.drawTextScreen(text, worldToScreen(pos).floor(), scale*cameraScale|0, center);
|
|
1989
|
-
}
|
|
1990
2065
|
}
|
|
1991
2066
|
|
|
1992
2067
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -2012,10 +2087,10 @@ function toggleFullscreen()
|
|
|
2012
2087
|
|
|
2013
2088
|
/**
|
|
2014
2089
|
* LittleJS Input System
|
|
2015
|
-
* - Tracks
|
|
2016
|
-
* -
|
|
2017
|
-
* -
|
|
2018
|
-
* - Virtual gamepad for touch devices
|
|
2090
|
+
* - Tracks keyboard down, pressed, and released
|
|
2091
|
+
* - Tracks mouse buttons, position, and wheel
|
|
2092
|
+
* - Tracks multiple analog gamepads
|
|
2093
|
+
* - Virtual gamepad for touch devices
|
|
2019
2094
|
* @namespace Input
|
|
2020
2095
|
*/
|
|
2021
2096
|
|
|
@@ -2287,40 +2362,32 @@ if (isTouchDevice)
|
|
|
2287
2362
|
let wasTouching, mouseDown = onmousedown, mouseUp = onmouseup;
|
|
2288
2363
|
onmousedown = onmouseup = ()=> 0;
|
|
2289
2364
|
|
|
2290
|
-
//
|
|
2291
|
-
ontouchstart = (e)=>
|
|
2365
|
+
// handle all touch events the same way
|
|
2366
|
+
ontouchstart = ontouchmove = ontouchend = (e)=>
|
|
2292
2367
|
{
|
|
2293
|
-
|
|
2294
|
-
zzfx(0);
|
|
2295
|
-
|
|
2296
|
-
// handle all touch events the same way
|
|
2297
|
-
ontouchstart = ontouchmove = ontouchend = (e)=>
|
|
2298
|
-
{
|
|
2299
|
-
e.button = 0; // all touches are left click
|
|
2368
|
+
e.button = 0; // all touches are left click
|
|
2300
2369
|
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
{
|
|
2305
|
-
// set event pos and pass it along
|
|
2306
|
-
e.x = e.touches[0].clientX;
|
|
2307
|
-
e.y = e.touches[0].clientY;
|
|
2308
|
-
wasTouching ? onmousemove(e) : mouseDown(e);
|
|
2309
|
-
}
|
|
2310
|
-
else if (wasTouching)
|
|
2311
|
-
mouseUp(e);
|
|
2370
|
+
// fix stalled audio on mobile
|
|
2371
|
+
if (soundEnable)
|
|
2372
|
+
audioContext ? audioContext.resume() : zzfx(0);
|
|
2312
2373
|
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2374
|
+
// check if touching and pass to mouse events
|
|
2375
|
+
const touching = e.touches.length;
|
|
2376
|
+
if (touching)
|
|
2377
|
+
{
|
|
2378
|
+
// set event pos and pass it along
|
|
2379
|
+
e.x = e.touches[0].clientX;
|
|
2380
|
+
e.y = e.touches[0].clientY;
|
|
2381
|
+
wasTouching ? onmousemove(e) : mouseDown(e);
|
|
2318
2382
|
}
|
|
2383
|
+
else if (wasTouching)
|
|
2384
|
+
mouseUp(e);
|
|
2319
2385
|
|
|
2320
|
-
//
|
|
2321
|
-
|
|
2386
|
+
// set was touching
|
|
2387
|
+
wasTouching = touching;
|
|
2322
2388
|
|
|
2323
|
-
return
|
|
2389
|
+
// must return true so the document will get focus
|
|
2390
|
+
return true;
|
|
2324
2391
|
}
|
|
2325
2392
|
}
|
|
2326
2393
|
|
|
@@ -2331,13 +2398,13 @@ if (isTouchDevice)
|
|
|
2331
2398
|
let touchGamepadTimer = new Timer, touchGamepadButtons, touchGamepadStick;
|
|
2332
2399
|
|
|
2333
2400
|
// create the touch gamepad, called automatically by the engine
|
|
2334
|
-
|
|
2401
|
+
if (touchGamepadEnable)
|
|
2335
2402
|
{
|
|
2336
2403
|
// touch input internal variables
|
|
2337
2404
|
touchGamepadButtons = [];
|
|
2338
2405
|
touchGamepadStick = vec2();
|
|
2339
2406
|
|
|
2340
|
-
|
|
2407
|
+
const touchHandler = ontouchstart;
|
|
2341
2408
|
ontouchstart = ontouchmove = ontouchend = (e)=>
|
|
2342
2409
|
{
|
|
2343
2410
|
// clear touch gamepad input
|
|
@@ -2456,12 +2523,12 @@ function touchGamepadRender()
|
|
|
2456
2523
|
}
|
|
2457
2524
|
/**
|
|
2458
2525
|
* LittleJS Audio System
|
|
2459
|
-
* - <a href=https://killedbyapixel.github.io/ZzFX/>ZzFX Sound Effects</a> - Sound Effect Generator
|
|
2460
|
-
* - <a href=https://keithclark.github.io/ZzFXM/>ZzFXM Music</a> - Music System
|
|
2526
|
+
* - <a href=https://killedbyapixel.github.io/ZzFX/>ZzFX Sound Effects</a> - ZzFX Sound Effect Generator
|
|
2527
|
+
* - <a href=https://keithclark.github.io/ZzFXM/>ZzFXM Music</a> - ZzFXM Music System
|
|
2461
2528
|
* - Caches sounds and music for fast playback
|
|
2462
2529
|
* - Can attenuate and apply stereo panning to sounds
|
|
2463
2530
|
* - Ability to play mp3, ogg, and wave files
|
|
2464
|
-
* - Speech synthesis
|
|
2531
|
+
* - Speech synthesis functions
|
|
2465
2532
|
* @namespace Audio
|
|
2466
2533
|
*/
|
|
2467
2534
|
|
|
@@ -2495,12 +2562,15 @@ class Sound
|
|
|
2495
2562
|
/** @property {Number} - At what percentage of range should it start tapering off */
|
|
2496
2563
|
this.taper = taper;
|
|
2497
2564
|
|
|
2498
|
-
|
|
2499
|
-
this.randomness =
|
|
2500
|
-
zzfxSound[1] = 0;
|
|
2565
|
+
/** @property {Number} - How much to randomize frequency each time sound plays */
|
|
2566
|
+
this.randomness = 0;
|
|
2501
2567
|
|
|
2502
|
-
|
|
2503
|
-
|
|
2568
|
+
if (zzfxSound)
|
|
2569
|
+
{
|
|
2570
|
+
// generate zzfx sound now for fast playback
|
|
2571
|
+
this.randomness = zzfxSound[1] || (zzfxSound[1] = 0);
|
|
2572
|
+
this.cachedSamples = zzfxSound && zzfxG(...zzfxSound);
|
|
2573
|
+
}
|
|
2504
2574
|
}
|
|
2505
2575
|
|
|
2506
2576
|
/** Play the sound
|
|
@@ -2512,7 +2582,7 @@ class Sound
|
|
|
2512
2582
|
*/
|
|
2513
2583
|
play(pos, volume=1, pitch=1, randomnessScale=1)
|
|
2514
2584
|
{
|
|
2515
|
-
if (!soundEnable) return;
|
|
2585
|
+
if (!soundEnable || !this.cachedSamples) return;
|
|
2516
2586
|
|
|
2517
2587
|
let pan;
|
|
2518
2588
|
if (pos)
|
|
@@ -2545,12 +2615,36 @@ class Sound
|
|
|
2545
2615
|
* @return {AudioBufferSourceNode} - The audio, can be used to stop sound later
|
|
2546
2616
|
*/
|
|
2547
2617
|
playNote(semitoneOffset, pos, volume)
|
|
2618
|
+
{ return this.play(pos, volume, 2**(semitoneOffset/12), 0); }
|
|
2619
|
+
}
|
|
2620
|
+
|
|
2621
|
+
/**
|
|
2622
|
+
* Sound Wave Object - Stores a wave sound for later use and can be played positionally
|
|
2623
|
+
*/
|
|
2624
|
+
class SoundWave extends Sound
|
|
2625
|
+
{
|
|
2626
|
+
/** Create a sound object and cache the wave file for later use
|
|
2627
|
+
* @param {String} waveFilename - Filename of wave file to load
|
|
2628
|
+
* @param {Number} [randomness=.05] - How much to randomize frequency each time sound plays
|
|
2629
|
+
* @param {Number} [range=soundDefaultRange] - World space max range of sound, will not play if camera is farther away
|
|
2630
|
+
* @param {Number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering off
|
|
2631
|
+
*/
|
|
2632
|
+
constructor(waveFilename, randomness=.05, range, taper)
|
|
2548
2633
|
{
|
|
2634
|
+
super(0, range, taper);
|
|
2635
|
+
this.randomness = randomness;
|
|
2636
|
+
|
|
2549
2637
|
if (!soundEnable) return;
|
|
2638
|
+
if (!soundWaveDecoderContext)
|
|
2639
|
+
soundDecoderContext = new AudioContext;
|
|
2550
2640
|
|
|
2551
|
-
|
|
2641
|
+
fetch(waveFilename)
|
|
2642
|
+
.then(response => response.arrayBuffer())
|
|
2643
|
+
.then(arrayBuffer => soundWaveDecoderContext.decodeAudioData(arrayBuffer))
|
|
2644
|
+
.then(audioBuffer => this.cachedSamples = audioBuffer.getChannelData(0));
|
|
2552
2645
|
}
|
|
2553
2646
|
}
|
|
2647
|
+
let soundDecoderContext; // audio context used only to decode audio files
|
|
2554
2648
|
|
|
2555
2649
|
/**
|
|
2556
2650
|
* Music Object - Stores a zzfx music track for later use
|
|
@@ -2693,16 +2787,17 @@ function playSamples(sampleChannels, volume=1, rate=1, pan=0, loop=0)
|
|
|
2693
2787
|
{
|
|
2694
2788
|
if (!soundEnable) return;
|
|
2695
2789
|
|
|
2696
|
-
// create audio context
|
|
2790
|
+
// create audio context if needed
|
|
2697
2791
|
if (!audioContext)
|
|
2698
2792
|
audioContext = new AudioContext;
|
|
2699
2793
|
|
|
2700
|
-
// fix stalled audio
|
|
2701
|
-
audioContext.resume();
|
|
2702
|
-
|
|
2703
2794
|
// prevent sounds from building up if they can't be played
|
|
2704
2795
|
if (audioContext.state != 'running')
|
|
2796
|
+
{
|
|
2797
|
+
// fix stalled audio
|
|
2798
|
+
audioContext.resume();
|
|
2705
2799
|
return;
|
|
2800
|
+
}
|
|
2706
2801
|
|
|
2707
2802
|
// create buffer and source
|
|
2708
2803
|
const buffer = audioContext.createBuffer(sampleChannels.length, sampleChannels[0].length, zzfxR),
|
|
@@ -2907,7 +3002,7 @@ function zzfxM(instruments, patterns, sequence, BPM = 125)
|
|
|
2907
3002
|
|
|
2908
3003
|
// stop if end, different instrument or new note
|
|
2909
3004
|
stop = i == patternChannel.length + isSequenceEnd - 1 && isSequenceEnd ||
|
|
2910
|
-
instrument != (patternChannel[0] || 0) || note;
|
|
3005
|
+
instrument != (patternChannel[0] || 0) || note | 0;
|
|
2911
3006
|
|
|
2912
3007
|
// fill buffer with samples for previous beat, most cpu intensive part
|
|
2913
3008
|
for (j = 0; j < beatLength && notFirstBeat;
|
|
@@ -4145,8 +4240,8 @@ function glFlush()
|
|
|
4145
4240
|
|
|
4146
4241
|
// draw all the sprites in the batch and reset the buffer
|
|
4147
4242
|
glContext.bufferSubData(gl_ARRAY_BUFFER, 0,
|
|
4148
|
-
glPositionData.subarray(0, glBatchCount *
|
|
4149
|
-
glContext.drawArrays(
|
|
4243
|
+
glPositionData.subarray(0, glBatchCount * gl_INDICIES_PER_VERT));
|
|
4244
|
+
glContext.drawArrays(gl_TRIANGLE_STRIP, 0, glBatchCount);
|
|
4150
4245
|
glBatchCount = 0;
|
|
4151
4246
|
glBatchAdditive = glAdditive;
|
|
4152
4247
|
}
|
|
@@ -4167,39 +4262,75 @@ function glCopyToContext(context, forceDraw)
|
|
|
4167
4262
|
}
|
|
4168
4263
|
|
|
4169
4264
|
/** Add a sprite to the gl draw list, used by all gl draw functions
|
|
4170
|
-
* @param x
|
|
4171
|
-
* @param y
|
|
4172
|
-
* @param sizeX
|
|
4173
|
-
* @param sizeY
|
|
4174
|
-
* @param angle
|
|
4175
|
-
* @param uv0X
|
|
4176
|
-
* @param uv0Y
|
|
4177
|
-
* @param uv1X
|
|
4178
|
-
* @param uv1Y
|
|
4179
|
-
* @param rgba
|
|
4180
|
-
* @param [rgbaAdditive=0]
|
|
4265
|
+
* @param {Number} x
|
|
4266
|
+
* @param {Number} y
|
|
4267
|
+
* @param {Number} sizeX
|
|
4268
|
+
* @param {Number} sizeY
|
|
4269
|
+
* @param {Number} angle
|
|
4270
|
+
* @param {Number} uv0X
|
|
4271
|
+
* @param {Number} uv0Y
|
|
4272
|
+
* @param {Number} uv1X
|
|
4273
|
+
* @param {Number} uv1Y
|
|
4274
|
+
* @param {Number} rgba
|
|
4275
|
+
* @param {Number} [rgbaAdditive=0]
|
|
4181
4276
|
* @memberof WebGL */
|
|
4182
4277
|
function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba, rgbaAdditive=0)
|
|
4183
4278
|
{
|
|
4184
|
-
// flush if there is
|
|
4185
|
-
|
|
4279
|
+
// flush if there is not enough room or if different blend mode
|
|
4280
|
+
const vertCount = 6;
|
|
4281
|
+
if (glBatchCount >= gl_MAX_BATCH-vertCount || glBatchAdditive != glAdditive)
|
|
4186
4282
|
glFlush();
|
|
4187
4283
|
|
|
4188
4284
|
// prepare to create the verts from size and angle
|
|
4189
4285
|
const c = Math.cos(angle)/2, s = Math.sin(angle)/2;
|
|
4190
4286
|
const cx = c*sizeX, cy = c*sizeY, sx = s*sizeX, sy = s*sizeY;
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4287
|
+
const positionData =
|
|
4288
|
+
[
|
|
4289
|
+
x-cx+sy, y+cy+sx, uv0X, uv0Y,
|
|
4290
|
+
x-cx-sy, y-cy+sx, uv0X, uv1Y,
|
|
4291
|
+
x+cx+sy, y+cy-sx, uv1X, uv0Y,
|
|
4292
|
+
x+cx-sy, y-cy-sx, uv1X, uv1Y,
|
|
4293
|
+
];
|
|
4294
|
+
|
|
4295
|
+
// setup 2 triangle strip quad
|
|
4296
|
+
for(let i = vertCount, offset = glBatchCount * gl_INDICIES_PER_VERT; i--;)
|
|
4194
4297
|
{
|
|
4195
|
-
|
|
4196
|
-
glPositionData[offset++] =
|
|
4197
|
-
glPositionData[offset++] =
|
|
4198
|
-
glPositionData[offset++] =
|
|
4199
|
-
glPositionData[offset++] =
|
|
4298
|
+
let j = clamp(i-1, 0, 3)*4; // degenerate tri at ends
|
|
4299
|
+
glPositionData[offset++] = positionData[j++];
|
|
4300
|
+
glPositionData[offset++] = positionData[j++];
|
|
4301
|
+
glPositionData[offset++] = positionData[j++];
|
|
4302
|
+
glPositionData[offset++] = positionData[j++];
|
|
4200
4303
|
glColorData[offset++] = rgba;
|
|
4201
4304
|
glColorData[offset++] = rgbaAdditive;
|
|
4202
4305
|
}
|
|
4306
|
+
glBatchCount += vertCount;
|
|
4307
|
+
}
|
|
4308
|
+
|
|
4309
|
+
/** Add a convex polygon to the gl draw list
|
|
4310
|
+
* @param {Array} points - Array of Vector2 points
|
|
4311
|
+
* @param {Number} rgba - Color of the polygon
|
|
4312
|
+
* @memberof WebGL */
|
|
4313
|
+
function glDrawPoints(points, rgba)
|
|
4314
|
+
{
|
|
4315
|
+
// flush if there is not enough room or if different blend mode
|
|
4316
|
+
const vertCount = points.length + 2;
|
|
4317
|
+
if (glBatchCount >= gl_MAX_BATCH-vertCount || glBatchAdditive != glAdditive)
|
|
4318
|
+
glFlush();
|
|
4319
|
+
|
|
4320
|
+
// setup triangle strip from list of points
|
|
4321
|
+
for(let i = vertCount, offset = glBatchCount * gl_INDICIES_PER_VERT; i--;)
|
|
4322
|
+
{
|
|
4323
|
+
const j = clamp(i-1, 0, vertCount-3); // degenerate tri at ends
|
|
4324
|
+
const h = j>>1;
|
|
4325
|
+
const point = points[j%2? h : vertCount-3-h];
|
|
4326
|
+
glPositionData[offset++] = point.x;
|
|
4327
|
+
glPositionData[offset++] = point.y;
|
|
4328
|
+
glPositionData[offset++] = 0; // uvx
|
|
4329
|
+
glPositionData[offset++] = 0; // uvy
|
|
4330
|
+
glColorData[offset++] = 0; // nothing to tint
|
|
4331
|
+
glColorData[offset++] = rgba; // apply rgba via additive
|
|
4332
|
+
}
|
|
4333
|
+
glBatchCount += vertCount;
|
|
4203
4334
|
}
|
|
4204
4335
|
|
|
4205
4336
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -4293,14 +4424,14 @@ function glRenderPostProcess()
|
|
|
4293
4424
|
glContext.uniform1i(uniformLocation('iChannel0'), 0);
|
|
4294
4425
|
glContext.uniform1f(uniformLocation('iTime'), time);
|
|
4295
4426
|
glContext.uniform3f(uniformLocation('iResolution'), mainCanvas.width, mainCanvas.height, 1);
|
|
4296
|
-
glContext.drawArrays(
|
|
4427
|
+
glContext.drawArrays(gl_TRIANGLE_STRIP, 0, 3);
|
|
4297
4428
|
}
|
|
4298
4429
|
|
|
4299
4430
|
///////////////////////////////////////////////////////////////////////////////
|
|
4300
4431
|
// store gl constants as integers so their name doesn't use space in minifed
|
|
4301
4432
|
const
|
|
4302
4433
|
gl_ONE = 1,
|
|
4303
|
-
|
|
4434
|
+
gl_TRIANGLE_STRIP = 5,
|
|
4304
4435
|
gl_SRC_ALPHA = 770,
|
|
4305
4436
|
gl_ONE_MINUS_SRC_ALPHA = 771,
|
|
4306
4437
|
gl_BLEND = 3042,
|
|
@@ -4331,9 +4462,9 @@ gl_UNPACK_FLIP_Y_WEBGL = 37440,
|
|
|
4331
4462
|
// constants for batch rendering
|
|
4332
4463
|
gl_VERTICES_PER_QUAD = 6,
|
|
4333
4464
|
gl_INDICIES_PER_VERT = 6,
|
|
4334
|
-
gl_MAX_BATCH =
|
|
4465
|
+
gl_MAX_BATCH = 1e5,
|
|
4335
4466
|
gl_VERTEX_BYTE_STRIDE = (4 * 2) * 2 + (4) * 2, // vec2 * 2 + (char * 4) * 2
|
|
4336
|
-
gl_VERTEX_BUFFER_SIZE = gl_MAX_BATCH *
|
|
4467
|
+
gl_VERTEX_BUFFER_SIZE = gl_MAX_BATCH * gl_VERTEX_BYTE_STRIDE;
|
|
4337
4468
|
/**
|
|
4338
4469
|
* LittleJS - The Tiny JavaScript Game Engine That Can!
|
|
4339
4470
|
* MIT License - Copyright 2021 Frank Force
|
|
@@ -4366,7 +4497,7 @@ const engineName = 'LittleJS';
|
|
|
4366
4497
|
* @type {String}
|
|
4367
4498
|
* @default
|
|
4368
4499
|
* @memberof Engine */
|
|
4369
|
-
const engineVersion = '1.
|
|
4500
|
+
const engineVersion = '1.7.01';
|
|
4370
4501
|
|
|
4371
4502
|
/** Frames per second to update objects
|
|
4372
4503
|
* @type {Number}
|
|
@@ -4464,7 +4595,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4464
4595
|
};
|
|
4465
4596
|
|
|
4466
4597
|
// frame time tracking
|
|
4467
|
-
let frameTimeLastMS = 0, frameTimeBufferMS = 0, averageFPS;
|
|
4598
|
+
let frameTimeLastMS = 0, frameTimeBufferMS = 0, averageFPS = 0;
|
|
4468
4599
|
|
|
4469
4600
|
// main update loop
|
|
4470
4601
|
function engineUpdate(frameTimeMS=0)
|
|
@@ -4659,7 +4790,7 @@ function engineObjectsCallback(pos, size, callbackFunction, objects=engineObject
|
|
|
4659
4790
|
|
|
4660
4791
|
/**
|
|
4661
4792
|
* LittleJS Module Export
|
|
4662
|
-
* - Export engine as a module with
|
|
4793
|
+
* - Export engine as a module with functions where necessary
|
|
4663
4794
|
*/
|
|
4664
4795
|
|
|
4665
4796
|
/** Set position of camera in world space
|
|
@@ -4954,6 +5085,10 @@ export {
|
|
|
4954
5085
|
mod,
|
|
4955
5086
|
clamp,
|
|
4956
5087
|
percent,
|
|
5088
|
+
distanceWrap,
|
|
5089
|
+
lerpWrap,
|
|
5090
|
+
distanceAngle,
|
|
5091
|
+
lerpAngle,
|
|
4957
5092
|
lerp,
|
|
4958
5093
|
smoothStep,
|
|
4959
5094
|
nearestPowerOfTwo,
|
|
@@ -4968,11 +5103,9 @@ export {
|
|
|
4968
5103
|
randInCircle,
|
|
4969
5104
|
randVector,
|
|
4970
5105
|
randColor,
|
|
4971
|
-
randSeed,
|
|
4972
|
-
setRandSeed,
|
|
4973
|
-
randSeeded,
|
|
4974
5106
|
|
|
4975
5107
|
// Utility Classes
|
|
5108
|
+
RandomGenerator,
|
|
4976
5109
|
Vector2,
|
|
4977
5110
|
Color,
|
|
4978
5111
|
Timer,
|