littlejsengine 1.7.21 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -55
- package/build/littlejs.d.ts +101 -58
- package/build/littlejs.esm.js +497 -419
- package/build/littlejs.esm.min.js +1 -1
- package/build/littlejs.js +493 -228
- package/build/littlejs.min.js +1 -1
- package/build/littlejs.release.js +493 -228
- package/examples/breakout/game.js +17 -14
- package/examples/breakout/gameObjects.js +29 -8
- package/examples/breakout/index.html +3 -3
- package/examples/breakoutTutorial/README.md +2 -2
- package/examples/breakoutTutorial/game.js +4 -4
- package/examples/breakoutTutorial/index.html +2 -2
- package/examples/electron/game.js +3 -2
- package/examples/electron/index.html +2 -2
- package/examples/empty/game.js +1 -1
- package/examples/favicon.png +0 -0
- package/examples/js13k/game.js +20 -15
- package/examples/js13k/index.html +14 -14
- package/examples/module/game.js +4 -3
- package/examples/module/index.html +1 -1
- package/examples/particles/index.html +19 -22
- package/examples/platformer/game.js +3 -3
- package/examples/platformer/gameEffects.js +21 -19
- package/examples/platformer/gameLevel.js +6 -6
- package/examples/platformer/gameObjects.js +18 -18
- package/examples/platformer/gamePlayer.js +4 -3
- package/examples/platformer/index.html +6 -6
- package/examples/platformer/tiles.png +0 -0
- package/examples/platformer/tilesLevel.png +0 -0
- package/examples/puzzle/game.js +10 -8
- package/examples/puzzle/index.html +2 -2
- package/examples/screenshot.jpg +0 -0
- package/examples/starter/game.js +32 -21
- package/examples/starter/index.html +13 -13
- package/examples/starter/tiles.png +0 -0
- package/examples/stress/index.html +2 -2
- package/examples/typescript/game.js +4 -3
- package/examples/typescript/game.ts +4 -3
- package/examples/typescript/index.html +1 -1
- package/package.json +1 -1
- package/src/engine.js +59 -52
- package/src/engineDraw.js +137 -38
- package/src/engineExport.js +4 -191
- package/src/engineMedals.js +13 -45
- package/src/engineObject.js +12 -13
- package/src/engineParticles.js +17 -17
- package/src/engineSettings.js +195 -2
- package/src/engineTileLayer.js +23 -22
- package/src/engineUtilities.js +6 -6
- package/src/engineWebGL.js +31 -32
|
@@ -240,10 +240,10 @@ function randColor(colorA=new Color, colorB=new Color(0,0,0,1), linear)
|
|
|
240
240
|
* - Can be used to create a deterministic random number sequence
|
|
241
241
|
* @example
|
|
242
242
|
* let r = new RandomGenerator(123); // random number generator with seed 123
|
|
243
|
-
* let a = r.
|
|
244
|
-
* let b = r.
|
|
243
|
+
* let a = r.float(); // random value between 0 and 1
|
|
244
|
+
* let b = r.int(10); // random integer between 0 and 9
|
|
245
245
|
* r.seed = 123; // reset the seed
|
|
246
|
-
* let c = r.
|
|
246
|
+
* let c = r.float(); // the same value as a
|
|
247
247
|
*/
|
|
248
248
|
class RandomGenerator
|
|
249
249
|
{
|
|
@@ -272,18 +272,18 @@ class RandomGenerator
|
|
|
272
272
|
* @param {Number} valueA
|
|
273
273
|
* @param {Number} [valueB=0]
|
|
274
274
|
* @return {Number} */
|
|
275
|
-
int(valueA, valueB=0) { return Math.floor(this.
|
|
275
|
+
int(valueA, valueB=0) { return Math.floor(this.float(valueA, valueB)); }
|
|
276
276
|
|
|
277
277
|
/** Randomly returns either -1 or 1 deterministically
|
|
278
278
|
* @return {Number} */
|
|
279
|
-
sign() { return this.
|
|
279
|
+
sign() { return this.int(2) * 2 - 1; }
|
|
280
280
|
}
|
|
281
281
|
|
|
282
282
|
///////////////////////////////////////////////////////////////////////////////
|
|
283
283
|
|
|
284
284
|
/**
|
|
285
285
|
* Create a 2d vector, can take another Vector2 to copy, 2 scalars, or 1 scalar
|
|
286
|
-
* @param {Number} [x=0]
|
|
286
|
+
* @param {(Number|Vector2)} [x=0]
|
|
287
287
|
* @param {Number} [y=0]
|
|
288
288
|
* @return {Vector2}
|
|
289
289
|
* @example
|
|
@@ -767,7 +767,7 @@ let glOverlay = 1;
|
|
|
767
767
|
* @memberof Settings */
|
|
768
768
|
let tileSizeDefault = vec2(16);
|
|
769
769
|
|
|
770
|
-
/**
|
|
770
|
+
/** How many pixels smaller to draw tiles to prevent bleeding from neighbors
|
|
771
771
|
* @type {Number}
|
|
772
772
|
* @default
|
|
773
773
|
* @memberof Settings */
|
|
@@ -941,7 +941,200 @@ let medalDisplayIconSize = 50;
|
|
|
941
941
|
* @type {Boolean}
|
|
942
942
|
* @default 0
|
|
943
943
|
* @memberof Settings */
|
|
944
|
-
let medalsPreventUnlock;
|
|
944
|
+
let medalsPreventUnlock;
|
|
945
|
+
|
|
946
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
947
|
+
// Setters for global variables
|
|
948
|
+
|
|
949
|
+
/** Set position of camera in world space
|
|
950
|
+
* @param {Vector2} pos
|
|
951
|
+
* @memberof Settings */
|
|
952
|
+
function setCameraPos(pos) { cameraPos = pos; }
|
|
953
|
+
|
|
954
|
+
/** Set scale of camera in world space
|
|
955
|
+
* @param {Number} scale
|
|
956
|
+
* @memberof Settings */
|
|
957
|
+
function setCameraScale(scale) { cameraScale = scale; }
|
|
958
|
+
|
|
959
|
+
/** Set max size of the canvas
|
|
960
|
+
* @param {Vector2} size
|
|
961
|
+
* @memberof Settings */
|
|
962
|
+
function setCanvasMaxSize(size) { canvasMaxSize = size; }
|
|
963
|
+
|
|
964
|
+
/** Set fixed size of the canvas
|
|
965
|
+
* @param {Vector2} size
|
|
966
|
+
* @memberof Settings */
|
|
967
|
+
function setCanvasFixedSize(size) { canvasFixedSize = size; }
|
|
968
|
+
|
|
969
|
+
/** Disables anti aliasing for pixel art if true
|
|
970
|
+
* @param {Boolean} pixelated
|
|
971
|
+
* @memberof Settings */
|
|
972
|
+
function setCanvasPixelated(pixelated) { canvasPixelated = pixelated; }
|
|
973
|
+
|
|
974
|
+
/** Set default font used for text rendering
|
|
975
|
+
* @param {String} font
|
|
976
|
+
* @memberof Settings */
|
|
977
|
+
function setFontDefault(font) { fontDefault = font; }
|
|
978
|
+
|
|
979
|
+
/** Set if webgl rendering is enabled
|
|
980
|
+
* @param {Boolean} enable
|
|
981
|
+
* @memberof Settings */
|
|
982
|
+
function setGlEnable(enable) { glEnable = enable; }
|
|
983
|
+
|
|
984
|
+
/** Set to not composite the WebGL canvas
|
|
985
|
+
* @param {Boolean} overlay
|
|
986
|
+
* @memberof Settings */
|
|
987
|
+
function setGlOverlay(overlay) { glOverlay = overlay; }
|
|
988
|
+
|
|
989
|
+
/** Set default size of tiles in pixels
|
|
990
|
+
* @param {Vector2} size
|
|
991
|
+
* @memberof Settings */
|
|
992
|
+
function setTileSizeDefault(size) { tileSizeDefault = size; }
|
|
993
|
+
|
|
994
|
+
/** Set to prevent tile bleeding from neighbors in pixels
|
|
995
|
+
* @param {Number} scale
|
|
996
|
+
* @memberof Settings */
|
|
997
|
+
function setTileFixBleedScale(scale) { tileFixBleedScale = scale; }
|
|
998
|
+
|
|
999
|
+
/** Set if collisions between objects are enabled
|
|
1000
|
+
* @param {Boolean} enable
|
|
1001
|
+
* @memberof Settings */
|
|
1002
|
+
function setEnablePhysicsSolver(enable) { enablePhysicsSolver = enable; }
|
|
1003
|
+
|
|
1004
|
+
/** Set default object mass for collison calcuations
|
|
1005
|
+
* @param {Number} mass
|
|
1006
|
+
* @memberof Settings */
|
|
1007
|
+
function setObjectDefaultMass(mass) { objectDefaultMass = mass; }
|
|
1008
|
+
|
|
1009
|
+
/** Set how much to slow velocity by each frame
|
|
1010
|
+
* @param {Number} damping
|
|
1011
|
+
* @memberof Settings */
|
|
1012
|
+
function setObjectDefaultDamping(damp) { objectDefaultDamping = damp; }
|
|
1013
|
+
|
|
1014
|
+
/** Set how much to slow angular velocity each frame
|
|
1015
|
+
* @param {Number} damping
|
|
1016
|
+
* @memberof Settings */
|
|
1017
|
+
function setObjectDefaultAngleDamping(damp) { objectDefaultAngleDamping = damp; }
|
|
1018
|
+
|
|
1019
|
+
/** Set how much to bounce when a collision occur
|
|
1020
|
+
* @param {Number} elasticity
|
|
1021
|
+
* @memberof Settings */
|
|
1022
|
+
function setObjectDefaultElasticity(elasticity) { objectDefaultElasticity = elasticity; }
|
|
1023
|
+
|
|
1024
|
+
/** Set how much to slow when touching
|
|
1025
|
+
* @param {Number} friction
|
|
1026
|
+
* @memberof Settings */
|
|
1027
|
+
function setObjectDefaultFriction(friction) { objectDefaultFriction = friction; }
|
|
1028
|
+
|
|
1029
|
+
/** Set max speed to avoid fast objects missing collisions
|
|
1030
|
+
* @param {Number} speed
|
|
1031
|
+
* @memberof Settings */
|
|
1032
|
+
function setObjectMaxSpeed(speed) { objectMaxSpeed = speed; }
|
|
1033
|
+
|
|
1034
|
+
/** Set how much gravity to apply to objects along the Y axis
|
|
1035
|
+
* @param {Number} gravity
|
|
1036
|
+
* @memberof Settings */
|
|
1037
|
+
function setGravity(g) { gravity = g; }
|
|
1038
|
+
|
|
1039
|
+
/** Set to scales emit rate of particles
|
|
1040
|
+
* @param {Number} scale
|
|
1041
|
+
* @memberof Settings */
|
|
1042
|
+
function setParticleEmitRateScale(scale) { particleEmitRateScale = scale; }
|
|
1043
|
+
|
|
1044
|
+
/** Set if gamepads are enabled
|
|
1045
|
+
* @param {Boolean} enable
|
|
1046
|
+
* @memberof Settings */
|
|
1047
|
+
function setGamepadsEnable(enable) { gamepadsEnable = enable; }
|
|
1048
|
+
|
|
1049
|
+
/** Set if the dpad input is also routed to the left analog stick
|
|
1050
|
+
* @param {Boolean} enable
|
|
1051
|
+
* @memberof Settings */
|
|
1052
|
+
function setGamepadDirectionEmulateStick(enable) { gamepadDirectionEmulateStick = enable; }
|
|
1053
|
+
|
|
1054
|
+
/** Set if true the WASD keys are also routed to the direction keys
|
|
1055
|
+
* @param {Boolean} enable
|
|
1056
|
+
* @memberof Settings */
|
|
1057
|
+
function setInputWASDEmulateDirection(enable) { inputWASDEmulateDirection = enable; }
|
|
1058
|
+
|
|
1059
|
+
/** Set if touch gamepad should appear on mobile devices
|
|
1060
|
+
* @param {Boolean} enable
|
|
1061
|
+
* @memberof Settings */
|
|
1062
|
+
function setTouchGamepadEnable(enable) { touchGamepadEnable = enable; }
|
|
1063
|
+
|
|
1064
|
+
/** Set if touch gamepad should be analog stick or 8 way dpad
|
|
1065
|
+
* @param {Boolean} analog
|
|
1066
|
+
* @memberof Settings */
|
|
1067
|
+
function setTouchGamepadAnalog(analog) { touchGamepadAnalog = analog; }
|
|
1068
|
+
|
|
1069
|
+
/** Set size of virutal gamepad for touch devices in pixels
|
|
1070
|
+
* @param {Number} size
|
|
1071
|
+
* @memberof Settings */
|
|
1072
|
+
function setTouchGamepadSize(size) { touchGamepadSize = size; }
|
|
1073
|
+
|
|
1074
|
+
/** Set transparency of touch gamepad overlay
|
|
1075
|
+
* @param {Number} alpha
|
|
1076
|
+
* @memberof Settings */
|
|
1077
|
+
function setTouchGamepadAlpha(alpha) { touchGamepadAlpha = alpha; }
|
|
1078
|
+
|
|
1079
|
+
/** Set to allow vibration hardware if it exists
|
|
1080
|
+
* @param {Boolean} enable
|
|
1081
|
+
* @memberof Settings */
|
|
1082
|
+
function setVibrateEnable(enable) { vibrateEnable = enable; }
|
|
1083
|
+
|
|
1084
|
+
/** Set to disable all audio code
|
|
1085
|
+
* @param {Boolean} enable
|
|
1086
|
+
* @memberof Settings */
|
|
1087
|
+
function setSoundEnable(enable) { soundEnable = enable; }
|
|
1088
|
+
|
|
1089
|
+
/** Set volume scale to apply to all sound, music and speech
|
|
1090
|
+
* @param {Number} volume
|
|
1091
|
+
* @memberof Settings */
|
|
1092
|
+
function setSoundVolume(volume) { soundVolume = volume; }
|
|
1093
|
+
|
|
1094
|
+
/** Set default range where sound no longer plays
|
|
1095
|
+
* @param {Number} range
|
|
1096
|
+
* @memberof Settings */
|
|
1097
|
+
function setSoundDefaultRange(range) { soundDefaultRange = range; }
|
|
1098
|
+
|
|
1099
|
+
/** Set default range percent to start tapering off sound
|
|
1100
|
+
* @param {Number} taper
|
|
1101
|
+
* @memberof Settings */
|
|
1102
|
+
function setSoundDefaultTaper(taper) { soundDefaultTaper = taper; }
|
|
1103
|
+
|
|
1104
|
+
/** Set how long to show medals for in seconds
|
|
1105
|
+
* @param {Number} time
|
|
1106
|
+
* @memberof Settings */
|
|
1107
|
+
function setMedalDisplayTime(time) { medalDisplayTime = time; }
|
|
1108
|
+
|
|
1109
|
+
/** Set how quickly to slide on/off medals in seconds
|
|
1110
|
+
* @param {Number} time
|
|
1111
|
+
* @memberof Settings */
|
|
1112
|
+
function setMedalDisplaySlideTime(time) { medalDisplaySlideTime = time; }
|
|
1113
|
+
|
|
1114
|
+
/** Set size of medal display
|
|
1115
|
+
* @param {Vector2} size
|
|
1116
|
+
* @memberof Settings */
|
|
1117
|
+
function setMedalDisplaySize(size) { medalDisplaySize = size; }
|
|
1118
|
+
|
|
1119
|
+
/** Set size of icon in medal display
|
|
1120
|
+
* @param {Number} size
|
|
1121
|
+
* @memberof Settings */
|
|
1122
|
+
function setMedalDisplayIconSize(size) { medalDisplayIconSize = size; }
|
|
1123
|
+
|
|
1124
|
+
/** Set to stop medals from being unlockable
|
|
1125
|
+
* @param {Boolean} preventUnlock
|
|
1126
|
+
* @memberof Settings */
|
|
1127
|
+
function setMedalsPreventUnlock(preventUnlock) { medalsPreventUnlock = preventUnlock; }
|
|
1128
|
+
|
|
1129
|
+
/** Set if watermark with FPS should be shown
|
|
1130
|
+
* @param {Boolean} show
|
|
1131
|
+
* @memberof Debug */
|
|
1132
|
+
function setShowWatermark(show) { showWatermark = show; }
|
|
1133
|
+
|
|
1134
|
+
/** Set key code used to toggle debug mode, Esc by default
|
|
1135
|
+
* @param {Number} key
|
|
1136
|
+
* @memberof Debug */
|
|
1137
|
+
function setDebugKey(key) { debugKey = key; }
|
|
945
1138
|
/**
|
|
946
1139
|
* LittleJS Object System
|
|
947
1140
|
*/
|
|
@@ -976,18 +1169,19 @@ let medalsPreventUnlock;
|
|
|
976
1169
|
class EngineObject
|
|
977
1170
|
{
|
|
978
1171
|
/** Create an engine object and adds it to the list of objects
|
|
979
|
-
* @param {Vector2} [
|
|
980
|
-
* @param {Vector2} [size=Vector2(1,1)]
|
|
981
|
-
* @param {
|
|
982
|
-
* @param {
|
|
983
|
-
* @param {
|
|
984
|
-
* @param {
|
|
985
|
-
* @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
|
|
1172
|
+
* @param {Vector2} [pos=Vector2()] - World space position of the object
|
|
1173
|
+
* @param {Vector2} [size=Vector2(1,1)] - World space size of the object
|
|
1174
|
+
* @param {TileInfo} [tileInfo] - Tile info to render object (undefined is untextured)
|
|
1175
|
+
* @param {Number} [angle=0] - Angle the object is rotated by
|
|
1176
|
+
* @param {Color} [color=Color()] - Color to apply to tile when rendered
|
|
1177
|
+
* @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
|
|
986
1178
|
*/
|
|
987
|
-
constructor(pos=vec2(), size=vec2(1),
|
|
1179
|
+
constructor(pos=vec2(), size=vec2(1), tileInfo, angle=0, color, renderOrder=0)
|
|
988
1180
|
{
|
|
989
1181
|
// set passed in params
|
|
990
1182
|
ASSERT(isVector2(pos) && isVector2(size)); // ensure pos and size are vec2s
|
|
1183
|
+
ASSERT(typeof tileInfo !== 'number' || !tileInfo); // prevent old style calls
|
|
1184
|
+
// to fix old calls, replace with tile(tileIndex, tileSize)
|
|
991
1185
|
|
|
992
1186
|
/** @property {Vector2} - World space position of the object */
|
|
993
1187
|
this.pos = pos.copy();
|
|
@@ -995,10 +1189,8 @@ class EngineObject
|
|
|
995
1189
|
this.size = size;
|
|
996
1190
|
/** @property {Vector2} - Size of object used for drawing, uses size if not set */
|
|
997
1191
|
this.drawSize;
|
|
998
|
-
/** @property {
|
|
999
|
-
this.
|
|
1000
|
-
/** @property {Vector2} - Size of tile in source pixels */
|
|
1001
|
-
this.tileSize = tileSize;
|
|
1192
|
+
/** @property {TileInfo} - Tile info to render object (undefined is untextured) */
|
|
1193
|
+
this.tileInfo = tileInfo;
|
|
1002
1194
|
/** @property {Number} - Angle to rotate the object */
|
|
1003
1195
|
this.angle = angle;
|
|
1004
1196
|
/** @property {Color} - Color to apply when rendered */
|
|
@@ -1214,7 +1406,7 @@ class EngineObject
|
|
|
1214
1406
|
render()
|
|
1215
1407
|
{
|
|
1216
1408
|
// default object render
|
|
1217
|
-
drawTile(this.pos, this.drawSize || this.size, this.
|
|
1409
|
+
drawTile(this.pos, this.drawSize || this.size, this.tileInfo, this.color, this.angle, this.mirror, this.additiveColor);
|
|
1218
1410
|
}
|
|
1219
1411
|
|
|
1220
1412
|
/** Destroy this object, destroy it's children, detach it's parent, and mark it for removal */
|
|
@@ -1369,13 +1561,109 @@ let overlayContext;
|
|
|
1369
1561
|
* @memberof Draw */
|
|
1370
1562
|
let mainCanvasSize = vec2();
|
|
1371
1563
|
|
|
1372
|
-
/**
|
|
1373
|
-
* @type {
|
|
1564
|
+
/** Array containing texture info for batch rendering system
|
|
1565
|
+
* @type {Array}
|
|
1374
1566
|
* @memberof Draw */
|
|
1375
|
-
|
|
1567
|
+
let textureInfos = [];
|
|
1376
1568
|
|
|
1377
1569
|
// Engine internal variables not exposed to documentation
|
|
1378
|
-
let
|
|
1570
|
+
let drawCount;
|
|
1571
|
+
|
|
1572
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
1573
|
+
|
|
1574
|
+
/**
|
|
1575
|
+
* Create a tile info object
|
|
1576
|
+
* - This can take vecs or floats for easier use and conversion
|
|
1577
|
+
* - If an index is passed in, the tile size and index will determine the position
|
|
1578
|
+
* @param {(Number|Vector2)} [pos=Vector2()] - Top left corner of tile in pixels or index
|
|
1579
|
+
* @param {(Number|Vector2)} [size=tileSizeDefault] - Size of tile in pixels
|
|
1580
|
+
* @param {Number} [textureIndex=0] - Texture index to use
|
|
1581
|
+
* @return {TileInfo}
|
|
1582
|
+
* @example
|
|
1583
|
+
* tile(2) // a tile at index 2 using the default tile size of 16
|
|
1584
|
+
* tile(5, 8) // a tile at index 5 using a tile size of 8
|
|
1585
|
+
* tile(1, 16, 3) // a tile at index 1 of size 16 on texture 3
|
|
1586
|
+
* tile(vec2(4,8), vec2(30,10)) // a tile at pixel location (4,8) with a size of (30,10)
|
|
1587
|
+
* @memberof Draw
|
|
1588
|
+
*/
|
|
1589
|
+
function tile(pos=vec2(), size=tileSizeDefault, textureIndex=0)
|
|
1590
|
+
{
|
|
1591
|
+
// if size is a number, make it a vector
|
|
1592
|
+
if (size.x == undefined)
|
|
1593
|
+
{
|
|
1594
|
+
ASSERT(size > 0);
|
|
1595
|
+
size = vec2(size);
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
// if pos is a number, use it as a tile index
|
|
1599
|
+
if (pos.x == undefined)
|
|
1600
|
+
{
|
|
1601
|
+
const textureInfo = textureInfos[textureIndex];
|
|
1602
|
+
if (textureInfo)
|
|
1603
|
+
{
|
|
1604
|
+
const cols = textureInfo.size.x / size.x |0;
|
|
1605
|
+
pos = vec2((pos%cols)*size.x, (pos/cols|0)*size.y);
|
|
1606
|
+
}
|
|
1607
|
+
else
|
|
1608
|
+
pos = vec2();
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
// return a tile info object
|
|
1612
|
+
return new TileInfo(pos, size, textureIndex);
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
/**
|
|
1616
|
+
* Tile Info - Stores info about how to draw a tile
|
|
1617
|
+
*/
|
|
1618
|
+
class TileInfo
|
|
1619
|
+
{
|
|
1620
|
+
/** Create a tile info object
|
|
1621
|
+
* @param {Vector2} [pos=Vector2()] - Top left corner of tile in pixels
|
|
1622
|
+
* @param {Vector2} [size=tileSizeDefault] - Size of tile in pixels
|
|
1623
|
+
* @param {Number} [textureIndex=0] - Texture index to use
|
|
1624
|
+
*/
|
|
1625
|
+
constructor(pos=vec2(), size=tileSizeDefault, textureIndex=0)
|
|
1626
|
+
{
|
|
1627
|
+
/** @property {Vector2} - Top left corner of tile in pixels */
|
|
1628
|
+
this.pos = pos;
|
|
1629
|
+
/** @property {Vector2} - Size of tile in pixels */
|
|
1630
|
+
this.size = size;
|
|
1631
|
+
/** @property {Number} - Texture index to use */
|
|
1632
|
+
this.textureIndex = textureIndex;
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
/** Returns an offset copy of this tile, useful for animation
|
|
1636
|
+
* @param {Vector2} offset - Offset to apply in pixels
|
|
1637
|
+
* @return {TileInfo}
|
|
1638
|
+
*/
|
|
1639
|
+
offset(offset)
|
|
1640
|
+
{ return new TileInfo(this.pos.add(offset), this.size, this.textureIndex); }
|
|
1641
|
+
|
|
1642
|
+
/** Returns the texture info for this tile
|
|
1643
|
+
* @return {TextureInfo}
|
|
1644
|
+
*/
|
|
1645
|
+
getTextureInfo()
|
|
1646
|
+
{ return textureInfos[this.textureIndex]; }
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
/** Texture Info - Stores info about each texture */
|
|
1650
|
+
class TextureInfo
|
|
1651
|
+
{
|
|
1652
|
+
// create a TextureInfo, called automatically by the engine
|
|
1653
|
+
constructor(image)
|
|
1654
|
+
{
|
|
1655
|
+
/** @property {CanvasImageSource} - image source */
|
|
1656
|
+
this.image = image;
|
|
1657
|
+
/** @property {Vector2} - size of the image */
|
|
1658
|
+
this.size = vec2(image.width, image.height);
|
|
1659
|
+
/** @property {WebGLTexture} - webgl texture */
|
|
1660
|
+
this.glTexture = glEnable && glCreateTexture(image);
|
|
1661
|
+
/** @property {Vector2} - size to adjust tile to fix bleeding */
|
|
1662
|
+
this.fixBleedSize = vec2(tileFixBleedScale).divide(this.size);
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1666
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
1379
1667
|
|
|
1380
1668
|
/** Convert from screen to world space coordinates
|
|
1381
1669
|
* @param {Vector2} screenPos
|
|
@@ -1406,7 +1694,7 @@ function worldToScreen(worldPos)
|
|
|
1406
1694
|
/** Draw textured tile centered in world space, with color applied if using WebGL
|
|
1407
1695
|
* @param {Vector2} pos - Center of the tile in world space
|
|
1408
1696
|
* @param {Vector2} [size=Vector2(1,1)] - Size of the tile in world space
|
|
1409
|
-
* @param {
|
|
1697
|
+
* @param {TileInfo}[tileInfo] - Tile info to use, untextured if undefined
|
|
1410
1698
|
* @param {Vector2} [tileSize=tileSizeDefault] - Tile size in source pixels
|
|
1411
1699
|
* @param {Color} [color=Color()] - Color to modulate with
|
|
1412
1700
|
* @param {Number} [angle=0] - Angle to rotate by
|
|
@@ -1415,11 +1703,14 @@ function worldToScreen(worldPos)
|
|
|
1415
1703
|
* @param {Boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering
|
|
1416
1704
|
* @param {Boolean} [screenSpace=0] - If true the pos and size are in screen space
|
|
1417
1705
|
* @memberof Draw */
|
|
1418
|
-
function drawTile(pos, size=vec2(1),
|
|
1706
|
+
function drawTile(pos, size=vec2(1), tileInfo, color=new Color,
|
|
1419
1707
|
angle=0, mirror, additiveColor=new Color(0,0,0,0), useWebGL=glEnable, screenSpace)
|
|
1420
1708
|
{
|
|
1709
|
+
ASSERT(typeof tileInfo !== 'number' || !tileInfo); // prevent old style calls
|
|
1710
|
+
// to fix old calls, replace with tile(tileIndex, tileSize)
|
|
1711
|
+
|
|
1421
1712
|
showWatermark && ++drawCount;
|
|
1422
|
-
|
|
1713
|
+
const textureInfo = tileInfo && tileInfo.getTextureInfo();
|
|
1423
1714
|
if (glEnable && useWebGL)
|
|
1424
1715
|
{
|
|
1425
1716
|
if (screenSpace)
|
|
@@ -1428,46 +1719,48 @@ function drawTile(pos, size=vec2(1), tileIndex=-1, tileSize=tileSizeDefault, col
|
|
|
1428
1719
|
pos = screenToWorld(pos);
|
|
1429
1720
|
size = size.scale(1/cameraScale);
|
|
1430
1721
|
}
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
// if negative tile index or image not found, force untextured
|
|
1434
|
-
glDraw(pos.x, pos.y, size.x, size.y, angle, 0, 0, 0, 0, 0, color.rgbaInt());
|
|
1435
|
-
}
|
|
1436
|
-
else
|
|
1722
|
+
|
|
1723
|
+
if (textureInfo)
|
|
1437
1724
|
{
|
|
1438
1725
|
// calculate uvs and render
|
|
1439
|
-
const
|
|
1440
|
-
const
|
|
1441
|
-
const
|
|
1442
|
-
const
|
|
1443
|
-
|
|
1726
|
+
const x = tileInfo.pos.x / textureInfo.size.x;
|
|
1727
|
+
const y = tileInfo.pos.y / textureInfo.size.y;
|
|
1728
|
+
const w = tileInfo.size.x / textureInfo.size.x;
|
|
1729
|
+
const h = tileInfo.size.y / textureInfo.size.y;
|
|
1730
|
+
const tileImageFixBleed = textureInfo.fixBleedSize;
|
|
1731
|
+
glSetTexture(textureInfo.glTexture);
|
|
1444
1732
|
glDraw(pos.x, pos.y, mirror ? -size.x : size.x, size.y, angle,
|
|
1445
|
-
|
|
1446
|
-
|
|
1733
|
+
x + tileImageFixBleed.x, y + tileImageFixBleed.y,
|
|
1734
|
+
x - tileImageFixBleed.x + w, y - tileImageFixBleed.y + h,
|
|
1447
1735
|
color.rgbaInt(), additiveColor.rgbaInt());
|
|
1448
1736
|
}
|
|
1737
|
+
else
|
|
1738
|
+
{
|
|
1739
|
+
// if no tile info, force untextured
|
|
1740
|
+
glDraw(pos.x, pos.y, size.x, size.y, angle, 0, 0, 0, 0, 0, color.rgbaInt());
|
|
1741
|
+
}
|
|
1449
1742
|
}
|
|
1450
1743
|
else
|
|
1451
1744
|
{
|
|
1452
1745
|
// normal canvas 2D rendering method (slower)
|
|
1453
1746
|
drawCanvas2D(pos, size, angle, mirror, (context)=>
|
|
1454
1747
|
{
|
|
1455
|
-
if (
|
|
1748
|
+
if (textureInfo)
|
|
1456
1749
|
{
|
|
1457
|
-
//
|
|
1458
|
-
|
|
1459
|
-
|
|
1750
|
+
// calculate uvs and render
|
|
1751
|
+
const x = tileInfo.pos.x + tileFixBleedScale;
|
|
1752
|
+
const y = tileInfo.pos.y + tileFixBleedScale;
|
|
1753
|
+
const w = tileInfo.size.x - 2*tileFixBleedScale;
|
|
1754
|
+
const h = tileInfo.size.y - 2*tileFixBleedScale;
|
|
1755
|
+
context.globalAlpha = color.a; // only alpha is supported
|
|
1756
|
+
context.drawImage(textureInfo.image, x, y, w, h, -.5, -.5, 1, 1);
|
|
1757
|
+
context.globalAlpha = 1; // set back to full alpha
|
|
1460
1758
|
}
|
|
1461
1759
|
else
|
|
1462
1760
|
{
|
|
1463
|
-
//
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
const sY = (tileIndex/cols|0)*tileSize.y + tileFixBleedScale;
|
|
1467
|
-
const sWidth = tileSize.x - 2*tileFixBleedScale;
|
|
1468
|
-
const sHeight = tileSize.y - 2*tileFixBleedScale;
|
|
1469
|
-
context.globalAlpha = color.a; // only alpha is supported
|
|
1470
|
-
context.drawImage(tileImage, sX, sY, sWidth, sHeight, -.5, -.5, 1, 1);
|
|
1761
|
+
// if no tile info, force untextured
|
|
1762
|
+
context.fillStyle = color;
|
|
1763
|
+
context.fillRect(-.5, -.5, 1, 1);
|
|
1471
1764
|
}
|
|
1472
1765
|
}, undefined, screenSpace);
|
|
1473
1766
|
}
|
|
@@ -1482,7 +1775,7 @@ function drawTile(pos, size=vec2(1), tileIndex=-1, tileSize=tileSizeDefault, col
|
|
|
1482
1775
|
* @param {Boolean} [screenSpace=0]
|
|
1483
1776
|
* @memberof Draw */
|
|
1484
1777
|
function drawRect(pos, size, color, angle, useWebGL, screenSpace)
|
|
1485
|
-
{ drawTile(pos, size,
|
|
1778
|
+
{ drawTile(pos, size, undefined, color, angle, 0, undefined, useWebGL, screenSpace); }
|
|
1486
1779
|
|
|
1487
1780
|
/** Draw colored polygon using passed in points
|
|
1488
1781
|
* @param {Array} points - Array of Vector2 points
|
|
@@ -1627,10 +1920,9 @@ class FontImage
|
|
|
1627
1920
|
* @param {HTMLImageElement} [image] - Image for the font, if undefined default font is used
|
|
1628
1921
|
* @param {Vector2} [tileSize=vec2(8)] - Size of the font source tiles
|
|
1629
1922
|
* @param {Vector2} [paddingSize=vec2(0,1)] - How much extra space to add between characters
|
|
1630
|
-
* @param {Number} [startTileIndex=0] - Tile index in image where font starts
|
|
1631
1923
|
* @param {CanvasRenderingContext2D} [context=overlayContext] - context to draw to
|
|
1632
1924
|
*/
|
|
1633
|
-
constructor(image, tileSize=vec2(8), paddingSize=vec2(0,1),
|
|
1925
|
+
constructor(image, tileSize=vec2(8), paddingSize=vec2(0,1), context=overlayContext)
|
|
1634
1926
|
{
|
|
1635
1927
|
// load default font image
|
|
1636
1928
|
if (!engineFontImage)
|
|
@@ -1639,7 +1931,6 @@ class FontImage
|
|
|
1639
1931
|
this.image = image || engineFontImage;
|
|
1640
1932
|
this.tileSize = tileSize;
|
|
1641
1933
|
this.paddingSize = paddingSize;
|
|
1642
|
-
this.startTileIndex = startTileIndex;
|
|
1643
1934
|
this.context = context;
|
|
1644
1935
|
}
|
|
1645
1936
|
|
|
@@ -1680,7 +1971,7 @@ class FontImage
|
|
|
1680
1971
|
charCode = 127; // unknown character
|
|
1681
1972
|
|
|
1682
1973
|
// get the character source location and draw it
|
|
1683
|
-
const tile =
|
|
1974
|
+
const tile = charCode - 32;
|
|
1684
1975
|
const x = tile % cols;
|
|
1685
1976
|
const y = tile / cols |0;
|
|
1686
1977
|
const drawPos = pos.add(vec2(j,i).multiply(drawSize));
|
|
@@ -1712,8 +2003,7 @@ function toggleFullscreen()
|
|
|
1712
2003
|
}
|
|
1713
2004
|
else if (document.body.requestFullscreen)
|
|
1714
2005
|
document.body.requestFullscreen();
|
|
1715
|
-
}
|
|
1716
|
-
|
|
2006
|
+
}
|
|
1717
2007
|
/**
|
|
1718
2008
|
* LittleJS Input System
|
|
1719
2009
|
* - Tracks keyboard down, pressed, and released
|
|
@@ -2871,7 +3161,7 @@ class TileLayerData
|
|
|
2871
3161
|
}
|
|
2872
3162
|
|
|
2873
3163
|
/**
|
|
2874
|
-
* Tile
|
|
3164
|
+
* Tile Layer - cached rendering system for tile layers
|
|
2875
3165
|
* - Each Tile layer is rendered to an off screen canvas
|
|
2876
3166
|
* - To allow dynamic modifications, layers are rendered using canvas 2d
|
|
2877
3167
|
* - Some devices like mobile phones are limited to 4k texture resolution
|
|
@@ -2887,13 +3177,13 @@ class TileLayer extends EngineObject
|
|
|
2887
3177
|
/** Create a tile layer object
|
|
2888
3178
|
* @param {Vector2} [position=Vector2()] - World space position
|
|
2889
3179
|
* @param {Vector2} [size=tileCollisionSize] - World space size
|
|
2890
|
-
* @param {
|
|
3180
|
+
* @param {TileInfo} [tileInfo] - Tile info for layer
|
|
2891
3181
|
* @param {Vector2} [scale=Vector2(1,1)] - How much to scale this layer when rendered
|
|
2892
3182
|
* @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
|
|
2893
3183
|
*/
|
|
2894
|
-
constructor(pos, size=tileCollisionSize,
|
|
3184
|
+
constructor(pos, size=tileCollisionSize, tileInfo=tile(), scale=vec2(1), renderOrder=0)
|
|
2895
3185
|
{
|
|
2896
|
-
super(pos, size,
|
|
3186
|
+
super(pos, size, tileInfo, 0, undefined, renderOrder);
|
|
2897
3187
|
|
|
2898
3188
|
/** @property {HTMLCanvasElement} - The canvas used by this tile layer */
|
|
2899
3189
|
this.canvas = document.createElement('canvas');
|
|
@@ -2970,13 +3260,13 @@ constructor(pos, size=tileCollisionSize, tileSize=tileSizeDefault, scale=vec2(1)
|
|
|
2970
3260
|
mainCanvas = this.canvas;
|
|
2971
3261
|
mainContext = this.context;
|
|
2972
3262
|
cameraPos = this.size.scale(.5);
|
|
2973
|
-
cameraScale = this.
|
|
3263
|
+
cameraScale = this.tileInfo.size.x;
|
|
2974
3264
|
|
|
2975
3265
|
if (clear)
|
|
2976
3266
|
{
|
|
2977
3267
|
// clear and set size
|
|
2978
|
-
mainCanvas.width = this.size.x * this.
|
|
2979
|
-
mainCanvas.height = this.size.y * this.
|
|
3268
|
+
mainCanvas.width = this.size.x * this.tileInfo.size.x;
|
|
3269
|
+
mainCanvas.height = this.size.y * this.tileInfo.size.y;
|
|
2980
3270
|
}
|
|
2981
3271
|
|
|
2982
3272
|
// begin a new render for the tile canvas
|
|
@@ -3007,7 +3297,8 @@ constructor(pos, size=tileCollisionSize, tileSize=tileSizeDefault, scale=vec2(1)
|
|
|
3007
3297
|
if (d.tile != undefined)
|
|
3008
3298
|
{
|
|
3009
3299
|
ASSERT(mainContext == this.context); // must call redrawStart() before drawing tiles
|
|
3010
|
-
|
|
3300
|
+
const tileInfo = tile(d.tile, this.tileInfo.size, this.tileInfo.textureIndex);
|
|
3301
|
+
drawTile(pos, vec2(1), tileInfo, d.color, d.direction*PI/2, d.mirror);
|
|
3011
3302
|
}
|
|
3012
3303
|
}
|
|
3013
3304
|
|
|
@@ -3029,8 +3320,8 @@ constructor(pos, size=tileCollisionSize, tileSize=tileSizeDefault, scale=vec2(1)
|
|
|
3029
3320
|
{
|
|
3030
3321
|
const context = this.context;
|
|
3031
3322
|
context.save();
|
|
3032
|
-
pos = pos.subtract(this.pos).multiply(this.
|
|
3033
|
-
size = size.multiply(this.
|
|
3323
|
+
pos = pos.subtract(this.pos).multiply(this.tileInfo.size);
|
|
3324
|
+
size = size.multiply(this.tileInfo.size);
|
|
3034
3325
|
context.translate(pos.x, this.canvas.height - pos.y);
|
|
3035
3326
|
context.rotate(angle);
|
|
3036
3327
|
context.scale(mirror ? -size.x : size.x, size.y);
|
|
@@ -3041,28 +3332,28 @@ constructor(pos, size=tileCollisionSize, tileSize=tileSizeDefault, scale=vec2(1)
|
|
|
3041
3332
|
/** Draw a tile directly onto the layer canvas
|
|
3042
3333
|
* @param {Vector2} pos
|
|
3043
3334
|
* @param {Vector2} [size=Vector2(1,1)]
|
|
3044
|
-
* @param {
|
|
3045
|
-
* @param {Vector2} [tileSize=tileSizeDefault]
|
|
3335
|
+
* @param {TileInfo} [tileInfo]
|
|
3046
3336
|
* @param {Color} [color=Color()]
|
|
3047
3337
|
* @param {Number} [angle=0]
|
|
3048
3338
|
* @param {Boolean} [mirror=0] */
|
|
3049
|
-
drawTile(pos, size=vec2(1),
|
|
3339
|
+
drawTile(pos, size=vec2(1), tileInfo, color=new Color, angle, mirror)
|
|
3050
3340
|
{
|
|
3051
3341
|
this.drawCanvas2D(pos, size, angle, mirror, (context)=>
|
|
3052
3342
|
{
|
|
3053
|
-
|
|
3343
|
+
const textureInfo = tileInfo && tileInfo.getTextureInfo();
|
|
3344
|
+
if (textureInfo)
|
|
3054
3345
|
{
|
|
3055
|
-
//
|
|
3056
|
-
context.
|
|
3057
|
-
|
|
3346
|
+
context.globalAlpha = color.a; // only alpha is supported
|
|
3347
|
+
context.drawImage(textureInfo.image,
|
|
3348
|
+
tileInfo.pos.x, tileInfo.pos.y,
|
|
3349
|
+
tileInfo.size.x, tileInfo.size.y, -.5, -.5, 1, 1);
|
|
3350
|
+
context.globalAlpha = 1;
|
|
3058
3351
|
}
|
|
3059
3352
|
else
|
|
3060
3353
|
{
|
|
3061
|
-
|
|
3062
|
-
context.
|
|
3063
|
-
context.
|
|
3064
|
-
(tileIndex%cols)*tileSize.x, (tileIndex/cols|0)*tileSize.y,
|
|
3065
|
-
tileSize.x, tileSize.y, -.5, -.5, 1, 1);
|
|
3354
|
+
// untextured
|
|
3355
|
+
context.fillStyle = color;
|
|
3356
|
+
context.fillRect(-.5, -.5, 1, 1);
|
|
3066
3357
|
}
|
|
3067
3358
|
});
|
|
3068
3359
|
}
|
|
@@ -3090,7 +3381,7 @@ constructor(pos, size=tileCollisionSize, tileSize=tileSizeDefault, scale=vec2(1)
|
|
|
3090
3381
|
* let particleEmiter = new ParticleEmitter
|
|
3091
3382
|
* (
|
|
3092
3383
|
* pos, 0, 1, 0, 500, PI, // pos, angle, emitSize, emitTime, emitRate, emiteCone
|
|
3093
|
-
* 0,
|
|
3384
|
+
* tile(0, 16), // tileInfo
|
|
3094
3385
|
* new Color(1,1,1), new Color(0,0,0), // colorStartA, colorStartB
|
|
3095
3386
|
* new Color(1,1,1,0), new Color(0,0,0,0), // colorEndA, colorEndB
|
|
3096
3387
|
* 2, .2, .2, .1, .05, // particleTime, sizeStart, sizeEnd, particleSpeed, particleAngleSpeed
|
|
@@ -3107,8 +3398,7 @@ class ParticleEmitter extends EngineObject
|
|
|
3107
3398
|
* @param {Number} [emitTime=0] - How long to stay alive (0 is forever)
|
|
3108
3399
|
* @param {Number} [emitRate=100] - How many particles per second to spawn, does not emit if 0
|
|
3109
3400
|
* @param {Number} [emitConeAngle=PI] - Local angle to apply velocity to particles from emitter
|
|
3110
|
-
* @param {
|
|
3111
|
-
* @param {Vector2} [tileSize=tileSizeDefault] - Tile size for particles
|
|
3401
|
+
* @param {TileInfo} [tileInfo] - Tile info to render particles (undefined is untextured)
|
|
3112
3402
|
* @param {Color} [colorStartA=Color()] - Color at start of life 1, randomized between start colors
|
|
3113
3403
|
* @param {Color} [colorStartB=Color()] - Color at start of life 2, randomized between start colors
|
|
3114
3404
|
* @param {Color} [colorEndA=Color(1,1,1,0)] - Color at end of life 1, randomized between end colors
|
|
@@ -3138,8 +3428,7 @@ class ParticleEmitter extends EngineObject
|
|
|
3138
3428
|
emitTime = 0,
|
|
3139
3429
|
emitRate = 100,
|
|
3140
3430
|
emitConeAngle = PI,
|
|
3141
|
-
|
|
3142
|
-
tileSize = tileSizeDefault,
|
|
3431
|
+
tileInfo,
|
|
3143
3432
|
colorStartA = new Color,
|
|
3144
3433
|
colorStartB = new Color,
|
|
3145
3434
|
colorEndA = new Color(1,1,1,0),
|
|
@@ -3162,7 +3451,7 @@ class ParticleEmitter extends EngineObject
|
|
|
3162
3451
|
localSpace
|
|
3163
3452
|
)
|
|
3164
3453
|
{
|
|
3165
|
-
super(pos, vec2(),
|
|
3454
|
+
super(pos, vec2(), tileInfo, angle, undefined, renderOrder);
|
|
3166
3455
|
|
|
3167
3456
|
// emitter settings
|
|
3168
3457
|
/** @property {Number} - World space size of the emitter (float for circle diameter, vec2 for rect) */
|
|
@@ -3261,7 +3550,7 @@ class ParticleEmitter extends EngineObject
|
|
|
3261
3550
|
angle += this.angle;
|
|
3262
3551
|
}
|
|
3263
3552
|
|
|
3264
|
-
const particle = new Particle(pos, this.
|
|
3553
|
+
const particle = new Particle(pos, this.tileInfo, this.tileSize, angle);
|
|
3265
3554
|
|
|
3266
3555
|
// randomness scales each paremeter by a percentage
|
|
3267
3556
|
const randomness = this.randomness;
|
|
@@ -3321,12 +3610,11 @@ class Particle extends EngineObject
|
|
|
3321
3610
|
/**
|
|
3322
3611
|
* Create a particle with the given settings
|
|
3323
3612
|
* @param {Vector2} position - World space position of the particle
|
|
3324
|
-
* @param {
|
|
3325
|
-
* @param {Vector2} [tileSize=tileSizeDefault] - Size of tile in source pixels
|
|
3613
|
+
* @param {TileInfo} [tileInfo] - Tile info to render particles (undefined is untextured)
|
|
3326
3614
|
* @param {Number} [angle=0] - Angle to rotate the particle
|
|
3327
3615
|
*/
|
|
3328
|
-
constructor(pos,
|
|
3329
|
-
{ super(pos, vec2(),
|
|
3616
|
+
constructor(pos, tileInfo, angle)
|
|
3617
|
+
{ super(pos, vec2(), tileInfo, angle); }
|
|
3330
3618
|
|
|
3331
3619
|
/** Render the particle, automatically called each frame, sorted by renderOrder */
|
|
3332
3620
|
render()
|
|
@@ -3360,14 +3648,17 @@ class Particle extends EngineObject
|
|
|
3360
3648
|
if (this.localSpaceEmitter)
|
|
3361
3649
|
velocity = velocity.rotate(-this.localSpaceEmitter.angle);
|
|
3362
3650
|
const speed = velocity.length();
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3651
|
+
if (speed)
|
|
3652
|
+
{
|
|
3653
|
+
const direction = velocity.scale(1/speed);
|
|
3654
|
+
const trailLength = speed * this.trailScale;
|
|
3655
|
+
size.y = max(size.x, trailLength);
|
|
3656
|
+
angle = direction.angle();
|
|
3657
|
+
drawTile(pos.add(direction.multiply(vec2(0,-trailLength/2))), size, this.tileInfo, color, angle, this.mirror);
|
|
3658
|
+
}
|
|
3368
3659
|
}
|
|
3369
3660
|
else
|
|
3370
|
-
drawTile(pos, size, this.
|
|
3661
|
+
drawTile(pos, size, this.tileInfo, color, angle, this.mirror);
|
|
3371
3662
|
this.additive && setBlendMode();
|
|
3372
3663
|
debugParticles && debugRect(pos, size, '#f005', 0, angle);
|
|
3373
3664
|
|
|
@@ -3414,7 +3705,7 @@ function medalsInit(saveName)
|
|
|
3414
3705
|
}
|
|
3415
3706
|
|
|
3416
3707
|
/**
|
|
3417
|
-
* Medal
|
|
3708
|
+
* Medal - Tracks an unlockable medal
|
|
3418
3709
|
* @example
|
|
3419
3710
|
* // create a medal
|
|
3420
3711
|
* const medal_example = new Medal(0, 'Example Medal', 'More info about the medal goes here.', '🎖️');
|
|
@@ -3427,7 +3718,7 @@ function medalsInit(saveName)
|
|
|
3427
3718
|
*/
|
|
3428
3719
|
class Medal
|
|
3429
3720
|
{
|
|
3430
|
-
/** Create
|
|
3721
|
+
/** Create a medal object and adds it to the list of medals
|
|
3431
3722
|
* @param {Number} id - The unique identifier of the medal
|
|
3432
3723
|
* @param {String} name - Name of the medal
|
|
3433
3724
|
* @param {String} [description] - Description of the medal
|
|
@@ -3539,33 +3830,33 @@ let newgrounds;
|
|
|
3539
3830
|
/** This can used to enable Newgrounds functionality
|
|
3540
3831
|
* @param {Number} app_id - The newgrounds App ID
|
|
3541
3832
|
* @param {String} [cipher] - The encryption Key (AES-128/Base64)
|
|
3833
|
+
* @param {Object} [cryptoJS] - An instance of CryptoJS, if there is a cipher
|
|
3542
3834
|
* @memberof Medals */
|
|
3543
|
-
function newgroundsInit(app_id, cipher
|
|
3835
|
+
function newgroundsInit(app_id, cipher, cryptoJS)
|
|
3836
|
+
{ newgrounds = new Newgrounds(app_id, cipher, cryptoJS); }
|
|
3544
3837
|
|
|
3545
3838
|
/**
|
|
3546
3839
|
* Newgrounds API wrapper object
|
|
3547
3840
|
* @example
|
|
3548
|
-
* // create a newgrounds object, replace the app id
|
|
3841
|
+
* // create a newgrounds object, replace the app id with your own
|
|
3549
3842
|
* const app_id = '53123:1ZuSTQ9l';
|
|
3550
|
-
*
|
|
3551
|
-
* newgrounds = new Newgrounds(app_id, cipher);
|
|
3843
|
+
* newgrounds = new Newgrounds(app_id);
|
|
3552
3844
|
*/
|
|
3553
3845
|
class Newgrounds
|
|
3554
3846
|
{
|
|
3555
3847
|
/** Create a newgrounds object
|
|
3556
3848
|
* @param {Number} app_id - The newgrounds App ID
|
|
3557
|
-
* @param {String} [cipher] - The encryption Key (AES-128/Base64)
|
|
3558
|
-
|
|
3849
|
+
* @param {String} [cipher] - The encryption Key (AES-128/Base64)
|
|
3850
|
+
* @param {Object} [cryptoJS] - An instance of CryptoJS, if there is a cipher */
|
|
3851
|
+
constructor(app_id, cipher, cryptoJS)
|
|
3559
3852
|
{
|
|
3560
|
-
ASSERT(!newgrounds && app_id);
|
|
3853
|
+
ASSERT(!newgrounds && app_id); // can only be one newgrounds object
|
|
3854
|
+
ASSERT(!cipher || cryptoJS); // must provide cryptojs if there is a cipher
|
|
3561
3855
|
|
|
3562
3856
|
this.app_id = app_id;
|
|
3563
3857
|
this.cipher = cipher;
|
|
3858
|
+
this.cryptoJS = cryptoJS;
|
|
3564
3859
|
this.host = location ? location.hostname : '';
|
|
3565
|
-
|
|
3566
|
-
// create an instance of CryptoJS for encrypted calls
|
|
3567
|
-
if (cipher)
|
|
3568
|
-
this.cryptoJS = this.CryptoJS();
|
|
3569
3860
|
|
|
3570
3861
|
// get session id from url search params
|
|
3571
3862
|
const url = new URL(location.href);
|
|
@@ -3669,38 +3960,6 @@ class Newgrounds
|
|
|
3669
3960
|
debugMedals && console.log(xmlHttp.responseText);
|
|
3670
3961
|
return xmlHttp.responseText && JSON.parse(xmlHttp.responseText);
|
|
3671
3962
|
}
|
|
3672
|
-
|
|
3673
|
-
CryptoJS()
|
|
3674
|
-
{
|
|
3675
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
3676
|
-
// Crypto-JS - https://github.com/brix/crypto-js - MIT License
|
|
3677
|
-
//
|
|
3678
|
-
// [The MIT License (MIT)](http://opensource.org/licenses/MIT)
|
|
3679
|
-
//
|
|
3680
|
-
// Copyright (c) 2009-2013 Jeff Mott
|
|
3681
|
-
// Copyright (c) 2013-2016 Evan Vosberg
|
|
3682
|
-
//
|
|
3683
|
-
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
3684
|
-
// of this software and associated documentation files (the "Software"), to deal
|
|
3685
|
-
// in the Software without restriction, including without limitation the rights
|
|
3686
|
-
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
3687
|
-
// copies of the Software, and to permit persons to whom the Software is
|
|
3688
|
-
// furnished to do so, subject to the following conditions:
|
|
3689
|
-
//
|
|
3690
|
-
// The above copyright notice and this permission notice shall be included in
|
|
3691
|
-
// all copies or substantial portions of the Software.
|
|
3692
|
-
//
|
|
3693
|
-
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
3694
|
-
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
3695
|
-
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
3696
|
-
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
3697
|
-
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
3698
|
-
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
3699
|
-
// THE SOFTWARE.
|
|
3700
|
-
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));
|
|
3701
|
-
// end of Crypto-JS
|
|
3702
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
3703
|
-
}
|
|
3704
3963
|
}
|
|
3705
3964
|
/**
|
|
3706
3965
|
* LittleJS WebGL Interface
|
|
@@ -3710,6 +3969,7 @@ class Newgrounds
|
|
|
3710
3969
|
* - Can be disabled with glEnable to revert to 2D canvas rendering
|
|
3711
3970
|
* - Batches sprite rendering on GPU for incredibly fast performance
|
|
3712
3971
|
* - Sprite transform math is done in the shader where possible
|
|
3972
|
+
* - Supports shadertoy style post processing shaders
|
|
3713
3973
|
* @namespace WebGL
|
|
3714
3974
|
*/
|
|
3715
3975
|
|
|
@@ -3725,11 +3985,6 @@ let glCanvas;
|
|
|
3725
3985
|
* @memberof WebGL */
|
|
3726
3986
|
let glContext;
|
|
3727
3987
|
|
|
3728
|
-
/** Main tile sheet texture automatically loaded by engine
|
|
3729
|
-
* @type {WebGLTexture}
|
|
3730
|
-
* @memberof WebGL */
|
|
3731
|
-
let glTileTexture;
|
|
3732
|
-
|
|
3733
3988
|
// WebGL internal variables not exposed to documentation
|
|
3734
3989
|
let glActiveTexture, glShader, glArrayBuffer, glPositionData, glColorData, glBatchCount, glBatchAdditive, glAdditive;
|
|
3735
3990
|
|
|
@@ -3738,32 +3993,34 @@ let glActiveTexture, glShader, glArrayBuffer, glPositionData, glColorData, glBat
|
|
|
3738
3993
|
// Initalize WebGL, called automatically by the engine
|
|
3739
3994
|
function glInit()
|
|
3740
3995
|
{
|
|
3741
|
-
// create the canvas and
|
|
3996
|
+
// create the canvas and textures
|
|
3742
3997
|
glCanvas = document.createElement('canvas');
|
|
3743
|
-
glContext = glCanvas.getContext('
|
|
3744
|
-
glTileTexture = glCreateTexture(tileImage);
|
|
3998
|
+
glContext = glCanvas.getContext('webgl2');
|
|
3745
3999
|
|
|
3746
4000
|
// some browsers are much faster without copying the gl buffer so we just overlay it instead
|
|
3747
4001
|
glOverlay && document.body.appendChild(glCanvas);
|
|
3748
4002
|
|
|
3749
4003
|
// setup vertex and fragment shaders
|
|
3750
4004
|
glShader = glCreateProgram(
|
|
4005
|
+
'#version 300 es\n' + // specify GLSL ES version
|
|
3751
4006
|
'precision highp float;'+ // use highp for better accuracy
|
|
3752
4007
|
'uniform mat4 m;'+ // transform matrix
|
|
3753
|
-
'
|
|
3754
|
-
'
|
|
3755
|
-
'
|
|
4008
|
+
'in vec2 p,t;'+ // position, uv
|
|
4009
|
+
'in vec4 c,a;'+ // color, additiveColor
|
|
4010
|
+
'out vec4 v,d,e;'+ // return uv, color, additiveColor
|
|
3756
4011
|
'void main(){'+ // shader entry point
|
|
3757
4012
|
'gl_Position=m*vec4(p,1,1);'+ // transform position
|
|
3758
4013
|
'v=vec4(t,p);d=c;e=a;'+ // pass stuff to fragment shader
|
|
3759
4014
|
'}' // end of shader
|
|
3760
4015
|
,
|
|
3761
|
-
'
|
|
3762
|
-
'
|
|
3763
|
-
'
|
|
3764
|
-
'
|
|
3765
|
-
'
|
|
3766
|
-
'
|
|
4016
|
+
'#version 300 es\n' + // specify GLSL ES version
|
|
4017
|
+
'precision highp float;'+ // use highp for better accuracy
|
|
4018
|
+
'in vec4 v,d,e;'+ // uv, color, additiveColor
|
|
4019
|
+
'uniform sampler2D s;'+ // texture
|
|
4020
|
+
'out vec4 c;'+ // out color
|
|
4021
|
+
'void main(){'+ // shader entry point
|
|
4022
|
+
'c=texture(s,v.xy)*d+e;'+ // modulate texture by color plus additive
|
|
4023
|
+
'}' // end of shader
|
|
3767
4024
|
);
|
|
3768
4025
|
|
|
3769
4026
|
// init buffers
|
|
@@ -3784,7 +4041,7 @@ function glPreRender()
|
|
|
3784
4041
|
// set up the shader
|
|
3785
4042
|
glContext.useProgram(glShader);
|
|
3786
4043
|
glContext.activeTexture(gl_TEXTURE0);
|
|
3787
|
-
glContext.bindTexture(gl_TEXTURE_2D, glActiveTexture =
|
|
4044
|
+
glContext.bindTexture(gl_TEXTURE_2D, glActiveTexture = textureInfos[0].glTexture);
|
|
3788
4045
|
glContext.bindBuffer(gl_ARRAY_BUFFER, glArrayBuffer);
|
|
3789
4046
|
glContext.bufferData(gl_ARRAY_BUFFER, gl_VERTEX_BUFFER_SIZE, gl_DYNAMIC_DRAW);
|
|
3790
4047
|
glSetBlendMode();
|
|
@@ -3819,22 +4076,23 @@ function glPreRender()
|
|
|
3819
4076
|
/** Set the WebGl blend mode, normally you should call setBlendMode instead
|
|
3820
4077
|
* @param {Boolean} [additive=0]
|
|
3821
4078
|
* @memberof WebGL */
|
|
3822
|
-
function glSetBlendMode(additive)
|
|
4079
|
+
function glSetBlendMode(additive=0)
|
|
3823
4080
|
{
|
|
3824
4081
|
// setup blending
|
|
3825
4082
|
glAdditive = additive;
|
|
3826
4083
|
}
|
|
3827
4084
|
|
|
3828
|
-
/** Set the WebGl texture,
|
|
4085
|
+
/** Set the WebGl texture, called automatically if using multiple textures
|
|
3829
4086
|
* - This may also flush the gl buffer resulting in more draw calls and worse performance
|
|
3830
|
-
* @param {WebGLTexture}
|
|
4087
|
+
* @param {WebGLTexture} texture
|
|
3831
4088
|
* @memberof WebGL */
|
|
3832
|
-
function glSetTexture(texture
|
|
4089
|
+
function glSetTexture(texture)
|
|
3833
4090
|
{
|
|
3834
4091
|
// must flush cache with the old texture to set a new one
|
|
3835
|
-
if (texture
|
|
3836
|
-
|
|
4092
|
+
if (texture == glActiveTexture)
|
|
4093
|
+
return;
|
|
3837
4094
|
|
|
4095
|
+
glFlush();
|
|
3838
4096
|
glContext.bindTexture(gl_TEXTURE_2D, glActiveTexture = texture);
|
|
3839
4097
|
}
|
|
3840
4098
|
|
|
@@ -4013,25 +4271,28 @@ function glInitPostProcess(shaderCode, includeOverlay)
|
|
|
4013
4271
|
{
|
|
4014
4272
|
ASSERT(!glPostShader); // can only have 1 post effects shader
|
|
4015
4273
|
|
|
4016
|
-
if (!shaderCode) // default shader
|
|
4017
|
-
shaderCode = 'void mainImage(out vec4 c,vec2 p){c=
|
|
4274
|
+
if (!shaderCode) // default shader pass through
|
|
4275
|
+
shaderCode = 'void mainImage(out vec4 c,vec2 p){c=texture(iChannel0,p/iResolution.xy);}';
|
|
4018
4276
|
|
|
4019
4277
|
// create the shader
|
|
4020
4278
|
glPostShader = glCreateProgram(
|
|
4279
|
+
'#version 300 es\n' + // specify GLSL ES version
|
|
4021
4280
|
'precision highp float;'+ // use highp for better accuracy
|
|
4022
|
-
'
|
|
4281
|
+
'in vec2 p;'+ // position
|
|
4023
4282
|
'void main(){'+ // shader entry point
|
|
4024
4283
|
'gl_Position=vec4(p,1,1);'+ // set position
|
|
4025
4284
|
'}' // end of shader
|
|
4026
4285
|
,
|
|
4286
|
+
'#version 300 es\n' + // specify GLSL ES version
|
|
4027
4287
|
'precision highp float;'+ // use highp for better accuracy
|
|
4028
4288
|
'uniform sampler2D iChannel0;'+ // input texture
|
|
4029
4289
|
'uniform vec3 iResolution;'+ // size of output texture
|
|
4030
4290
|
'uniform float iTime;'+ // time passed
|
|
4291
|
+
'out vec4 c;'+ // out color
|
|
4031
4292
|
'\n' + shaderCode + '\n'+ // insert custom shader code
|
|
4032
4293
|
'void main(){'+ // shader entry point
|
|
4033
|
-
'mainImage(
|
|
4034
|
-
'
|
|
4294
|
+
'mainImage(c,gl_FragCoord.xy);'+ // call post process function
|
|
4295
|
+
'c.a=1.;'+ // always use full alpha
|
|
4035
4296
|
'}' // end of shader
|
|
4036
4297
|
);
|
|
4037
4298
|
|
|
@@ -4104,7 +4365,6 @@ gl_ONE_MINUS_SRC_ALPHA = 771,
|
|
|
4104
4365
|
gl_BLEND = 3042,
|
|
4105
4366
|
gl_TEXTURE_2D = 3553,
|
|
4106
4367
|
gl_UNSIGNED_BYTE = 5121,
|
|
4107
|
-
gl_BYTE = 5120,
|
|
4108
4368
|
gl_FLOAT = 5126,
|
|
4109
4369
|
gl_RGBA = 6408,
|
|
4110
4370
|
gl_NEAREST = 9728,
|
|
@@ -4116,7 +4376,6 @@ gl_TEXTURE_WRAP_T = 10243,
|
|
|
4116
4376
|
gl_COLOR_BUFFER_BIT = 16384,
|
|
4117
4377
|
gl_CLAMP_TO_EDGE = 33071,
|
|
4118
4378
|
gl_TEXTURE0 = 33984,
|
|
4119
|
-
gl_TEXTURE1 = 33985,
|
|
4120
4379
|
gl_ARRAY_BUFFER = 34962,
|
|
4121
4380
|
gl_STATIC_DRAW = 35044,
|
|
4122
4381
|
gl_DYNAMIC_DRAW = 35048,
|
|
@@ -4127,7 +4386,6 @@ gl_LINK_STATUS = 35714,
|
|
|
4127
4386
|
gl_UNPACK_FLIP_Y_WEBGL = 37440,
|
|
4128
4387
|
|
|
4129
4388
|
// constants for batch rendering
|
|
4130
|
-
gl_VERTICES_PER_QUAD = 6,
|
|
4131
4389
|
gl_INDICIES_PER_VERT = 6,
|
|
4132
4390
|
gl_MAX_BATCH = 1e5,
|
|
4133
4391
|
gl_VERTEX_BYTE_STRIDE = (4 * 2) * 2 + (4) * 2, // vec2 * 2 + (char * 4) * 2
|
|
@@ -4164,7 +4422,7 @@ const engineName = 'LittleJS';
|
|
|
4164
4422
|
* @type {String}
|
|
4165
4423
|
* @default
|
|
4166
4424
|
* @memberof Engine */
|
|
4167
|
-
const engineVersion = '1.
|
|
4425
|
+
const engineVersion = '1.8.1';
|
|
4168
4426
|
|
|
4169
4427
|
/** Frames per second to update objects
|
|
4170
4428
|
* @type {Number}
|
|
@@ -4214,6 +4472,9 @@ let paused = 0;
|
|
|
4214
4472
|
* @memberof Engine */
|
|
4215
4473
|
function setPaused(_paused) { paused = _paused; }
|
|
4216
4474
|
|
|
4475
|
+
// Frame time tracking
|
|
4476
|
+
let frameTimeLastMS = 0, frameTimeBufferMS = 0, averageFPS = 0;
|
|
4477
|
+
|
|
4217
4478
|
///////////////////////////////////////////////////////////////////////////////
|
|
4218
4479
|
|
|
4219
4480
|
/** Start up LittleJS engine with your callback functions
|
|
@@ -4222,52 +4483,13 @@ function setPaused(_paused) { paused = _paused; }
|
|
|
4222
4483
|
* @param {Function} gameUpdatePost - Called after physics and objects are updated, setup camera and prepare for render
|
|
4223
4484
|
* @param {Function} gameRender - Called before objects are rendered, draw any background effects that appear behind objects
|
|
4224
4485
|
* @param {Function} gameRenderPost - Called after objects are rendered, draw effects or hud that appear above all objects
|
|
4225
|
-
* @param {String} [
|
|
4486
|
+
* @param {String} [imageSources='tiles.png'] - Image to load
|
|
4226
4487
|
* @memberof Engine */
|
|
4227
|
-
function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost,
|
|
4488
|
+
function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, imageSources=['tiles.png'])
|
|
4228
4489
|
{
|
|
4229
|
-
//
|
|
4230
|
-
tileImage.onerror = tileImage.onload = ()=>
|
|
4231
|
-
{
|
|
4232
|
-
// save tile image info
|
|
4233
|
-
tileImageFixBleed = vec2(tileFixBleedScale).divide(tileImageSize = vec2(tileImage.width, tileImage.height));
|
|
4234
|
-
debug && (tileImage.onload=()=>ASSERT(1)); // tile sheet can not reloaded
|
|
4235
|
-
|
|
4236
|
-
// setup html
|
|
4237
|
-
const styleBody =
|
|
4238
|
-
'margin:0;overflow:hidden;' + // fill the window
|
|
4239
|
-
'background:#000;' + // set background color
|
|
4240
|
-
'touch-action:none;' + // prevent mobile pinch to resize
|
|
4241
|
-
'user-select:none;' + // prevent mobile hold to select
|
|
4242
|
-
'-webkit-user-select:none;' + // compatibility for ios
|
|
4243
|
-
'-webkit-touch-callout:none'; // compatibility for ios
|
|
4244
|
-
document.body.style = styleBody;
|
|
4245
|
-
document.body.appendChild(mainCanvas = document.createElement('canvas'));
|
|
4246
|
-
mainContext = mainCanvas.getContext('2d');
|
|
4247
|
-
|
|
4248
|
-
// init stuff and start engine
|
|
4249
|
-
debugInit();
|
|
4250
|
-
glEnable && glInit();
|
|
4251
|
-
|
|
4252
|
-
// create overlay canvas for hud to appear above gl canvas
|
|
4253
|
-
document.body.appendChild(overlayCanvas = document.createElement('canvas'));
|
|
4254
|
-
overlayContext = overlayCanvas.getContext('2d');
|
|
4255
|
-
|
|
4256
|
-
// set canvas style
|
|
4257
|
-
const styleCanvas =
|
|
4258
|
-
'position:absolute;' + // position canvas
|
|
4259
|
-
'top:50%;left:50%;transform:translate(-50%,-50%);' + // center the canvas
|
|
4260
|
-
(canvasPixelated?'image-rendering:pixelated':''); // set pixelated rendering
|
|
4261
|
-
(glCanvas||mainCanvas).style = mainCanvas.style = overlayCanvas.style = styleCanvas;
|
|
4262
|
-
|
|
4263
|
-
gameInit();
|
|
4264
|
-
engineUpdate();
|
|
4265
|
-
};
|
|
4490
|
+
ASSERT(Array.isArray(imageSources)); // pass in images as array
|
|
4266
4491
|
|
|
4267
|
-
//
|
|
4268
|
-
let frameTimeLastMS = 0, frameTimeBufferMS = 0, averageFPS = 0;
|
|
4269
|
-
|
|
4270
|
-
// main update loop
|
|
4492
|
+
// internal update loop for engine
|
|
4271
4493
|
function engineUpdate(frameTimeMS=0)
|
|
4272
4494
|
{
|
|
4273
4495
|
// update time keeping
|
|
@@ -4298,9 +4520,9 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4298
4520
|
}
|
|
4299
4521
|
else
|
|
4300
4522
|
{
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4523
|
+
// clear canvas and set size to same as window
|
|
4524
|
+
mainCanvas.width = min(innerWidth, canvasMaxSize.x);
|
|
4525
|
+
mainCanvas.height = min(innerHeight, canvasMaxSize.y);
|
|
4304
4526
|
}
|
|
4305
4527
|
|
|
4306
4528
|
// clear overlay canvas and set size
|
|
@@ -4332,6 +4554,9 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4332
4554
|
// update multiple frames if necessary in case of slow framerate
|
|
4333
4555
|
for (;frameTimeBufferMS >= 0; frameTimeBufferMS -= 1e3 / frameRate)
|
|
4334
4556
|
{
|
|
4557
|
+
// increment frame and update time
|
|
4558
|
+
time = frame++ / frameRate;
|
|
4559
|
+
|
|
4335
4560
|
// update game and objects
|
|
4336
4561
|
inputUpdate();
|
|
4337
4562
|
gameUpdate();
|
|
@@ -4379,8 +4604,51 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4379
4604
|
requestAnimationFrame(engineUpdate);
|
|
4380
4605
|
}
|
|
4381
4606
|
|
|
4382
|
-
//
|
|
4383
|
-
|
|
4607
|
+
// setup html
|
|
4608
|
+
const styleBody =
|
|
4609
|
+
'margin:0;overflow:hidden;' + // fill the window
|
|
4610
|
+
'background:#000;' + // set background color
|
|
4611
|
+
'touch-action:none;' + // prevent mobile pinch to resize
|
|
4612
|
+
'user-select:none;' + // prevent mobile hold to select
|
|
4613
|
+
'-webkit-user-select:none;' + // compatibility for ios
|
|
4614
|
+
'-webkit-touch-callout:none'; // compatibility for ios
|
|
4615
|
+
document.body.style = styleBody;
|
|
4616
|
+
document.body.appendChild(mainCanvas = document.createElement('canvas'));
|
|
4617
|
+
mainContext = mainCanvas.getContext('2d');
|
|
4618
|
+
|
|
4619
|
+
// init stuff and start engine
|
|
4620
|
+
debugInit();
|
|
4621
|
+
glEnable && glInit();
|
|
4622
|
+
|
|
4623
|
+
// create overlay canvas for hud to appear above gl canvas
|
|
4624
|
+
document.body.appendChild(overlayCanvas = document.createElement('canvas'));
|
|
4625
|
+
overlayContext = overlayCanvas.getContext('2d');
|
|
4626
|
+
|
|
4627
|
+
// set canvas style
|
|
4628
|
+
const styleCanvas =
|
|
4629
|
+
'position:absolute;' + // position
|
|
4630
|
+
'top:50%;left:50%;transform:translate(-50%,-50%);' + // center
|
|
4631
|
+
(canvasPixelated?'image-rendering:pixelated':''); // pixelated rendering
|
|
4632
|
+
(glCanvas||mainCanvas).style = mainCanvas.style = overlayCanvas.style = styleCanvas;
|
|
4633
|
+
|
|
4634
|
+
// load all of the images
|
|
4635
|
+
Promise.all(imageSources.map((src, textureIndex)=>
|
|
4636
|
+
new Promise((resolve, reject)=>
|
|
4637
|
+
{
|
|
4638
|
+
const image = new Image;
|
|
4639
|
+
image.onerror = image.onload = ()=>
|
|
4640
|
+
{
|
|
4641
|
+
textureInfos[textureIndex] = new TextureInfo(image);
|
|
4642
|
+
resolve();
|
|
4643
|
+
}
|
|
4644
|
+
image.src = src;
|
|
4645
|
+
})
|
|
4646
|
+
)).then(()=>
|
|
4647
|
+
{
|
|
4648
|
+
// start the engine
|
|
4649
|
+
gameInit();
|
|
4650
|
+
engineUpdate();
|
|
4651
|
+
});
|
|
4384
4652
|
}
|
|
4385
4653
|
|
|
4386
4654
|
// Called automatically by engine to setup render system
|
|
@@ -4418,9 +4686,6 @@ function engineObjectsUpdate()
|
|
|
4418
4686
|
|
|
4419
4687
|
// remove destroyed objects
|
|
4420
4688
|
engineObjects = engineObjects.filter(o=>!o.destroyed);
|
|
4421
|
-
|
|
4422
|
-
// increment frame and update time
|
|
4423
|
-
time = ++frame / frameRate;
|
|
4424
4689
|
}
|
|
4425
4690
|
|
|
4426
4691
|
/** Destroy and remove all objects
|