littlejsengine 1.3.0 → 1.3.8
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/build.bat +1 -1
- package/buildSetup.bat +4 -1
- package/engine/engine.all.js +128 -77
- package/engine/engine.all.min.js +1 -1
- package/engine/engine.all.release.js +129 -78
- package/engine/engine.js +30 -27
- package/engine/engineAudio.js +5 -7
- package/engine/engineBuild.bat +0 -1
- package/engine/engineDebug.js +1 -1
- package/engine/engineDraw.js +15 -6
- package/engine/engineInput.js +6 -2
- package/engine/engineMedals.js +1 -1
- package/engine/engineObject.js +22 -19
- package/engine/engineParticles.js +1 -1
- package/engine/engineRelease.js +2 -2
- package/engine/engineSettings.js +7 -1
- package/engine/engineUtilities.js +39 -11
- package/engine/engineWebGL.js +1 -1
- package/engine/index.d.ts +23 -10
- package/examples/breakout/index.html +3 -3
- package/examples/particles/index.html +151 -103
- package/examples/platformer/index.html +5 -5
- package/examples/puzzle/game.js +3 -1
- package/examples/puzzle/index.html +2 -2
- package/examples/stress/index.html +1 -1
- package/game.js +10 -21
- package/index.html +13 -13
- package/package.json +9 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
LittleJS is a super lightweight JavaScript game engine with a fast hybrid rendering system. It provides everything necessary to make amazing games, including rendering, physics, particles, sound effects, music, input handling, and debug tools. LittleJS is designed to be extremely small yet powerful enough for a variety of applications, from game jams to commercial releases. The code is very well documented with a variety of examples to get you started. Choo-Choo! 🚂
|
|
6
6
|
|
|
7
|
-
## [LittleJS Documentation](https://killedbyapixel.github.io/LittleJS/docs) - [LittleJS Trailer](https://youtu.be/chuBzGjv7Ms) - [LittleJS
|
|
7
|
+
## [LittleJS Documentation](https://killedbyapixel.github.io/LittleJS/docs) - [LittleJS Trailer](https://youtu.be/chuBzGjv7Ms) - [LittleJS Discord](https://discord.gg/zb7hcGkyZe)
|
|
8
8
|
|
|
9
9
|

|
|
10
10
|
|
|
@@ -29,7 +29,8 @@ LittleJS is a super lightweight JavaScript game engine with a fast hybrid render
|
|
|
29
29
|
- Debug tools and debug rendering system
|
|
30
30
|
- [Full documentation](https://killedbyapixel.github.io/LittleJS/docs) automatically generated from the source code block tags with [JSDoc](https://github.com/jsdoc/jsdoc)
|
|
31
31
|
- Build system automatically combines everything, minifies, and removes unused code
|
|
32
|
-
- For size coding competitions like [js13kGames](https://js13kgames.com/), starter project builds to a 7KB zip
|
|
32
|
+
- For size coding competitions like [js13kGames](https://js13kgames.com/), starter project builds to a 7KB zip file
|
|
33
|
+
- (https://github.com/lifthrasiir/roadroller)
|
|
33
34
|
- Easily build a Windows executable with [Electron](https://www.electronjs.org/) for distribution on platforms like Steam
|
|
34
35
|
- Open Source with the [MIT license](https://github.com/KilledByAPixel/LittleJS/blob/main/LICENSE) so it can be used for anything you want
|
|
35
36
|
|
|
@@ -41,11 +42,13 @@ To easily include LittleJS in your game, you can use one of the 3 pre-built js f
|
|
|
41
42
|
- [engine.all.release.js](https://github.com/KilledByAPixel/LittleJS/blob/main/engine/engine.all.release.js) - The engine optimized for release builds
|
|
42
43
|
- [engine.all.min.js](https://github.com/KilledByAPixel/LittleJS/blob/main/engine/engine.all.min.js) - The engine in release mode and minified
|
|
43
44
|
|
|
44
|
-
The hello world example includes a batch file [build.bat](https://github.com/KilledByAPixel/LittleJS/blob/main/build.bat) that compresses everything into a tiny zip file using Google Closure, UglifyJS, Roadroller, and ECT. You must run buildSetup.bat to install the necessary npm dependencies.
|
|
45
|
+
The hello world example includes a batch file [build.bat](https://github.com/KilledByAPixel/LittleJS/blob/main/build.bat) that compresses everything into a tiny zip file using Google Closure, UglifyJS, Roadroller, and ECT. You must run [buildSetup.bat](https://github.com/KilledByAPixel/LittleJS/blob/main/buildSetup.bat) to install the necessary npm dependencies.
|
|
45
46
|
|
|
46
47
|
## Games Made With LittleJS
|
|
47
48
|
|
|
48
|
-
- [Space Huggers](https://
|
|
49
|
+
- [Space Huggers](https://www.newgrounds.com/portal/view/819609) - Run and gun platformer with procedural levels
|
|
50
|
+
- [Space Huggers - JS13k Edition](https://github.com/KilledByAPixel/SpaceHuggers) - Original js13k game with source code
|
|
51
|
+
- [Isletopia](https://store.steampowered.com/app/1861260/Isletopia) - Relaxing strategy game of greenifying barren islands
|
|
49
52
|
- Send me your games!
|
|
50
53
|
|
|
51
54
|

|
package/build.bat
CHANGED
|
@@ -49,7 +49,7 @@ if %ERRORLEVEL% NEQ 0 (
|
|
|
49
49
|
exit /b %ERRORLEVEL%
|
|
50
50
|
)
|
|
51
51
|
|
|
52
|
-
rem
|
|
52
|
+
rem roadroller compresses the code better then zip
|
|
53
53
|
copy %BUILD_FILENAME% roadroller_%BUILD_FILENAME%
|
|
54
54
|
call npx roadroller roadroller_%BUILD_FILENAME% -o roadroller_%BUILD_FILENAME%
|
|
55
55
|
if %ERRORLEVEL% NEQ 0 (
|
package/buildSetup.bat
CHANGED
package/engine/engine.all.js
CHANGED
|
@@ -30,7 +30,7 @@ const enableAsserts = 1;
|
|
|
30
30
|
* @memberof Debug */
|
|
31
31
|
const debugPointSize = .5;
|
|
32
32
|
|
|
33
|
-
/** True if watermark with FPS should be down
|
|
33
|
+
/** True if watermark with FPS should be down, false in release builds
|
|
34
34
|
* @default
|
|
35
35
|
* @memberof Debug */
|
|
36
36
|
let showWatermark = 1;
|
|
@@ -650,7 +650,7 @@ class Vector2
|
|
|
650
650
|
/** Returns a new vector in same direction as this one with the length passed in
|
|
651
651
|
* @param {Number} [length=1]
|
|
652
652
|
* @return {Vector2} */
|
|
653
|
-
normalize(length=1) { const l = this.length(); return l ? this.scale(length/l) : new Vector2(length); }
|
|
653
|
+
normalize(length=1) { const l = this.length(); return l ? this.scale(length/l) : new Vector2(0, length); }
|
|
654
654
|
|
|
655
655
|
/** Returns a new vector clamped to length passed in
|
|
656
656
|
* @param {Number} [length=1]
|
|
@@ -695,7 +695,7 @@ class Vector2
|
|
|
695
695
|
|
|
696
696
|
/** Returns the area this vector covers as a rectangle
|
|
697
697
|
* @return {Number} */
|
|
698
|
-
area() { return this.x * this.y; }
|
|
698
|
+
area() { return abs(this.x * this.y); }
|
|
699
699
|
|
|
700
700
|
/** Returns a new vector that is p percent between this and the vector passed in
|
|
701
701
|
* @param {Vector2} vector
|
|
@@ -804,6 +804,34 @@ class Color
|
|
|
804
804
|
return this;
|
|
805
805
|
}
|
|
806
806
|
|
|
807
|
+
/** Returns this color expressed in hsla format
|
|
808
|
+
* @return {Array} */
|
|
809
|
+
getHSLA()
|
|
810
|
+
{
|
|
811
|
+
const r = this.r;
|
|
812
|
+
const g = this.g;
|
|
813
|
+
const b = this.b;
|
|
814
|
+
const a = this.a;
|
|
815
|
+
const max = Math.max(r, g, b);
|
|
816
|
+
const min = Math.min(r, g, b);
|
|
817
|
+
const l = (max + min) / 2;
|
|
818
|
+
|
|
819
|
+
let h = 0, s = 0;
|
|
820
|
+
if (max != min)
|
|
821
|
+
{
|
|
822
|
+
let d = max - min;
|
|
823
|
+
s = l > .5 ? d / (2 - max - min) : d / (max + min);
|
|
824
|
+
if (r == max)
|
|
825
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
826
|
+
else if (g == max)
|
|
827
|
+
h = (b - r) / d + 2;
|
|
828
|
+
else if (b == max)
|
|
829
|
+
h = (r - g) / d + 4;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
return [h / 6, s, l, a];
|
|
833
|
+
}
|
|
834
|
+
|
|
807
835
|
/** Returns a new color that has each component randomly adjusted
|
|
808
836
|
* @param {Number} [amount=.05]
|
|
809
837
|
* @param {Number} [alphaAmount=0]
|
|
@@ -835,14 +863,6 @@ class Color
|
|
|
835
863
|
return (this.r*255|0) + (this.g*255<<8) + (this.b*255<<16) + (this.a*255<<24);
|
|
836
864
|
}
|
|
837
865
|
|
|
838
|
-
/** Returns this color expressed as a hex code
|
|
839
|
-
* @return {String} */
|
|
840
|
-
hex()
|
|
841
|
-
{
|
|
842
|
-
const toHex = (c)=> ((c=c*255|0)<16 ? '0' : '') + c.toString(16);
|
|
843
|
-
return '#' + toHex(this.r) + toHex(this.g) + toHex(this.b);
|
|
844
|
-
}
|
|
845
|
-
|
|
846
866
|
/** Set this color from a hex code
|
|
847
867
|
* @param {String} hex - html hex code
|
|
848
868
|
* @return {Color} */
|
|
@@ -856,6 +876,14 @@ class Color
|
|
|
856
876
|
ASSERT(this.r>=0 && this.r<=1 && this.g>=0 && this.g<=1 && this.b>=0 && this.b<=1);
|
|
857
877
|
return this;
|
|
858
878
|
}
|
|
879
|
+
|
|
880
|
+
/** Returns this color expressed as a hex code
|
|
881
|
+
* @return {String} */
|
|
882
|
+
getHex()
|
|
883
|
+
{
|
|
884
|
+
const toHex = (c)=> ((c=c*255|0)<16 ? '0' : '') + c.toString(16);
|
|
885
|
+
return '#' + toHex(this.r) + toHex(this.g) + toHex(this.b);
|
|
886
|
+
}
|
|
859
887
|
}
|
|
860
888
|
|
|
861
889
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -904,7 +932,7 @@ class Timer
|
|
|
904
932
|
|
|
905
933
|
/** Returns this timer expressed as a string
|
|
906
934
|
* @return {String} */
|
|
907
|
-
toString() { return this.unset() ? 'unset' : Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ); }
|
|
935
|
+
toString() { if (debug) { return this.unset() ? 'unset' : Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ); } }
|
|
908
936
|
}
|
|
909
937
|
/**
|
|
910
938
|
* LittleJS Engine Settings
|
|
@@ -922,7 +950,8 @@ class Timer
|
|
|
922
950
|
* @memberof Settings */
|
|
923
951
|
let canvasMaxSize = vec2(1920, 1200);
|
|
924
952
|
|
|
925
|
-
/** Fixed size of the canvas, if enabled
|
|
953
|
+
/** Fixed size of the canvas, if enabled canvas size never changes
|
|
954
|
+
* - you may also need to set mainCanvasSize if using screen space coords in startup
|
|
926
955
|
* @type {Vector2}
|
|
927
956
|
* @default
|
|
928
957
|
* @memberof Settings */
|
|
@@ -961,6 +990,11 @@ let tileFixBleedScale = .3;
|
|
|
961
990
|
* @memberof Settings */
|
|
962
991
|
let objectDefaultSize = vec2(1);
|
|
963
992
|
|
|
993
|
+
/** Enable physics solver for collisions between objects
|
|
994
|
+
* @default
|
|
995
|
+
* @memberof Settings */
|
|
996
|
+
let enablePhysicsSolver = 1;
|
|
997
|
+
|
|
964
998
|
/** Default object mass for collison calcuations (how heavy objects are)
|
|
965
999
|
* @default
|
|
966
1000
|
* @memberof Settings */
|
|
@@ -1159,7 +1193,7 @@ class EngineObject
|
|
|
1159
1193
|
/** Create an engine object and adds it to the list of objects
|
|
1160
1194
|
* @param {Vector2} [position=new Vector2()] - World space position of the object
|
|
1161
1195
|
* @param {Vector2} [size=objectDefaultSize] - World space size of the object
|
|
1162
|
-
* @param {Number} [tileIndex=-1] - Tile to use to render object
|
|
1196
|
+
* @param {Number} [tileIndex=-1] - Tile to use to render object (-1 is untextured)
|
|
1163
1197
|
* @param {Vector2} [tileSize=tileSizeDefault] - Size of tile in source pixels
|
|
1164
1198
|
* @param {Number} [angle=0] - Angle the object is rotated by
|
|
1165
1199
|
* @param {Color} [color] - Color to apply to tile when rendered
|
|
@@ -1176,7 +1210,7 @@ class EngineObject
|
|
|
1176
1210
|
this.size = size;
|
|
1177
1211
|
/** @property {Vector2} - Size of object used for drawing, uses size if not set */
|
|
1178
1212
|
this.drawSize;
|
|
1179
|
-
/** @property {Number} - Tile to use to render object
|
|
1213
|
+
/** @property {Number} - Tile to use to render object (-1 is untextured) */
|
|
1180
1214
|
this.tileIndex = tileIndex;
|
|
1181
1215
|
/** @property {Vector2} - Size of tile in source pixels */
|
|
1182
1216
|
this.tileSize = tileSize;
|
|
@@ -1188,7 +1222,7 @@ class EngineObject
|
|
|
1188
1222
|
this.additiveColor;
|
|
1189
1223
|
|
|
1190
1224
|
// set object defaults
|
|
1191
|
-
/** @property {Number} [mass=objectDefaultMass] - How heavy the object is */
|
|
1225
|
+
/** @property {Number} [mass=objectDefaultMass] - How heavy the object is, static if 0 */
|
|
1192
1226
|
this.mass = objectDefaultMass;
|
|
1193
1227
|
/** @property {Number} [damping=objectDefaultDamping] - How much to slow down velocity each frame (0-1) */
|
|
1194
1228
|
this.damping = objectDefaultDamping;
|
|
@@ -1242,7 +1276,7 @@ class EngineObject
|
|
|
1242
1276
|
ASSERT(this.angleDamping >= 0 && this.angleDamping <= 1);
|
|
1243
1277
|
ASSERT(this.damping >= 0 && this.damping <= 1);
|
|
1244
1278
|
|
|
1245
|
-
if (!this.mass) // do not update collision for fixed objects
|
|
1279
|
+
if (!enablePhysicsSolver || !this.mass) // do not update collision for fixed objects
|
|
1246
1280
|
return;
|
|
1247
1281
|
|
|
1248
1282
|
const wasMovingDown = this.velocity.y < 0;
|
|
@@ -1252,7 +1286,7 @@ class EngineObject
|
|
|
1252
1286
|
const groundSpeed = this.groundObject.velocity ? this.groundObject.velocity.x : 0;
|
|
1253
1287
|
this.velocity.x = groundSpeed + (this.velocity.x - groundSpeed) * this.friction;
|
|
1254
1288
|
this.groundObject = 0;
|
|
1255
|
-
//debugPhysics && debugPoint(this.pos.subtract(vec2(0,this.size.y/2)), '#0f0');
|
|
1289
|
+
//debugOverlay && debugPhysics && debugPoint(this.pos.subtract(vec2(0,this.size.y/2)), '#0f0');
|
|
1256
1290
|
}
|
|
1257
1291
|
|
|
1258
1292
|
if (this.collideSolidObjects)
|
|
@@ -1284,7 +1318,7 @@ class EngineObject
|
|
|
1284
1318
|
if (o.mass) // push away if not fixed
|
|
1285
1319
|
o.velocity = o.velocity.subtract(velocity);
|
|
1286
1320
|
|
|
1287
|
-
debugPhysics && debugAABB(this.pos, this.size, o.pos, o.size, '#f00');
|
|
1321
|
+
debugOverlay && debugPhysics && debugAABB(this.pos, this.size, o.pos, o.size, '#f00');
|
|
1288
1322
|
continue;
|
|
1289
1323
|
}
|
|
1290
1324
|
|
|
@@ -1347,7 +1381,7 @@ class EngineObject
|
|
|
1347
1381
|
else // bounce if other object is fixed
|
|
1348
1382
|
this.velocity.x *= -this.elasticity;
|
|
1349
1383
|
}
|
|
1350
|
-
debugPhysics && debugAABB(this.pos, this.size, o.pos, o.size, '#f0f');
|
|
1384
|
+
debugOverlay && debugPhysics && debugAABB(this.pos, this.size, o.pos, o.size, '#f0f');
|
|
1351
1385
|
}
|
|
1352
1386
|
}
|
|
1353
1387
|
if (this.collideTiles)
|
|
@@ -1480,18 +1514,21 @@ class EngineObject
|
|
|
1480
1514
|
|
|
1481
1515
|
toString()
|
|
1482
1516
|
{
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
text
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1517
|
+
if (debug)
|
|
1518
|
+
{
|
|
1519
|
+
let text = 'type = ' + this.constructor.name;
|
|
1520
|
+
if (this.pos.x || this.pos.y)
|
|
1521
|
+
text += '\npos = ' + this.pos;
|
|
1522
|
+
if (this.velocity.x || this.velocity.y)
|
|
1523
|
+
text += '\nvelocity = ' + this.velocity;
|
|
1524
|
+
if (this.size.x || this.size.y)
|
|
1525
|
+
text += '\nsize = ' + this.size;
|
|
1526
|
+
if (this.angle)
|
|
1527
|
+
text += '\nangle = ' + this.angle.toFixed(3);
|
|
1528
|
+
if (this.color)
|
|
1529
|
+
text += '\ncolor = ' + this.color;
|
|
1530
|
+
return text;
|
|
1531
|
+
}
|
|
1495
1532
|
}
|
|
1496
1533
|
}
|
|
1497
1534
|
/**
|
|
@@ -1549,18 +1586,26 @@ let overlayContext;
|
|
|
1549
1586
|
let mainCanvasSize = vec2();
|
|
1550
1587
|
|
|
1551
1588
|
/** Convert from screen to world space coordinates
|
|
1589
|
+
* - if calling outside of render, you may need to manually set mainCanvasSize
|
|
1552
1590
|
* @param {Vector2} screenPos
|
|
1553
1591
|
* @return {Vector2}
|
|
1554
1592
|
* @memberof Draw */
|
|
1555
1593
|
const screenToWorld = (screenPos)=>
|
|
1556
|
-
|
|
1594
|
+
{
|
|
1595
|
+
ASSERT(mainCanvasSize.x && mainCanvasSize.y, 'mainCanvasSize is invalid');
|
|
1596
|
+
return screenPos.add(vec2(.5)).subtract(mainCanvasSize.scale(.5)).multiply(vec2(1/cameraScale,-1/cameraScale)).add(cameraPos);
|
|
1597
|
+
}
|
|
1557
1598
|
|
|
1558
1599
|
/** Convert from world to screen space coordinates
|
|
1600
|
+
* - if calling outside of render, you may need to manually set mainCanvasSize
|
|
1559
1601
|
* @param {Vector2} worldPos
|
|
1560
1602
|
* @return {Vector2}
|
|
1561
1603
|
* @memberof Draw */
|
|
1562
1604
|
const worldToScreen = (worldPos)=>
|
|
1563
|
-
|
|
1605
|
+
{
|
|
1606
|
+
ASSERT(mainCanvasSize.x && mainCanvasSize.y, 'mainCanvasSize is invalid');
|
|
1607
|
+
return worldPos.subtract(cameraPos).multiply(vec2(cameraScale,-cameraScale)).add(mainCanvasSize.scale(.5)).subtract(vec2(.5));
|
|
1608
|
+
}
|
|
1564
1609
|
|
|
1565
1610
|
/** Draw textured tile centered in world space, with color applied if using WebGL
|
|
1566
1611
|
* @param {Vector2} pos - Center of the tile in world space
|
|
@@ -1661,7 +1706,7 @@ function drawTileScreenSpace(pos, size=vec2(1), tileIndex, tileSize, color, angl
|
|
|
1661
1706
|
* @memberof Draw */
|
|
1662
1707
|
function drawRectScreenSpace(pos, size, color, angle, useWebGL)
|
|
1663
1708
|
{
|
|
1664
|
-
|
|
1709
|
+
drawTileScreenSpace(pos, size, -1, tileSizeDefault, color, angle, 0, 0, useWebGL);
|
|
1665
1710
|
}
|
|
1666
1711
|
|
|
1667
1712
|
/** Draw colored line between two points
|
|
@@ -1724,14 +1769,15 @@ function setBlendMode(additive, useWebGL=glEnable)
|
|
|
1724
1769
|
function drawTextScreen(text, pos, size=1, color=new Color, lineWidth=0, lineColor=new Color(0,0,0), textAlign='center', font=fontDefault)
|
|
1725
1770
|
{
|
|
1726
1771
|
overlayContext.fillStyle = color;
|
|
1727
|
-
overlayContext.lineWidth = lineWidth
|
|
1772
|
+
overlayContext.lineWidth = lineWidth;
|
|
1728
1773
|
overlayContext.strokeStyle = lineColor;
|
|
1729
1774
|
overlayContext.textAlign = textAlign;
|
|
1730
1775
|
overlayContext.font = size + 'px '+ font;
|
|
1731
1776
|
overlayContext.textBaseline = 'middle';
|
|
1777
|
+
overlayContext.lineJoin = 'round';
|
|
1732
1778
|
|
|
1733
1779
|
pos = pos.copy();
|
|
1734
|
-
text.split('\n').forEach(line=>
|
|
1780
|
+
(text+'').split('\n').forEach(line=>
|
|
1735
1781
|
{
|
|
1736
1782
|
lineWidth && overlayContext.strokeText(line, pos.x, pos.y);
|
|
1737
1783
|
overlayContext.fillText(line, pos.x, pos.y);
|
|
@@ -1751,7 +1797,7 @@ function drawTextScreen(text, pos, size=1, color=new Color, lineWidth=0, lineCol
|
|
|
1751
1797
|
* @memberof Draw */
|
|
1752
1798
|
function drawText(text, pos, size=1, color, lineWidth, lineColor, textAlign, font)
|
|
1753
1799
|
{
|
|
1754
|
-
drawTextScreen(text, worldToScreen(pos), size*cameraScale, color, lineWidth, lineColor, textAlign, font);
|
|
1800
|
+
drawTextScreen(text, worldToScreen(pos), size*cameraScale, color, lineWidth*cameraScale, lineColor, textAlign, font);
|
|
1755
1801
|
}
|
|
1756
1802
|
|
|
1757
1803
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -1945,6 +1991,10 @@ let mouseWheel = 0;
|
|
|
1945
1991
|
* @memberof Input */
|
|
1946
1992
|
let isUsingGamepad = 0;
|
|
1947
1993
|
|
|
1994
|
+
/** Prevents input continuing to the default browser handling (false by default)
|
|
1995
|
+
* @memberof Input */
|
|
1996
|
+
let preventDefaultInput = 0;
|
|
1997
|
+
|
|
1948
1998
|
/** Returns true if gamepad button is down
|
|
1949
1999
|
* @param {Number} button
|
|
1950
2000
|
* @param {Number} [gamepad=0]
|
|
@@ -2008,7 +2058,7 @@ onkeydown = (e)=>
|
|
|
2008
2058
|
{
|
|
2009
2059
|
if (debug && e.target != document.body) return;
|
|
2010
2060
|
e.repeat || (inputData[isUsingGamepad = 0][remapKeyCode(e.keyCode)] = 3);
|
|
2011
|
-
|
|
2061
|
+
preventDefaultInput && e.preventDefault();
|
|
2012
2062
|
}
|
|
2013
2063
|
onkeyup = (e)=>
|
|
2014
2064
|
{
|
|
@@ -2033,7 +2083,7 @@ const mouseToScreen = (mousePos)=>
|
|
|
2033
2083
|
return vec2(); // fix bug that can occur if user clicks before page loads
|
|
2034
2084
|
|
|
2035
2085
|
const rect = mainCanvas.getBoundingClientRect();
|
|
2036
|
-
return
|
|
2086
|
+
return vec2(mainCanvas.width, mainCanvas.height).multiply(
|
|
2037
2087
|
vec2(percent(mousePos.x, rect.left, rect.right), percent(mousePos.y, rect.top, rect.bottom)));
|
|
2038
2088
|
}
|
|
2039
2089
|
|
|
@@ -2572,8 +2622,7 @@ function zzfxG
|
|
|
2572
2622
|
)
|
|
2573
2623
|
{
|
|
2574
2624
|
// init parameters
|
|
2575
|
-
let PI2 = PI*2,
|
|
2576
|
-
startSlide = slide *= 500 * PI2 / zzfxR / zzfxR, b=[],
|
|
2625
|
+
let PI2 = PI*2, startSlide = slide *= 500 * PI2 / zzfxR / zzfxR, b=[],
|
|
2577
2626
|
startFrequency = frequency *= (1 + randomness*rand(-1,1)) * PI2 / zzfxR,
|
|
2578
2627
|
t=0, tm=0, i=0, j=1, r=0, c=0, s=0, f, length;
|
|
2579
2628
|
|
|
@@ -2597,15 +2646,15 @@ function zzfxG
|
|
|
2597
2646
|
{
|
|
2598
2647
|
s = shape? shape>1? shape>2? shape>3? // wave shape
|
|
2599
2648
|
Math.sin((t%PI2)**3) : // 4 noise
|
|
2600
|
-
|
|
2649
|
+
max(min(Math.tan(t),1),-1): // 3 tan
|
|
2601
2650
|
1-(2*t/PI2%2+2)%2: // 2 saw
|
|
2602
|
-
1-4*abs(Math.round(t/PI2)-t/PI2):
|
|
2651
|
+
1-4*abs(Math.round(t/PI2)-t/PI2): // 1 triangle
|
|
2603
2652
|
Math.sin(t); // 0 sin
|
|
2604
2653
|
|
|
2605
2654
|
s = (repeatTime ?
|
|
2606
2655
|
1 - tremolo + tremolo*Math.sin(PI2*i/repeatTime) // tremolo
|
|
2607
2656
|
: 1) *
|
|
2608
|
-
sign(s)*(abs(s)**shapeCurve) *
|
|
2657
|
+
sign(s)*(abs(s)**shapeCurve) * // curve 0=square, 2=pointy
|
|
2609
2658
|
volume * soundVolume * ( // envelope
|
|
2610
2659
|
i < attack ? i/attack : // attack
|
|
2611
2660
|
i < attack + decay ? // decay
|
|
@@ -2666,7 +2715,6 @@ function zzfxM(instruments, patterns, sequence, BPM = 125)
|
|
|
2666
2715
|
let notFirstBeat;
|
|
2667
2716
|
let stop;
|
|
2668
2717
|
let instrument;
|
|
2669
|
-
let pitch;
|
|
2670
2718
|
let attenuation;
|
|
2671
2719
|
let outSampleOffset;
|
|
2672
2720
|
let isSequenceEnd;
|
|
@@ -2685,7 +2733,7 @@ function zzfxM(instruments, patterns, sequence, BPM = 125)
|
|
|
2685
2733
|
for (; hasMore; channelIndex++) {
|
|
2686
2734
|
|
|
2687
2735
|
// reset current values
|
|
2688
|
-
sampleBuffer = [hasMore = notFirstBeat =
|
|
2736
|
+
sampleBuffer = [hasMore = notFirstBeat = outSampleOffset = 0];
|
|
2689
2737
|
|
|
2690
2738
|
// for each pattern in sequence
|
|
2691
2739
|
sequence.forEach((patternIndex, sequenceIndex) => {
|
|
@@ -3210,7 +3258,7 @@ class ParticleEmitter extends EngineObject
|
|
|
3210
3258
|
// particle settings
|
|
3211
3259
|
/** @property {Number} - How long particles live */
|
|
3212
3260
|
this.particleTime = particleTime;
|
|
3213
|
-
/** @property {Number} -
|
|
3261
|
+
/** @property {Number} - How big are particles at start */
|
|
3214
3262
|
this.sizeStart = sizeStart;
|
|
3215
3263
|
/** @property {Number} - How big are particles at end */
|
|
3216
3264
|
this.sizeEnd = sizeEnd;
|
|
@@ -3573,7 +3621,7 @@ class Newgrounds
|
|
|
3573
3621
|
cipher && (this.cryptoJS = CryptoJS());
|
|
3574
3622
|
|
|
3575
3623
|
// get session id from url search params
|
|
3576
|
-
const url = new URL(
|
|
3624
|
+
const url = new URL(location.href);
|
|
3577
3625
|
this.session_id = url.searchParams.get('ngio_session_id') || 0;
|
|
3578
3626
|
|
|
3579
3627
|
if (this.session_id == 0)
|
|
@@ -3926,7 +3974,7 @@ function glFlush()
|
|
|
3926
3974
|
* @memberof WebGL */
|
|
3927
3975
|
function glCopyToContext(context, forceDraw)
|
|
3928
3976
|
{
|
|
3929
|
-
if (!glEnable || !glBatchCount) return;
|
|
3977
|
+
if ((!glEnable || !glBatchCount) && !forceDraw) return;
|
|
3930
3978
|
|
|
3931
3979
|
glFlush();
|
|
3932
3980
|
|
|
@@ -4056,7 +4104,7 @@ gl_VERTEX_BYTE_STRIDE = (4 * 2) * 2 + (4) * 2; // vec2 * 2 + (char * 4) * 2
|
|
|
4056
4104
|
const engineName = 'LittleJS';
|
|
4057
4105
|
|
|
4058
4106
|
/** Version of engine */
|
|
4059
|
-
const engineVersion = '1.3.
|
|
4107
|
+
const engineVersion = '1.3.8';
|
|
4060
4108
|
|
|
4061
4109
|
/** Frames per second to update objects
|
|
4062
4110
|
* @default */
|
|
@@ -4147,6 +4195,33 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4147
4195
|
timeReal += frameTimeDeltaMS / 1e3;
|
|
4148
4196
|
frameTimeBufferMS = min(frameTimeBufferMS + !paused * frameTimeDeltaMS, 50); // clamp incase of slow framerate
|
|
4149
4197
|
|
|
4198
|
+
if (canvasFixedSize.x)
|
|
4199
|
+
{
|
|
4200
|
+
// clear set fixed size
|
|
4201
|
+
overlayCanvas.width = mainCanvas.width = canvasFixedSize.x;
|
|
4202
|
+
overlayCanvas.height = mainCanvas.height = canvasFixedSize.y;
|
|
4203
|
+
|
|
4204
|
+
// fit to window by adding space on top or bottom if necessary
|
|
4205
|
+
const aspect = innerWidth / innerHeight;
|
|
4206
|
+
const fixedAspect = mainCanvas.width / mainCanvas.height;
|
|
4207
|
+
mainCanvas.style.width = overlayCanvas.style.width = aspect < fixedAspect ? '100%' : '';
|
|
4208
|
+
mainCanvas.style.height = overlayCanvas.style.height = aspect < fixedAspect ? '' : '100%';
|
|
4209
|
+
if (glCanvas)
|
|
4210
|
+
{
|
|
4211
|
+
glCanvas.style.width = mainCanvas.style.width;
|
|
4212
|
+
glCanvas.style.height = mainCanvas.style.height;
|
|
4213
|
+
}
|
|
4214
|
+
}
|
|
4215
|
+
else
|
|
4216
|
+
{
|
|
4217
|
+
// clear and set size to same as window
|
|
4218
|
+
overlayCanvas.width = mainCanvas.width = min(innerWidth, canvasMaxSize.x);
|
|
4219
|
+
overlayCanvas.height = mainCanvas.height = min(innerHeight, canvasMaxSize.y);
|
|
4220
|
+
}
|
|
4221
|
+
|
|
4222
|
+
// save canvas size
|
|
4223
|
+
mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
|
|
4224
|
+
|
|
4150
4225
|
if (paused)
|
|
4151
4226
|
{
|
|
4152
4227
|
// do post update even when paused
|
|
@@ -4183,30 +4258,6 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4183
4258
|
// add the time smoothing back in
|
|
4184
4259
|
frameTimeBufferMS += deltaSmooth;
|
|
4185
4260
|
}
|
|
4186
|
-
|
|
4187
|
-
if (canvasFixedSize.x)
|
|
4188
|
-
{
|
|
4189
|
-
// clear set fixed size
|
|
4190
|
-
mainCanvas.width = canvasFixedSize.x;
|
|
4191
|
-
mainCanvas.height = canvasFixedSize.y;
|
|
4192
|
-
|
|
4193
|
-
// fit to window by adding space on top or bottom if necessary
|
|
4194
|
-
const aspect = innerWidth / innerHeight;
|
|
4195
|
-
const fixedAspect = mainCanvas.width / mainCanvas.height;
|
|
4196
|
-
mainCanvas.style.width = overlayCanvas.style.width = aspect < fixedAspect ? '100%' : '';
|
|
4197
|
-
mainCanvas.style.height = overlayCanvas.style.height = aspect < fixedAspect ? '' : '100%';
|
|
4198
|
-
if (glCanvas)
|
|
4199
|
-
{
|
|
4200
|
-
glCanvas.style.width = mainCanvas.style.width;
|
|
4201
|
-
glCanvas.style.height = mainCanvas.style.height;
|
|
4202
|
-
}
|
|
4203
|
-
}
|
|
4204
|
-
else
|
|
4205
|
-
{
|
|
4206
|
-
// clear and set size to same as window
|
|
4207
|
-
mainCanvas.width = min(innerWidth, canvasMaxSize.x);
|
|
4208
|
-
mainCanvas.height = min(innerHeight, canvasMaxSize.y);
|
|
4209
|
-
}
|
|
4210
4261
|
|
|
4211
4262
|
// render sort then render while removing destroyed objects
|
|
4212
4263
|
enginePreRender();
|
|
@@ -4246,8 +4297,8 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4246
4297
|
// called by engine to setup render system
|
|
4247
4298
|
function enginePreRender()
|
|
4248
4299
|
{
|
|
4249
|
-
// save canvas size
|
|
4250
|
-
mainCanvasSize = vec2(
|
|
4300
|
+
// save canvas size
|
|
4301
|
+
mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
|
|
4251
4302
|
|
|
4252
4303
|
// disable smoothing for pixel art
|
|
4253
4304
|
mainContext.imageSmoothingEnabled = !cavasPixelated;
|