littlejsengine 1.11.2 → 1.11.5
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/.vscode/launch.json +14 -0
- package/README.md +16 -18
- package/dist/littlejs.d.ts +41 -30
- package/dist/littlejs.esm.js +165 -143
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +161 -142
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +157 -135
- package/examples/box2d/gameObjects.js +4 -4
- package/examples/box2d/scenes.js +2 -2
- package/examples/breakout/game.js +1 -1
- package/examples/breakout/gameObjects.js +28 -29
- package/examples/breakout/index.html +1 -1
- package/examples/breakoutTutorial/game.js +1 -1
- package/examples/index.html +1 -7
- package/examples/logo.png +0 -0
- package/examples/module/game.js +1 -1
- package/examples/platformer/game.js +2 -2
- package/examples/platformer/gameCharacter.js +5 -5
- package/examples/platformer/gameEffects.js +4 -4
- package/examples/platformer/gameObjects.js +2 -2
- package/examples/puzzle/game.js +3 -3
- package/examples/starter/game.js +11 -45
- package/examples/starter/tiles.png +0 -0
- package/jsconfig.json +1 -0
- package/package.json +1 -1
- package/plugins/box2d.js +10 -10
- package/plugins/newgrounds.js +1 -1
- package/plugins/postProcess.js +8 -8
- package/shortExamples/base.html +36 -0
- package/shortExamples/code/blending.js +12 -0
- package/shortExamples/code/helloWorld.js +7 -0
- package/shortExamples/code/particles.js +28 -0
- package/shortExamples/code/playSound.js +36 -0
- package/shortExamples/code/pong.js +40 -0
- package/shortExamples/code/shapes.js +24 -0
- package/shortExamples/code/spriteAtlas.js +27 -0
- package/shortExamples/code/systemFont.js +14 -0
- package/shortExamples/code/texture.js +12 -0
- package/shortExamples/code/tileLayer.js +50 -0
- package/shortExamples/index.html +242 -0
- package/shortExamples/tiles.png +0 -0
- package/src/engine.js +17 -3
- package/src/engineAudio.js +4 -4
- package/src/engineBuild.js +2 -1
- package/src/engineDebug.js +4 -7
- package/src/engineDraw.js +50 -25
- package/src/engineExport.js +4 -1
- package/src/engineInput.js +1 -1
- package/src/engineObject.js +8 -8
- package/src/engineParticles.js +7 -7
- package/src/engineSettings.js +5 -5
- package/src/engineTileLayer.js +6 -2
- package/src/engineUtilities.js +5 -5
- package/src/engineWebGL.js +52 -74
- package/examples/electron/build.js +0 -107
- package/examples/electron/electron.js +0 -43
- package/examples/electron/game.js +0 -131
- package/examples/electron/index.html +0 -13
- package/examples/electron/package.json +0 -22
- package/examples/electron/tiles.png +0 -0
- package/examples/js13k/build.bat +0 -2
- package/examples/js13k/build.js +0 -131
- package/examples/js13k/game.js +0 -118
- package/examples/js13k/index.html +0 -21
- package/examples/js13k/tiles.png +0 -0
- package/examples/typescript/build.bat +0 -5
- package/examples/typescript/build.js +0 -33
- package/examples/typescript/game.js +0 -102
- package/examples/typescript/game.ts +0 -134
- package/examples/typescript/index.html +0 -10
- package/examples/typescript/tiles.png +0 -0
- package/examples/typescript/tsconfig.json +0 -8
package/dist/littlejs.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
// LittleJS - MIT License - Copyright 2021 Frank Force
|
|
1
|
+
// LittleJS Engine - MIT License - Copyright 2021 Frank Force
|
|
2
|
+
// https://github.com/KilledByAPixel/LittleJS
|
|
2
3
|
|
|
3
4
|
'use strict';
|
|
4
5
|
|
|
@@ -20,7 +21,7 @@
|
|
|
20
21
|
* @memberof Debug */
|
|
21
22
|
const debug = true;
|
|
22
23
|
|
|
23
|
-
/** True if asserts are
|
|
24
|
+
/** True if asserts are enabled
|
|
24
25
|
* @type {Boolean}
|
|
25
26
|
* @default
|
|
26
27
|
* @memberof Debug */
|
|
@@ -204,6 +205,7 @@ function debugShowErrors()
|
|
|
204
205
|
const showError = (message)=>
|
|
205
206
|
{
|
|
206
207
|
// replace entire page with error message
|
|
208
|
+
document.body.style.display = '';
|
|
207
209
|
document.body.style.backgroundColor = '#111';
|
|
208
210
|
document.body.innerHTML = `<pre style=color:#f00;font-size:50px>` + message;
|
|
209
211
|
}
|
|
@@ -248,12 +250,8 @@ function debugRender()
|
|
|
248
250
|
|
|
249
251
|
if (debugTakeScreenshot)
|
|
250
252
|
{
|
|
251
|
-
//
|
|
252
|
-
|
|
253
|
-
mainContext.drawImage(overlayCanvas, 0, 0);
|
|
254
|
-
overlayCanvas.width |= 0;
|
|
255
|
-
|
|
256
|
-
// remove alpha and save
|
|
253
|
+
// combine canvases, remove alpha and save
|
|
254
|
+
combineCanvases();
|
|
257
255
|
const w = mainCanvas.width, h = mainCanvas.height;
|
|
258
256
|
overlayContext.fillRect(0,0,w,h);
|
|
259
257
|
overlayContext.drawImage(mainCanvas, 0, 0);
|
|
@@ -486,7 +484,7 @@ function debugRender()
|
|
|
486
484
|
* @memberof Utilities */
|
|
487
485
|
const PI = Math.PI;
|
|
488
486
|
|
|
489
|
-
/** Returns
|
|
487
|
+
/** Returns absolute value of value passed in
|
|
490
488
|
* @param {Number} value
|
|
491
489
|
* @return {Number}
|
|
492
490
|
* @memberof Utilities */
|
|
@@ -519,7 +517,7 @@ function sign(value) { return Math.sign(value); }
|
|
|
519
517
|
* @memberof Utilities */
|
|
520
518
|
function mod(dividend, divisor=1) { return ((dividend % divisor) + divisor) % divisor; }
|
|
521
519
|
|
|
522
|
-
/** Clamps the value
|
|
520
|
+
/** Clamps the value between max and min
|
|
523
521
|
* @param {Number} value
|
|
524
522
|
* @param {Number} [min]
|
|
525
523
|
* @param {Number} [max]
|
|
@@ -955,7 +953,7 @@ class Vector2
|
|
|
955
953
|
return new Vector2(this.x*c - this.y*s, this.x*s + this.y*c);
|
|
956
954
|
}
|
|
957
955
|
|
|
958
|
-
/** Set the integer direction of this vector,
|
|
956
|
+
/** Set the integer direction of this vector, corresponding to multiples of 90 degree rotation (0-3)
|
|
959
957
|
* @param {Number} [direction]
|
|
960
958
|
* @param {Number} [length] */
|
|
961
959
|
setDirection(direction, length=1)
|
|
@@ -966,7 +964,7 @@ class Vector2
|
|
|
966
964
|
direction%2 ? 0 : direction ? -length : length);
|
|
967
965
|
}
|
|
968
966
|
|
|
969
|
-
/** Returns the integer direction of this vector,
|
|
967
|
+
/** Returns the integer direction of this vector, corresponding to multiples of 90 degree rotation (0-3)
|
|
970
968
|
* @return {Number} */
|
|
971
969
|
direction()
|
|
972
970
|
{ return abs(this.x) > abs(this.y) ? this.x < 0 ? 3 : 1 : this.y < 0 ? 2 : 0; }
|
|
@@ -1351,7 +1349,7 @@ const MAGENTA = rgb(1,0,1);
|
|
|
1351
1349
|
* a.set(3); // sets the timer to 3 seconds
|
|
1352
1350
|
*
|
|
1353
1351
|
* let b = new Timer(1); // creates a timer with 1 second left
|
|
1354
|
-
* b.unset(); //
|
|
1352
|
+
* b.unset(); // unset the timer
|
|
1355
1353
|
*/
|
|
1356
1354
|
class Timer
|
|
1357
1355
|
{
|
|
@@ -1502,7 +1500,7 @@ let tileFixBleedScale = 0;
|
|
|
1502
1500
|
* @memberof Settings */
|
|
1503
1501
|
let enablePhysicsSolver = true;
|
|
1504
1502
|
|
|
1505
|
-
/** Default object mass for collision
|
|
1503
|
+
/** Default object mass for collision calculations (how heavy objects are)
|
|
1506
1504
|
* @type {Number}
|
|
1507
1505
|
* @default
|
|
1508
1506
|
* @memberof Settings */
|
|
@@ -1713,7 +1711,7 @@ function setFontDefault(font) { fontDefault = font; }
|
|
|
1713
1711
|
* @memberof Settings */
|
|
1714
1712
|
function setShowSplashScreen(show) { showSplashScreen = show; }
|
|
1715
1713
|
|
|
1716
|
-
/** Set to
|
|
1714
|
+
/** Set to disable rendering, audio, and input for servers
|
|
1717
1715
|
* @param {Boolean} headless
|
|
1718
1716
|
* @memberof Settings */
|
|
1719
1717
|
function setHeadlessMode(headless) { headlessMode = headless; }
|
|
@@ -1743,7 +1741,7 @@ function setTileFixBleedScale(scale) { tileFixBleedScale = scale; }
|
|
|
1743
1741
|
* @memberof Settings */
|
|
1744
1742
|
function setEnablePhysicsSolver(enable) { enablePhysicsSolver = enable; }
|
|
1745
1743
|
|
|
1746
|
-
/** Set default object mass for
|
|
1744
|
+
/** Set default object mass for collision calculations
|
|
1747
1745
|
* @param {Number} mass
|
|
1748
1746
|
* @memberof Settings */
|
|
1749
1747
|
function setObjectDefaultMass(mass) { objectDefaultMass = mass; }
|
|
@@ -1813,7 +1811,7 @@ function setTouchGamepadEnable(enable) { touchGamepadEnable = enable; }
|
|
|
1813
1811
|
* @memberof Settings */
|
|
1814
1812
|
function setTouchGamepadAnalog(analog) { touchGamepadAnalog = analog; }
|
|
1815
1813
|
|
|
1816
|
-
/** Set size of
|
|
1814
|
+
/** Set size of virtual gamepad for touch devices in pixels
|
|
1817
1815
|
* @param {Number} size
|
|
1818
1816
|
* @memberof Settings */
|
|
1819
1817
|
function setTouchGamepadSize(size) { touchGamepadSize = size; }
|
|
@@ -1840,7 +1838,7 @@ function setSoundVolume(volume)
|
|
|
1840
1838
|
{
|
|
1841
1839
|
soundVolume = volume;
|
|
1842
1840
|
if (soundEnable && !headlessMode && audioGainNode)
|
|
1843
|
-
audioGainNode.gain.value = volume; // update gain
|
|
1841
|
+
audioGainNode.gain.value = volume; // update gain immediately
|
|
1844
1842
|
}
|
|
1845
1843
|
|
|
1846
1844
|
/** Set default range where sound no longer plays
|
|
@@ -2044,7 +2042,7 @@ class EngineObject
|
|
|
2044
2042
|
const oldPos = this.pos.copy();
|
|
2045
2043
|
this.velocity.x *= this.damping;
|
|
2046
2044
|
this.velocity.y *= this.damping;
|
|
2047
|
-
if (this.mass) //
|
|
2045
|
+
if (this.mass) // don't apply gravity to static objects
|
|
2048
2046
|
this.velocity.y += gravity * this.gravityScale;
|
|
2049
2047
|
this.pos.x += this.velocity.x;
|
|
2050
2048
|
this.pos.y += this.velocity.y;
|
|
@@ -2053,7 +2051,7 @@ class EngineObject
|
|
|
2053
2051
|
// physics sanity checks
|
|
2054
2052
|
ASSERT(this.angleDamping >= 0 && this.angleDamping <= 1);
|
|
2055
2053
|
ASSERT(this.damping >= 0 && this.damping <= 1);
|
|
2056
|
-
if (!enablePhysicsSolver || !this.mass) //
|
|
2054
|
+
if (!enablePhysicsSolver || !this.mass) // don't do collision for static objects
|
|
2057
2055
|
return;
|
|
2058
2056
|
|
|
2059
2057
|
const wasMovingDown = this.velocity.y < 0;
|
|
@@ -2072,7 +2070,7 @@ class EngineObject
|
|
|
2072
2070
|
const epsilon = .001; // necessary to push slightly outside of the collision
|
|
2073
2071
|
for (const o of engineObjectsCollide)
|
|
2074
2072
|
{
|
|
2075
|
-
// non solid objects don't collide with
|
|
2073
|
+
// non solid objects don't collide with each other
|
|
2076
2074
|
if (!this.isSolid && !o.isSolid || o.destroyed || o.parent || o == this)
|
|
2077
2075
|
continue;
|
|
2078
2076
|
|
|
@@ -2132,7 +2130,7 @@ class EngineObject
|
|
|
2132
2130
|
const elastic1 = o.velocity.y * (o.mass - this.mass) / (this.mass + o.mass)
|
|
2133
2131
|
+ this.velocity.y * 2 * this.mass / (this.mass + o.mass);
|
|
2134
2132
|
|
|
2135
|
-
// lerp
|
|
2133
|
+
// lerp between elastic or inelastic based on elasticity
|
|
2136
2134
|
this.velocity.y = lerp(elasticity, inelastic, elastic0);
|
|
2137
2135
|
o.velocity.y = lerp(elasticity, inelastic, elastic1);
|
|
2138
2136
|
}
|
|
@@ -2152,7 +2150,7 @@ class EngineObject
|
|
|
2152
2150
|
const elastic1 = o.velocity.x * (o.mass - this.mass) / (this.mass + o.mass)
|
|
2153
2151
|
+ this.velocity.x * 2 * this.mass / (this.mass + o.mass);
|
|
2154
2152
|
|
|
2155
|
-
// lerp
|
|
2153
|
+
// lerp between elastic or inelastic based on elasticity
|
|
2156
2154
|
this.velocity.x = lerp(elasticity, inelastic, elastic0);
|
|
2157
2155
|
o.velocity.x = lerp(elasticity, inelastic, elastic1);
|
|
2158
2156
|
}
|
|
@@ -2218,7 +2216,7 @@ class EngineObject
|
|
|
2218
2216
|
if (this.destroyed)
|
|
2219
2217
|
return;
|
|
2220
2218
|
|
|
2221
|
-
// disconnect from parent and destroy
|
|
2219
|
+
// disconnect from parent and destroy children
|
|
2222
2220
|
this.destroyed = 1;
|
|
2223
2221
|
this.parent && this.parent.removeChild(this);
|
|
2224
2222
|
for (const child of this.children)
|
|
@@ -2243,7 +2241,7 @@ class EngineObject
|
|
|
2243
2241
|
|
|
2244
2242
|
/** Called to check if a tile collision should be resolved
|
|
2245
2243
|
* @param {Number} tileData - the value of the tile at the position
|
|
2246
|
-
* @param {Vector2} pos - tile where the collision
|
|
2244
|
+
* @param {Vector2} pos - tile where the collision occurred
|
|
2247
2245
|
* @return {Boolean} - true if the collision should be resolved */
|
|
2248
2246
|
collideWithTile(tileData, pos) { return tileData > 0; }
|
|
2249
2247
|
|
|
@@ -2306,7 +2304,7 @@ class EngineObject
|
|
|
2306
2304
|
this.collideRaycast = collideRaycast;
|
|
2307
2305
|
}
|
|
2308
2306
|
|
|
2309
|
-
/** Returns string
|
|
2307
|
+
/** Returns string containing info about this object for debugging
|
|
2310
2308
|
* @return {String} */
|
|
2311
2309
|
toString()
|
|
2312
2310
|
{
|
|
@@ -2392,7 +2390,7 @@ let overlayContext;
|
|
|
2392
2390
|
let mainCanvasSize = vec2();
|
|
2393
2391
|
|
|
2394
2392
|
/** Array containing texture info for batch rendering system
|
|
2395
|
-
* @type {Array}
|
|
2393
|
+
* @type {Array<TextureInfo>}
|
|
2396
2394
|
* @memberof Draw */
|
|
2397
2395
|
let textureInfos = [];
|
|
2398
2396
|
|
|
@@ -2431,11 +2429,13 @@ function tile(pos=vec2(), size=tileSizeDefault, textureIndex=0, padding=0)
|
|
|
2431
2429
|
|
|
2432
2430
|
// use pos as a tile index
|
|
2433
2431
|
const textureInfo = textureInfos[textureIndex];
|
|
2434
|
-
ASSERT(textureInfo, 'Texture not loaded');
|
|
2432
|
+
ASSERT(!!textureInfo, 'Texture not loaded');
|
|
2435
2433
|
const sizePadded = size.add(vec2(padding*2));
|
|
2436
|
-
const cols = textureInfo.size.x / sizePadded.x |0;
|
|
2437
2434
|
if (typeof pos === 'number')
|
|
2438
|
-
|
|
2435
|
+
{
|
|
2436
|
+
const cols = textureInfo.size.x / sizePadded.x |0;
|
|
2437
|
+
pos = cols>0 ? vec2(pos%cols, pos/cols|0) : vec2();
|
|
2438
|
+
}
|
|
2439
2439
|
pos = vec2(pos.x*sizePadded.x+padding, pos.y*sizePadded.y+padding);
|
|
2440
2440
|
|
|
2441
2441
|
// return a tile info object
|
|
@@ -2741,24 +2741,6 @@ function drawCanvas2D(pos, size, angle, mirror, drawFunction, screenSpace, conte
|
|
|
2741
2741
|
context.restore();
|
|
2742
2742
|
}
|
|
2743
2743
|
|
|
2744
|
-
/** Enable normal or additive blend mode
|
|
2745
|
-
* @param {Boolean} [additive]
|
|
2746
|
-
* @param {Boolean} [useWebGL=glEnable]
|
|
2747
|
-
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=mainContext]
|
|
2748
|
-
* @memberof Draw */
|
|
2749
|
-
function setBlendMode(additive, useWebGL=glEnable, context)
|
|
2750
|
-
{
|
|
2751
|
-
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
2752
|
-
if (useWebGL)
|
|
2753
|
-
glAdditive = additive;
|
|
2754
|
-
else
|
|
2755
|
-
{
|
|
2756
|
-
if (!context)
|
|
2757
|
-
context = mainContext;
|
|
2758
|
-
context.globalCompositeOperation = additive ? 'lighter' : 'source-over';
|
|
2759
|
-
}
|
|
2760
|
-
}
|
|
2761
|
-
|
|
2762
2744
|
/** Draw text on main canvas in world space
|
|
2763
2745
|
* Automatically splits new lines into rows
|
|
2764
2746
|
* @param {String} text
|
|
@@ -2826,6 +2808,38 @@ function drawTextScreen(text, pos, size=1, color=new Color, lineWidth=0, lineCol
|
|
|
2826
2808
|
});
|
|
2827
2809
|
}
|
|
2828
2810
|
|
|
2811
|
+
/** Enable normal or additive blend mode
|
|
2812
|
+
* @param {Boolean} [additive]
|
|
2813
|
+
* @param {Boolean} [useWebGL=glEnable]
|
|
2814
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=mainContext]
|
|
2815
|
+
* @memberof Draw */
|
|
2816
|
+
function setBlendMode(additive, useWebGL=glEnable, context)
|
|
2817
|
+
{
|
|
2818
|
+
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
2819
|
+
if (useWebGL)
|
|
2820
|
+
glAdditive = additive;
|
|
2821
|
+
else
|
|
2822
|
+
{
|
|
2823
|
+
if (!context)
|
|
2824
|
+
context = mainContext;
|
|
2825
|
+
context.globalCompositeOperation = additive ? 'lighter' : 'source-over';
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
|
|
2829
|
+
/** Combines all LittleJS canvases onto the main canvas and clears them
|
|
2830
|
+
* This is necessary for things like saving a screenshot
|
|
2831
|
+
* @memberof Draw */
|
|
2832
|
+
function combineCanvases()
|
|
2833
|
+
{
|
|
2834
|
+
// combine canvases
|
|
2835
|
+
glCopyToContext(mainContext, true);
|
|
2836
|
+
mainContext.drawImage(overlayCanvas, 0, 0);
|
|
2837
|
+
|
|
2838
|
+
// clear canvases
|
|
2839
|
+
glClearCanvas();
|
|
2840
|
+
overlayCanvas.width |= 0;
|
|
2841
|
+
}
|
|
2842
|
+
|
|
2829
2843
|
///////////////////////////////////////////////////////////////////////////////
|
|
2830
2844
|
|
|
2831
2845
|
let engineFontImage;
|
|
@@ -2837,7 +2851,7 @@ let engineFontImage;
|
|
|
2837
2851
|
* - You can also use fonts from the main tile sheet
|
|
2838
2852
|
* @example
|
|
2839
2853
|
* // use built in font
|
|
2840
|
-
* const font = new
|
|
2854
|
+
* const font = new FontImage;
|
|
2841
2855
|
*
|
|
2842
2856
|
* // draw text
|
|
2843
2857
|
* font.drawTextScreen("LittleJS\nHello World!", vec2(200, 50));
|
|
@@ -2912,14 +2926,14 @@ class FontImage
|
|
|
2912
2926
|
}
|
|
2913
2927
|
|
|
2914
2928
|
///////////////////////////////////////////////////////////////////////////////
|
|
2915
|
-
//
|
|
2929
|
+
// Display functions
|
|
2916
2930
|
|
|
2917
2931
|
/** Returns true if fullscreen mode is active
|
|
2918
2932
|
* @return {Boolean}
|
|
2919
2933
|
* @memberof Draw */
|
|
2920
2934
|
function isFullscreen() { return !!document.fullscreenElement; }
|
|
2921
2935
|
|
|
2922
|
-
/** Toggle
|
|
2936
|
+
/** Toggle fullscreen mode
|
|
2923
2937
|
* @memberof Draw */
|
|
2924
2938
|
function toggleFullscreen()
|
|
2925
2939
|
{
|
|
@@ -2931,6 +2945,15 @@ function toggleFullscreen()
|
|
|
2931
2945
|
}
|
|
2932
2946
|
else if (rootElement.requestFullscreen)
|
|
2933
2947
|
rootElement.requestFullscreen();
|
|
2948
|
+
}
|
|
2949
|
+
|
|
2950
|
+
/** Set the cursor style
|
|
2951
|
+
* @param {String} cursorStyle - CSS cursor style (auto, none, crosshair, etc)
|
|
2952
|
+
* @memberof Draw */
|
|
2953
|
+
function setCursor(cursorStyle = 'auto')
|
|
2954
|
+
{
|
|
2955
|
+
const rootElement = mainCanvas.parentElement;
|
|
2956
|
+
rootElement.style.cursor = cursorStyle;
|
|
2934
2957
|
}
|
|
2935
2958
|
/**
|
|
2936
2959
|
* LittleJS Input System
|
|
@@ -3275,7 +3298,7 @@ function vibrateStop() { vibrate(0); }
|
|
|
3275
3298
|
|
|
3276
3299
|
/** True if a touch device has been detected
|
|
3277
3300
|
* @memberof Input */
|
|
3278
|
-
const isTouchDevice = window.ontouchstart !== undefined;
|
|
3301
|
+
const isTouchDevice = !headlessMode && window.ontouchstart !== undefined;
|
|
3279
3302
|
|
|
3280
3303
|
// touch gamepad internal variables
|
|
3281
3304
|
let touchGamepadTimer = new Timer, touchGamepadButtons, touchGamepadStick;
|
|
@@ -3473,7 +3496,7 @@ function audioInit()
|
|
|
3473
3496
|
{
|
|
3474
3497
|
if (!soundEnable || headlessMode) return;
|
|
3475
3498
|
|
|
3476
|
-
// (createGain is more widely
|
|
3499
|
+
// (createGain is more widely supported then GainNode constructor)
|
|
3477
3500
|
audioGainNode = audioContext.createGain();
|
|
3478
3501
|
audioGainNode.connect(audioContext.destination);
|
|
3479
3502
|
audioGainNode.gain.value = soundVolume; // set starting value
|
|
@@ -3823,7 +3846,7 @@ const zzfxR = 44100;
|
|
|
3823
3846
|
* @param {Number} [sustain] - Sustain time, how long sound holds (seconds)
|
|
3824
3847
|
* @param {Number} [release] - Release time, how fast sound fades out (seconds)
|
|
3825
3848
|
* @param {Number} [shape] - Shape of the sound wave
|
|
3826
|
-
* @param {Number} [shapeCurve] -
|
|
3849
|
+
* @param {Number} [shapeCurve] - Squareness of wave (0=square, 1=normal, 2=pointy)
|
|
3827
3850
|
* @param {Number} [slide] - How much to slide frequency (kHz/s)
|
|
3828
3851
|
* @param {Number} [deltaSlide] - How much to change slide (kHz/s/s)
|
|
3829
3852
|
* @param {Number} [pitchJump] - Frequency of pitch jump (Hz)
|
|
@@ -3835,7 +3858,7 @@ const zzfxR = 44100;
|
|
|
3835
3858
|
* @param {Number} [delay] - Overlap sound with itself for reverb and flanger effects (seconds)
|
|
3836
3859
|
* @param {Number} [sustainVolume] - Volume level for sustain (percent)
|
|
3837
3860
|
* @param {Number} [decay] - Decay time, how long to reach sustain after attack (seconds)
|
|
3838
|
-
* @param {Number} [tremolo] - Trembling effect, rate controlled by repeat time (
|
|
3861
|
+
* @param {Number} [tremolo] - Trembling effect, rate controlled by repeat time (percent)
|
|
3839
3862
|
* @param {Number} [filter] - Filter cutoff frequency, positive for HPF, negative for LPF (Hz)
|
|
3840
3863
|
* @return {Array} - Array of audio samples
|
|
3841
3864
|
* @memberof Audio
|
|
@@ -3939,7 +3962,7 @@ function zzfxG
|
|
|
3939
3962
|
// ZzFX Music Renderer v2.0.3 by Keith Clark and Frank Force
|
|
3940
3963
|
|
|
3941
3964
|
/** Generate samples for a ZzFM song with given parameters
|
|
3942
|
-
* @param {Array} instruments - Array of ZzFX sound
|
|
3965
|
+
* @param {Array} instruments - Array of ZzFX sound parameters
|
|
3943
3966
|
* @param {Array} patterns - Array of pattern data
|
|
3944
3967
|
* @param {Array} sequence - Array of pattern indexes
|
|
3945
3968
|
* @param {Number} [BPM] - Playback speed of the song in BPM
|
|
@@ -4280,6 +4303,10 @@ class TileLayer extends EngineObject
|
|
|
4280
4303
|
|
|
4281
4304
|
// draw the entire cached level onto the canvas
|
|
4282
4305
|
const pos = worldToScreen(this.pos.add(vec2(0,this.size.y*this.scale.y)));
|
|
4306
|
+
|
|
4307
|
+
// fix canvas jitter in some browsers if position is not an integer
|
|
4308
|
+
pos.x |= 0; pos.y |= 0;
|
|
4309
|
+
|
|
4283
4310
|
(this.isOverlay ? overlayContext : mainContext).drawImage
|
|
4284
4311
|
(
|
|
4285
4312
|
this.canvas, pos.x, pos.y,
|
|
@@ -4342,7 +4369,7 @@ class TileLayer extends EngineObject
|
|
|
4342
4369
|
|
|
4343
4370
|
/** Draw the tile at a given position in the tile grid
|
|
4344
4371
|
* This can be used to clear out tiles when they are destroyed
|
|
4345
|
-
* Tiles can also be redrawn if
|
|
4372
|
+
* Tiles can also be redrawn if inside a redrawStart/End block
|
|
4346
4373
|
* @param {Vector2} layerPos
|
|
4347
4374
|
* @param {Boolean} [clear] - should the old tile be cleared out
|
|
4348
4375
|
*/
|
|
@@ -4367,7 +4394,7 @@ class TileLayer extends EngineObject
|
|
|
4367
4394
|
}
|
|
4368
4395
|
}
|
|
4369
4396
|
|
|
4370
|
-
/** Draw directly to the 2D canvas in world space (
|
|
4397
|
+
/** Draw directly to the 2D canvas in world space (bypass webgl)
|
|
4371
4398
|
* @param {Vector2} pos
|
|
4372
4399
|
* @param {Vector2} size
|
|
4373
4400
|
* @param {Number} angle
|
|
@@ -4437,7 +4464,7 @@ class TileLayer extends EngineObject
|
|
|
4437
4464
|
* let pos = vec2(2,3);
|
|
4438
4465
|
* let particleEmitter = new ParticleEmitter
|
|
4439
4466
|
* (
|
|
4440
|
-
* pos, 0, 1, 0, 500, PI, // pos, angle, emitSize, emitTime, emitRate,
|
|
4467
|
+
* pos, 0, 1, 0, 500, PI, // pos, angle, emitSize, emitTime, emitRate, emitCone
|
|
4441
4468
|
* tile(0, 16), // tileInfo
|
|
4442
4469
|
* rgb(1,1,1), rgb(0,0,0), // colorStartA, colorStartB
|
|
4443
4470
|
* rgb(1,1,1,0), rgb(0,0,0,0), // colorEndA, colorEndB
|
|
@@ -4472,7 +4499,7 @@ class ParticleEmitter extends EngineObject
|
|
|
4472
4499
|
* @param {Number} [fadeRate] - How quick to fade particles at start/end in percent of life
|
|
4473
4500
|
* @param {Number} [randomness] - Apply extra randomness percent
|
|
4474
4501
|
* @param {Boolean} [collideTiles] - Do particles collide against tiles
|
|
4475
|
-
* @param {Boolean} [additive] - Should particles use
|
|
4502
|
+
* @param {Boolean} [additive] - Should particles use additive blend
|
|
4476
4503
|
* @param {Boolean} [randomColorLinear] - Should color be randomized linearly or across each component
|
|
4477
4504
|
* @param {Number} [renderOrder] - Render order for particles (additive is above other stuff by default)
|
|
4478
4505
|
* @param {Boolean} [localSpace] - Should it be in local space of emitter (world space is default)
|
|
@@ -4557,11 +4584,11 @@ class ParticleEmitter extends EngineObject
|
|
|
4557
4584
|
this.randomness = randomness;
|
|
4558
4585
|
/** @property {Boolean} - Do particles collide against tiles */
|
|
4559
4586
|
this.collideTiles = collideTiles;
|
|
4560
|
-
/** @property {Boolean} - Should particles use
|
|
4587
|
+
/** @property {Boolean} - Should particles use additive blend */
|
|
4561
4588
|
this.additive = additive;
|
|
4562
4589
|
/** @property {Boolean} - Should it be in local space of emitter */
|
|
4563
4590
|
this.localSpace = localSpace;
|
|
4564
|
-
/** @property {Number} - If non zero the
|
|
4591
|
+
/** @property {Number} - If non zero the particle is drawn as a trail, stretched in the direction of velocity */
|
|
4565
4592
|
this.trailScale = 0;
|
|
4566
4593
|
/** @property {Function} - Callback when particle is destroyed */
|
|
4567
4594
|
this.particleDestroyCallback = undefined;
|
|
@@ -4610,7 +4637,7 @@ class ParticleEmitter extends EngineObject
|
|
|
4610
4637
|
angle += this.angle;
|
|
4611
4638
|
}
|
|
4612
4639
|
|
|
4613
|
-
// randomness scales each
|
|
4640
|
+
// randomness scales each parameter by a percentage
|
|
4614
4641
|
const randomness = this.randomness;
|
|
4615
4642
|
const randomizeScale = (v)=> v + v*rand(randomness, -randomness);
|
|
4616
4643
|
|
|
@@ -4639,7 +4666,7 @@ class ParticleEmitter extends EngineObject
|
|
|
4639
4666
|
particle.renderOrder = this.renderOrder;
|
|
4640
4667
|
particle.mirror = !!randInt(2);
|
|
4641
4668
|
|
|
4642
|
-
// call particle create
|
|
4669
|
+
// call particle create callback
|
|
4643
4670
|
this.particleCreateCallback && this.particleCreateCallback(particle);
|
|
4644
4671
|
|
|
4645
4672
|
// return the newly created particle
|
|
@@ -4708,7 +4735,7 @@ class Particle extends EngineObject
|
|
|
4708
4735
|
render()
|
|
4709
4736
|
{
|
|
4710
4737
|
// modulate size and color
|
|
4711
|
-
const p = min((time - this.spawnTime) / this.lifeTime, 1);
|
|
4738
|
+
const p = this.lifeTime > 0 ? min((time - this.spawnTime) / this.lifeTime, 1) : 1;
|
|
4712
4739
|
const radius = this.sizeStart + p * this.sizeEndDelta;
|
|
4713
4740
|
const size = vec2(radius);
|
|
4714
4741
|
const fadeRate = this.fadeRate/2;
|
|
@@ -4959,7 +4986,7 @@ let glCanvas;
|
|
|
4959
4986
|
* @memberof WebGL */
|
|
4960
4987
|
let glContext;
|
|
4961
4988
|
|
|
4962
|
-
/**
|
|
4989
|
+
/** Should webgl be setup with anti-aliasing? must be set before calling engineInit
|
|
4963
4990
|
* @type {Boolean}
|
|
4964
4991
|
* @memberof WebGL */
|
|
4965
4992
|
let glAntialias = true;
|
|
@@ -4967,9 +4994,15 @@ let glAntialias = true;
|
|
|
4967
4994
|
// WebGL internal variables not exposed to documentation
|
|
4968
4995
|
let glShader, glActiveTexture, glArrayBuffer, glGeometryBuffer, glPositionData, glColorData, glInstanceCount, glAdditive, glBatchAdditive;
|
|
4969
4996
|
|
|
4997
|
+
// WebGL internal constants
|
|
4998
|
+
const gl_MAX_INSTANCES = 1e4;
|
|
4999
|
+
const gl_INDICES_PER_INSTANCE = 11;
|
|
5000
|
+
const gl_INSTANCE_BYTE_STRIDE = gl_INDICES_PER_INSTANCE * 4;
|
|
5001
|
+
const gl_INSTANCE_BUFFER_SIZE = gl_MAX_INSTANCES * gl_INSTANCE_BYTE_STRIDE;
|
|
5002
|
+
|
|
4970
5003
|
///////////////////////////////////////////////////////////////////////////////
|
|
4971
5004
|
|
|
4972
|
-
//
|
|
5005
|
+
// Initialize WebGL, called automatically by the engine
|
|
4973
5006
|
function glInit()
|
|
4974
5007
|
{
|
|
4975
5008
|
if (!glEnable || headlessMode) return;
|
|
@@ -5019,8 +5052,8 @@ function glInit()
|
|
|
5019
5052
|
|
|
5020
5053
|
// create the geometry buffer, triangle strip square
|
|
5021
5054
|
const geometry = new Float32Array([glInstanceCount=0,0,1,0,0,1,1,1]);
|
|
5022
|
-
glContext.bindBuffer(
|
|
5023
|
-
glContext.bufferData(
|
|
5055
|
+
glContext.bindBuffer(glContext.ARRAY_BUFFER, glGeometryBuffer);
|
|
5056
|
+
glContext.bufferData(glContext.ARRAY_BUFFER, geometry, glContext.STATIC_DRAW);
|
|
5024
5057
|
}
|
|
5025
5058
|
|
|
5026
5059
|
// Setup render each frame, called automatically by engine
|
|
@@ -5028,15 +5061,12 @@ function glPreRender()
|
|
|
5028
5061
|
{
|
|
5029
5062
|
if (!glEnable || headlessMode) return;
|
|
5030
5063
|
|
|
5031
|
-
//
|
|
5032
|
-
|
|
5033
|
-
glContext.clear(gl_COLOR_BUFFER_BIT);
|
|
5034
|
-
|
|
5035
|
-
// set up the shader
|
|
5064
|
+
// set up the shader and canvas
|
|
5065
|
+
glClearCanvas();
|
|
5036
5066
|
glContext.useProgram(glShader);
|
|
5037
|
-
glContext.activeTexture(
|
|
5067
|
+
glContext.activeTexture(glContext.TEXTURE0);
|
|
5038
5068
|
if (textureInfos[0])
|
|
5039
|
-
glContext.bindTexture(
|
|
5069
|
+
glContext.bindTexture(glContext.TEXTURE_2D, glActiveTexture = textureInfos[0].glTexture);
|
|
5040
5070
|
|
|
5041
5071
|
// set vertex attributes
|
|
5042
5072
|
let offset = glAdditive = glBatchAdditive = 0;
|
|
@@ -5051,15 +5081,15 @@ function glPreRender()
|
|
|
5051
5081
|
glContext.vertexAttribDivisor(location, divisor);
|
|
5052
5082
|
offset += size*typeSize;
|
|
5053
5083
|
}
|
|
5054
|
-
glContext.bindBuffer(
|
|
5055
|
-
initVertexAttribArray('g',
|
|
5056
|
-
glContext.bindBuffer(
|
|
5057
|
-
glContext.bufferData(
|
|
5058
|
-
initVertexAttribArray('p',
|
|
5059
|
-
initVertexAttribArray('u',
|
|
5060
|
-
initVertexAttribArray('c',
|
|
5061
|
-
initVertexAttribArray('a',
|
|
5062
|
-
initVertexAttribArray('r',
|
|
5084
|
+
glContext.bindBuffer(glContext.ARRAY_BUFFER, glGeometryBuffer);
|
|
5085
|
+
initVertexAttribArray('g', glContext.FLOAT, 0, 2); // geometry
|
|
5086
|
+
glContext.bindBuffer(glContext.ARRAY_BUFFER, glArrayBuffer);
|
|
5087
|
+
glContext.bufferData(glContext.ARRAY_BUFFER, gl_INSTANCE_BUFFER_SIZE, glContext.DYNAMIC_DRAW);
|
|
5088
|
+
initVertexAttribArray('p', glContext.FLOAT, 4, 4); // position & size
|
|
5089
|
+
initVertexAttribArray('u', glContext.FLOAT, 4, 4); // texture coords
|
|
5090
|
+
initVertexAttribArray('c', glContext.UNSIGNED_BYTE, 1, 4); // color
|
|
5091
|
+
initVertexAttribArray('a', glContext.UNSIGNED_BYTE, 1, 4); // additiveColor
|
|
5092
|
+
initVertexAttribArray('r', glContext.FLOAT, 4, 1); // rotation
|
|
5063
5093
|
|
|
5064
5094
|
// build the transform matrix
|
|
5065
5095
|
const s = vec2(2*cameraScale).divide(mainCanvasSize);
|
|
@@ -5074,6 +5104,15 @@ function glPreRender()
|
|
|
5074
5104
|
);
|
|
5075
5105
|
}
|
|
5076
5106
|
|
|
5107
|
+
/** Clear the canvas and setup the viewport
|
|
5108
|
+
* @memberof WebGL */
|
|
5109
|
+
function glClearCanvas()
|
|
5110
|
+
{
|
|
5111
|
+
// clear and set to same size as main canvas
|
|
5112
|
+
glContext.viewport(0, 0, glCanvas.width=mainCanvas.width, glCanvas.height=mainCanvas.height);
|
|
5113
|
+
glContext.clear(glContext.COLOR_BUFFER_BIT);
|
|
5114
|
+
}
|
|
5115
|
+
|
|
5077
5116
|
/** Set the WebGl texture, called automatically if using multiple textures
|
|
5078
5117
|
* - This may also flush the gl buffer resulting in more draw calls and worse performance
|
|
5079
5118
|
* @param {WebGLTexture} texture
|
|
@@ -5085,7 +5124,7 @@ function glSetTexture(texture)
|
|
|
5085
5124
|
return;
|
|
5086
5125
|
|
|
5087
5126
|
glFlush();
|
|
5088
|
-
glContext.bindTexture(
|
|
5127
|
+
glContext.bindTexture(glContext.TEXTURE_2D, glActiveTexture = texture);
|
|
5089
5128
|
}
|
|
5090
5129
|
|
|
5091
5130
|
/** Compile WebGL shader of the given type, will throw errors if in debug mode
|
|
@@ -5101,7 +5140,7 @@ function glCompileShader(source, type)
|
|
|
5101
5140
|
glContext.compileShader(shader);
|
|
5102
5141
|
|
|
5103
5142
|
// check for errors
|
|
5104
|
-
if (debug && !glContext.getShaderParameter(shader,
|
|
5143
|
+
if (debug && !glContext.getShaderParameter(shader, glContext.COMPILE_STATUS))
|
|
5105
5144
|
throw glContext.getShaderInfoLog(shader);
|
|
5106
5145
|
return shader;
|
|
5107
5146
|
}
|
|
@@ -5115,12 +5154,12 @@ function glCreateProgram(vsSource, fsSource)
|
|
|
5115
5154
|
{
|
|
5116
5155
|
// build the program
|
|
5117
5156
|
const program = glContext.createProgram();
|
|
5118
|
-
glContext.attachShader(program, glCompileShader(vsSource,
|
|
5119
|
-
glContext.attachShader(program, glCompileShader(fsSource,
|
|
5157
|
+
glContext.attachShader(program, glCompileShader(vsSource, glContext.VERTEX_SHADER));
|
|
5158
|
+
glContext.attachShader(program, glCompileShader(fsSource, glContext.FRAGMENT_SHADER));
|
|
5120
5159
|
glContext.linkProgram(program);
|
|
5121
5160
|
|
|
5122
5161
|
// check for errors
|
|
5123
|
-
if (debug && !glContext.getProgramParameter(program,
|
|
5162
|
+
if (debug && !glContext.getProgramParameter(program, glContext.LINK_STATUS))
|
|
5124
5163
|
throw glContext.getProgramInfoLog(program);
|
|
5125
5164
|
return program;
|
|
5126
5165
|
}
|
|
@@ -5133,20 +5172,20 @@ function glCreateTexture(image)
|
|
|
5133
5172
|
{
|
|
5134
5173
|
// build the texture
|
|
5135
5174
|
const texture = glContext.createTexture();
|
|
5136
|
-
glContext.bindTexture(
|
|
5175
|
+
glContext.bindTexture(glContext.TEXTURE_2D, texture);
|
|
5137
5176
|
if (image && image.width)
|
|
5138
|
-
glContext.texImage2D(
|
|
5177
|
+
glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, glContext.RGBA, glContext.UNSIGNED_BYTE, image);
|
|
5139
5178
|
else
|
|
5140
5179
|
{
|
|
5141
5180
|
// create a white texture
|
|
5142
5181
|
const whitePixel = new Uint8Array([255, 255, 255, 255]);
|
|
5143
|
-
glContext.texImage2D(
|
|
5182
|
+
glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, 1, 1, 0, glContext.RGBA, glContext.UNSIGNED_BYTE, whitePixel);
|
|
5144
5183
|
}
|
|
5145
5184
|
|
|
5146
5185
|
// use point filtering for pixelated rendering
|
|
5147
|
-
const filter = tilesPixelated ?
|
|
5148
|
-
glContext.texParameteri(
|
|
5149
|
-
glContext.texParameteri(
|
|
5186
|
+
const filter = tilesPixelated ? glContext.NEAREST : glContext.LINEAR;
|
|
5187
|
+
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MIN_FILTER, filter);
|
|
5188
|
+
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MAG_FILTER, filter);
|
|
5150
5189
|
return texture;
|
|
5151
5190
|
}
|
|
5152
5191
|
|
|
@@ -5156,20 +5195,20 @@ function glFlush()
|
|
|
5156
5195
|
{
|
|
5157
5196
|
if (!glInstanceCount) return;
|
|
5158
5197
|
|
|
5159
|
-
const destBlend = glBatchAdditive ?
|
|
5160
|
-
glContext.blendFuncSeparate(
|
|
5161
|
-
glContext.enable(
|
|
5198
|
+
const destBlend = glBatchAdditive ? glContext.ONE : glContext.ONE_MINUS_SRC_ALPHA;
|
|
5199
|
+
glContext.blendFuncSeparate(glContext.SRC_ALPHA, destBlend, glContext.ONE, destBlend);
|
|
5200
|
+
glContext.enable(glContext.BLEND);
|
|
5162
5201
|
|
|
5163
5202
|
// draw all the sprites in the batch and reset the buffer
|
|
5164
|
-
glContext.bufferSubData(
|
|
5165
|
-
glContext.drawArraysInstanced(
|
|
5203
|
+
glContext.bufferSubData(glContext.ARRAY_BUFFER, 0, glPositionData);
|
|
5204
|
+
glContext.drawArraysInstanced(glContext.TRIANGLE_STRIP, 0, 4, glInstanceCount);
|
|
5166
5205
|
if (showWatermark)
|
|
5167
5206
|
drawCount += glInstanceCount;
|
|
5168
5207
|
glInstanceCount = 0;
|
|
5169
5208
|
glBatchAdditive = glAdditive;
|
|
5170
5209
|
}
|
|
5171
5210
|
|
|
5172
|
-
/** Draw any sprites still in the buffer
|
|
5211
|
+
/** Draw any sprites still in the buffer and copy to main canvas
|
|
5173
5212
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} context
|
|
5174
5213
|
* @param {Boolean} [forceDraw]
|
|
5175
5214
|
* @memberof WebGL */
|
|
@@ -5184,7 +5223,7 @@ function glCopyToContext(context, forceDraw=false)
|
|
|
5184
5223
|
context.drawImage(glCanvas, 0, 0);
|
|
5185
5224
|
}
|
|
5186
5225
|
|
|
5187
|
-
/** Set
|
|
5226
|
+
/** Set anti-aliasing for webgl canvas
|
|
5188
5227
|
* @param {Boolean} [antialias]
|
|
5189
5228
|
* @memberof WebGL */
|
|
5190
5229
|
function glSetAntialias(antialias=true)
|
|
@@ -5214,7 +5253,7 @@ function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba, rgbaAdd
|
|
|
5214
5253
|
if (glInstanceCount >= gl_MAX_INSTANCES || glBatchAdditive != glAdditive)
|
|
5215
5254
|
glFlush();
|
|
5216
5255
|
|
|
5217
|
-
let offset = glInstanceCount *
|
|
5256
|
+
let offset = glInstanceCount++ * gl_INDICES_PER_INSTANCE;
|
|
5218
5257
|
glPositionData[offset++] = x;
|
|
5219
5258
|
glPositionData[offset++] = y;
|
|
5220
5259
|
glPositionData[offset++] = sizeX;
|
|
@@ -5226,41 +5265,7 @@ function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba, rgbaAdd
|
|
|
5226
5265
|
glColorData[offset++] = rgba;
|
|
5227
5266
|
glColorData[offset++] = rgbaAdditive;
|
|
5228
5267
|
glPositionData[offset++] = angle;
|
|
5229
|
-
|
|
5230
|
-
}
|
|
5231
|
-
|
|
5232
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
5233
|
-
// store gl constants as integers so their name doesn't use space in minifed
|
|
5234
|
-
const
|
|
5235
|
-
gl_ONE = 1,
|
|
5236
|
-
gl_TRIANGLE_STRIP = 5,
|
|
5237
|
-
gl_SRC_ALPHA = 770,
|
|
5238
|
-
gl_ONE_MINUS_SRC_ALPHA = 771,
|
|
5239
|
-
gl_BLEND = 3042,
|
|
5240
|
-
gl_TEXTURE_2D = 3553,
|
|
5241
|
-
gl_UNSIGNED_BYTE = 5121,
|
|
5242
|
-
gl_FLOAT = 5126,
|
|
5243
|
-
gl_RGBA = 6408,
|
|
5244
|
-
gl_NEAREST = 9728,
|
|
5245
|
-
gl_LINEAR = 9729,
|
|
5246
|
-
gl_TEXTURE_MAG_FILTER = 10240,
|
|
5247
|
-
gl_TEXTURE_MIN_FILTER = 10241,
|
|
5248
|
-
gl_COLOR_BUFFER_BIT = 16384,
|
|
5249
|
-
gl_TEXTURE0 = 33984,
|
|
5250
|
-
gl_ARRAY_BUFFER = 34962,
|
|
5251
|
-
gl_STATIC_DRAW = 35044,
|
|
5252
|
-
gl_DYNAMIC_DRAW = 35048,
|
|
5253
|
-
gl_FRAGMENT_SHADER = 35632,
|
|
5254
|
-
gl_VERTEX_SHADER = 35633,
|
|
5255
|
-
gl_COMPILE_STATUS = 35713,
|
|
5256
|
-
gl_LINK_STATUS = 35714,
|
|
5257
|
-
gl_UNPACK_FLIP_Y_WEBGL = 37440,
|
|
5258
|
-
|
|
5259
|
-
// constants for batch rendering
|
|
5260
|
-
gl_INDICIES_PER_INSTANCE = 11,
|
|
5261
|
-
gl_MAX_INSTANCES = 1e4,
|
|
5262
|
-
gl_INSTANCE_BYTE_STRIDE = gl_INDICIES_PER_INSTANCE * 4, // 11 * 4
|
|
5263
|
-
gl_INSTANCE_BUFFER_SIZE = gl_MAX_INSTANCES * gl_INSTANCE_BYTE_STRIDE;
|
|
5268
|
+
}
|
|
5264
5269
|
/**
|
|
5265
5270
|
* LittleJS - The Tiny Fast JavaScript Game Engine
|
|
5266
5271
|
* MIT License - Copyright 2021 Frank Force
|
|
@@ -5293,7 +5298,7 @@ const engineName = 'LittleJS';
|
|
|
5293
5298
|
* @type {String}
|
|
5294
5299
|
* @default
|
|
5295
5300
|
* @memberof Engine */
|
|
5296
|
-
const engineVersion = '1.11.
|
|
5301
|
+
const engineVersion = '1.11.5';
|
|
5297
5302
|
|
|
5298
5303
|
/** Frames per second to update
|
|
5299
5304
|
* @type {Number}
|
|
@@ -5376,8 +5381,21 @@ function engineAddPlugin(updateFunction, renderFunction)
|
|
|
5376
5381
|
* @memberof Engine */
|
|
5377
5382
|
function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, imageSources=[], rootElement=document.body)
|
|
5378
5383
|
{
|
|
5384
|
+
ASSERT(!mainContext, 'engine already initialized');
|
|
5379
5385
|
ASSERT(Array.isArray(imageSources), 'pass in images as array');
|
|
5380
5386
|
|
|
5387
|
+
// allow passing in empty functions
|
|
5388
|
+
if (!gameInit)
|
|
5389
|
+
gameInit = ()=>{};
|
|
5390
|
+
if (!gameUpdate)
|
|
5391
|
+
gameUpdate = ()=>{};
|
|
5392
|
+
if (!gameUpdatePost)
|
|
5393
|
+
gameUpdatePost = ()=>{};
|
|
5394
|
+
if (!gameRender)
|
|
5395
|
+
gameRender = ()=>{};
|
|
5396
|
+
if (!gameRenderPost)
|
|
5397
|
+
gameRenderPost = ()=>{};
|
|
5398
|
+
|
|
5381
5399
|
// Called automatically by engine to setup render system
|
|
5382
5400
|
function enginePreRender()
|
|
5383
5401
|
{
|
|
@@ -5542,7 +5560,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
5542
5560
|
(canvasPixelated ? 'image-rendering:pixelated;' : '') + // pixel art
|
|
5543
5561
|
'user-select:none;' + // prevent hold to select
|
|
5544
5562
|
'-webkit-user-select:none;' + // compatibility for ios
|
|
5545
|
-
(!touchInputEnable ? '' : // no touch css
|
|
5563
|
+
(!touchInputEnable ? '' : // no touch css settings
|
|
5546
5564
|
'touch-action:none;' + // prevent mobile pinch to resize
|
|
5547
5565
|
'-webkit-touch-callout:none');// compatibility for ios
|
|
5548
5566
|
rootElement.style.cssText = styleRoot;
|
|
@@ -5571,6 +5589,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
5571
5589
|
new Promise(resolve =>
|
|
5572
5590
|
{
|
|
5573
5591
|
const image = new Image;
|
|
5592
|
+
image.crossOrigin = 'anonymous';
|
|
5574
5593
|
image.onerror = image.onload = ()=>
|
|
5575
5594
|
{
|
|
5576
5595
|
textureInfos[textureIndex] = new TextureInfo(image);
|
|
@@ -5615,7 +5634,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
5615
5634
|
* @memberof Engine */
|
|
5616
5635
|
function engineObjectsUpdate()
|
|
5617
5636
|
{
|
|
5618
|
-
// get list of solid objects for physics
|
|
5637
|
+
// get list of solid objects for physics optimization
|
|
5619
5638
|
engineObjectsCollide = engineObjects.filter(o=>o.collideSolidObjects);
|
|
5620
5639
|
|
|
5621
5640
|
// recursive object update
|