littlejsengine 1.4.7 → 1.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build.bat +7 -3
- package/engine/engine.all.js +291 -323
- package/engine/engine.all.min.js +1 -1
- package/engine/engine.all.module.js +307 -352
- package/engine/engine.all.module.min.js +1 -0
- package/engine/engine.all.release.js +291 -323
- package/engine/engine.js +21 -30
- package/engine/engineAudio.js +8 -15
- package/engine/engineBuild.bat +10 -3
- package/engine/engineDraw.js +18 -24
- package/engine/engineExport.js +16 -29
- package/engine/engineInput.js +84 -71
- package/engine/engineMedals.js +30 -38
- package/engine/engineObject.js +8 -8
- package/engine/engineParticles.js +5 -4
- package/engine/engineSettings.js +38 -38
- package/engine/engineTileLayer.js +15 -16
- package/engine/engineUtilities.js +26 -13
- package/engine/engineWebGL.js +38 -66
- package/engine/index.d.ts +65 -54
- package/examples/breakout/game.js +10 -10
- package/examples/breakout/gameObjects.js +7 -7
- package/examples/breakout/index.html +3 -3
- package/examples/empty/tiles.png +0 -0
- package/examples/module/game.js +5 -7
- package/examples/module/index.html +1 -1
- package/examples/particles/index.html +4 -14
- package/examples/platformer/index.html +6 -6
- package/examples/puzzle/index.html +2 -2
- package/examples/stress/index.html +1 -1
- package/favicon.png +0 -0
- package/game.js +6 -9
- package/index.html +13 -13
- package/package.json +1 -1
- package/README.md +0 -75
- package/engine/engine.all.release.module.js +0 -4464
|
@@ -492,7 +492,7 @@ const wave = (frequency=1, amplitude=1, t=time)=> amplitude/2 * (1 - Math.cos(t*
|
|
|
492
492
|
* @param {Number} t - time in seconds
|
|
493
493
|
* @return {String}
|
|
494
494
|
* @memberof Utilities */
|
|
495
|
-
const formatTime = (t)=> (t/60|0)+':'+(t%60<10?'0':'')+(t%60|0);
|
|
495
|
+
const formatTime = (t)=> (t/60|0) + ':' + (t%60<10?'0':'') + (t%60|0);
|
|
496
496
|
|
|
497
497
|
///////////////////////////////////////////////////////////////////////////////
|
|
498
498
|
|
|
@@ -516,7 +516,7 @@ const randInt = (a=1, b=0)=> rand(a,b)|0;
|
|
|
516
516
|
/** Randomly returns either -1 or 1
|
|
517
517
|
* @return {Number}
|
|
518
518
|
* @memberof Random */
|
|
519
|
-
const randSign = ()=> (
|
|
519
|
+
const randSign = ()=> randInt(2) * 2 - 1;
|
|
520
520
|
|
|
521
521
|
/** Returns a random Vector2 within a circular shape
|
|
522
522
|
* @param {Number} [radius=1]
|
|
@@ -540,10 +540,15 @@ const randVector = (length=1)=> new Vector2().setAngle(rand(2*PI), length);
|
|
|
540
540
|
const randColor = (cA = new Color, cB = new Color(0,0,0,1), linear)=>
|
|
541
541
|
linear ? cA.lerp(cB, rand()) : new Color(rand(cA.r,cB.r),rand(cA.g,cB.g),rand(cA.b,cB.b),rand(cA.a,cB.a));
|
|
542
542
|
|
|
543
|
-
/**
|
|
543
|
+
/** Seed used by the randSeeded function
|
|
544
544
|
* @memberof Random */
|
|
545
545
|
let randSeed = 1;
|
|
546
546
|
|
|
547
|
+
/** Set seed used by the randSeeded function, should not be 0
|
|
548
|
+
* @param {Number} seed
|
|
549
|
+
* @memberof Random */
|
|
550
|
+
const setRandSeed = (seed)=> randSeed = seed;
|
|
551
|
+
|
|
547
552
|
/** Returns a seeded random value between the two values passed in using randSeed
|
|
548
553
|
* @param {Number} [valueA=1]
|
|
549
554
|
* @param {Number} [valueB=0]
|
|
@@ -571,6 +576,14 @@ const randSeeded = (a=1, b=0)=>
|
|
|
571
576
|
*/
|
|
572
577
|
const vec2 = (x=0, y)=> x.x == undefined ? new Vector2(x, y == undefined? x : y) : new Vector2(x.x, x.y);
|
|
573
578
|
|
|
579
|
+
/**
|
|
580
|
+
* Check if object is a valid Vector2
|
|
581
|
+
* @param {Vector2} vector
|
|
582
|
+
* @return {Boolean}
|
|
583
|
+
* @memberof Utilities
|
|
584
|
+
*/
|
|
585
|
+
const isVector2 = (v)=> !isNaN(v.x) && !isNaN(v.y);
|
|
586
|
+
|
|
574
587
|
/**
|
|
575
588
|
* 2D Vector object with vector math library
|
|
576
589
|
* <br> - Functions do not change this so they can be chained together
|
|
@@ -600,27 +613,27 @@ class Vector2
|
|
|
600
613
|
/** Returns a copy of this vector plus the vector passed in
|
|
601
614
|
* @param {Vector2} vector
|
|
602
615
|
* @return {Vector2} */
|
|
603
|
-
add(v) { ASSERT(v
|
|
616
|
+
add(v) { ASSERT(isVector2(v)); return new Vector2(this.x + v.x, this.y + v.y); }
|
|
604
617
|
|
|
605
618
|
/** Returns a copy of this vector minus the vector passed in
|
|
606
619
|
* @param {Vector2} vector
|
|
607
620
|
* @return {Vector2} */
|
|
608
|
-
subtract(v) { ASSERT(v
|
|
621
|
+
subtract(v) { ASSERT(isVector2(v)); return new Vector2(this.x - v.x, this.y - v.y); }
|
|
609
622
|
|
|
610
623
|
/** Returns a copy of this vector times the vector passed in
|
|
611
624
|
* @param {Vector2} vector
|
|
612
625
|
* @return {Vector2} */
|
|
613
|
-
multiply(v) { ASSERT(v
|
|
626
|
+
multiply(v) { ASSERT(isVector2(v)); return new Vector2(this.x * v.x, this.y * v.y); }
|
|
614
627
|
|
|
615
628
|
/** Returns a copy of this vector divided by the vector passed in
|
|
616
629
|
* @param {Vector2} vector
|
|
617
630
|
* @return {Vector2} */
|
|
618
|
-
divide(v) { ASSERT(v
|
|
631
|
+
divide(v) { ASSERT(isVector2(v)); return new Vector2(this.x / v.x, this.y / v.y); }
|
|
619
632
|
|
|
620
633
|
/** Returns a copy of this vector scaled by the vector passed in
|
|
621
634
|
* @param {Number} scale
|
|
622
635
|
* @return {Vector2} */
|
|
623
|
-
scale(s) { ASSERT(s
|
|
636
|
+
scale(s) { ASSERT(!isVector2(s)); return new Vector2(this.x * s, this.y * s); }
|
|
624
637
|
|
|
625
638
|
/** Returns the length of this vector
|
|
626
639
|
* @return {Number} */
|
|
@@ -653,12 +666,12 @@ class Vector2
|
|
|
653
666
|
/** Returns the dot product of this and the vector passed in
|
|
654
667
|
* @param {Vector2} vector
|
|
655
668
|
* @return {Number} */
|
|
656
|
-
dot(v) { ASSERT(v
|
|
669
|
+
dot(v) { ASSERT(isVector2(v)); return this.x*v.x + this.y*v.y; }
|
|
657
670
|
|
|
658
671
|
/** Returns the cross product of this and the vector passed in
|
|
659
672
|
* @param {Vector2} vector
|
|
660
673
|
* @return {Number} */
|
|
661
|
-
cross(v) { ASSERT(v
|
|
674
|
+
cross(v) { ASSERT(isVector2(v)); return this.x*v.y - this.y*v.x; }
|
|
662
675
|
|
|
663
676
|
/** Returns the angle of this vector, up is angle 0
|
|
664
677
|
* @return {Number} */
|
|
@@ -694,7 +707,7 @@ class Vector2
|
|
|
694
707
|
* @param {Vector2} vector
|
|
695
708
|
* @param {Number} percent
|
|
696
709
|
* @return {Vector2} */
|
|
697
|
-
lerp(v, p) { ASSERT(v
|
|
710
|
+
lerp(v, p) { ASSERT(isVector2(v)); return this.add(v.subtract(this).scale(clamp(p))); }
|
|
698
711
|
|
|
699
712
|
/** Returns true if this vector is within the bounds of an array size passed in
|
|
700
713
|
* @param {Vector2} arraySize
|
|
@@ -705,7 +718,7 @@ class Vector2
|
|
|
705
718
|
* @param {float} digits - precision to display
|
|
706
719
|
* @return {String} */
|
|
707
720
|
toString(digits=3)
|
|
708
|
-
{ return `(${(this.x<0?'':' ') + this.x.toFixed(digits)},${(this.y<0?'':' ') + this.y.toFixed(digits)} )`; }
|
|
721
|
+
{ if (debug) { return `(${(this.x<0?'':' ') + this.x.toFixed(digits)},${(this.y<0?'':' ') + this.y.toFixed(digits)} )`; }}
|
|
709
722
|
}
|
|
710
723
|
|
|
711
724
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -943,7 +956,7 @@ class Timer
|
|
|
943
956
|
|
|
944
957
|
/** Returns this timer expressed as a string
|
|
945
958
|
* @return {String} */
|
|
946
|
-
toString() { if (debug) { return this.unset() ? 'unset' : Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ); }
|
|
959
|
+
toString() { if (debug) { return this.unset() ? 'unset' : Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ); }}
|
|
947
960
|
|
|
948
961
|
/** Get how long since elapsed, returns 0 if not set (returns negative if currently active)
|
|
949
962
|
* @return {Number} */
|
|
@@ -956,6 +969,20 @@ class Timer
|
|
|
956
969
|
|
|
957
970
|
'use strict';
|
|
958
971
|
|
|
972
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
973
|
+
// Camera settings
|
|
974
|
+
|
|
975
|
+
/** Position of camera in world space
|
|
976
|
+
* @type {Vector2}
|
|
977
|
+
* @default
|
|
978
|
+
* @memberof Settings */
|
|
979
|
+
let cameraPos = vec2();
|
|
980
|
+
|
|
981
|
+
/** Scale of camera in world space
|
|
982
|
+
* @default
|
|
983
|
+
* @memberof Settings */
|
|
984
|
+
let cameraScale = 32;
|
|
985
|
+
|
|
959
986
|
///////////////////////////////////////////////////////////////////////////////
|
|
960
987
|
// Display settings
|
|
961
988
|
|
|
@@ -982,6 +1009,19 @@ let cavasPixelated = 1;
|
|
|
982
1009
|
* @memberof Settings */
|
|
983
1010
|
let fontDefault = 'arial';
|
|
984
1011
|
|
|
1012
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
1013
|
+
// WebGL settings
|
|
1014
|
+
|
|
1015
|
+
/** Enable webgl rendering, webgl can be disabled and removed from build (with some features disabled)
|
|
1016
|
+
* @default
|
|
1017
|
+
* @memberof Settings */
|
|
1018
|
+
let glEnable = 1;
|
|
1019
|
+
|
|
1020
|
+
/** Fixes slow rendering in some browsers by not compositing the WebGL canvas
|
|
1021
|
+
* @default
|
|
1022
|
+
* @memberof Settings */
|
|
1023
|
+
let glOverlay = 1;
|
|
1024
|
+
|
|
985
1025
|
///////////////////////////////////////////////////////////////////////////////
|
|
986
1026
|
// Tile sheet settings
|
|
987
1027
|
|
|
@@ -1050,33 +1090,6 @@ let gravity = 0;
|
|
|
1050
1090
|
* @memberof Settings */
|
|
1051
1091
|
let particleEmitRateScale = 1;
|
|
1052
1092
|
|
|
1053
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
1054
|
-
// Camera settings
|
|
1055
|
-
|
|
1056
|
-
/** Position of camera in world space
|
|
1057
|
-
* @type {Vector2}
|
|
1058
|
-
* @default
|
|
1059
|
-
* @memberof Settings */
|
|
1060
|
-
let cameraPos = vec2();
|
|
1061
|
-
|
|
1062
|
-
/** Scale of camera in world space
|
|
1063
|
-
* @default
|
|
1064
|
-
* @memberof Settings */
|
|
1065
|
-
let cameraScale = max(tileSizeDefault.x, tileSizeDefault.y);
|
|
1066
|
-
|
|
1067
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
1068
|
-
// WebGL settings
|
|
1069
|
-
|
|
1070
|
-
/** Enable webgl rendering, webgl can be disabled and removed from build (with some features disabled)
|
|
1071
|
-
* @default
|
|
1072
|
-
* @memberof Settings */
|
|
1073
|
-
let glEnable = 1;
|
|
1074
|
-
|
|
1075
|
-
/** Fixes slow rendering in some browsers by not compositing the WebGL canvas
|
|
1076
|
-
* @default
|
|
1077
|
-
* @memberof Settings */
|
|
1078
|
-
let glOverlay = 1;
|
|
1079
|
-
|
|
1080
1093
|
///////////////////////////////////////////////////////////////////////////////
|
|
1081
1094
|
// Input settings
|
|
1082
1095
|
|
|
@@ -1125,20 +1138,20 @@ let vibrateEnable = 1;
|
|
|
1125
1138
|
///////////////////////////////////////////////////////////////////////////////
|
|
1126
1139
|
// Audio settings
|
|
1127
1140
|
|
|
1128
|
-
/**
|
|
1141
|
+
/** All audio code can be disabled and removed from build
|
|
1129
1142
|
* @default
|
|
1130
1143
|
* @memberof Settings */
|
|
1131
|
-
let
|
|
1144
|
+
let soundEnable = 1;
|
|
1132
1145
|
|
|
1133
|
-
/**
|
|
1146
|
+
/** Volume scale to apply to all sound, music and speech
|
|
1134
1147
|
* @default
|
|
1135
1148
|
* @memberof Settings */
|
|
1136
|
-
let
|
|
1149
|
+
let soundVolume = .5;
|
|
1137
1150
|
|
|
1138
1151
|
/** Default range where sound no longer plays
|
|
1139
1152
|
* @default
|
|
1140
1153
|
* @memberof Settings */
|
|
1141
|
-
let soundDefaultRange =
|
|
1154
|
+
let soundDefaultRange = 40;
|
|
1142
1155
|
|
|
1143
1156
|
/** Default range percent to start tapering off sound (0-1)
|
|
1144
1157
|
* @default
|
|
@@ -1158,20 +1171,20 @@ let medalDisplayTime = 5;
|
|
|
1158
1171
|
* @memberof Settings */
|
|
1159
1172
|
let medalDisplaySlideTime = .5;
|
|
1160
1173
|
|
|
1161
|
-
/**
|
|
1174
|
+
/** Size of medal display
|
|
1162
1175
|
* @default
|
|
1163
1176
|
* @memberof Settings */
|
|
1164
|
-
let
|
|
1177
|
+
let medalDisplaySize = vec2(640, 80);
|
|
1165
1178
|
|
|
1166
|
-
/**
|
|
1179
|
+
/** Size of icon in medal display
|
|
1167
1180
|
* @default
|
|
1168
1181
|
* @memberof Settings */
|
|
1169
|
-
let
|
|
1182
|
+
let medalDisplayIconSize = 50;
|
|
1170
1183
|
|
|
1171
|
-
/**
|
|
1184
|
+
/** Set to stop medals from being unlockable (like if cheats are enabled)
|
|
1172
1185
|
* @default
|
|
1173
1186
|
* @memberof Settings */
|
|
1174
|
-
let
|
|
1187
|
+
let medalsPreventUnlock;
|
|
1175
1188
|
/*
|
|
1176
1189
|
LittleJS Object System
|
|
1177
1190
|
*/
|
|
@@ -1217,7 +1230,7 @@ class EngineObject
|
|
|
1217
1230
|
constructor(pos=vec2(), size=objectDefaultSize, tileIndex=-1, tileSize=tileSizeDefault, angle=0, color, renderOrder=0)
|
|
1218
1231
|
{
|
|
1219
1232
|
// set passed in params
|
|
1220
|
-
ASSERT(pos &&
|
|
1233
|
+
ASSERT(isVector2(pos) && isVector2(size)); // ensure pos and size are vec2s
|
|
1221
1234
|
|
|
1222
1235
|
/** @property {Vector2} - World space position of the object */
|
|
1223
1236
|
this.pos = pos.copy();
|
|
@@ -1283,9 +1296,9 @@ class EngineObject
|
|
|
1283
1296
|
|
|
1284
1297
|
// apply physics
|
|
1285
1298
|
const oldPos = this.pos.copy();
|
|
1286
|
-
this.
|
|
1287
|
-
this.pos.
|
|
1288
|
-
this.
|
|
1299
|
+
this.velocity.y += gravity * this.gravityScale;
|
|
1300
|
+
this.pos.x += this.velocity.x *= this.damping;
|
|
1301
|
+
this.pos.y += this.velocity.y *= this.damping;
|
|
1289
1302
|
|
|
1290
1303
|
// physics sanity checks
|
|
1291
1304
|
ASSERT(this.angleDamping >= 0 && this.angleDamping <= 1);
|
|
@@ -1307,7 +1320,7 @@ class EngineObject
|
|
|
1307
1320
|
if (this.collideSolidObjects)
|
|
1308
1321
|
{
|
|
1309
1322
|
// check collisions against solid objects
|
|
1310
|
-
const epsilon =
|
|
1323
|
+
const epsilon = .001; // necessary to push slightly outside of the collision
|
|
1311
1324
|
for (const o of engineObjectsCollide)
|
|
1312
1325
|
{
|
|
1313
1326
|
// non solid objects don't collide with eachother
|
|
@@ -1343,7 +1356,7 @@ class EngineObject
|
|
|
1343
1356
|
const isBlockedX = abs(oldPos.y - o.pos.y)*2 < sizeBoth.y;
|
|
1344
1357
|
const isBlockedY = abs(oldPos.x - o.pos.x)*2 < sizeBoth.x;
|
|
1345
1358
|
|
|
1346
|
-
if (smallStepUp
|
|
1359
|
+
if (smallStepUp | isBlockedY | !isBlockedX) // resolve y collision
|
|
1347
1360
|
{
|
|
1348
1361
|
// push outside object collision
|
|
1349
1362
|
this.pos.y = o.pos.y + (sizeBoth.y/2 + epsilon) * sign(oldPos.y - o.pos.y);
|
|
@@ -1373,7 +1386,7 @@ class EngineObject
|
|
|
1373
1386
|
o.velocity.y = lerp(elasticity, inelastic, elastic1);
|
|
1374
1387
|
}
|
|
1375
1388
|
}
|
|
1376
|
-
if (!smallStepUp
|
|
1389
|
+
if (!smallStepUp & isBlockedX) // resolve x collision
|
|
1377
1390
|
{
|
|
1378
1391
|
// push outside collision
|
|
1379
1392
|
this.pos.x = o.pos.x + (sizeBoth.x/2 + epsilon) * sign(oldPos.x - o.pos.x);
|
|
@@ -1411,7 +1424,7 @@ class EngineObject
|
|
|
1411
1424
|
// test which side we bounced off (or both if a corner)
|
|
1412
1425
|
const isBlockedY = tileCollisionTest(new Vector2(oldPos.x, this.pos.y), this.size, this);
|
|
1413
1426
|
const isBlockedX = tileCollisionTest(new Vector2(this.pos.x, oldPos.y), this.size, this);
|
|
1414
|
-
if (isBlockedY
|
|
1427
|
+
if (isBlockedY | !isBlockedX)
|
|
1415
1428
|
{
|
|
1416
1429
|
// set if landed on ground
|
|
1417
1430
|
this.groundObject = wasMovingDown;
|
|
@@ -1570,11 +1583,6 @@ class EngineObject
|
|
|
1570
1583
|
|
|
1571
1584
|
'use strict';
|
|
1572
1585
|
|
|
1573
|
-
/** Tile sheet for batch rendering system
|
|
1574
|
-
* @type {Image}
|
|
1575
|
-
* @memberof Draw */
|
|
1576
|
-
const tileImage = new Image();
|
|
1577
|
-
|
|
1578
1586
|
/** The primary 2D canvas visible to the user
|
|
1579
1587
|
* @type {HTMLCanvasElement}
|
|
1580
1588
|
* @memberof Draw */
|
|
@@ -1600,6 +1608,14 @@ let overlayContext;
|
|
|
1600
1608
|
* @memberof Draw */
|
|
1601
1609
|
let mainCanvasSize = vec2();
|
|
1602
1610
|
|
|
1611
|
+
/** Tile sheet for batch rendering system
|
|
1612
|
+
* @type {Image}
|
|
1613
|
+
* @memberof Draw */
|
|
1614
|
+
const tileImage = new Image;
|
|
1615
|
+
|
|
1616
|
+
// Engine internal variables not exposed to documentation
|
|
1617
|
+
let tileImageSize, tileImageFixBleed, drawCount;
|
|
1618
|
+
|
|
1603
1619
|
/** Convert from screen to world space coordinates
|
|
1604
1620
|
* - if calling outside of render, you may need to manually set mainCanvasSize
|
|
1605
1621
|
* @param {Vector2} screenPos
|
|
@@ -1624,7 +1640,7 @@ const worldToScreen = (worldPos)=>
|
|
|
1624
1640
|
|
|
1625
1641
|
/** Draw textured tile centered in world space, with color applied if using WebGL
|
|
1626
1642
|
* @param {Vector2} pos - Center of the tile in world space
|
|
1627
|
-
* @param {Vector2} [size=new Vector2(1,1)] - Size of the tile in world space
|
|
1643
|
+
* @param {Vector2} [size=new Vector2(1,1)] - Size of the tile in world space
|
|
1628
1644
|
* @param {Number} [tileIndex=-1] - Tile index to use, negative is untextured
|
|
1629
1645
|
* @param {Vector2} [tileSize=tileSizeDefault] - Tile size in source pixels
|
|
1630
1646
|
* @param {Color} [color=new Color(1,1,1)] - Color to modulate with
|
|
@@ -1830,25 +1846,23 @@ function drawText(text, pos, size=1, color, lineWidth, lineColor, textAlign, fon
|
|
|
1830
1846
|
* font.drawTextScreen("LittleJS\nHello World!", vec2(200, 50));
|
|
1831
1847
|
*/
|
|
1832
1848
|
|
|
1849
|
+
// default font image created by engine
|
|
1833
1850
|
let engineFontImage;
|
|
1834
1851
|
|
|
1835
1852
|
class FontImage
|
|
1836
1853
|
{
|
|
1837
1854
|
/** Create an image font
|
|
1838
|
-
* @param {HTMLImageElement}
|
|
1839
|
-
* @param {Vector2} [tileSize=vec2(8)] -
|
|
1855
|
+
* @param {HTMLImageElement} [image] - Image for the font, if undefined default font is used
|
|
1856
|
+
* @param {Vector2} [tileSize=vec2(8)] - Size of the font source tiles
|
|
1840
1857
|
* @param {Vector2} [paddingSize=vec2(0,1)] - How much extra space to add between characters
|
|
1841
1858
|
* @param {Number} [startTileIndex=0] - Tile index in image where font starts
|
|
1842
1859
|
* @param {CanvasRenderingContext2D} [context=overlayContext] - context to draw to
|
|
1843
1860
|
*/
|
|
1844
1861
|
constructor(image, tileSize=vec2(8), paddingSize=vec2(0,1), startTileIndex=0, context=overlayContext)
|
|
1845
1862
|
{
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
engineFontImage = new Image();
|
|
1850
|
-
engineFontImage.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAAYAQAAAAA9+x6JAAAAAnRSTlMAAHaTzTgAAAGiSURBVHjaZZABhxxBEIUf6ECLBdFY+Q0PMNgf0yCgsSAGZcT9sgIPtBWwIA5wgAPEoHUyJeeSlW+gjK+fegWwtROWpVQEyWh2npdpBmTUFVhb29RINgLIukoXr5LIAvYQ5ve+1FqWEMqNKTX3FAJHyQDRZvmKWubAACcv5z5Gtg2oyCWE+Yk/8JZQX1jTTCpKAFGIgza+dJCNBF2UskRlsgwitHbSV0QLgt9sTPtsRlvJjEr8C/FARWA2bJ/TtJ7lko34dNDn6usJUMzuErP89UUBJbWeozrwLLncXczd508deAjLWipLO4Q5XGPcJvPu92cNDaN0P5G1FL0nSOzddZOrJ6rNhbXGmeDvO3TF7DeJWl4bvaYQTNHCTeuqKZmbjHaSOFes+IX/+IhHrnAkXOAsfn24EM68XieIECoccD4KZLk/odiwzeo2rovYdhvb2HYFgyznJyDpYJdYOmfXgVdJTaUi4xA2uWYNYec9BLeqdl9EsoTw582mSFDX2DxVLbNt9U3YYoeatBad1c2Tj8t2akrjaIGJNywKB/7h75/gN3vCMSaadIUTAAAAAElFTkSuQmCC';
|
|
1851
|
-
}
|
|
1863
|
+
// load default font image
|
|
1864
|
+
if (!engineFontImage)
|
|
1865
|
+
(engineFontImage = new Image).src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAAYAQAAAAA9+x6JAAAAAnRSTlMAAHaTzTgAAAGiSURBVHjaZZABhxxBEIUf6ECLBdFY+Q0PMNgf0yCgsSAGZcT9sgIPtBWwIA5wgAPEoHUyJeeSlW+gjK+fegWwtROWpVQEyWh2npdpBmTUFVhb29RINgLIukoXr5LIAvYQ5ve+1FqWEMqNKTX3FAJHyQDRZvmKWubAACcv5z5Gtg2oyCWE+Yk/8JZQX1jTTCpKAFGIgza+dJCNBF2UskRlsgwitHbSV0QLgt9sTPtsRlvJjEr8C/FARWA2bJ/TtJ7lko34dNDn6usJUMzuErP89UUBJbWeozrwLLncXczd508deAjLWipLO4Q5XGPcJvPu92cNDaN0P5G1FL0nSOzddZOrJ6rNhbXGmeDvO3TF7DeJWl4bvaYQTNHCTeuqKZmbjHaSOFes+IX/+IhHrnAkXOAsfn24EM68XieIECoccD4KZLk/odiwzeo2rovYdhvb2HYFgyznJyDpYJdYOmfXgVdJTaUi4xA2uWYNYec9BLeqdl9EsoTw582mSFDX2DxVLbNt9U3YYoeatBad1c2Tj8t2akrjaIGJNywKB/7h75/gN3vCMSaadIUTAAAAAElFTkSuQmCC';
|
|
1852
1866
|
|
|
1853
1867
|
this.image = image || engineFontImage;
|
|
1854
1868
|
this.tileSize = tileSize;
|
|
@@ -1913,7 +1927,7 @@ class FontImage
|
|
|
1913
1927
|
/** Returns true if fullscreen mode is active
|
|
1914
1928
|
* @return {Boolean}
|
|
1915
1929
|
* @memberof Draw */
|
|
1916
|
-
const isFullscreen =()=> document.fullscreenElement;
|
|
1930
|
+
const isFullscreen = ()=> document.fullscreenElement;
|
|
1917
1931
|
|
|
1918
1932
|
/** Toggle fullsceen mode
|
|
1919
1933
|
* @memberof Draw */
|
|
@@ -1923,16 +1937,9 @@ function toggleFullscreen()
|
|
|
1923
1937
|
{
|
|
1924
1938
|
if (document.exitFullscreen)
|
|
1925
1939
|
document.exitFullscreen();
|
|
1926
|
-
else if (document.mozCancelFullScreen)
|
|
1927
|
-
document.mozCancelFullScreen();
|
|
1928
|
-
}
|
|
1929
|
-
else
|
|
1930
|
-
{
|
|
1931
|
-
if (document.body.webkitRequestFullScreen)
|
|
1932
|
-
document.body.webkitRequestFullScreen();
|
|
1933
|
-
else if (document.body.mozRequestFullScreen)
|
|
1934
|
-
document.body.mozRequestFullScreen();
|
|
1935
1940
|
}
|
|
1941
|
+
else if (document.body.requestFullscreen)
|
|
1942
|
+
document.body.requestFullscreen();
|
|
1936
1943
|
}
|
|
1937
1944
|
|
|
1938
1945
|
/**
|
|
@@ -1951,7 +1958,7 @@ function toggleFullscreen()
|
|
|
1951
1958
|
* @param {Number} [device=0]
|
|
1952
1959
|
* @return {Boolean}
|
|
1953
1960
|
* @memberof Input */
|
|
1954
|
-
const keyIsDown = (key, device=0)=> inputData[device] && inputData[device][key] & 1
|
|
1961
|
+
const keyIsDown = (key, device=0)=> inputData[device] && inputData[device][key] & 1;
|
|
1955
1962
|
|
|
1956
1963
|
/** Returns true if device key was pressed this frame
|
|
1957
1964
|
* @param {Number} key
|
|
@@ -2191,35 +2198,40 @@ const isTouchDevice = window.ontouchstart !== undefined;
|
|
|
2191
2198
|
if (isTouchDevice)
|
|
2192
2199
|
{
|
|
2193
2200
|
// override mouse events
|
|
2194
|
-
|
|
2195
|
-
onmousedown = onmouseup =
|
|
2201
|
+
let wasTouching, mouseDown = onmousedown, mouseUp = onmouseup;
|
|
2202
|
+
onmousedown = onmouseup = ()=> 0;
|
|
2196
2203
|
|
|
2197
|
-
//
|
|
2198
|
-
|
|
2199
|
-
ontouchstart = ontouchmove = ontouchend = (e)=>
|
|
2204
|
+
// setup touch input
|
|
2205
|
+
ontouchstart = (e)=>
|
|
2200
2206
|
{
|
|
2201
|
-
|
|
2207
|
+
// fix mobile audio, force it to play a sound on first touch
|
|
2208
|
+
zzfx(0);
|
|
2202
2209
|
|
|
2203
|
-
//
|
|
2204
|
-
|
|
2205
|
-
if (touching)
|
|
2210
|
+
// handle all touch events the same way
|
|
2211
|
+
ontouchstart = ontouchmove = ontouchend = (e)=>
|
|
2206
2212
|
{
|
|
2207
|
-
|
|
2208
|
-
hadTouch || zzfx(0, hadTouch=1);
|
|
2213
|
+
e.button = 0; // all touches are left click
|
|
2209
2214
|
|
|
2210
|
-
//
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2215
|
+
// check if touching and pass to mouse events
|
|
2216
|
+
const touching = e.touches.length;
|
|
2217
|
+
if (touching)
|
|
2218
|
+
{
|
|
2219
|
+
// set event pos and pass it along
|
|
2220
|
+
e.x = e.touches[0].clientX;
|
|
2221
|
+
e.y = e.touches[0].clientY;
|
|
2222
|
+
wasTouching ? onmousemove(e) : mouseDown(e);
|
|
2223
|
+
}
|
|
2224
|
+
else if (wasTouching)
|
|
2225
|
+
mouseUp(e);
|
|
2226
|
+
|
|
2227
|
+
// set was touching
|
|
2228
|
+
wasTouching = touching;
|
|
2217
2229
|
|
|
2218
|
-
|
|
2219
|
-
|
|
2230
|
+
// must return true so the document will get focus
|
|
2231
|
+
return true;
|
|
2232
|
+
}
|
|
2220
2233
|
|
|
2221
|
-
|
|
2222
|
-
return true;
|
|
2234
|
+
return ontouchstart(e);
|
|
2223
2235
|
}
|
|
2224
2236
|
}
|
|
2225
2237
|
|
|
@@ -2227,7 +2239,7 @@ if (isTouchDevice)
|
|
|
2227
2239
|
// touch gamepad, virtual on screen gamepad emulator for touch devices
|
|
2228
2240
|
|
|
2229
2241
|
// touch input internal variables
|
|
2230
|
-
let touchGamepadTimer = new Timer, touchGamepadButtons
|
|
2242
|
+
let touchGamepadTimer = new Timer, touchGamepadButtons, touchGamepadStick;
|
|
2231
2243
|
|
|
2232
2244
|
// create the touch gamepad, called automatically by the engine
|
|
2233
2245
|
function touchGamepadCreate()
|
|
@@ -2235,65 +2247,73 @@ function touchGamepadCreate()
|
|
|
2235
2247
|
if (!touchGamepadEnable || !isTouchDevice)
|
|
2236
2248
|
return;
|
|
2237
2249
|
|
|
2238
|
-
|
|
2250
|
+
// touch input internal variables
|
|
2251
|
+
touchGamepadButtons = [];
|
|
2252
|
+
touchGamepadStick = vec2();
|
|
2253
|
+
|
|
2254
|
+
// setup touch input
|
|
2255
|
+
ontouchstart = (e)=>
|
|
2239
2256
|
{
|
|
2240
|
-
|
|
2241
|
-
|
|
2257
|
+
// fix mobile audio, force it to play a sound on first touch
|
|
2258
|
+
zzfx(0);
|
|
2242
2259
|
|
|
2243
|
-
|
|
2244
|
-
touchGamepadStick = vec2();
|
|
2245
|
-
touchGamepadButtons = [];
|
|
2246
|
-
|
|
2247
|
-
const touching = e.touches.length;
|
|
2248
|
-
if (touching)
|
|
2260
|
+
ontouchstart = ontouchmove = ontouchend = (e)=>
|
|
2249
2261
|
{
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
if (paused)
|
|
2262
|
+
// clear touch gamepad input
|
|
2263
|
+
touchGamepadStick = vec2();
|
|
2264
|
+
touchGamepadButtons = [];
|
|
2265
|
+
|
|
2266
|
+
const touching = e.touches.length;
|
|
2267
|
+
if (touching)
|
|
2257
2268
|
{
|
|
2258
|
-
//
|
|
2259
|
-
|
|
2260
|
-
|
|
2269
|
+
// set that gamepad is active
|
|
2270
|
+
isUsingGamepad = 1;
|
|
2271
|
+
touchGamepadTimer.set();
|
|
2272
|
+
|
|
2273
|
+
if (paused)
|
|
2274
|
+
{
|
|
2275
|
+
// touch anywhere to press start when paused
|
|
2276
|
+
touchGamepadButtons[9] = 1;
|
|
2277
|
+
return;
|
|
2278
|
+
}
|
|
2261
2279
|
}
|
|
2262
|
-
}
|
|
2263
2280
|
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2281
|
+
// get center of left and right sides
|
|
2282
|
+
const stickCenter = vec2(touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
|
|
2283
|
+
const buttonCenter = mainCanvasSize.subtract(vec2(touchGamepadSize, touchGamepadSize));
|
|
2284
|
+
const startCenter = mainCanvasSize.scale(.5);
|
|
2268
2285
|
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
{
|
|
2272
|
-
const touchPos = mouseToScreen(vec2(touch.clientX, touch.clientY));
|
|
2273
|
-
if (touchPos.distance(stickCenter) < touchGamepadSize)
|
|
2286
|
+
// check each touch point
|
|
2287
|
+
for (const touch of e.touches)
|
|
2274
2288
|
{
|
|
2275
|
-
|
|
2276
|
-
if (
|
|
2277
|
-
touchGamepadStick = touchPos.subtract(stickCenter).scale(2/touchGamepadSize).clampLength();
|
|
2278
|
-
else
|
|
2289
|
+
const touchPos = mouseToScreen(vec2(touch.clientX, touch.clientY));
|
|
2290
|
+
if (touchPos.distance(stickCenter) < touchGamepadSize)
|
|
2279
2291
|
{
|
|
2280
|
-
//
|
|
2281
|
-
|
|
2282
|
-
|
|
2292
|
+
// virtual analog stick
|
|
2293
|
+
if (touchGamepadAnalog)
|
|
2294
|
+
touchGamepadStick = touchPos.subtract(stickCenter).scale(2/touchGamepadSize).clampLength();
|
|
2295
|
+
else
|
|
2296
|
+
{
|
|
2297
|
+
// 8 way dpad
|
|
2298
|
+
const angle = touchPos.subtract(stickCenter).angle();
|
|
2299
|
+
touchGamepadStick.setAngle((angle * 4 / PI + 8.5 | 0) * PI / 4);
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
else if (touchPos.distance(buttonCenter) < touchGamepadSize)
|
|
2303
|
+
{
|
|
2304
|
+
// virtual face buttons
|
|
2305
|
+
const button = touchPos.subtract(buttonCenter).direction();
|
|
2306
|
+
touchGamepadButtons[button] = 1;
|
|
2307
|
+
}
|
|
2308
|
+
else if (touchPos.distance(startCenter) < touchGamepadSize)
|
|
2309
|
+
{
|
|
2310
|
+
// virtual start button in center
|
|
2311
|
+
touchGamepadButtons[9] = 1;
|
|
2283
2312
|
}
|
|
2284
|
-
}
|
|
2285
|
-
else if (touchPos.distance(buttonCenter) < touchGamepadSize)
|
|
2286
|
-
{
|
|
2287
|
-
// virtual face buttons
|
|
2288
|
-
const button = touchPos.subtract(buttonCenter).direction();
|
|
2289
|
-
touchGamepadButtons[button] = 1;
|
|
2290
|
-
}
|
|
2291
|
-
else if (touchPos.distance(startCenter) < touchGamepadSize)
|
|
2292
|
-
{
|
|
2293
|
-
// virtual start button in center
|
|
2294
|
-
touchGamepadButtons[9] = 1;
|
|
2295
2313
|
}
|
|
2296
2314
|
}
|
|
2315
|
+
|
|
2316
|
+
return ontouchstart(e);
|
|
2297
2317
|
}
|
|
2298
2318
|
}
|
|
2299
2319
|
|
|
@@ -2411,7 +2431,7 @@ class Sound
|
|
|
2411
2431
|
{
|
|
2412
2432
|
if (!soundEnable) return;
|
|
2413
2433
|
|
|
2414
|
-
let pan
|
|
2434
|
+
let pan;
|
|
2415
2435
|
if (pos)
|
|
2416
2436
|
{
|
|
2417
2437
|
const range = this.range;
|
|
@@ -2441,7 +2461,7 @@ class Sound
|
|
|
2441
2461
|
* @param {Number} [volume=1] - How much to scale volume by (in addition to range fade)
|
|
2442
2462
|
* @return {AudioBufferSourceNode} - The audio, can be used to stop sound later
|
|
2443
2463
|
*/
|
|
2444
|
-
playNote(semitoneOffset, pos, volume
|
|
2464
|
+
playNote(semitoneOffset, pos, volume)
|
|
2445
2465
|
{
|
|
2446
2466
|
if (!soundEnable) return;
|
|
2447
2467
|
|
|
@@ -2496,7 +2516,7 @@ class Music
|
|
|
2496
2516
|
* @param {Boolean} [loop=1] - True if the music should loop when it reaches the end
|
|
2497
2517
|
* @return {AudioBufferSourceNode} - The audio node, can be used to stop sound later
|
|
2498
2518
|
*/
|
|
2499
|
-
play(volume
|
|
2519
|
+
play(volume, loop = 1)
|
|
2500
2520
|
{
|
|
2501
2521
|
if (!soundEnable) return;
|
|
2502
2522
|
|
|
@@ -2578,7 +2598,7 @@ function playSamples(sampleChannels, volume=1, rate=1, pan=0, loop=0)
|
|
|
2578
2598
|
|
|
2579
2599
|
// create audio context
|
|
2580
2600
|
if (!audioContext)
|
|
2581
|
-
audioContext = new
|
|
2601
|
+
audioContext = new AudioContext;
|
|
2582
2602
|
|
|
2583
2603
|
// fix stalled audio
|
|
2584
2604
|
audioContext.resume();
|
|
@@ -2597,18 +2617,13 @@ function playSamples(sampleChannels, volume=1, rate=1, pan=0, loop=0)
|
|
|
2597
2617
|
source.playbackRate.value = rate;
|
|
2598
2618
|
source.loop = loop;
|
|
2599
2619
|
|
|
2600
|
-
// create and connect gain node (createGain is more
|
|
2620
|
+
// create and connect gain node (createGain is more widely spported then GainNode construtor)
|
|
2601
2621
|
const gainNode = audioContext.createGain();
|
|
2602
2622
|
gainNode.gain.value = soundVolume*volume;
|
|
2603
2623
|
gainNode.connect(audioContext.destination);
|
|
2604
2624
|
|
|
2605
|
-
// connect source to gain
|
|
2606
|
-
(
|
|
2607
|
-
window.StereoPannerNode ? // create pan node if possible
|
|
2608
|
-
source.connect(new StereoPannerNode(audioContext, {'pan':clamp(pan, -1, 1)}))
|
|
2609
|
-
: source
|
|
2610
|
-
)
|
|
2611
|
-
.connect(gainNode);
|
|
2625
|
+
// connect source to stereo panner and gain
|
|
2626
|
+
source.connect(new StereoPannerNode(audioContext, {'pan':clamp(pan, -1, 1)})).connect(gainNode);
|
|
2612
2627
|
|
|
2613
2628
|
// play and return sound
|
|
2614
2629
|
source.start();
|
|
@@ -2726,10 +2741,8 @@ function zzfxG
|
|
|
2726
2741
|
* @memberof Audio */
|
|
2727
2742
|
function zzfxM(instruments, patterns, sequence, BPM = 125)
|
|
2728
2743
|
{
|
|
2744
|
+
let i, j, k;
|
|
2729
2745
|
let instrumentParameters;
|
|
2730
|
-
let i;
|
|
2731
|
-
let j;
|
|
2732
|
-
let k;
|
|
2733
2746
|
let note;
|
|
2734
2747
|
let sample;
|
|
2735
2748
|
let patternChannel;
|
|
@@ -2899,14 +2912,11 @@ function tileCollisionRaycast(posStart, posEnd, object)
|
|
|
2899
2912
|
{
|
|
2900
2913
|
// test if a ray collides with tiles from start to end
|
|
2901
2914
|
// todo: a way to get the exact hit point, it must still register as inside the hit tile
|
|
2902
|
-
posStart = posStart.floor();
|
|
2903
|
-
posEnd = posEnd.floor();
|
|
2904
|
-
const posDelta = posEnd.subtract(posStart);
|
|
2915
|
+
const posDelta = (posEnd = posEnd.floor()).subtract(posStart = posStart.floor());
|
|
2905
2916
|
const dx = abs(posDelta.x), dy = -abs(posDelta.y);
|
|
2906
2917
|
const sx = sign(posDelta.x), sy = sign(posDelta.y);
|
|
2907
|
-
let e = dx + dy;
|
|
2908
2918
|
|
|
2909
|
-
for (let x = posStart.x, y = posStart.y;;)
|
|
2919
|
+
for (let x = posStart.x, y = posStart.y, e = dx + dy;;)
|
|
2910
2920
|
{
|
|
2911
2921
|
const tileData = getTileCollisionData(vec2(x,y));
|
|
2912
2922
|
if (tileData && (object ? object.collideWithTileRaycast(tileData, new Vector2(x, y)) : tileData > 0))
|
|
@@ -2998,7 +3008,7 @@ constructor(pos, size=tileCollisionSize, tileSize=tileSizeDefault, scale=vec2(1)
|
|
|
2998
3008
|
// init tile data
|
|
2999
3009
|
this.data = [];
|
|
3000
3010
|
for (let j = this.size.area(); j--;)
|
|
3001
|
-
this.data.push(new TileLayerData
|
|
3011
|
+
this.data.push(new TileLayerData);
|
|
3002
3012
|
}
|
|
3003
3013
|
|
|
3004
3014
|
/** Set data at a given position in the array
|
|
@@ -3054,21 +3064,23 @@ constructor(pos, size=tileCollisionSize, tileSize=tileSizeDefault, scale=vec2(1)
|
|
|
3054
3064
|
* @param {Boolean} [clear=0] - Should it clear the canvas before drawing */
|
|
3055
3065
|
redrawStart(clear = 0)
|
|
3056
3066
|
{
|
|
3057
|
-
if (clear)
|
|
3058
|
-
{
|
|
3059
|
-
// clear and set size
|
|
3060
|
-
this.canvas.width = this.size.x * this.tileSize.x;
|
|
3061
|
-
this.canvas.height = this.size.y * this.tileSize.y;
|
|
3062
|
-
}
|
|
3063
|
-
|
|
3064
3067
|
// save current render settings
|
|
3065
|
-
this.savedRenderSettings = [mainCanvas, mainContext, cameraPos, cameraScale];
|
|
3068
|
+
this.savedRenderSettings = [mainCanvas, mainContext, mainCanvasSize, cameraPos, cameraScale];
|
|
3066
3069
|
|
|
3067
|
-
// use normal rendering system to render the tiles
|
|
3070
|
+
// hack: use normal rendering system to render the tiles
|
|
3068
3071
|
mainCanvas = this.canvas;
|
|
3069
3072
|
mainContext = this.context;
|
|
3070
3073
|
cameraPos = this.size.scale(.5);
|
|
3071
3074
|
cameraScale = this.tileSize.x;
|
|
3075
|
+
|
|
3076
|
+
if (clear)
|
|
3077
|
+
{
|
|
3078
|
+
// clear and set size
|
|
3079
|
+
mainCanvas.width = this.size.x * this.tileSize.x;
|
|
3080
|
+
mainCanvas.height = this.size.y * this.tileSize.y;
|
|
3081
|
+
}
|
|
3082
|
+
|
|
3083
|
+
// begin a new render for the tile canvas
|
|
3072
3084
|
enginePreRender();
|
|
3073
3085
|
}
|
|
3074
3086
|
|
|
@@ -3080,7 +3092,7 @@ constructor(pos, size=tileCollisionSize, tileSize=tileSizeDefault, scale=vec2(1)
|
|
|
3080
3092
|
//debugSaveCanvas(this.canvas);
|
|
3081
3093
|
|
|
3082
3094
|
// set stuff back to normal
|
|
3083
|
-
[mainCanvas, mainContext, cameraPos, cameraScale] = this.savedRenderSettings;
|
|
3095
|
+
[mainCanvas, mainContext, mainCanvasSize, cameraPos, cameraScale] = this.savedRenderSettings;
|
|
3084
3096
|
}
|
|
3085
3097
|
|
|
3086
3098
|
/** Draw the tile at a given position
|
|
@@ -3321,7 +3333,7 @@ class ParticleEmitter extends EngineObject
|
|
|
3321
3333
|
this.parent && super.update();
|
|
3322
3334
|
|
|
3323
3335
|
// update emitter
|
|
3324
|
-
if (!this.emitTime
|
|
3336
|
+
if (!this.emitTime | this.getAliveTime() <= this.emitTime)
|
|
3325
3337
|
{
|
|
3326
3338
|
// emit particles
|
|
3327
3339
|
if (this.emitRate * particleEmitRateScale)
|
|
@@ -3345,7 +3357,7 @@ class ParticleEmitter extends EngineObject
|
|
|
3345
3357
|
let pos = this.emitSize.x != undefined ? // check if vec2 was used for size
|
|
3346
3358
|
(new Vector2(rand(-.5,.5), rand(-.5,.5)))
|
|
3347
3359
|
.multiply(this.emitSize).rotate(this.angle) // box emitter
|
|
3348
|
-
: randInCircle(this.emitSize
|
|
3360
|
+
: randInCircle(this.emitSize/2); // circle emitter
|
|
3349
3361
|
let angle = rand(this.particleConeAngle, -this.particleConeAngle);
|
|
3350
3362
|
if (!this.localSpace)
|
|
3351
3363
|
{
|
|
@@ -3388,7 +3400,7 @@ class ParticleEmitter extends EngineObject
|
|
|
3388
3400
|
particle.additive = this.additive;
|
|
3389
3401
|
particle.renderOrder = this.renderOrder;
|
|
3390
3402
|
particle.trailScale = this.trailScale;
|
|
3391
|
-
particle.mirror =
|
|
3403
|
+
particle.mirror = randInt(2);
|
|
3392
3404
|
particle.localSpaceEmitter = this.localSpace && this;
|
|
3393
3405
|
|
|
3394
3406
|
// setup callbacks for particles
|
|
@@ -3417,7 +3429,8 @@ class Particle extends EngineObject
|
|
|
3417
3429
|
* @param {Vector2} [tileSize=tileSizeDefault] - Size of tile in source pixels
|
|
3418
3430
|
* @param {Number} [angle=0] - Angle to rotate the particle
|
|
3419
3431
|
*/
|
|
3420
|
-
constructor(pos, tileIndex, tileSize, angle)
|
|
3432
|
+
constructor(pos, tileIndex, tileSize, angle)
|
|
3433
|
+
{ super(pos, new Vector2, tileIndex, tileSize, angle); }
|
|
3421
3434
|
|
|
3422
3435
|
/** Render the particle, automatically called each frame, sorted by renderOrder */
|
|
3423
3436
|
render()
|
|
@@ -3486,10 +3499,6 @@ class Particle extends EngineObject
|
|
|
3486
3499
|
* @memberof Medals */
|
|
3487
3500
|
const medals = [];
|
|
3488
3501
|
|
|
3489
|
-
/** Set to stop medals from being unlockable (like if cheats are enabled)
|
|
3490
|
-
* @memberof Medals */
|
|
3491
|
-
let medalsPreventUnlock;
|
|
3492
|
-
|
|
3493
3502
|
// Engine internal variables not exposed to documentation
|
|
3494
3503
|
let medalsDisplayQueue = [], medalsSaveName, medalsDisplayTimeLast;
|
|
3495
3504
|
|
|
@@ -3537,9 +3546,8 @@ class Medal
|
|
|
3537
3546
|
this.name = name;
|
|
3538
3547
|
this.description = description;
|
|
3539
3548
|
this.icon = icon;
|
|
3540
|
-
this.image = new Image();
|
|
3541
3549
|
if (src)
|
|
3542
|
-
this.image.src = src;
|
|
3550
|
+
(this.image = new Image).src = src;
|
|
3543
3551
|
}
|
|
3544
3552
|
|
|
3545
3553
|
/** Unlocks a medal if not already unlocked */
|
|
@@ -3552,10 +3560,7 @@ class Medal
|
|
|
3552
3560
|
ASSERT(medalsSaveName); // save name must be set
|
|
3553
3561
|
localStorage[this.storageKey()] = this.unlocked = 1;
|
|
3554
3562
|
medalsDisplayQueue.push(this);
|
|
3555
|
-
|
|
3556
|
-
// save for newgrounds and OS13K
|
|
3557
3563
|
newgrounds && newgrounds.unlockMedal(this.id);
|
|
3558
|
-
localStorage['OS13kTrophy,' + this.icon + ',' + medalsSaveName + ',' + this.name] = this.description;
|
|
3559
3564
|
}
|
|
3560
3565
|
|
|
3561
3566
|
/** Render a medal
|
|
@@ -3564,27 +3569,26 @@ class Medal
|
|
|
3564
3569
|
render(hidePercent=0)
|
|
3565
3570
|
{
|
|
3566
3571
|
const context = overlayContext;
|
|
3567
|
-
const width = min(
|
|
3572
|
+
const width = min(medalDisplaySize.x, mainCanvas.width);
|
|
3568
3573
|
const x = overlayCanvas.width - width;
|
|
3569
|
-
const y = -
|
|
3574
|
+
const y = -medalDisplaySize.y*hidePercent;
|
|
3570
3575
|
|
|
3571
3576
|
// draw containing rect and clip to that region
|
|
3572
3577
|
context.save();
|
|
3573
3578
|
context.beginPath();
|
|
3574
|
-
context.fillStyle =
|
|
3575
|
-
context.
|
|
3576
|
-
context.strokeStyle = '#000';
|
|
3579
|
+
context.fillStyle = new Color(.9,.9,.9);
|
|
3580
|
+
context.strokeStyle = new Color(0,0,0);
|
|
3577
3581
|
context.lineWidth = 3;
|
|
3582
|
+
context.fill(context.rect(x, y, width, medalDisplaySize.y));
|
|
3578
3583
|
context.stroke();
|
|
3579
3584
|
context.clip();
|
|
3580
3585
|
|
|
3581
3586
|
// draw the icon and text
|
|
3582
|
-
this.renderIcon(x+15+medalDisplayIconSize/2, y+
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
context.fillText(this.description, x+medalDisplayIconSize+30, y+60);
|
|
3587
|
+
this.renderIcon(vec2(x+15+medalDisplayIconSize/2, y+medalDisplaySize.y/2));
|
|
3588
|
+
const pos = vec2(x+medalDisplayIconSize+30, y+28);
|
|
3589
|
+
drawTextScreen(this.name, pos, 38, new Color(0,0,0), 0, 0, 'left');
|
|
3590
|
+
pos.y += 32;
|
|
3591
|
+
drawTextScreen(this.description, pos, 24, new Color(0,0,0), 0, 0, 'left');
|
|
3588
3592
|
context.restore();
|
|
3589
3593
|
}
|
|
3590
3594
|
|
|
@@ -3593,18 +3597,13 @@ class Medal
|
|
|
3593
3597
|
* @param {Number} y - Screen space Y position
|
|
3594
3598
|
* @param {Number} [size=medalDisplayIconSize] - Screen space size
|
|
3595
3599
|
*/
|
|
3596
|
-
renderIcon(
|
|
3600
|
+
renderIcon(pos, size=medalDisplayIconSize)
|
|
3597
3601
|
{
|
|
3598
3602
|
// draw the image or icon
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
context.textAlign = 'center';
|
|
3602
|
-
context.textBaseline = 'middle';
|
|
3603
|
-
context.font = size*.7 + 'px '+ fontDefault;
|
|
3604
|
-
if (this.image.src)
|
|
3605
|
-
context.drawImage(this.image, x-size/2, y-size/2, size, size);
|
|
3603
|
+
if (this.image)
|
|
3604
|
+
overlayContext.drawImage(this.image, pos.x-size/2, pos.y-size/2, size, size);
|
|
3606
3605
|
else
|
|
3607
|
-
|
|
3606
|
+
drawTextScreen(this.icon, pos, size*.7, new Color(0,0,0));
|
|
3608
3607
|
}
|
|
3609
3608
|
|
|
3610
3609
|
// Get local storage key used by the medal
|
|
@@ -3662,18 +3661,20 @@ class Newgrounds
|
|
|
3662
3661
|
constructor(app_id, cipher)
|
|
3663
3662
|
{
|
|
3664
3663
|
ASSERT(!newgrounds && app_id);
|
|
3664
|
+
|
|
3665
3665
|
this.app_id = app_id;
|
|
3666
3666
|
this.cipher = cipher;
|
|
3667
3667
|
this.host = location ? location.hostname : '';
|
|
3668
|
-
|
|
3668
|
+
|
|
3669
3669
|
// create an instance of CryptoJS for encrypted calls
|
|
3670
|
-
|
|
3670
|
+
if (cipher)
|
|
3671
|
+
this.cryptoJS = this.CryptoJS();
|
|
3671
3672
|
|
|
3672
3673
|
// get session id from url search params
|
|
3673
3674
|
const url = new URL(location.href);
|
|
3674
|
-
this.session_id = url.searchParams.get('ngio_session_id')
|
|
3675
|
+
this.session_id = url.searchParams.get('ngio_session_id');
|
|
3675
3676
|
|
|
3676
|
-
if (this.session_id
|
|
3677
|
+
if (!this.session_id)
|
|
3677
3678
|
return; // only use newgrounds when logged in
|
|
3678
3679
|
|
|
3679
3680
|
// get medals
|
|
@@ -3686,6 +3687,7 @@ class Newgrounds
|
|
|
3686
3687
|
if (medal)
|
|
3687
3688
|
{
|
|
3688
3689
|
// copy newgrounds medal data
|
|
3690
|
+
medal.image = new Image;
|
|
3689
3691
|
medal.image.src = newgroundsMedal['icon'];
|
|
3690
3692
|
medal.name = newgroundsMedal['name'];
|
|
3691
3693
|
medal.description = newgroundsMedal['description'];
|
|
@@ -3770,13 +3772,16 @@ class Newgrounds
|
|
|
3770
3772
|
debugMedals && console.log(xmlHttp.responseText);
|
|
3771
3773
|
return xmlHttp.responseText && JSON.parse(xmlHttp.responseText);
|
|
3772
3774
|
}
|
|
3773
|
-
}
|
|
3774
3775
|
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3776
|
+
CryptoJS()
|
|
3777
|
+
{
|
|
3778
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
3779
|
+
// Crypto-JS - https://github.com/brix/crypto-js [The MIT License (MIT)]
|
|
3780
|
+
// Copyright (c) 2009-2013 Jeff Mott Copyright (c) 2013-2016 Evan Vosberg
|
|
3778
3781
|
|
|
3779
|
-
|
|
3782
|
+
return eval(Function("[M='GBMGXz^oVYPPKKbB`agTXU|LxPc_ZBcMrZvCr~wyGfWrwk@ATqlqeTp^N?p{we}jIpEnB_sEr`l?YDkDhWhprc|Er|XETG?pTl`e}dIc[_N~}fzRycIfpW{HTolvoPB_FMe_eH~BTMx]yyOhv?biWPCGc]kABencBhgERHGf{OL`Dj`c^sh@canhy[secghiyotcdOWgO{tJIE^JtdGQRNSCrwKYciZOa]Y@tcRATYKzv|sXpboHcbCBf`}SKeXPFM|RiJsSNaIb]QPc[D]Jy_O^XkOVTZep`ONmntLL`Qz~UupHBX_Ia~WX]yTRJIxG`ioZ{fefLJFhdyYoyLPvqgH?b`[TMnTwwfzDXhfM?rKs^aFr|nyBdPmVHTtAjXoYUloEziWDCw_suyYT~lSMksI~ZNCS[Bex~j]Vz?kx`gdYSEMCsHpjbyxQvw|XxX_^nQYue{sBzVWQKYndtYQMWRef{bOHSfQhiNdtR{o?cUAHQAABThwHPT}F{VvFmgN`E@FiFYS`UJmpQNM`X|tPKHlccT}z}k{sACHL?Rt@MkWplxO`ASgh?hBsuuP|xD~LSH~KBlRs]t|l|_tQAroDRqWS^SEr[sYdPB}TAROtW{mIkE|dWOuLgLmJrucGLpebrAFKWjikTUzS|j}M}szasKOmrjy[?hpwnEfX[jGpLt@^v_eNwSQHNwtOtDgWD{rk|UgASs@mziIXrsHN_|hZuxXlPJOsA^^?QY^yGoCBx{ekLuZzRqQZdsNSx@ezDAn{XNj@fRXIwrDX?{ZQHwTEfu@GhxDOykqts|n{jOeZ@c`dvTY?e^]ATvWpb?SVyg]GC?SlzteilZJAL]mlhLjYZazY__qcVFYvt@|bIQnSno@OXyt]OulzkWqH`rYFWrwGs`v|~XeTsIssLrbmHZCYHiJrX}eEzSssH}]l]IhPQhPoQ}rCXLyhFIT[clhzYOvyHqigxmjz`phKUU^TPf[GRAIhNqSOdayFP@FmKmuIzMOeoqdpxyCOwCthcLq?n`L`tLIBboNn~uXeFcPE{C~mC`h]jUUUQe^`UqvzCutYCgct|SBrAeiYQW?X~KzCz}guXbsUw?pLsg@hDArw?KeJD[BN?GD@wgFWCiHq@Ypp_QKFixEKWqRp]oJFuVIEvjDcTFu~Zz]a{IcXhWuIdMQjJ]lwmGQ|]g~c]Hl]pl`Pd^?loIcsoNir_kikBYyg?NarXZEGYspt_vLBIoj}LI[uBFvm}tbqvC|xyR~a{kob|HlctZslTGtPDhBKsNsoZPuH`U`Fqg{gKnGSHVLJ^O`zmNgMn~{rsQuoymw^JY?iUBvw_~mMr|GrPHTERS[MiNpY[Mm{ggHpzRaJaoFomtdaQ_?xuTRm}@KjU~RtPsAdxa|uHmy}n^i||FVL[eQAPrWfLm^ndczgF~Nk~aplQvTUpHvnTya]kOenZlLAQIm{lPl@CCTchvCF[fI{^zPkeYZTiamoEcKmBMfZhk_j_~Fjp|wPVZlkh_nHu]@tP|hS@^G^PdsQ~f[RqgTDqezxNFcaO}HZhb|MMiNSYSAnQWCDJukT~e|OTgc}sf[cnr?fyzTa|EwEtRG|I~|IO}O]S|rp]CQ}}DWhSjC_|z|oY|FYl@WkCOoPuWuqr{fJu?Brs^_EBI[@_OCKs}?]O`jnDiXBvaIWhhMAQDNb{U`bqVR}oqVAvR@AZHEBY@depD]OLh`kf^UsHhzKT}CS}HQKy}Q~AeMydXPQztWSSzDnghULQgMAmbWIZ|lWWeEXrE^EeNoZApooEmrXe{NAnoDf`m}UNlRdqQ@jOc~HLOMWs]IDqJHYoMziEedGBPOxOb?[X`KxkFRg@`mgFYnP{hSaxwZfBQqTm}_?RSEaQga]w[vxc]hMne}VfSlqUeMo_iqmd`ilnJXnhdj^EEFifvZyxYFRf^VaqBhLyrGlk~qowqzHOBlOwtx?i{m~`n^G?Yxzxux}b{LSlx]dS~thO^lYE}bzKmUEzwW^{rPGhbEov[Plv??xtyKJshbG`KuO?hjBdS@Ru}iGpvFXJRrvOlrKN?`I_n_tplk}kgwSXuKylXbRQ]]?a|{xiT[li?k]CJpwy^o@ebyGQrPfF`aszGKp]baIx~H?ElETtFh]dz[OjGl@C?]VDhr}OE@V]wLTc[WErXacM{We`F|utKKjgllAxvsVYBZ@HcuMgLboFHVZmi}eIXAIFhS@A@FGRbjeoJWZ_NKd^oEH`qgy`q[Tq{x?LRP|GfBFFJV|fgZs`MLbpPYUdIV^]mD@FG]pYAT^A^RNCcXVrPsgk{jTrAIQPs_`mD}rOqAZA[}RETFz]WkXFTz_m{N@{W@_fPKZLT`@aIqf|L^Mb|crNqZ{BVsijzpGPEKQQZGlApDn`ruH}cvF|iXcNqK}cxe_U~HRnKV}sCYb`D~oGvwG[Ca|UaybXea~DdD~LiIbGRxJ_VGheI{ika}KC[OZJLn^IBkPrQj_EuoFwZ}DpoBRcK]Q}?EmTv~i_Tul{bky?Iit~tgS|o}JL_VYcCQdjeJ_MfaA`FgCgc[Ii|CBHwq~nbJeYTK{e`CNstKfTKPzw{jdhp|qsZyP_FcugxCFNpKitlR~vUrx^NrSVsSTaEgnxZTmKc`R|lGJeX}ccKLsQZQhsFkeFd|ckHIVTlGMg`~uPwuHRJS_CPuN_ogXe{Ba}dO_UBhuNXby|h?JlgBIqMKx^_u{molgL[W_iavNQuOq?ap]PGB`clAicnl@k~pA?MWHEZ{HuTLsCpOxxrKlBh]FyMjLdFl|nMIvTHyGAlPogqfZ?PlvlFJvYnDQd}R@uAhtJmDfe|iJqdkYr}r@mEjjIetDl_I`TELfoR|qTBu@Tic[BaXjP?dCS~MUK[HPRI}OUOwAaf|_}HZzrwXvbnNgltjTwkBE~MztTQhtRSWoQHajMoVyBBA`kdgK~h`o[J`dm~pm]tk@i`[F~F]DBlJKklrkR]SNw@{aG~Vhl`KINsQkOy?WhcqUMTGDOM_]bUjVd|Yh_KUCCgIJ|LDIGZCPls{RzbVWVLEhHvWBzKq|^N?DyJB|__aCUjoEgsARki}j@DQXS`RNU|DJ^a~d{sh_Iu{ONcUtSrGWW@cvUjefHHi}eSSGrNtO?cTPBShLqzwMVjWQQCCFB^culBjZHEK_{dO~Q`YhJYFn]jq~XSnG@[lQr]eKrjXpG~L^h~tDgEma^AUFThlaR{xyuP@[^VFwXSeUbVetufa@dX]CLyAnDV@Bs[DnpeghJw^?UIana}r_CKGDySoRudklbgio}kIDpA@McDoPK?iYcG?_zOmnWfJp}a[JLR[stXMo?_^Ng[whQlrDbrawZeSZ~SJstIObdDSfAA{MV}?gNunLOnbMv_~KFQUAjIMj^GkoGxuYtYbGDImEYiwEMyTpMxN_LSnSMdl{bg@dtAnAMvhDTBR_FxoQgANniRqxd`pWv@rFJ|mWNWmh[GMJz_Nq`BIN@KsjMPASXORcdHjf~rJfgZYe_uulzqM_KdPlMsuvU^YJuLtofPhGonVOQxCMuXliNvJIaoC?hSxcxKVVxWlNs^ENDvCtSmO~WxI[itnjs^RDvI@KqG}YekaSbTaB]ki]XM@[ZnDAP~@|BzLRgOzmjmPkRE@_sobkT|SszXK[rZN?F]Z_u}Yue^[BZgLtR}FHzWyxWEX^wXC]MJmiVbQuBzkgRcKGUhOvUc_bga|Tx`KEM`JWEgTpFYVeXLCm|mctZR@uKTDeUONPozBeIkrY`cz]]~WPGMUf`MNUGHDbxZuO{gmsKYkAGRPqjc|_FtblEOwy}dnwCHo]PJhN~JoteaJ?dmYZeB^Xd?X^pOKDbOMF@Ugg^hETLdhwlA}PL@_ur|o{VZosP?ntJ_kG][g{Zq`Tu]dzQlSWiKfnxDnk}KOzp~tdFstMobmy[oPYjyOtUzMWdjcNSUAjRuqhLS@AwB^{BFnqjCmmlk?jpn}TksS{KcKkDboXiwK]qMVjm~V`LgWhjS^nLGwfhAYrjDSBL_{cRus~{?xar_xqPlArrYFd?pHKdMEZzzjJpfC?Hv}mAuIDkyBxFpxhstTx`IO{rp}XGuQ]VtbHerlRc_LFGWK[XluFcNGUtDYMZny[M^nVKVeMllQI[xtvwQnXFlWYqxZZFp_|]^oWX[{pOMpxXxvkbyJA[DrPzwD|LW|QcV{Nw~U^dgguSpG]ClmO@j_TENIGjPWwgdVbHganhM?ema|dBaqla|WBd`poj~klxaasKxGG^xbWquAl~_lKWxUkDFagMnE{zHug{b`A~IYcQYBF_E}wiA}K@yxWHrZ{[d~|ARsYsjeNWzkMs~IOqqp[yzDE|WFrivsidTcnbHFRoW@XpAV`lv_zj?B~tPCppRjgbbDTALeFaOf?VcjnKTQMLyp{NwdylHCqmo?oelhjWuXj~}{fpuX`fra?GNkDiChYgVSh{R[BgF~eQa^WVz}ATI_CpY?g_diae]|ijH`TyNIF}|D_xpmBq_JpKih{Ba|sWzhnAoyraiDvk`h{qbBfsylBGmRH}DRPdryEsSaKS~tIaeF[s]I~xxHVrcNe@Jjxa@jlhZueLQqHh_]twVMqG_EGuwyab{nxOF?`HCle}nBZzlTQjkLmoXbXhOtBglFoMz?eqre`HiE@vNwBulglmQjj]DB@pPkPUgA^sjOAUNdSu_`oAzar?n?eMnw{{hYmslYi[TnlJD'",...']charCodeAtUinyxpf',"for(;e<10359;c[e++]=p-=128,A=A?p-A&&A:p==34&&p)for(p=1;p<128;y=f.map((n,x)=>(U=r[n]*2+1,U=Math.log(U/(h-U)),t-=a[x]*U,U/500)),t=~-h/(1+Math.exp(t))|1,i=o%h<t,o=o%h+(i?t:h-t)*(o>>17)-!i*t,f.map((n,x)=>(U=r[n]+=(i*h/2-r[n]<<13)/((C[n]+=C[n]<5)+1/20)>>13,a[x]+=y[x]*(i-t/h))),p=p*2+i)for(f='010202103203210431053105410642065206541'.split(t=0).map((n,x)=>(U=0,[...n].map((n,x)=>(U=U*997+(c[e-n]|0)|0)),h*32-1&U*997+p+!!A*129)*12+x);o<h*32;o=o*64|M.charCodeAt(d++)&63);for(C=String.fromCharCode(...c);r=/[\0-#?@\\\\~]/.exec(C);)with(C.split(r))C=join(shift());return C")([],[],1<<17,[0,0,0,0,0,0,0,0,0,0,0,0],new Uint16Array(51e6).fill(1<<15),new Uint8Array(51e6),0,0,0,0));
|
|
3783
|
+
}
|
|
3784
|
+
}
|
|
3780
3785
|
/**
|
|
3781
3786
|
* LittleJS WebGL Interface
|
|
3782
3787
|
* <br> - All webgl used by the engine is wrapped up here
|
|
@@ -3806,7 +3811,7 @@ let glContext;
|
|
|
3806
3811
|
let glTileTexture;
|
|
3807
3812
|
|
|
3808
3813
|
// WebGL internal variables not exposed to documentation
|
|
3809
|
-
let glActiveTexture, glShader, glArrayBuffer,
|
|
3814
|
+
let glActiveTexture, glShader, glArrayBuffer, glPositionData, glColorData, glBatchCount, glBatchAdditive, glAdditive;
|
|
3810
3815
|
|
|
3811
3816
|
///////////////////////////////////////////////////////////////////////////////
|
|
3812
3817
|
|
|
@@ -3827,27 +3832,25 @@ function glInit()
|
|
|
3827
3832
|
'uniform mat4 m;'+ // transform matrix
|
|
3828
3833
|
'attribute vec2 p,t;'+ // position, uv
|
|
3829
3834
|
'attribute vec4 c,a;'+ // color, additiveColor
|
|
3830
|
-
'varying
|
|
3831
|
-
'varying vec4 d,e;'+ // return color, additiveColor
|
|
3835
|
+
'varying vec4 v,d,e;'+ // return uv, color, additiveColor
|
|
3832
3836
|
'void main(){'+ // shader entry point
|
|
3833
3837
|
'gl_Position=m*vec4(p,1,1);'+ // transform position
|
|
3834
|
-
'v=t;d=c;e=a;'+
|
|
3838
|
+
'v=vec4(t,p);d=c;e=a;'+ // pass stuff to fragment shader
|
|
3835
3839
|
'}' // end of shader
|
|
3836
3840
|
,
|
|
3837
|
-
'precision highp float;'+
|
|
3838
|
-
'varying
|
|
3839
|
-
'
|
|
3840
|
-
'
|
|
3841
|
-
'
|
|
3842
|
-
'
|
|
3843
|
-
'}' // end of shader
|
|
3841
|
+
'precision highp float;'+ // use highp for better accuracy
|
|
3842
|
+
'varying vec4 v,d,e;'+ // uv, color, additiveColor
|
|
3843
|
+
'uniform sampler2D s;'+ // texture
|
|
3844
|
+
'void main(){'+ // shader entry point
|
|
3845
|
+
'gl_FragColor=texture2D(s,v.xy)*d+e;'+ // modulate texture by color plus additive
|
|
3846
|
+
'}' // end of shader
|
|
3844
3847
|
);
|
|
3845
3848
|
|
|
3846
3849
|
// init buffers
|
|
3847
|
-
|
|
3850
|
+
const vertexData = new ArrayBuffer(gl_VERTEX_BUFFER_SIZE);
|
|
3848
3851
|
glArrayBuffer = glContext.createBuffer();
|
|
3849
|
-
glPositionData = new Float32Array(
|
|
3850
|
-
glColorData = new Uint32Array(
|
|
3852
|
+
glPositionData = new Float32Array(vertexData);
|
|
3853
|
+
glColorData = new Uint32Array(vertexData);
|
|
3851
3854
|
glBatchCount = 0;
|
|
3852
3855
|
}
|
|
3853
3856
|
|
|
@@ -3922,18 +3925,19 @@ function glCreateTexture(image)
|
|
|
3922
3925
|
image && image.width && glContext.texImage2D(gl_TEXTURE_2D, 0, gl_RGBA, gl_RGBA, gl_UNSIGNED_BYTE, image);
|
|
3923
3926
|
|
|
3924
3927
|
// use point filtering for pixelated rendering
|
|
3925
|
-
|
|
3926
|
-
glContext.texParameteri(gl_TEXTURE_2D,
|
|
3928
|
+
const filter = cavasPixelated ? gl_NEAREST : gl_LINEAR;
|
|
3929
|
+
glContext.texParameteri(gl_TEXTURE_2D, gl_TEXTURE_MIN_FILTER, filter);
|
|
3930
|
+
glContext.texParameteri(gl_TEXTURE_2D, gl_TEXTURE_MAG_FILTER, filter);
|
|
3927
3931
|
glContext.texParameteri(gl_TEXTURE_2D, gl_TEXTURE_WRAP_S, gl_CLAMP_TO_EDGE);
|
|
3928
3932
|
glContext.texParameteri(gl_TEXTURE_2D, gl_TEXTURE_WRAP_T, gl_CLAMP_TO_EDGE);
|
|
3929
3933
|
return texture;
|
|
3930
3934
|
}
|
|
3931
3935
|
|
|
3932
3936
|
// called automatically by engine before render
|
|
3933
|
-
function glPreRender(
|
|
3937
|
+
function glPreRender()
|
|
3934
3938
|
{
|
|
3935
3939
|
// clear and set to same size as main canvas
|
|
3936
|
-
glContext.viewport(0, 0, glCanvas.width = width, glCanvas.height = height);
|
|
3940
|
+
glContext.viewport(0, 0, glCanvas.width = mainCanvas.width, glCanvas.height = mainCanvas.height);
|
|
3937
3941
|
glContext.clear(gl_COLOR_BUFFER_BIT);
|
|
3938
3942
|
|
|
3939
3943
|
// set up the shader
|
|
@@ -3941,7 +3945,7 @@ function glPreRender(width, height, cameraX, cameraY, cameraScale)
|
|
|
3941
3945
|
glContext.activeTexture(gl_TEXTURE0);
|
|
3942
3946
|
glContext.bindTexture(gl_TEXTURE_2D, glActiveTexture = glTileTexture);
|
|
3943
3947
|
glContext.bindBuffer(gl_ARRAY_BUFFER, glArrayBuffer);
|
|
3944
|
-
glContext.bufferData(gl_ARRAY_BUFFER,
|
|
3948
|
+
glContext.bufferData(gl_ARRAY_BUFFER, gl_VERTEX_BUFFER_SIZE, gl_DYNAMIC_DRAW);
|
|
3945
3949
|
glSetBlendMode();
|
|
3946
3950
|
|
|
3947
3951
|
// set vertex attributes
|
|
@@ -3959,14 +3963,14 @@ function glPreRender(width, height, cameraX, cameraY, cameraScale)
|
|
|
3959
3963
|
initVertexAttribArray('a', gl_UNSIGNED_BYTE, 1, 4, 1); // additiveColor
|
|
3960
3964
|
|
|
3961
3965
|
// build the transform matrix
|
|
3962
|
-
const sx = 2 * cameraScale / width;
|
|
3963
|
-
const sy = 2 * cameraScale / height;
|
|
3966
|
+
const sx = 2 * cameraScale / mainCanvas.width;
|
|
3967
|
+
const sy = 2 * cameraScale / mainCanvas.height;
|
|
3964
3968
|
glContext.uniformMatrix4fv(glContext.getUniformLocation(glShader, 'm'), 0,
|
|
3965
3969
|
new Float32Array([
|
|
3966
3970
|
sx, 0, 0, 0,
|
|
3967
3971
|
0, sy, 0, 0,
|
|
3968
3972
|
1, 1, -1, 1,
|
|
3969
|
-
-1-sx*
|
|
3973
|
+
-1-sx*cameraPos.x, -1-sy*cameraPos.y, 0, 0
|
|
3970
3974
|
])
|
|
3971
3975
|
);
|
|
3972
3976
|
}
|
|
@@ -4014,10 +4018,10 @@ function glCopyToContext(context, forceDraw)
|
|
|
4014
4018
|
* @param uv0Y
|
|
4015
4019
|
* @param uv1X
|
|
4016
4020
|
* @param uv1Y
|
|
4017
|
-
* @param
|
|
4021
|
+
* @param rgba
|
|
4018
4022
|
* @param [rgbaAdditive=0]
|
|
4019
4023
|
* @memberof WebGL */
|
|
4020
|
-
function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba
|
|
4024
|
+
function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba, rgbaAdditive=0)
|
|
4021
4025
|
{
|
|
4022
4026
|
// flush if there is no room for more verts or if different blend mode
|
|
4023
4027
|
if (glBatchCount == gl_MAX_BATCH || glBatchAdditive != glAdditive)
|
|
@@ -4028,43 +4032,16 @@ function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba=0xffffff
|
|
|
4028
4032
|
const cx = c*sizeX, cy = c*sizeY, sx = s*sizeX, sy = s*sizeY;
|
|
4029
4033
|
|
|
4030
4034
|
// setup 2 triangles to form a quad
|
|
4031
|
-
let offset = glBatchCount++ * gl_VERTICES_PER_QUAD * gl_INDICIES_PER_VERT;
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
glPositionData[offset++] = y + cy - sx;
|
|
4042
|
-
glPositionData[offset++] = uv1X; glPositionData[offset++] = uv0Y;
|
|
4043
|
-
glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
|
|
4044
|
-
|
|
4045
|
-
// vertex 2
|
|
4046
|
-
glPositionData[offset++] = x - cx + sy;
|
|
4047
|
-
glPositionData[offset++] = y + cy + sx;
|
|
4048
|
-
glPositionData[offset++] = uv0X; glPositionData[offset++] = uv0Y;
|
|
4049
|
-
glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
|
|
4050
|
-
|
|
4051
|
-
// vertex 0
|
|
4052
|
-
glPositionData[offset++] = x - cx - sy;
|
|
4053
|
-
glPositionData[offset++] = y - cy + sx;
|
|
4054
|
-
glPositionData[offset++] = uv0X; glPositionData[offset++] = uv1Y;
|
|
4055
|
-
glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
|
|
4056
|
-
|
|
4057
|
-
// vertex 3
|
|
4058
|
-
glPositionData[offset++] = x + cx - sy;
|
|
4059
|
-
glPositionData[offset++] = y - cy - sx;
|
|
4060
|
-
glPositionData[offset++] = uv1X; glPositionData[offset++] = uv1Y;
|
|
4061
|
-
glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
|
|
4062
|
-
|
|
4063
|
-
// vertex 1
|
|
4064
|
-
glPositionData[offset++] = x + cx + sy;
|
|
4065
|
-
glPositionData[offset++] = y + cy - sx;
|
|
4066
|
-
glPositionData[offset++] = uv1X; glPositionData[offset++] = uv0Y;
|
|
4067
|
-
glColorData[offset++] = rgba; glColorData[offset++] = rgbaAdditive;
|
|
4035
|
+
for(let i=6, offset = glBatchCount++ * gl_VERTICES_PER_QUAD * gl_INDICIES_PER_VERT; i--;)
|
|
4036
|
+
{
|
|
4037
|
+
const a = i-4&&i>1, b = i-5&&i-2&&i-1;
|
|
4038
|
+
glPositionData[offset++] = x + (a?-cx:cx) + (b?sy:-sy);
|
|
4039
|
+
glPositionData[offset++] = y + (b?cy:-cy) + (a?sx:-sx);
|
|
4040
|
+
glPositionData[offset++] = a ? uv0X : uv1X;
|
|
4041
|
+
glPositionData[offset++] = b ? uv0Y : uv1Y;
|
|
4042
|
+
glColorData[offset++] = rgba;
|
|
4043
|
+
glColorData[offset++] = rgbaAdditive;
|
|
4044
|
+
}
|
|
4068
4045
|
}
|
|
4069
4046
|
|
|
4070
4047
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -4116,14 +4093,13 @@ function glRenderPostProcess()
|
|
|
4116
4093
|
return;
|
|
4117
4094
|
|
|
4118
4095
|
// prepare to render post process shader
|
|
4119
|
-
const width = mainCanvas.width, height = mainCanvas.height;
|
|
4120
4096
|
if (glEnable)
|
|
4121
4097
|
{
|
|
4122
4098
|
glFlush(); // clear out the buffer
|
|
4123
4099
|
mainContext.drawImage(glCanvas, 0, 0); // copy to the main canvas
|
|
4124
4100
|
}
|
|
4125
|
-
else
|
|
4126
|
-
glContext.viewport(0, 0, glCanvas.width = width, glCanvas.height = height);
|
|
4101
|
+
else // set viewport
|
|
4102
|
+
glContext.viewport(0, 0, glCanvas.width = mainCanvas.width, glCanvas.height = mainCanvas.height);
|
|
4127
4103
|
|
|
4128
4104
|
// setup shader program to draw one triangle
|
|
4129
4105
|
glContext.useProgram(glPostShader);
|
|
@@ -4147,7 +4123,7 @@ function glRenderPostProcess()
|
|
|
4147
4123
|
const uniformLocation = (name)=>glContext.getUniformLocation(glPostShader, name);
|
|
4148
4124
|
glContext.uniform1i(uniformLocation('iChannel0'), 0);
|
|
4149
4125
|
glContext.uniform1f(uniformLocation('iTime'), time);
|
|
4150
|
-
glContext.uniform3f(uniformLocation('iResolution'), width, height, 1);
|
|
4126
|
+
glContext.uniform3f(uniformLocation('iResolution'), mainCanvas.width, mainCanvas.height, 1);
|
|
4151
4127
|
glContext.drawArrays(gl_TRIANGLES, 0, 3);
|
|
4152
4128
|
}
|
|
4153
4129
|
|
|
@@ -4187,7 +4163,8 @@ gl_UNPACK_FLIP_Y_WEBGL = 37440,
|
|
|
4187
4163
|
gl_VERTICES_PER_QUAD = 6,
|
|
4188
4164
|
gl_INDICIES_PER_VERT = 6,
|
|
4189
4165
|
gl_MAX_BATCH = 1<<16,
|
|
4190
|
-
gl_VERTEX_BYTE_STRIDE = (4 * 2) * 2 + (4) * 2
|
|
4166
|
+
gl_VERTEX_BYTE_STRIDE = (4 * 2) * 2 + (4) * 2, // vec2 * 2 + (char * 4) * 2
|
|
4167
|
+
gl_VERTEX_BUFFER_SIZE = gl_MAX_BATCH * gl_VERTICES_PER_QUAD * gl_VERTEX_BYTE_STRIDE;
|
|
4191
4168
|
/*
|
|
4192
4169
|
LittleJS - The Tiny JavaScript Game Engine That Can!
|
|
4193
4170
|
MIT License - Copyright 2021 Frank Force
|
|
@@ -4203,6 +4180,7 @@ gl_VERTEX_BYTE_STRIDE = (4 * 2) * 2 + (4) * 2; // vec2 * 2 + (char * 4) * 2
|
|
|
4203
4180
|
- Particle effect system
|
|
4204
4181
|
- Medal system tracks and displays achievements
|
|
4205
4182
|
- Debug tools and debug rendering system
|
|
4183
|
+
- Post processing effects
|
|
4206
4184
|
- Call engineInit() to start it up!
|
|
4207
4185
|
*/
|
|
4208
4186
|
|
|
@@ -4212,7 +4190,7 @@ gl_VERTEX_BYTE_STRIDE = (4 * 2) * 2 + (4) * 2; // vec2 * 2 + (char * 4) * 2
|
|
|
4212
4190
|
const engineName = 'LittleJS';
|
|
4213
4191
|
|
|
4214
4192
|
/** Version of engine */
|
|
4215
|
-
const engineVersion = '1.4.
|
|
4193
|
+
const engineVersion = '1.4.9';
|
|
4216
4194
|
|
|
4217
4195
|
/** Frames per second to update objects
|
|
4218
4196
|
* @default */
|
|
@@ -4237,14 +4215,13 @@ let time = 0;
|
|
|
4237
4215
|
/** Actual clock time since start in seconds (not affected by pause or frame rate clamping) */
|
|
4238
4216
|
let timeReal = 0;
|
|
4239
4217
|
|
|
4240
|
-
/** Is the game paused? Causes time and objects to not be updated
|
|
4218
|
+
/** Is the game paused? Causes time and objects to not be updated */
|
|
4241
4219
|
let paused = 0;
|
|
4242
4220
|
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
let averageFPS, drawCount;
|
|
4221
|
+
/** Set if game is paused
|
|
4222
|
+
* @param {Boolean} paused
|
|
4223
|
+
*/
|
|
4224
|
+
function setPaused(_paused) { paused = _paused; }
|
|
4248
4225
|
|
|
4249
4226
|
///////////////////////////////////////////////////////////////////////////////
|
|
4250
4227
|
|
|
@@ -4265,13 +4242,11 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4265
4242
|
tileImageFixBleed = vec2(tileFixBleedScale).divide(tileImageSize = vec2(tileImage.width, tileImage.height));
|
|
4266
4243
|
debug && (tileImage.onload=()=>ASSERT(1)); // tile sheet can not reloaded
|
|
4267
4244
|
|
|
4268
|
-
// setup
|
|
4245
|
+
// setup html
|
|
4269
4246
|
const styleBody = 'margin:0;overflow:hidden;background:#000' + // fill the window
|
|
4270
4247
|
';touch-action:none' + // prevent mobile pinch to resize
|
|
4271
4248
|
';user-select:none' + // prevent mobile hold to select
|
|
4272
|
-
';-webkit-user-select:none
|
|
4273
|
-
|
|
4274
|
-
// setup html
|
|
4249
|
+
';-webkit-user-select:none'; // compatibility for ios
|
|
4275
4250
|
document.body.style = styleBody;
|
|
4276
4251
|
document.body.appendChild(mainCanvas = document.createElement('canvas'));
|
|
4277
4252
|
mainContext = mainCanvas.getContext('2d');
|
|
@@ -4286,7 +4261,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4286
4261
|
|
|
4287
4262
|
// set canvas style to fill the window
|
|
4288
4263
|
const styleCanvas = 'position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)';
|
|
4289
|
-
(glCanvas||mainCanvas).style =
|
|
4264
|
+
(glCanvas||mainCanvas).style = mainCanvas.style = overlayCanvas.style = styleCanvas;
|
|
4290
4265
|
|
|
4291
4266
|
gameInit();
|
|
4292
4267
|
touchGamepadCreate();
|
|
@@ -4294,16 +4269,16 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4294
4269
|
};
|
|
4295
4270
|
|
|
4296
4271
|
// frame time tracking
|
|
4297
|
-
let frameTimeLastMS = 0, frameTimeBufferMS
|
|
4272
|
+
let frameTimeLastMS = 0, frameTimeBufferMS, averageFPS;
|
|
4298
4273
|
|
|
4299
4274
|
// main update loop
|
|
4300
|
-
|
|
4275
|
+
function engineUpdate(frameTimeMS=0)
|
|
4301
4276
|
{
|
|
4302
4277
|
// update time keeping
|
|
4303
4278
|
let frameTimeDeltaMS = frameTimeMS - frameTimeLastMS;
|
|
4304
4279
|
frameTimeLastMS = frameTimeMS;
|
|
4305
4280
|
if (debug || showWatermark)
|
|
4306
|
-
averageFPS = lerp(.05, averageFPS
|
|
4281
|
+
averageFPS = lerp(.05, averageFPS, 1e3/(frameTimeDeltaMS||1));
|
|
4307
4282
|
const debugSpeedUp = debug && keyIsDown(107); // +
|
|
4308
4283
|
const debugSpeedDown = debug && keyIsDown(109); // -
|
|
4309
4284
|
if (debug)
|
|
@@ -4315,24 +4290,19 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4315
4290
|
|
|
4316
4291
|
if (canvasFixedSize.x)
|
|
4317
4292
|
{
|
|
4318
|
-
// clear set fixed size
|
|
4293
|
+
// clear canvas and set fixed size
|
|
4319
4294
|
overlayCanvas.width = mainCanvas.width = canvasFixedSize.x;
|
|
4320
4295
|
overlayCanvas.height = mainCanvas.height = canvasFixedSize.y;
|
|
4321
4296
|
|
|
4322
4297
|
// fit to window by adding space on top or bottom if necessary
|
|
4323
4298
|
const aspect = innerWidth / innerHeight;
|
|
4324
4299
|
const fixedAspect = mainCanvas.width / mainCanvas.height;
|
|
4325
|
-
mainCanvas.style.width
|
|
4326
|
-
mainCanvas.style.height = overlayCanvas.style.height = aspect < fixedAspect ? '' : '100%';
|
|
4327
|
-
if (glCanvas)
|
|
4328
|
-
{
|
|
4329
|
-
glCanvas.style.width = mainCanvas.style.width;
|
|
4330
|
-
glCanvas.style.height = mainCanvas.style.height;
|
|
4331
|
-
}
|
|
4300
|
+
(glCanvas||mainCanvas).style.width = mainCanvas.style.width = overlayCanvas.style.width = aspect < fixedAspect ? '100%' : '';
|
|
4301
|
+
(glCanvas||mainCanvas).style.height = mainCanvas.style.height = overlayCanvas.style.height = aspect < fixedAspect ? '' : '100%';
|
|
4332
4302
|
}
|
|
4333
4303
|
else
|
|
4334
4304
|
{
|
|
4335
|
-
|
|
4305
|
+
// clear canvas and set size to same as window
|
|
4336
4306
|
overlayCanvas.width = mainCanvas.width = min(innerWidth, canvasMaxSize.x);
|
|
4337
4307
|
overlayCanvas.height = mainCanvas.height = min(innerHeight, canvasMaxSize.y);
|
|
4338
4308
|
}
|
|
@@ -4399,7 +4369,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4399
4369
|
overlayContext.fillStyle = '#000';
|
|
4400
4370
|
const text = engineName + ' ' + 'v' + engineVersion + ' / '
|
|
4401
4371
|
+ drawCount + ' / ' + engineObjects.length + ' / ' + averageFPS.toFixed(1)
|
|
4402
|
-
+
|
|
4372
|
+
+ (glEnable ? ' GL' : ' 2D') ;
|
|
4403
4373
|
overlayContext.fillText(text, mainCanvas.width-3, 3);
|
|
4404
4374
|
overlayContext.fillStyle = '#fff';
|
|
4405
4375
|
overlayContext.fillText(text, mainCanvas.width-2, 2);
|
|
@@ -4413,7 +4383,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4413
4383
|
tileImageSource ? tileImage.src = tileImageSource : tileImage.onload();
|
|
4414
4384
|
}
|
|
4415
4385
|
|
|
4416
|
-
//
|
|
4386
|
+
// Called automatically by engine to setup render system
|
|
4417
4387
|
function enginePreRender()
|
|
4418
4388
|
{
|
|
4419
4389
|
// save canvas size
|
|
@@ -4423,12 +4393,10 @@ function enginePreRender()
|
|
|
4423
4393
|
mainContext.imageSmoothingEnabled = !cavasPixelated;
|
|
4424
4394
|
|
|
4425
4395
|
// setup gl rendering if enabled
|
|
4426
|
-
glEnable && glPreRender(
|
|
4396
|
+
glEnable && glPreRender();
|
|
4427
4397
|
}
|
|
4428
4398
|
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
/** Calls update on each engine object (recursively if child), removes destroyed objects, and updated time */
|
|
4399
|
+
/** Update each engine object, remove destroyed objects, and update time */
|
|
4432
4400
|
function engineObjectsUpdate()
|
|
4433
4401
|
{
|
|
4434
4402
|
// get list of solid objects for physics optimzation
|
|
@@ -4492,14 +4460,15 @@ function engineObjectsCallback(pos, size, callbackFunction, objects=engineObject
|
|
|
4492
4460
|
* <br> - Export engine as a module with extra functions where necessary
|
|
4493
4461
|
*/
|
|
4494
4462
|
|
|
4495
|
-
//
|
|
4463
|
+
// Setters for all variables that devs will need to modify
|
|
4496
4464
|
const setCameraPos = (v)=> cameraPos = v;
|
|
4497
4465
|
const setCameraScale = (v)=> cameraScale = v;
|
|
4498
|
-
const setRandSeed = (v)=> randSeed = v;
|
|
4499
4466
|
const setCanvasMaxSize = (v)=> canvasMaxSize = v;
|
|
4500
4467
|
const setCanvasFixedSize = (v)=> canvasFixedSize = v;
|
|
4501
4468
|
const setCavasPixelated = (v)=> cavasPixelated = v;
|
|
4502
4469
|
const setFontDefault = (v)=> fontDefault = v;
|
|
4470
|
+
const setGlEnable = (v)=> glEnable = v;
|
|
4471
|
+
const setGlOverlay = (v)=> glOverlay = v;
|
|
4503
4472
|
const setTileSizeDefault = (v)=> tileSizeDefault = v;
|
|
4504
4473
|
const setTileFixBleedScale = (v)=> tileFixBleedScale = v;
|
|
4505
4474
|
const setObjectDefaultSize = (v)=> objectDefaultSize = v;
|
|
@@ -4512,8 +4481,6 @@ const setObjectDefaultFriction = (v)=> objectDefaultFriction = v;
|
|
|
4512
4481
|
const setObjectMaxSpeed = (v)=> objectMaxSpeed = v;
|
|
4513
4482
|
const setGravity = (v)=> gravity = v;
|
|
4514
4483
|
const setParticleEmitRateScale = (v)=> particleEmitRateScale = v;
|
|
4515
|
-
const setGlEnable = (v)=> glEnable = v;
|
|
4516
|
-
const setGlOverlay = (v)=> glOverlay = v;
|
|
4517
4484
|
const setGamepadsEnable = (v)=> gamepadsEnable = v;
|
|
4518
4485
|
const setGamepadDirectionEmulateStick = (v)=> gamepadDirectionEmulateStick = v;
|
|
4519
4486
|
const setInputWASDEmulateDirection = (v)=> inputWASDEmulateDirection = v;
|
|
@@ -4522,28 +4489,26 @@ const setTouchGamepadAnalog = (v)=> touchGamepadAnalog = v;
|
|
|
4522
4489
|
const setTouchGamepadSize = (v)=> touchGamepadSize = v;
|
|
4523
4490
|
const setTouchGamepadAlpha = (v)=> touchGamepadAlpha = v;
|
|
4524
4491
|
const setVibrateEnable = (v)=> vibrateEnable = v;
|
|
4525
|
-
const setSoundVolume = (v)=> soundVolume = v;
|
|
4526
4492
|
const setSoundEnable = (v)=> soundEnable = v;
|
|
4493
|
+
const setSoundVolume = (v)=> soundVolume = v;
|
|
4527
4494
|
const setSoundDefaultRange = (v)=> soundDefaultRange = v;
|
|
4528
4495
|
const setSoundDefaultTaper = (v)=> soundDefaultTaper = v;
|
|
4529
4496
|
const setMedalDisplayTime = (v)=> medalDisplayTime = v;
|
|
4530
4497
|
const setMedalDisplaySlideTime = (v)=> medalDisplaySlideTime = v;
|
|
4531
|
-
const
|
|
4532
|
-
const setMedalDisplayHeight = (v)=> medalDisplayHeight = v;
|
|
4498
|
+
const setMedalDisplaySize = (v)=> medalDisplaySize = v;
|
|
4533
4499
|
const setMedalDisplayIconSize = (v)=> medalDisplayIconSize = v;
|
|
4534
4500
|
const setMedalsPreventUnlock = (v)=> medalsPreventUnlock = v;
|
|
4535
|
-
const setShowWatermark = (v)=> showWatermark = v;
|
|
4536
|
-
const setGodMode = (v)=> godMode = v;
|
|
4537
4501
|
|
|
4538
4502
|
export {
|
|
4539
|
-
//
|
|
4503
|
+
// Setters for global variables
|
|
4540
4504
|
setCameraPos,
|
|
4541
4505
|
setCameraScale,
|
|
4542
|
-
setRandSeed,
|
|
4543
4506
|
setCanvasMaxSize,
|
|
4544
4507
|
setCanvasFixedSize,
|
|
4545
4508
|
setCavasPixelated,
|
|
4546
4509
|
setFontDefault,
|
|
4510
|
+
setGlEnable,
|
|
4511
|
+
setGlOverlay,
|
|
4547
4512
|
setTileSizeDefault,
|
|
4548
4513
|
setTileFixBleedScale,
|
|
4549
4514
|
setObjectDefaultSize,
|
|
@@ -4556,8 +4521,6 @@ export {
|
|
|
4556
4521
|
setObjectMaxSpeed,
|
|
4557
4522
|
setGravity,
|
|
4558
4523
|
setParticleEmitRateScale,
|
|
4559
|
-
setGlEnable,
|
|
4560
|
-
setGlOverlay,
|
|
4561
4524
|
setGamepadsEnable,
|
|
4562
4525
|
setGamepadDirectionEmulateStick,
|
|
4563
4526
|
setInputWASDEmulateDirection,
|
|
@@ -4566,18 +4529,15 @@ export {
|
|
|
4566
4529
|
setTouchGamepadSize,
|
|
4567
4530
|
setTouchGamepadAlpha,
|
|
4568
4531
|
setVibrateEnable,
|
|
4569
|
-
setSoundVolume,
|
|
4570
4532
|
setSoundEnable,
|
|
4533
|
+
setSoundVolume,
|
|
4571
4534
|
setSoundDefaultRange,
|
|
4572
4535
|
setSoundDefaultTaper,
|
|
4573
4536
|
setMedalDisplayTime,
|
|
4574
4537
|
setMedalDisplaySlideTime,
|
|
4575
|
-
|
|
4576
|
-
setMedalDisplayHeight,
|
|
4538
|
+
setMedalDisplaySize,
|
|
4577
4539
|
setMedalDisplayIconSize,
|
|
4578
4540
|
setMedalsPreventUnlock,
|
|
4579
|
-
setShowWatermark,
|
|
4580
|
-
setGodMode,
|
|
4581
4541
|
|
|
4582
4542
|
// Settings
|
|
4583
4543
|
canvasMaxSize,
|
|
@@ -4608,14 +4568,13 @@ export {
|
|
|
4608
4568
|
touchGamepadSize,
|
|
4609
4569
|
touchGamepadAlpha,
|
|
4610
4570
|
vibrateEnable,
|
|
4611
|
-
soundVolume,
|
|
4612
4571
|
soundEnable,
|
|
4572
|
+
soundVolume,
|
|
4613
4573
|
soundDefaultRange,
|
|
4614
4574
|
soundDefaultTaper,
|
|
4615
4575
|
medalDisplayTime,
|
|
4616
4576
|
medalDisplaySlideTime,
|
|
4617
|
-
|
|
4618
|
-
medalDisplayHeight,
|
|
4577
|
+
medalDisplaySize,
|
|
4619
4578
|
medalDisplayIconSize,
|
|
4620
4579
|
|
|
4621
4580
|
// Globals
|
|
@@ -4669,6 +4628,7 @@ export {
|
|
|
4669
4628
|
randVector,
|
|
4670
4629
|
randColor,
|
|
4671
4630
|
randSeed,
|
|
4631
|
+
setRandSeed,
|
|
4672
4632
|
randSeeded,
|
|
4673
4633
|
|
|
4674
4634
|
// Utility Classes
|
|
@@ -4733,15 +4693,12 @@ export {
|
|
|
4733
4693
|
// onmousemove,
|
|
4734
4694
|
// onwheel,
|
|
4735
4695
|
// oncontextmenu,
|
|
4736
|
-
mouseToScreen,
|
|
4737
4696
|
//stickData,
|
|
4697
|
+
mouseToScreen,
|
|
4738
4698
|
gamepadsUpdate,
|
|
4739
4699
|
vibrate,
|
|
4740
4700
|
vibrateStop,
|
|
4741
4701
|
isTouchDevice,
|
|
4742
|
-
//touchGamepadTimer,
|
|
4743
|
-
touchGamepadCreate,
|
|
4744
|
-
touchGamepadRender,
|
|
4745
4702
|
|
|
4746
4703
|
// Audio
|
|
4747
4704
|
Sound,
|
|
@@ -4809,11 +4766,9 @@ export {
|
|
|
4809
4766
|
time,
|
|
4810
4767
|
timeReal,
|
|
4811
4768
|
paused,
|
|
4812
|
-
|
|
4813
|
-
drawCount,
|
|
4769
|
+
setPaused,
|
|
4814
4770
|
engineInit,
|
|
4815
|
-
|
|
4816
|
-
//engineObjectsUpdate,
|
|
4771
|
+
engineObjectsUpdate,
|
|
4817
4772
|
engineObjectsDestroy,
|
|
4818
4773
|
engineObjectsCallback,
|
|
4819
4774
|
};
|