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
|
@@ -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;
|
|
@@ -288,7 +288,7 @@ class Vector2
|
|
|
288
288
|
/** Returns a new vector in same direction as this one with the length passed in
|
|
289
289
|
* @param {Number} [length=1]
|
|
290
290
|
* @return {Vector2} */
|
|
291
|
-
normalize(length=1) { const l = this.length(); return l ? this.scale(length/l) : new Vector2(length); }
|
|
291
|
+
normalize(length=1) { const l = this.length(); return l ? this.scale(length/l) : new Vector2(0, length); }
|
|
292
292
|
|
|
293
293
|
/** Returns a new vector clamped to length passed in
|
|
294
294
|
* @param {Number} [length=1]
|
|
@@ -333,7 +333,7 @@ class Vector2
|
|
|
333
333
|
|
|
334
334
|
/** Returns the area this vector covers as a rectangle
|
|
335
335
|
* @return {Number} */
|
|
336
|
-
area() { return this.x * this.y; }
|
|
336
|
+
area() { return abs(this.x * this.y); }
|
|
337
337
|
|
|
338
338
|
/** Returns a new vector that is p percent between this and the vector passed in
|
|
339
339
|
* @param {Vector2} vector
|
|
@@ -442,6 +442,34 @@ class Color
|
|
|
442
442
|
return this;
|
|
443
443
|
}
|
|
444
444
|
|
|
445
|
+
/** Returns this color expressed in hsla format
|
|
446
|
+
* @return {Array} */
|
|
447
|
+
getHSLA()
|
|
448
|
+
{
|
|
449
|
+
const r = this.r;
|
|
450
|
+
const g = this.g;
|
|
451
|
+
const b = this.b;
|
|
452
|
+
const a = this.a;
|
|
453
|
+
const max = Math.max(r, g, b);
|
|
454
|
+
const min = Math.min(r, g, b);
|
|
455
|
+
const l = (max + min) / 2;
|
|
456
|
+
|
|
457
|
+
let h = 0, s = 0;
|
|
458
|
+
if (max != min)
|
|
459
|
+
{
|
|
460
|
+
let d = max - min;
|
|
461
|
+
s = l > .5 ? d / (2 - max - min) : d / (max + min);
|
|
462
|
+
if (r == max)
|
|
463
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
464
|
+
else if (g == max)
|
|
465
|
+
h = (b - r) / d + 2;
|
|
466
|
+
else if (b == max)
|
|
467
|
+
h = (r - g) / d + 4;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
return [h / 6, s, l, a];
|
|
471
|
+
}
|
|
472
|
+
|
|
445
473
|
/** Returns a new color that has each component randomly adjusted
|
|
446
474
|
* @param {Number} [amount=.05]
|
|
447
475
|
* @param {Number} [alphaAmount=0]
|
|
@@ -473,14 +501,6 @@ class Color
|
|
|
473
501
|
return (this.r*255|0) + (this.g*255<<8) + (this.b*255<<16) + (this.a*255<<24);
|
|
474
502
|
}
|
|
475
503
|
|
|
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
504
|
/** Set this color from a hex code
|
|
485
505
|
* @param {String} hex - html hex code
|
|
486
506
|
* @return {Color} */
|
|
@@ -494,6 +514,14 @@ class Color
|
|
|
494
514
|
ASSERT(this.r>=0 && this.r<=1 && this.g>=0 && this.g<=1 && this.b>=0 && this.b<=1);
|
|
495
515
|
return this;
|
|
496
516
|
}
|
|
517
|
+
|
|
518
|
+
/** Returns this color expressed as a hex code
|
|
519
|
+
* @return {String} */
|
|
520
|
+
getHex()
|
|
521
|
+
{
|
|
522
|
+
const toHex = (c)=> ((c=c*255|0)<16 ? '0' : '') + c.toString(16);
|
|
523
|
+
return '#' + toHex(this.r) + toHex(this.g) + toHex(this.b);
|
|
524
|
+
}
|
|
497
525
|
}
|
|
498
526
|
|
|
499
527
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -542,7 +570,7 @@ class Timer
|
|
|
542
570
|
|
|
543
571
|
/** Returns this timer expressed as a string
|
|
544
572
|
* @return {String} */
|
|
545
|
-
toString() { return this.unset() ? 'unset' : Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ); }
|
|
573
|
+
toString() { if (debug) { return this.unset() ? 'unset' : Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ); } }
|
|
546
574
|
}
|
|
547
575
|
/**
|
|
548
576
|
* LittleJS Engine Settings
|
|
@@ -560,7 +588,8 @@ class Timer
|
|
|
560
588
|
* @memberof Settings */
|
|
561
589
|
let canvasMaxSize = vec2(1920, 1200);
|
|
562
590
|
|
|
563
|
-
/** Fixed size of the canvas, if enabled
|
|
591
|
+
/** Fixed size of the canvas, if enabled canvas size never changes
|
|
592
|
+
* - you may also need to set mainCanvasSize if using screen space coords in startup
|
|
564
593
|
* @type {Vector2}
|
|
565
594
|
* @default
|
|
566
595
|
* @memberof Settings */
|
|
@@ -599,6 +628,11 @@ let tileFixBleedScale = .3;
|
|
|
599
628
|
* @memberof Settings */
|
|
600
629
|
let objectDefaultSize = vec2(1);
|
|
601
630
|
|
|
631
|
+
/** Enable physics solver for collisions between objects
|
|
632
|
+
* @default
|
|
633
|
+
* @memberof Settings */
|
|
634
|
+
let enablePhysicsSolver = 1;
|
|
635
|
+
|
|
602
636
|
/** Default object mass for collison calcuations (how heavy objects are)
|
|
603
637
|
* @default
|
|
604
638
|
* @memberof Settings */
|
|
@@ -785,7 +819,7 @@ let medalDisplayIconSize = 50;
|
|
|
785
819
|
const engineName = 'LittleJS';
|
|
786
820
|
|
|
787
821
|
/** Version of engine */
|
|
788
|
-
const engineVersion = '1.3.
|
|
822
|
+
const engineVersion = '1.3.8';
|
|
789
823
|
|
|
790
824
|
/** Frames per second to update objects
|
|
791
825
|
* @default */
|
|
@@ -876,6 +910,33 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
876
910
|
timeReal += frameTimeDeltaMS / 1e3;
|
|
877
911
|
frameTimeBufferMS = min(frameTimeBufferMS + !paused * frameTimeDeltaMS, 50); // clamp incase of slow framerate
|
|
878
912
|
|
|
913
|
+
if (canvasFixedSize.x)
|
|
914
|
+
{
|
|
915
|
+
// clear set fixed size
|
|
916
|
+
overlayCanvas.width = mainCanvas.width = canvasFixedSize.x;
|
|
917
|
+
overlayCanvas.height = mainCanvas.height = canvasFixedSize.y;
|
|
918
|
+
|
|
919
|
+
// fit to window by adding space on top or bottom if necessary
|
|
920
|
+
const aspect = innerWidth / innerHeight;
|
|
921
|
+
const fixedAspect = mainCanvas.width / mainCanvas.height;
|
|
922
|
+
mainCanvas.style.width = overlayCanvas.style.width = aspect < fixedAspect ? '100%' : '';
|
|
923
|
+
mainCanvas.style.height = overlayCanvas.style.height = aspect < fixedAspect ? '' : '100%';
|
|
924
|
+
if (glCanvas)
|
|
925
|
+
{
|
|
926
|
+
glCanvas.style.width = mainCanvas.style.width;
|
|
927
|
+
glCanvas.style.height = mainCanvas.style.height;
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
else
|
|
931
|
+
{
|
|
932
|
+
// clear and set size to same as window
|
|
933
|
+
overlayCanvas.width = mainCanvas.width = min(innerWidth, canvasMaxSize.x);
|
|
934
|
+
overlayCanvas.height = mainCanvas.height = min(innerHeight, canvasMaxSize.y);
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
// save canvas size
|
|
938
|
+
mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
|
|
939
|
+
|
|
879
940
|
if (paused)
|
|
880
941
|
{
|
|
881
942
|
// do post update even when paused
|
|
@@ -912,30 +973,6 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
912
973
|
// add the time smoothing back in
|
|
913
974
|
frameTimeBufferMS += deltaSmooth;
|
|
914
975
|
}
|
|
915
|
-
|
|
916
|
-
if (canvasFixedSize.x)
|
|
917
|
-
{
|
|
918
|
-
// clear set fixed size
|
|
919
|
-
mainCanvas.width = canvasFixedSize.x;
|
|
920
|
-
mainCanvas.height = canvasFixedSize.y;
|
|
921
|
-
|
|
922
|
-
// fit to window by adding space on top or bottom if necessary
|
|
923
|
-
const aspect = innerWidth / innerHeight;
|
|
924
|
-
const fixedAspect = mainCanvas.width / mainCanvas.height;
|
|
925
|
-
mainCanvas.style.width = overlayCanvas.style.width = aspect < fixedAspect ? '100%' : '';
|
|
926
|
-
mainCanvas.style.height = overlayCanvas.style.height = aspect < fixedAspect ? '' : '100%';
|
|
927
|
-
if (glCanvas)
|
|
928
|
-
{
|
|
929
|
-
glCanvas.style.width = mainCanvas.style.width;
|
|
930
|
-
glCanvas.style.height = mainCanvas.style.height;
|
|
931
|
-
}
|
|
932
|
-
}
|
|
933
|
-
else
|
|
934
|
-
{
|
|
935
|
-
// clear and set size to same as window
|
|
936
|
-
mainCanvas.width = min(innerWidth, canvasMaxSize.x);
|
|
937
|
-
mainCanvas.height = min(innerHeight, canvasMaxSize.y);
|
|
938
|
-
}
|
|
939
976
|
|
|
940
977
|
// render sort then render while removing destroyed objects
|
|
941
978
|
enginePreRender();
|
|
@@ -975,8 +1012,8 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
975
1012
|
// called by engine to setup render system
|
|
976
1013
|
function enginePreRender()
|
|
977
1014
|
{
|
|
978
|
-
// save canvas size
|
|
979
|
-
mainCanvasSize = vec2(
|
|
1015
|
+
// save canvas size
|
|
1016
|
+
mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
|
|
980
1017
|
|
|
981
1018
|
// disable smoothing for pixel art
|
|
982
1019
|
mainContext.imageSmoothingEnabled = !cavasPixelated;
|
|
@@ -1081,7 +1118,7 @@ class EngineObject
|
|
|
1081
1118
|
/** Create an engine object and adds it to the list of objects
|
|
1082
1119
|
* @param {Vector2} [position=new Vector2()] - World space position of the object
|
|
1083
1120
|
* @param {Vector2} [size=objectDefaultSize] - World space size of the object
|
|
1084
|
-
* @param {Number} [tileIndex=-1] - Tile to use to render object
|
|
1121
|
+
* @param {Number} [tileIndex=-1] - Tile to use to render object (-1 is untextured)
|
|
1085
1122
|
* @param {Vector2} [tileSize=tileSizeDefault] - Size of tile in source pixels
|
|
1086
1123
|
* @param {Number} [angle=0] - Angle the object is rotated by
|
|
1087
1124
|
* @param {Color} [color] - Color to apply to tile when rendered
|
|
@@ -1098,7 +1135,7 @@ class EngineObject
|
|
|
1098
1135
|
this.size = size;
|
|
1099
1136
|
/** @property {Vector2} - Size of object used for drawing, uses size if not set */
|
|
1100
1137
|
this.drawSize;
|
|
1101
|
-
/** @property {Number} - Tile to use to render object
|
|
1138
|
+
/** @property {Number} - Tile to use to render object (-1 is untextured) */
|
|
1102
1139
|
this.tileIndex = tileIndex;
|
|
1103
1140
|
/** @property {Vector2} - Size of tile in source pixels */
|
|
1104
1141
|
this.tileSize = tileSize;
|
|
@@ -1110,7 +1147,7 @@ class EngineObject
|
|
|
1110
1147
|
this.additiveColor;
|
|
1111
1148
|
|
|
1112
1149
|
// set object defaults
|
|
1113
|
-
/** @property {Number} [mass=objectDefaultMass] - How heavy the object is */
|
|
1150
|
+
/** @property {Number} [mass=objectDefaultMass] - How heavy the object is, static if 0 */
|
|
1114
1151
|
this.mass = objectDefaultMass;
|
|
1115
1152
|
/** @property {Number} [damping=objectDefaultDamping] - How much to slow down velocity each frame (0-1) */
|
|
1116
1153
|
this.damping = objectDefaultDamping;
|
|
@@ -1164,7 +1201,7 @@ class EngineObject
|
|
|
1164
1201
|
ASSERT(this.angleDamping >= 0 && this.angleDamping <= 1);
|
|
1165
1202
|
ASSERT(this.damping >= 0 && this.damping <= 1);
|
|
1166
1203
|
|
|
1167
|
-
if (!this.mass) // do not update collision for fixed objects
|
|
1204
|
+
if (!enablePhysicsSolver || !this.mass) // do not update collision for fixed objects
|
|
1168
1205
|
return;
|
|
1169
1206
|
|
|
1170
1207
|
const wasMovingDown = this.velocity.y < 0;
|
|
@@ -1174,7 +1211,7 @@ class EngineObject
|
|
|
1174
1211
|
const groundSpeed = this.groundObject.velocity ? this.groundObject.velocity.x : 0;
|
|
1175
1212
|
this.velocity.x = groundSpeed + (this.velocity.x - groundSpeed) * this.friction;
|
|
1176
1213
|
this.groundObject = 0;
|
|
1177
|
-
//debugPhysics && debugPoint(this.pos.subtract(vec2(0,this.size.y/2)), '#0f0');
|
|
1214
|
+
//debugOverlay && debugPhysics && debugPoint(this.pos.subtract(vec2(0,this.size.y/2)), '#0f0');
|
|
1178
1215
|
}
|
|
1179
1216
|
|
|
1180
1217
|
if (this.collideSolidObjects)
|
|
@@ -1206,7 +1243,7 @@ class EngineObject
|
|
|
1206
1243
|
if (o.mass) // push away if not fixed
|
|
1207
1244
|
o.velocity = o.velocity.subtract(velocity);
|
|
1208
1245
|
|
|
1209
|
-
debugPhysics && debugAABB(this.pos, this.size, o.pos, o.size, '#f00');
|
|
1246
|
+
debugOverlay && debugPhysics && debugAABB(this.pos, this.size, o.pos, o.size, '#f00');
|
|
1210
1247
|
continue;
|
|
1211
1248
|
}
|
|
1212
1249
|
|
|
@@ -1269,7 +1306,7 @@ class EngineObject
|
|
|
1269
1306
|
else // bounce if other object is fixed
|
|
1270
1307
|
this.velocity.x *= -this.elasticity;
|
|
1271
1308
|
}
|
|
1272
|
-
debugPhysics && debugAABB(this.pos, this.size, o.pos, o.size, '#f0f');
|
|
1309
|
+
debugOverlay && debugPhysics && debugAABB(this.pos, this.size, o.pos, o.size, '#f0f');
|
|
1273
1310
|
}
|
|
1274
1311
|
}
|
|
1275
1312
|
if (this.collideTiles)
|
|
@@ -1402,18 +1439,21 @@ class EngineObject
|
|
|
1402
1439
|
|
|
1403
1440
|
toString()
|
|
1404
1441
|
{
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
text
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1442
|
+
if (debug)
|
|
1443
|
+
{
|
|
1444
|
+
let text = 'type = ' + this.constructor.name;
|
|
1445
|
+
if (this.pos.x || this.pos.y)
|
|
1446
|
+
text += '\npos = ' + this.pos;
|
|
1447
|
+
if (this.velocity.x || this.velocity.y)
|
|
1448
|
+
text += '\nvelocity = ' + this.velocity;
|
|
1449
|
+
if (this.size.x || this.size.y)
|
|
1450
|
+
text += '\nsize = ' + this.size;
|
|
1451
|
+
if (this.angle)
|
|
1452
|
+
text += '\nangle = ' + this.angle.toFixed(3);
|
|
1453
|
+
if (this.color)
|
|
1454
|
+
text += '\ncolor = ' + this.color;
|
|
1455
|
+
return text;
|
|
1456
|
+
}
|
|
1417
1457
|
}
|
|
1418
1458
|
}
|
|
1419
1459
|
/**
|
|
@@ -1471,18 +1511,26 @@ let overlayContext;
|
|
|
1471
1511
|
let mainCanvasSize = vec2();
|
|
1472
1512
|
|
|
1473
1513
|
/** Convert from screen to world space coordinates
|
|
1514
|
+
* - if calling outside of render, you may need to manually set mainCanvasSize
|
|
1474
1515
|
* @param {Vector2} screenPos
|
|
1475
1516
|
* @return {Vector2}
|
|
1476
1517
|
* @memberof Draw */
|
|
1477
1518
|
const screenToWorld = (screenPos)=>
|
|
1478
|
-
|
|
1519
|
+
{
|
|
1520
|
+
ASSERT(mainCanvasSize.x && mainCanvasSize.y, 'mainCanvasSize is invalid');
|
|
1521
|
+
return screenPos.add(vec2(.5)).subtract(mainCanvasSize.scale(.5)).multiply(vec2(1/cameraScale,-1/cameraScale)).add(cameraPos);
|
|
1522
|
+
}
|
|
1479
1523
|
|
|
1480
1524
|
/** Convert from world to screen space coordinates
|
|
1525
|
+
* - if calling outside of render, you may need to manually set mainCanvasSize
|
|
1481
1526
|
* @param {Vector2} worldPos
|
|
1482
1527
|
* @return {Vector2}
|
|
1483
1528
|
* @memberof Draw */
|
|
1484
1529
|
const worldToScreen = (worldPos)=>
|
|
1485
|
-
|
|
1530
|
+
{
|
|
1531
|
+
ASSERT(mainCanvasSize.x && mainCanvasSize.y, 'mainCanvasSize is invalid');
|
|
1532
|
+
return worldPos.subtract(cameraPos).multiply(vec2(cameraScale,-cameraScale)).add(mainCanvasSize.scale(.5)).subtract(vec2(.5));
|
|
1533
|
+
}
|
|
1486
1534
|
|
|
1487
1535
|
/** Draw textured tile centered in world space, with color applied if using WebGL
|
|
1488
1536
|
* @param {Vector2} pos - Center of the tile in world space
|
|
@@ -1583,7 +1631,7 @@ function drawTileScreenSpace(pos, size=vec2(1), tileIndex, tileSize, color, angl
|
|
|
1583
1631
|
* @memberof Draw */
|
|
1584
1632
|
function drawRectScreenSpace(pos, size, color, angle, useWebGL)
|
|
1585
1633
|
{
|
|
1586
|
-
|
|
1634
|
+
drawTileScreenSpace(pos, size, -1, tileSizeDefault, color, angle, 0, 0, useWebGL);
|
|
1587
1635
|
}
|
|
1588
1636
|
|
|
1589
1637
|
/** Draw colored line between two points
|
|
@@ -1646,14 +1694,15 @@ function setBlendMode(additive, useWebGL=glEnable)
|
|
|
1646
1694
|
function drawTextScreen(text, pos, size=1, color=new Color, lineWidth=0, lineColor=new Color(0,0,0), textAlign='center', font=fontDefault)
|
|
1647
1695
|
{
|
|
1648
1696
|
overlayContext.fillStyle = color;
|
|
1649
|
-
overlayContext.lineWidth = lineWidth
|
|
1697
|
+
overlayContext.lineWidth = lineWidth;
|
|
1650
1698
|
overlayContext.strokeStyle = lineColor;
|
|
1651
1699
|
overlayContext.textAlign = textAlign;
|
|
1652
1700
|
overlayContext.font = size + 'px '+ font;
|
|
1653
1701
|
overlayContext.textBaseline = 'middle';
|
|
1702
|
+
overlayContext.lineJoin = 'round';
|
|
1654
1703
|
|
|
1655
1704
|
pos = pos.copy();
|
|
1656
|
-
text.split('\n').forEach(line=>
|
|
1705
|
+
(text+'').split('\n').forEach(line=>
|
|
1657
1706
|
{
|
|
1658
1707
|
lineWidth && overlayContext.strokeText(line, pos.x, pos.y);
|
|
1659
1708
|
overlayContext.fillText(line, pos.x, pos.y);
|
|
@@ -1673,7 +1722,7 @@ function drawTextScreen(text, pos, size=1, color=new Color, lineWidth=0, lineCol
|
|
|
1673
1722
|
* @memberof Draw */
|
|
1674
1723
|
function drawText(text, pos, size=1, color, lineWidth, lineColor, textAlign, font)
|
|
1675
1724
|
{
|
|
1676
|
-
drawTextScreen(text, worldToScreen(pos), size*cameraScale, color, lineWidth, lineColor, textAlign, font);
|
|
1725
|
+
drawTextScreen(text, worldToScreen(pos), size*cameraScale, color, lineWidth*cameraScale, lineColor, textAlign, font);
|
|
1677
1726
|
}
|
|
1678
1727
|
|
|
1679
1728
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -1867,6 +1916,10 @@ let mouseWheel = 0;
|
|
|
1867
1916
|
* @memberof Input */
|
|
1868
1917
|
let isUsingGamepad = 0;
|
|
1869
1918
|
|
|
1919
|
+
/** Prevents input continuing to the default browser handling (false by default)
|
|
1920
|
+
* @memberof Input */
|
|
1921
|
+
let preventDefaultInput = 0;
|
|
1922
|
+
|
|
1870
1923
|
/** Returns true if gamepad button is down
|
|
1871
1924
|
* @param {Number} button
|
|
1872
1925
|
* @param {Number} [gamepad=0]
|
|
@@ -1930,7 +1983,7 @@ onkeydown = (e)=>
|
|
|
1930
1983
|
{
|
|
1931
1984
|
if (debug && e.target != document.body) return;
|
|
1932
1985
|
e.repeat || (inputData[isUsingGamepad = 0][remapKeyCode(e.keyCode)] = 3);
|
|
1933
|
-
|
|
1986
|
+
preventDefaultInput && e.preventDefault();
|
|
1934
1987
|
}
|
|
1935
1988
|
onkeyup = (e)=>
|
|
1936
1989
|
{
|
|
@@ -1955,7 +2008,7 @@ const mouseToScreen = (mousePos)=>
|
|
|
1955
2008
|
return vec2(); // fix bug that can occur if user clicks before page loads
|
|
1956
2009
|
|
|
1957
2010
|
const rect = mainCanvas.getBoundingClientRect();
|
|
1958
|
-
return
|
|
2011
|
+
return vec2(mainCanvas.width, mainCanvas.height).multiply(
|
|
1959
2012
|
vec2(percent(mousePos.x, rect.left, rect.right), percent(mousePos.y, rect.top, rect.bottom)));
|
|
1960
2013
|
}
|
|
1961
2014
|
|
|
@@ -2494,8 +2547,7 @@ function zzfxG
|
|
|
2494
2547
|
)
|
|
2495
2548
|
{
|
|
2496
2549
|
// init parameters
|
|
2497
|
-
let PI2 = PI*2,
|
|
2498
|
-
startSlide = slide *= 500 * PI2 / zzfxR / zzfxR, b=[],
|
|
2550
|
+
let PI2 = PI*2, startSlide = slide *= 500 * PI2 / zzfxR / zzfxR, b=[],
|
|
2499
2551
|
startFrequency = frequency *= (1 + randomness*rand(-1,1)) * PI2 / zzfxR,
|
|
2500
2552
|
t=0, tm=0, i=0, j=1, r=0, c=0, s=0, f, length;
|
|
2501
2553
|
|
|
@@ -2519,15 +2571,15 @@ function zzfxG
|
|
|
2519
2571
|
{
|
|
2520
2572
|
s = shape? shape>1? shape>2? shape>3? // wave shape
|
|
2521
2573
|
Math.sin((t%PI2)**3) : // 4 noise
|
|
2522
|
-
|
|
2574
|
+
max(min(Math.tan(t),1),-1): // 3 tan
|
|
2523
2575
|
1-(2*t/PI2%2+2)%2: // 2 saw
|
|
2524
|
-
1-4*abs(Math.round(t/PI2)-t/PI2):
|
|
2576
|
+
1-4*abs(Math.round(t/PI2)-t/PI2): // 1 triangle
|
|
2525
2577
|
Math.sin(t); // 0 sin
|
|
2526
2578
|
|
|
2527
2579
|
s = (repeatTime ?
|
|
2528
2580
|
1 - tremolo + tremolo*Math.sin(PI2*i/repeatTime) // tremolo
|
|
2529
2581
|
: 1) *
|
|
2530
|
-
sign(s)*(abs(s)**shapeCurve) *
|
|
2582
|
+
sign(s)*(abs(s)**shapeCurve) * // curve 0=square, 2=pointy
|
|
2531
2583
|
volume * soundVolume * ( // envelope
|
|
2532
2584
|
i < attack ? i/attack : // attack
|
|
2533
2585
|
i < attack + decay ? // decay
|
|
@@ -2588,7 +2640,6 @@ function zzfxM(instruments, patterns, sequence, BPM = 125)
|
|
|
2588
2640
|
let notFirstBeat;
|
|
2589
2641
|
let stop;
|
|
2590
2642
|
let instrument;
|
|
2591
|
-
let pitch;
|
|
2592
2643
|
let attenuation;
|
|
2593
2644
|
let outSampleOffset;
|
|
2594
2645
|
let isSequenceEnd;
|
|
@@ -2607,7 +2658,7 @@ function zzfxM(instruments, patterns, sequence, BPM = 125)
|
|
|
2607
2658
|
for (; hasMore; channelIndex++) {
|
|
2608
2659
|
|
|
2609
2660
|
// reset current values
|
|
2610
|
-
sampleBuffer = [hasMore = notFirstBeat =
|
|
2661
|
+
sampleBuffer = [hasMore = notFirstBeat = outSampleOffset = 0];
|
|
2611
2662
|
|
|
2612
2663
|
// for each pattern in sequence
|
|
2613
2664
|
sequence.forEach((patternIndex, sequenceIndex) => {
|
|
@@ -3132,7 +3183,7 @@ class ParticleEmitter extends EngineObject
|
|
|
3132
3183
|
// particle settings
|
|
3133
3184
|
/** @property {Number} - How long particles live */
|
|
3134
3185
|
this.particleTime = particleTime;
|
|
3135
|
-
/** @property {Number} -
|
|
3186
|
+
/** @property {Number} - How big are particles at start */
|
|
3136
3187
|
this.sizeStart = sizeStart;
|
|
3137
3188
|
/** @property {Number} - How big are particles at end */
|
|
3138
3189
|
this.sizeEnd = sizeEnd;
|
|
@@ -3495,7 +3546,7 @@ class Newgrounds
|
|
|
3495
3546
|
cipher && (this.cryptoJS = CryptoJS());
|
|
3496
3547
|
|
|
3497
3548
|
// get session id from url search params
|
|
3498
|
-
const url = new URL(
|
|
3549
|
+
const url = new URL(location.href);
|
|
3499
3550
|
this.session_id = url.searchParams.get('ngio_session_id') || 0;
|
|
3500
3551
|
|
|
3501
3552
|
if (this.session_id == 0)
|
|
@@ -3848,7 +3899,7 @@ function glFlush()
|
|
|
3848
3899
|
* @memberof WebGL */
|
|
3849
3900
|
function glCopyToContext(context, forceDraw)
|
|
3850
3901
|
{
|
|
3851
|
-
if (!glEnable || !glBatchCount) return;
|
|
3902
|
+
if ((!glEnable || !glBatchCount) && !forceDraw) return;
|
|
3852
3903
|
|
|
3853
3904
|
glFlush();
|
|
3854
3905
|
|
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.3.
|
|
25
|
+
const engineVersion = '1.3.8';
|
|
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/engineAudio.js
CHANGED
|
@@ -289,8 +289,7 @@ function zzfxG
|
|
|
289
289
|
)
|
|
290
290
|
{
|
|
291
291
|
// init parameters
|
|
292
|
-
let PI2 = PI*2,
|
|
293
|
-
startSlide = slide *= 500 * PI2 / zzfxR / zzfxR, b=[],
|
|
292
|
+
let PI2 = PI*2, startSlide = slide *= 500 * PI2 / zzfxR / zzfxR, b=[],
|
|
294
293
|
startFrequency = frequency *= (1 + randomness*rand(-1,1)) * PI2 / zzfxR,
|
|
295
294
|
t=0, tm=0, i=0, j=1, r=0, c=0, s=0, f, length;
|
|
296
295
|
|
|
@@ -314,15 +313,15 @@ function zzfxG
|
|
|
314
313
|
{
|
|
315
314
|
s = shape? shape>1? shape>2? shape>3? // wave shape
|
|
316
315
|
Math.sin((t%PI2)**3) : // 4 noise
|
|
317
|
-
|
|
316
|
+
max(min(Math.tan(t),1),-1): // 3 tan
|
|
318
317
|
1-(2*t/PI2%2+2)%2: // 2 saw
|
|
319
|
-
1-4*abs(Math.round(t/PI2)-t/PI2):
|
|
318
|
+
1-4*abs(Math.round(t/PI2)-t/PI2): // 1 triangle
|
|
320
319
|
Math.sin(t); // 0 sin
|
|
321
320
|
|
|
322
321
|
s = (repeatTime ?
|
|
323
322
|
1 - tremolo + tremolo*Math.sin(PI2*i/repeatTime) // tremolo
|
|
324
323
|
: 1) *
|
|
325
|
-
sign(s)*(abs(s)**shapeCurve) *
|
|
324
|
+
sign(s)*(abs(s)**shapeCurve) * // curve 0=square, 2=pointy
|
|
326
325
|
volume * soundVolume * ( // envelope
|
|
327
326
|
i < attack ? i/attack : // attack
|
|
328
327
|
i < attack + decay ? // decay
|
|
@@ -383,7 +382,6 @@ function zzfxM(instruments, patterns, sequence, BPM = 125)
|
|
|
383
382
|
let notFirstBeat;
|
|
384
383
|
let stop;
|
|
385
384
|
let instrument;
|
|
386
|
-
let pitch;
|
|
387
385
|
let attenuation;
|
|
388
386
|
let outSampleOffset;
|
|
389
387
|
let isSequenceEnd;
|
|
@@ -402,7 +400,7 @@ function zzfxM(instruments, patterns, sequence, BPM = 125)
|
|
|
402
400
|
for (; hasMore; channelIndex++) {
|
|
403
401
|
|
|
404
402
|
// reset current values
|
|
405
|
-
sampleBuffer = [hasMore = notFirstBeat =
|
|
403
|
+
sampleBuffer = [hasMore = notFirstBeat = outSampleOffset = 0];
|
|
406
404
|
|
|
407
405
|
// for each pattern in sequence
|
|
408
406
|
sequence.forEach((patternIndex, sequenceIndex) => {
|
package/engine/engineBuild.bat
CHANGED
package/engine/engineDebug.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;
|