littlejsengine 1.11.17 → 1.12.6
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/dist/box2d.wasm.js +630 -0
- package/dist/box2d.wasm.wasm +0 -0
- package/dist/littlejs.d.ts +158 -81
- package/dist/littlejs.esm.js +882 -793
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +3048 -175
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +3047 -172
- package/examples/box2d/game.js +82 -56
- package/examples/box2d/gameObjects.js +114 -107
- package/examples/box2d/index.html +2 -7
- package/examples/box2d/scenes.js +72 -78
- package/examples/box2d/tiles.png +0 -0
- package/examples/breakout/game.js +63 -28
- package/examples/breakout/gameObjects.js +45 -47
- package/examples/breakout/index.html +1 -5
- package/examples/breakoutTutorial/game.js +36 -29
- package/examples/breakoutTutorial/index.html +1 -3
- package/examples/empty/game.js +5 -2
- package/examples/empty/index.html +1 -3
- package/examples/htmlMenu/game.js +24 -15
- package/examples/htmlMenu/index.html +5 -7
- package/examples/index.html +24 -17
- package/examples/module/game.js +32 -34
- package/examples/module/index.html +1 -1
- package/examples/particles/index.html +27 -22
- package/examples/platformer/game.js +62 -45
- package/examples/platformer/gameCharacter.js +42 -34
- package/examples/platformer/gameEffects.js +82 -75
- package/examples/platformer/gameLevel.js +67 -38
- package/examples/platformer/{gameLevelData.js → gameLevelData.json} +1 -11
- package/examples/platformer/gameObjects.js +70 -64
- package/examples/platformer/gamePlayer.js +12 -7
- package/examples/platformer/index.html +1 -9
- package/examples/puzzle/game.js +59 -40
- package/examples/puzzle/index.html +1 -3
- package/examples/shorts/base.html +3 -2
- package/examples/shorts/box2d.js +46 -0
- package/examples/shorts/box2dCar.js +49 -0
- package/examples/shorts/particles.js +1 -1
- package/examples/shorts/platformer.js +1 -1
- package/examples/shorts/postProcess.js +45 -0
- package/examples/shorts/tileLayer.js +5 -6
- package/examples/shorts/tiles.png +0 -0
- package/examples/shorts/uiSystem.js +39 -0
- package/examples/starter/game.js +9 -10
- package/examples/starter/index.html +13 -13
- package/examples/stress/index.html +44 -44
- package/examples/typescript/build.js +17 -18
- package/examples/typescript/game.js +32 -34
- package/examples/typescript/game.ts +32 -34
- package/examples/typescript/index.html +1 -1
- package/examples/uiSystem/game.js +34 -31
- package/examples/uiSystem/index.html +1 -5
- package/package.json +1 -1
- package/plugins/box2d.js +28 -30
- package/plugins/pluginExport.js +2 -3
- package/plugins/uiSystem.js +9 -3
- package/reference.md +29 -27
- package/src/engine.js +10 -11
- package/src/engineAudio.js +24 -15
- package/src/engineBuild.js +25 -8
- package/src/engineDebug.js +1 -3
- package/src/engineExport.js +3 -6
- package/src/engineInput.js +6 -4
- package/src/engineObject.js +18 -14
- package/src/engineSettings.js +6 -6
- package/src/engineTileLayer.js +179 -96
- package/src/engineUtilities.js +16 -0
- package/src/engineWebGL.js +13 -1
- package/examples/typescript/build/dist/littlejs.esm.js +0 -4834
- package/examples/typescript/build/examples/typescript/build.js +0 -24
- package/examples/typescript/build/examples/typescript/game.js +0 -102
package/dist/littlejs.esm.js
CHANGED
|
@@ -13,8 +13,6 @@
|
|
|
13
13
|
* @namespace Debug
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
16
|
/** True if debug is enabled
|
|
19
17
|
* @type {boolean}
|
|
20
18
|
* @default
|
|
@@ -334,11 +332,9 @@ function debugRender()
|
|
|
334
332
|
}
|
|
335
333
|
}
|
|
336
334
|
|
|
337
|
-
if (
|
|
335
|
+
if (tileCollisionLayers.length) // show floored tile pick if there is tile collision
|
|
338
336
|
drawRect(mousePos.floor().add(vec2(.5)), vec2(1), rgb(0,0,1,.5), 0, false);
|
|
339
337
|
mainContext = saveContext;
|
|
340
|
-
|
|
341
|
-
//glCopyToContext(mainContext = saveContext);
|
|
342
338
|
}
|
|
343
339
|
|
|
344
340
|
{
|
|
@@ -581,8 +577,6 @@ function debugVideoCaptureUpdate()
|
|
|
581
577
|
* @namespace Utilities
|
|
582
578
|
*/
|
|
583
579
|
|
|
584
|
-
|
|
585
|
-
|
|
586
580
|
/** A shortcut to get Math.PI
|
|
587
581
|
* @type {number}
|
|
588
582
|
* @default Math.PI
|
|
@@ -762,6 +756,16 @@ function wave(frequency=1, amplitude=1, t=time)
|
|
|
762
756
|
* @memberof Utilities */
|
|
763
757
|
function formatTime(t) { return (t/60|0) + ':' + (t%60<10?'0':'') + (t%60|0); }
|
|
764
758
|
|
|
759
|
+
/** Fetches a JSON file from a URL and returns the parsed JSON object. Must be used with await!
|
|
760
|
+
* @param {string} url - URL of JSON file
|
|
761
|
+
* @return {Promise<object>}
|
|
762
|
+
* @memberof Utilities */
|
|
763
|
+
async function fetchJSON(url)
|
|
764
|
+
{
|
|
765
|
+
const response = await fetch(url);
|
|
766
|
+
return response.json();
|
|
767
|
+
}
|
|
768
|
+
|
|
765
769
|
///////////////////////////////////////////////////////////////////////////////
|
|
766
770
|
|
|
767
771
|
/** Random global functions
|
|
@@ -857,6 +861,12 @@ class RandomGenerator
|
|
|
857
861
|
/** Randomly returns either -1 or 1 deterministically
|
|
858
862
|
* @return {number} */
|
|
859
863
|
sign() { return this.float() > .5 ? 1 : -1; }
|
|
864
|
+
|
|
865
|
+
/** Returns a seeded random value between the two values passed in with a random sign
|
|
866
|
+
* @param {number} [valueA]
|
|
867
|
+
* @param {number} [valueB]
|
|
868
|
+
* @return {number} */
|
|
869
|
+
floatSign(valueA=1, valueB=0) { return this.float(valueA, valueB) * this.sign(); }
|
|
860
870
|
}
|
|
861
871
|
|
|
862
872
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -1497,8 +1507,6 @@ class Timer
|
|
|
1497
1507
|
* @namespace Settings
|
|
1498
1508
|
*/
|
|
1499
1509
|
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
1510
|
///////////////////////////////////////////////////////////////////////////////
|
|
1503
1511
|
// Camera settings
|
|
1504
1512
|
|
|
@@ -1530,7 +1538,7 @@ let canvasMaxSize = vec2(1920, 1080);
|
|
|
1530
1538
|
* @memberof Settings */
|
|
1531
1539
|
let canvasFixedSize = vec2();
|
|
1532
1540
|
|
|
1533
|
-
/** Use nearest neighbor scaling
|
|
1541
|
+
/** Use nearest neighbor canvas scaling for more pixelated look
|
|
1534
1542
|
* - Must be set before startup to take effect
|
|
1535
1543
|
* - If enabled sets css image-rendering:pixelated
|
|
1536
1544
|
* @type {boolean}
|
|
@@ -1640,11 +1648,11 @@ let objectDefaultFriction = .8;
|
|
|
1640
1648
|
* @memberof Settings */
|
|
1641
1649
|
let objectMaxSpeed = 1;
|
|
1642
1650
|
|
|
1643
|
-
/** How much gravity to apply to objects
|
|
1644
|
-
* @type {
|
|
1651
|
+
/** How much gravity to apply to objects, negative Y is down
|
|
1652
|
+
* @type {Vector2}
|
|
1645
1653
|
* @default
|
|
1646
1654
|
* @memberof Settings */
|
|
1647
|
-
let gravity =
|
|
1655
|
+
let gravity = vec2();
|
|
1648
1656
|
|
|
1649
1657
|
/** Scales emit rate of particles, useful for low graphics mode (0 disables particle emitters)
|
|
1650
1658
|
* @type {number}
|
|
@@ -1870,8 +1878,8 @@ function setObjectDefaultFriction(friction) { objectDefaultFriction = friction;
|
|
|
1870
1878
|
* @memberof Settings */
|
|
1871
1879
|
function setObjectMaxSpeed(speed) { objectMaxSpeed = speed; }
|
|
1872
1880
|
|
|
1873
|
-
/** Set how much gravity to apply to objects
|
|
1874
|
-
* @param {
|
|
1881
|
+
/** Set how much gravity to apply to objects
|
|
1882
|
+
* @param {Vector2} newGravity
|
|
1875
1883
|
* @memberof Settings */
|
|
1876
1884
|
function setGravity(newGravity) { gravity = newGravity; }
|
|
1877
1885
|
|
|
@@ -1983,8 +1991,6 @@ function setDebugKey(key) { debugKey = key; }
|
|
|
1983
1991
|
* LittleJS Object System
|
|
1984
1992
|
*/
|
|
1985
1993
|
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
1994
|
/**
|
|
1989
1995
|
* LittleJS Object Base Object Class
|
|
1990
1996
|
* - Top level object class used by the engine
|
|
@@ -2139,7 +2145,10 @@ class EngineObject
|
|
|
2139
2145
|
this.velocity.x *= this.damping;
|
|
2140
2146
|
this.velocity.y *= this.damping;
|
|
2141
2147
|
if (this.mass) // don't apply gravity to static objects
|
|
2142
|
-
|
|
2148
|
+
{
|
|
2149
|
+
this.velocity.x += gravity.x * this.gravityScale;
|
|
2150
|
+
this.velocity.y += gravity.y * this.gravityScale;
|
|
2151
|
+
}
|
|
2143
2152
|
this.pos.x += this.velocity.x;
|
|
2144
2153
|
this.pos.y += this.velocity.y;
|
|
2145
2154
|
this.angle += this.angleVelocity *= this.angleDamping;
|
|
@@ -2154,9 +2163,9 @@ class EngineObject
|
|
|
2154
2163
|
if (this.groundObject)
|
|
2155
2164
|
{
|
|
2156
2165
|
// apply friction in local space of ground object
|
|
2157
|
-
const
|
|
2158
|
-
|
|
2159
|
-
this.velocity.x = groundSpeed + (this.velocity.x - groundSpeed) *
|
|
2166
|
+
const friction = max(this.friction, this.groundObject.friction);
|
|
2167
|
+
const groundSpeed = this.groundObject.velocity ? this.groundObject.velocity.x : 0;
|
|
2168
|
+
this.velocity.x = groundSpeed + (this.velocity.x - groundSpeed) * friction;
|
|
2160
2169
|
this.groundObject = undefined;
|
|
2161
2170
|
//debugOverlay && debugPhysics && debugPoint(this.pos.subtract(vec2(0,this.size.y/2)), '#0f0');
|
|
2162
2171
|
}
|
|
@@ -2198,7 +2207,7 @@ class EngineObject
|
|
|
2198
2207
|
|
|
2199
2208
|
// check for collision
|
|
2200
2209
|
const sizeBoth = this.size.add(o.size);
|
|
2201
|
-
const smallStepUp = (oldPos.y - o.pos.y)*2 > sizeBoth.y + gravity; // prefer to push up if small delta
|
|
2210
|
+
const smallStepUp = (oldPos.y - o.pos.y)*2 > sizeBoth.y + gravity.y; // prefer to push up if small delta
|
|
2202
2211
|
const isBlockedX = abs(oldPos.y - o.pos.y)*2 < sizeBoth.y;
|
|
2203
2212
|
const isBlockedY = abs(oldPos.x - o.pos.x)*2 < sizeBoth.x;
|
|
2204
2213
|
const elasticity = max(this.elasticity, o.elasticity);
|
|
@@ -2260,19 +2269,21 @@ class EngineObject
|
|
|
2260
2269
|
if (this.collideTiles)
|
|
2261
2270
|
{
|
|
2262
2271
|
// check collision against tiles
|
|
2263
|
-
|
|
2272
|
+
const hitLayer = tileCollisionTest(this.pos, this.size, this)
|
|
2273
|
+
if (hitLayer)
|
|
2264
2274
|
{
|
|
2265
2275
|
// if already was stuck in collision, don't do anything
|
|
2266
2276
|
// this should not happen unless something starts in collision
|
|
2267
2277
|
if (!tileCollisionTest(oldPos, this.size, this))
|
|
2268
2278
|
{
|
|
2269
2279
|
// test which side we bounced off (or both if a corner)
|
|
2270
|
-
const
|
|
2271
|
-
const
|
|
2272
|
-
if (
|
|
2280
|
+
const blockedLayerY = tileCollisionTest(vec2(oldPos.x, this.pos.y), this.size, this);
|
|
2281
|
+
const blockedLayerX = tileCollisionTest(vec2(this.pos.x, oldPos.y), this.size, this);
|
|
2282
|
+
if (blockedLayerY || !blockedLayerX)
|
|
2273
2283
|
{
|
|
2274
2284
|
// bounce velocity
|
|
2275
|
-
|
|
2285
|
+
const elasticity = max(this.elasticity, hitLayer.elasticity);
|
|
2286
|
+
this.velocity.y *= -elasticity;
|
|
2276
2287
|
|
|
2277
2288
|
if (wasMovingDown)
|
|
2278
2289
|
{
|
|
@@ -2281,9 +2292,8 @@ class EngineObject
|
|
|
2281
2292
|
const epsilon = .0001;
|
|
2282
2293
|
this.pos.y = (oldPos.y-this.size.y/2|0)+this.size.y/2+epsilon;
|
|
2283
2294
|
|
|
2284
|
-
// set ground object
|
|
2285
|
-
|
|
2286
|
-
this.groundObject = this;
|
|
2295
|
+
// set ground object for tile collision
|
|
2296
|
+
this.groundObject = hitLayer;
|
|
2287
2297
|
}
|
|
2288
2298
|
else
|
|
2289
2299
|
{
|
|
@@ -2292,7 +2302,7 @@ class EngineObject
|
|
|
2292
2302
|
this.groundObject = undefined;
|
|
2293
2303
|
}
|
|
2294
2304
|
}
|
|
2295
|
-
if (
|
|
2305
|
+
if (blockedLayerX)
|
|
2296
2306
|
{
|
|
2297
2307
|
// move to previous position and bounce
|
|
2298
2308
|
this.pos.x = oldPos.x;
|
|
@@ -2463,8 +2473,6 @@ class EngineObject
|
|
|
2463
2473
|
* @namespace Draw
|
|
2464
2474
|
*/
|
|
2465
2475
|
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
2476
|
/** The primary 2D canvas visible to the user
|
|
2469
2477
|
* @type {HTMLCanvasElement}
|
|
2470
2478
|
* @memberof Draw */
|
|
@@ -3086,8 +3094,6 @@ function setCursor(cursorStyle = 'auto')
|
|
|
3086
3094
|
* @namespace Input
|
|
3087
3095
|
*/
|
|
3088
3096
|
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
3097
|
/** Returns true if device key is down
|
|
3092
3098
|
* @param {string|number} key
|
|
3093
3099
|
* @param {number} [device]
|
|
@@ -3139,21 +3145,21 @@ function clearInput() { inputData = [[]]; touchGamepadButtons = []; }
|
|
|
3139
3145
|
* @param {number} button
|
|
3140
3146
|
* @return {boolean}
|
|
3141
3147
|
* @memberof Input */
|
|
3142
|
-
|
|
3148
|
+
function mouseIsDown(button) { return keyIsDown(button); }
|
|
3143
3149
|
|
|
3144
3150
|
/** Returns true if mouse button was pressed
|
|
3145
3151
|
* @function
|
|
3146
3152
|
* @param {number} button
|
|
3147
3153
|
* @return {boolean}
|
|
3148
3154
|
* @memberof Input */
|
|
3149
|
-
|
|
3155
|
+
function mouseWasPressed(button) { return keyWasPressed(button); }
|
|
3150
3156
|
|
|
3151
3157
|
/** Returns true if mouse button was released
|
|
3152
3158
|
* @function
|
|
3153
3159
|
* @param {number} button
|
|
3154
3160
|
* @return {boolean}
|
|
3155
3161
|
* @memberof Input */
|
|
3156
|
-
|
|
3162
|
+
function mouseWasReleased(button) { return keyWasReleased(button); }
|
|
3157
3163
|
|
|
3158
3164
|
/** Mouse pos in world space
|
|
3159
3165
|
* @type {Vector2}
|
|
@@ -3392,7 +3398,9 @@ function gamepadsUpdate()
|
|
|
3392
3398
|
const button = gamepad.buttons[j];
|
|
3393
3399
|
const wasDown = gamepadIsDown(j,i);
|
|
3394
3400
|
data[j] = button.pressed ? wasDown ? 1 : 3 : wasDown ? 4 : 0;
|
|
3395
|
-
|
|
3401
|
+
if (!button.value || button.value > .9) // must be a full press
|
|
3402
|
+
if (!i && button.pressed)
|
|
3403
|
+
isUsingGamepad = true;
|
|
3396
3404
|
}
|
|
3397
3405
|
|
|
3398
3406
|
if (gamepadDirectionEmulateStick)
|
|
@@ -3610,8 +3618,6 @@ function touchGamepadRender()
|
|
|
3610
3618
|
* @namespace Audio
|
|
3611
3619
|
*/
|
|
3612
3620
|
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
3621
|
/** Audio context used by the engine
|
|
3616
3622
|
* @type {AudioContext}
|
|
3617
3623
|
* @memberof Audio */
|
|
@@ -3648,17 +3654,17 @@ class Sound
|
|
|
3648
3654
|
{
|
|
3649
3655
|
/** Create a sound object and cache the zzfx samples for later use
|
|
3650
3656
|
* @param {Array} zzfxSound - Array of zzfx parameters, ex. [.5,.5]
|
|
3651
|
-
* @param {number} [range=soundDefaultRange] - World space max range of sound
|
|
3657
|
+
* @param {number} [range=soundDefaultRange] - World space max range of sound
|
|
3652
3658
|
* @param {number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering
|
|
3653
3659
|
*/
|
|
3654
3660
|
constructor(zzfxSound, range=soundDefaultRange, taper=soundDefaultTaper)
|
|
3655
3661
|
{
|
|
3656
3662
|
if (!soundEnable || headlessMode) return;
|
|
3657
3663
|
|
|
3658
|
-
/** @property {number} - World space max range of sound
|
|
3664
|
+
/** @property {number} - World space max range of sound */
|
|
3659
3665
|
this.range = range;
|
|
3660
3666
|
|
|
3661
|
-
/** @property {number} - At what percentage of range should it start tapering
|
|
3667
|
+
/** @property {number} - At what percentage of range should it start tapering */
|
|
3662
3668
|
this.taper = taper;
|
|
3663
3669
|
|
|
3664
3670
|
/** @property {number} - How much to randomize frequency each time sound plays */
|
|
@@ -3774,8 +3780,8 @@ class SoundWave extends Sound
|
|
|
3774
3780
|
/** Create a sound object and cache the wave file for later use
|
|
3775
3781
|
* @param {string} filename - Filename of audio file to load
|
|
3776
3782
|
* @param {number} [randomness] - How much to randomize frequency each time sound plays
|
|
3777
|
-
* @param {number} [range=soundDefaultRange] - World space max range of sound
|
|
3778
|
-
* @param {number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering
|
|
3783
|
+
* @param {number} [range=soundDefaultRange] - World space max range of sound
|
|
3784
|
+
* @param {number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering
|
|
3779
3785
|
* @param {Function} [onloadCallback] - callback function to call when sound is loaded
|
|
3780
3786
|
*/
|
|
3781
3787
|
constructor(filename, randomness=0, range, taper, onloadCallback)
|
|
@@ -3783,17 +3789,26 @@ class SoundWave extends Sound
|
|
|
3783
3789
|
super(undefined, range, taper);
|
|
3784
3790
|
if (!soundEnable || headlessMode) return;
|
|
3785
3791
|
|
|
3792
|
+
/** @property {Function} - callback function to call when sound is loaded */
|
|
3793
|
+
this.onloadCallback = onloadCallback;
|
|
3786
3794
|
this.randomness = randomness;
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3795
|
+
this.loadSound(filename);
|
|
3796
|
+
}
|
|
3797
|
+
|
|
3798
|
+
/** Loads a sound from a URL and decodes it into sample data. Must be used with await!
|
|
3799
|
+
* @param {string} filename
|
|
3800
|
+
* @return {Promise<void>} */
|
|
3801
|
+
async loadSound(filename)
|
|
3802
|
+
{
|
|
3803
|
+
const response = await fetch(filename);
|
|
3804
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
3805
|
+
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
|
|
3806
|
+
this.sampleChannels = [];
|
|
3807
|
+
for (let i = audioBuffer.numberOfChannels; i--;)
|
|
3808
|
+
this.sampleChannels[i] = Array.from(audioBuffer.getChannelData(i));
|
|
3809
|
+
this.sampleRate = audioBuffer.sampleRate;
|
|
3810
|
+
if (this.onloadCallback)
|
|
3811
|
+
this.onloadCallback();
|
|
3797
3812
|
}
|
|
3798
3813
|
}
|
|
3799
3814
|
|
|
@@ -4067,75 +4082,45 @@ function zzfxG
|
|
|
4067
4082
|
* LittleJS Tile Layer System
|
|
4068
4083
|
* - Caches arrays of tiles to off screen canvas for fast rendering
|
|
4069
4084
|
* - Unlimited numbers of layers, allocates canvases as needed
|
|
4070
|
-
* - Interfaces with EngineObject for collision
|
|
4071
|
-
* - Collision layer is separate from visible layers
|
|
4072
|
-
* - It is recommended to have a visible layer that matches the collision
|
|
4073
4085
|
* - Tile layers can be drawn to using their context with canvas2d
|
|
4074
4086
|
* - Drawn directly to the main canvas without using WebGL
|
|
4087
|
+
* - Tile layers can also have collision with EngineObjects
|
|
4075
4088
|
* @namespace TileCollision
|
|
4076
4089
|
*/
|
|
4077
4090
|
|
|
4091
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
4092
|
+
// Tile Layer System
|
|
4078
4093
|
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
* @type {Array<number>}
|
|
4082
|
-
* @memberof TileCollision */
|
|
4083
|
-
let tileCollision = [];
|
|
4084
|
-
|
|
4085
|
-
/** Size of the tile collision layer 2d grid
|
|
4086
|
-
* @type {Vector2}
|
|
4087
|
-
* @memberof TileCollision */
|
|
4088
|
-
let tileCollisionSize = vec2();
|
|
4089
|
-
|
|
4090
|
-
/** Clear and initialize tile collision
|
|
4091
|
-
* @param {Vector2} size - width and height of tile collision 2d grid
|
|
4092
|
-
* @memberof TileCollision */
|
|
4093
|
-
function initTileCollision(size)
|
|
4094
|
-
{
|
|
4095
|
-
tileCollisionSize = size;
|
|
4096
|
-
tileCollision = [];
|
|
4097
|
-
for (let i=tileCollision.length = tileCollisionSize.area(); i--;)
|
|
4098
|
-
tileCollision[i] = 0;
|
|
4099
|
-
}
|
|
4100
|
-
|
|
4101
|
-
/** Set tile collision data for a given cell in the grid
|
|
4102
|
-
* @param {Vector2} pos
|
|
4103
|
-
* @param {number} [data]
|
|
4094
|
+
/** Keep track of all tile layers with collision
|
|
4095
|
+
* @type {Array<TileCollisionLayer>}
|
|
4104
4096
|
* @memberof TileCollision */
|
|
4105
|
-
|
|
4106
|
-
{
|
|
4107
|
-
pos.arrayCheck(tileCollisionSize) && (tileCollision[(pos.y|0)*tileCollisionSize.x+pos.x|0] = data);
|
|
4108
|
-
}
|
|
4097
|
+
let tileCollisionLayers = [];
|
|
4109
4098
|
|
|
4110
4099
|
/** Get tile collision data for a given cell in the grid
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4100
|
+
* @param {Vector2} pos
|
|
4101
|
+
* @return {number}
|
|
4102
|
+
* @memberof TileCollision */
|
|
4114
4103
|
function getTileCollisionData(pos)
|
|
4115
4104
|
{
|
|
4116
|
-
|
|
4105
|
+
// check all tile collision layers
|
|
4106
|
+
for (const layer of tileCollisionLayers)
|
|
4107
|
+
if (pos.arrayCheck(layer.size))
|
|
4108
|
+
return layer.getCollisionData(pos);
|
|
4109
|
+
return 0;
|
|
4117
4110
|
}
|
|
4118
4111
|
|
|
4119
|
-
/** Check if
|
|
4112
|
+
/** Check if a tile layer collides with another object
|
|
4120
4113
|
* @param {Vector2} pos
|
|
4121
4114
|
* @param {Vector2} [size=(0,0)]
|
|
4122
4115
|
* @param {EngineObject} [object]
|
|
4123
|
-
* @return {
|
|
4116
|
+
* @return {TileCollisionLayer}
|
|
4124
4117
|
* @memberof TileCollision */
|
|
4125
4118
|
function tileCollisionTest(pos, size=vec2(), object)
|
|
4126
4119
|
{
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
for (let y = minY; y < maxY; ++y)
|
|
4132
|
-
for (let x = minX; x < maxX; ++x)
|
|
4133
|
-
{
|
|
4134
|
-
const tileData = tileCollision[y*tileCollisionSize.x+x];
|
|
4135
|
-
if (tileData && (!object || object.collideWithTile(tileData, vec2(x, y))))
|
|
4136
|
-
return true;
|
|
4137
|
-
}
|
|
4138
|
-
return false;
|
|
4120
|
+
// check all tile collision layers
|
|
4121
|
+
for (const layer of tileCollisionLayers)
|
|
4122
|
+
if (layer.collisionTest(pos, size, object))
|
|
4123
|
+
return layer;
|
|
4139
4124
|
}
|
|
4140
4125
|
|
|
4141
4126
|
/** Return the center of first tile hit, undefined if nothing was hit.
|
|
@@ -4147,49 +4132,17 @@ function tileCollisionTest(pos, size=vec2(), object)
|
|
|
4147
4132
|
* @memberof TileCollision */
|
|
4148
4133
|
function tileCollisionRaycast(posStart, posEnd, object)
|
|
4149
4134
|
{
|
|
4150
|
-
//
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
const flooredPosStart = posStart.floor();
|
|
4157
|
-
|
|
4158
|
-
// setup iteration variables
|
|
4159
|
-
let pos = flooredPosStart;
|
|
4160
|
-
let xi = unit.x * (delta.x < 0 ? posStart.x - pos.x : pos.x - posStart.x + 1);
|
|
4161
|
-
let yi = unit.y * (delta.y < 0 ? posStart.y - pos.y : pos.y - posStart.y + 1);
|
|
4162
|
-
|
|
4163
|
-
while (true)
|
|
4164
|
-
{
|
|
4165
|
-
// check for tile collision
|
|
4166
|
-
const tileData = getTileCollisionData(pos);
|
|
4167
|
-
if (tileData && (!object || object.collideWithTile(tileData, pos)))
|
|
4168
|
-
{
|
|
4169
|
-
debugRaycast && debugLine(posStart, posEnd, '#f00', .02);
|
|
4170
|
-
debugRaycast && debugPoint(pos.add(vec2(.5)), '#ff0');
|
|
4171
|
-
return pos.add(vec2(.5));
|
|
4172
|
-
}
|
|
4173
|
-
|
|
4174
|
-
// check if past the end
|
|
4175
|
-
if (xi > totalLength && yi > totalLength)
|
|
4176
|
-
break;
|
|
4177
|
-
|
|
4178
|
-
// get coordinates of the next tile to check
|
|
4179
|
-
if (xi > yi)
|
|
4180
|
-
pos.y += sign(delta.y), yi += unit.y;
|
|
4181
|
-
else
|
|
4182
|
-
pos.x += sign(delta.x), xi += unit.x;
|
|
4135
|
+
// check all tile collision layers
|
|
4136
|
+
for (const layer of tileCollisionLayers)
|
|
4137
|
+
{
|
|
4138
|
+
const hitPos = layer.collisionRaycast(posStart, posEnd, object)
|
|
4139
|
+
if (hitPos)
|
|
4140
|
+
return hitPos;
|
|
4183
4141
|
}
|
|
4184
|
-
|
|
4185
|
-
debugRaycast && debugLine(posStart, posEnd, '#00f', .02);
|
|
4186
4142
|
}
|
|
4187
4143
|
|
|
4188
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
4189
|
-
// Tile Layer Rendering System
|
|
4190
|
-
|
|
4191
4144
|
/**
|
|
4192
|
-
* Tile layer data object stores info about how to
|
|
4145
|
+
* Tile layer data object stores info about how to draw a tile
|
|
4193
4146
|
* @example
|
|
4194
4147
|
* // create tile layer data with tile index 0 and random orientation and color
|
|
4195
4148
|
* const tileIndex = 0;
|
|
@@ -4221,28 +4174,27 @@ class TileLayerData
|
|
|
4221
4174
|
clear() { this.tile = this.direction = 0; this.mirror = false; this.color = new Color; }
|
|
4222
4175
|
}
|
|
4223
4176
|
|
|
4177
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
4224
4178
|
/**
|
|
4225
4179
|
* Tile Layer - cached rendering system for tile layers
|
|
4226
4180
|
* - Each Tile layer is rendered to an off screen canvas
|
|
4227
4181
|
* - To allow dynamic modifications, layers are rendered using canvas 2d
|
|
4228
4182
|
* - Some devices like mobile phones are limited to 4k texture resolution
|
|
4229
|
-
* -
|
|
4183
|
+
* - For with 16x16 tiles this limits layers to 256x256 on mobile devices
|
|
4230
4184
|
* @extends EngineObject
|
|
4231
4185
|
* @example
|
|
4232
|
-
*
|
|
4233
|
-
* initTileCollision(vec2(200,100));
|
|
4234
|
-
* const tileLayer = new TileLayer();
|
|
4186
|
+
* const tileLayer = new TileLayer(vec2(), vec2(200,100));
|
|
4235
4187
|
*/
|
|
4236
4188
|
class TileLayer extends EngineObject
|
|
4237
4189
|
{
|
|
4238
4190
|
/** Create a tile layer object
|
|
4239
|
-
* @param {Vector2} [position=(0,0)]
|
|
4240
|
-
* @param {Vector2} [size=
|
|
4241
|
-
* @param {TileInfo} [tileInfo]
|
|
4242
|
-
* @param {Vector2} [scale=(1,1)]
|
|
4243
|
-
* @param {number} [renderOrder]
|
|
4191
|
+
* @param {Vector2} [position=(0,0)] - World space position
|
|
4192
|
+
* @param {Vector2} [size=(1,1)] - World space size
|
|
4193
|
+
* @param {TileInfo} [tileInfo] - Tile info for layer
|
|
4194
|
+
* @param {Vector2} [scale=(1,1)] - How much to scale this layer when rendered
|
|
4195
|
+
* @param {number} [renderOrder] - Objects are sorted by renderOrder
|
|
4244
4196
|
*/
|
|
4245
|
-
constructor(position, size
|
|
4197
|
+
constructor(position, size, tileInfo=tile(), scale=vec2(1), renderOrder=0)
|
|
4246
4198
|
{
|
|
4247
4199
|
super(position, size, tileInfo, 0, undefined, renderOrder);
|
|
4248
4200
|
|
|
@@ -4254,6 +4206,10 @@ class TileLayer extends EngineObject
|
|
|
4254
4206
|
this.scale = scale;
|
|
4255
4207
|
/** @property {boolean} - If true this layer will render to overlay canvas and appear above all objects */
|
|
4256
4208
|
this.isOverlay = false;
|
|
4209
|
+
// set no friction by default, applied friction is max of both objects
|
|
4210
|
+
this.friction = 0;
|
|
4211
|
+
// set no elasticity by default, applied elasticity is max of both objects
|
|
4212
|
+
this.elasticity = 0;
|
|
4257
4213
|
|
|
4258
4214
|
// init tile data
|
|
4259
4215
|
this.data = [];
|
|
@@ -4450,13 +4406,151 @@ class TileLayer extends EngineObject
|
|
|
4450
4406
|
* @param {number} [angle=0] */
|
|
4451
4407
|
drawRect(pos, size, color, angle)
|
|
4452
4408
|
{ this.drawTile(pos, size, undefined, color, angle); }
|
|
4409
|
+
}
|
|
4410
|
+
|
|
4411
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
4412
|
+
/**
|
|
4413
|
+
* Tile Collision Layer - a tile layer with collision
|
|
4414
|
+
* - adds collision data and functions to TileLayer
|
|
4415
|
+
* - there can be multiple tile collision layers
|
|
4416
|
+
* - tile collison layers should not overlap each other
|
|
4417
|
+
* @extends TileLayer
|
|
4418
|
+
*/
|
|
4419
|
+
class TileCollisionLayer extends TileLayer
|
|
4420
|
+
{
|
|
4421
|
+
/** Create a tile layer object
|
|
4422
|
+
* @param {Vector2} [position=(0,0)] - World space position
|
|
4423
|
+
* @param {Vector2} [size=(0,0)] - World space size
|
|
4424
|
+
* @param {TileInfo} [tileInfo] - Tile info for layer
|
|
4425
|
+
* @param {number} [renderOrder] - Objects are sorted by renderOrder
|
|
4426
|
+
*/
|
|
4427
|
+
constructor(position, size, tileInfo=tile(), renderOrder=0)
|
|
4428
|
+
{
|
|
4429
|
+
const scale = vec2(1); // collision layers are not scaled
|
|
4430
|
+
super(position, size.floor(), tileInfo, scale, renderOrder);
|
|
4431
|
+
|
|
4432
|
+
/** @property {Array<number>} - The tile collision grid */
|
|
4433
|
+
this.collisionData = [];
|
|
4434
|
+
this.initCollision(this.size);
|
|
4435
|
+
|
|
4436
|
+
// keep track of all collision layers
|
|
4437
|
+
tileCollisionLayers.push(this);
|
|
4438
|
+
}
|
|
4439
|
+
|
|
4440
|
+
/** Destroy this collision layer */
|
|
4441
|
+
destroy()
|
|
4442
|
+
{
|
|
4443
|
+
if (this.destroyed)
|
|
4444
|
+
return;
|
|
4445
|
+
|
|
4446
|
+
// remove from collision layers array and destroy
|
|
4447
|
+
const index = tileCollisionLayers.indexOf(this);
|
|
4448
|
+
ASSERT(index >= 0, 'tile collision layer not found in array');
|
|
4449
|
+
tileCollisionLayers.splice(index, 1);
|
|
4450
|
+
super.destroy();
|
|
4451
|
+
}
|
|
4452
|
+
|
|
4453
|
+
/** Clear and initialize tile collision to new size
|
|
4454
|
+
* @param {Vector2} size - width and height of tile collision 2d grid */
|
|
4455
|
+
initCollision(size)
|
|
4456
|
+
{
|
|
4457
|
+
this.size = size.floor();
|
|
4458
|
+
this.collisionData = [];
|
|
4459
|
+
this.collisionData.length = size.area();
|
|
4460
|
+
this.collisionData.fill(0);
|
|
4461
|
+
}
|
|
4462
|
+
|
|
4463
|
+
/** Set tile collision data for a given cell in the grid
|
|
4464
|
+
* @param {Vector2} pos
|
|
4465
|
+
* @param {number} [data] */
|
|
4466
|
+
setCollisionData(pos, data=1)
|
|
4467
|
+
{
|
|
4468
|
+
const i = (pos.y|0)*this.size.x + pos.x|0;
|
|
4469
|
+
pos.arrayCheck(this.size) && (this.collisionData[i] = data);
|
|
4470
|
+
}
|
|
4471
|
+
|
|
4472
|
+
/** Get tile collision data for a given cell in the grid
|
|
4473
|
+
* @param {Vector2} pos
|
|
4474
|
+
* @return {number} */
|
|
4475
|
+
getCollisionData(pos)
|
|
4476
|
+
{
|
|
4477
|
+
const i = (pos.y|0)*this.size.x + pos.x|0;
|
|
4478
|
+
return pos.arrayCheck(this.size) ? this.collisionData[i] : 0;
|
|
4479
|
+
}
|
|
4480
|
+
|
|
4481
|
+
/** Check if collision with another object should occur
|
|
4482
|
+
* @param {Vector2} pos
|
|
4483
|
+
* @param {Vector2} [size=(0,0)]
|
|
4484
|
+
* @param {EngineObject} [object]
|
|
4485
|
+
* @return {boolean} */
|
|
4486
|
+
collisionTest(pos, size=vec2(), object)
|
|
4487
|
+
{
|
|
4488
|
+
const minX = max(pos.x - size.x/2|0, 0);
|
|
4489
|
+
const minY = max(pos.y - size.y/2|0, 0);
|
|
4490
|
+
const maxX = min(pos.x + size.x/2, this.size.x);
|
|
4491
|
+
const maxY = min(pos.y + size.y/2, this.size.y);
|
|
4492
|
+
for (let y = minY; y < maxY; ++y)
|
|
4493
|
+
for (let x = minX; x < maxX; ++x)
|
|
4494
|
+
{
|
|
4495
|
+
// check if the object should collide with this tile
|
|
4496
|
+
const tileData = this.collisionData[y*this.size.x+x];
|
|
4497
|
+
if (tileData && (!object || object.collideWithTile(tileData, vec2(x, y))))
|
|
4498
|
+
return true;
|
|
4499
|
+
}
|
|
4500
|
+
return false;
|
|
4501
|
+
}
|
|
4502
|
+
|
|
4503
|
+
/** Return the center of first tile hit, undefined if nothing was hit.
|
|
4504
|
+
* This does not return the exact intersection, but the center of the tile hit.
|
|
4505
|
+
* @param {Vector2} posStart
|
|
4506
|
+
* @param {Vector2} posEnd
|
|
4507
|
+
* @param {EngineObject} [object]
|
|
4508
|
+
* @return {Vector2} */
|
|
4509
|
+
collisionRaycast(posStart, posEnd, object)
|
|
4510
|
+
{
|
|
4511
|
+
// test if a ray collides with tiles from start to end
|
|
4512
|
+
// todo: a way to get the exact hit point, it must still be inside the hit tile
|
|
4513
|
+
const delta = posEnd.subtract(posStart);
|
|
4514
|
+
const totalLength = delta.length();
|
|
4515
|
+
const normalizedDelta = delta.normalize();
|
|
4516
|
+
const unit = vec2(abs(1/normalizedDelta.x), abs(1/normalizedDelta.y));
|
|
4517
|
+
const flooredPosStart = posStart.floor();
|
|
4518
|
+
|
|
4519
|
+
// setup iteration variables
|
|
4520
|
+
let pos = flooredPosStart;
|
|
4521
|
+
let xi = unit.x * (delta.x < 0 ? posStart.x - pos.x : pos.x - posStart.x + 1);
|
|
4522
|
+
let yi = unit.y * (delta.y < 0 ? posStart.y - pos.y : pos.y - posStart.y + 1);
|
|
4523
|
+
|
|
4524
|
+
// use line drawing algorithm to test for collisions
|
|
4525
|
+
while (true)
|
|
4526
|
+
{
|
|
4527
|
+
// check for tile collision
|
|
4528
|
+
const tileData = this.getCollisionData(pos);
|
|
4529
|
+
if (tileData && (!object || object.collideWithTile(tileData, pos)))
|
|
4530
|
+
{
|
|
4531
|
+
debugRaycast && debugLine(posStart, posEnd, '#f00', .02);
|
|
4532
|
+
debugRaycast && debugPoint(pos.add(vec2(.5)), '#ff0');
|
|
4533
|
+
return pos.add(vec2(.5));
|
|
4534
|
+
}
|
|
4535
|
+
|
|
4536
|
+
// check if past the end
|
|
4537
|
+
if (xi > totalLength && yi > totalLength)
|
|
4538
|
+
break;
|
|
4539
|
+
|
|
4540
|
+
// get coordinates of next tile to check
|
|
4541
|
+
if (xi > yi)
|
|
4542
|
+
pos.y += sign(delta.y), yi += unit.y;
|
|
4543
|
+
else
|
|
4544
|
+
pos.x += sign(delta.x), xi += unit.x;
|
|
4545
|
+
}
|
|
4546
|
+
|
|
4547
|
+
debugRaycast && debugLine(posStart, posEnd, '#00f', .02);
|
|
4548
|
+
}
|
|
4453
4549
|
}
|
|
4454
4550
|
/**
|
|
4455
4551
|
* LittleJS Particle System
|
|
4456
4552
|
*/
|
|
4457
4553
|
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
4554
|
/**
|
|
4461
4555
|
* Particle Emitter - Spawns particles with the given settings
|
|
4462
4556
|
* @extends EngineObject
|
|
@@ -4801,8 +4895,6 @@ class Particle extends EngineObject
|
|
|
4801
4895
|
* @namespace Medals
|
|
4802
4896
|
*/
|
|
4803
4897
|
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
4898
|
/** List of all medals
|
|
4807
4899
|
* @type {Object}
|
|
4808
4900
|
* @memberof Medals */
|
|
@@ -4990,8 +5082,6 @@ class Medal
|
|
|
4990
5082
|
* @namespace WebGL
|
|
4991
5083
|
*/
|
|
4992
5084
|
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
5085
|
/** The WebGL canvas which appears above the main canvas and below the overlay canvas
|
|
4996
5086
|
* @type {HTMLCanvasElement}
|
|
4997
5087
|
* @memberof WebGL */
|
|
@@ -5190,7 +5280,19 @@ function glCreateTexture(image)
|
|
|
5190
5280
|
const texture = glContext.createTexture();
|
|
5191
5281
|
glContext.bindTexture(glContext.TEXTURE_2D, texture);
|
|
5192
5282
|
if (image && image.width)
|
|
5283
|
+
{
|
|
5193
5284
|
glSetTextureData(texture, image);
|
|
5285
|
+
|
|
5286
|
+
const isPowerOfTwo = (value)=> !(value & (value - 1));
|
|
5287
|
+
if (!tilesPixelated && isPowerOfTwo(image.width) && isPowerOfTwo(image.height))
|
|
5288
|
+
{
|
|
5289
|
+
// use mipmap filtering
|
|
5290
|
+
glContext.generateMipmap(glContext.TEXTURE_2D);
|
|
5291
|
+
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MIN_FILTER, glContext.LINEAR_MIPMAP_LINEAR);
|
|
5292
|
+
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MAG_FILTER, glContext.LINEAR);
|
|
5293
|
+
return texture;
|
|
5294
|
+
}
|
|
5295
|
+
}
|
|
5194
5296
|
else
|
|
5195
5297
|
{
|
|
5196
5298
|
// create a white texture
|
|
@@ -5198,7 +5300,7 @@ function glCreateTexture(image)
|
|
|
5198
5300
|
glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, 1, 1, 0, glContext.RGBA, glContext.UNSIGNED_BYTE, whitePixel);
|
|
5199
5301
|
}
|
|
5200
5302
|
|
|
5201
|
-
//
|
|
5303
|
+
// set texture filtering
|
|
5202
5304
|
const filter = tilesPixelated ? glContext.NEAREST : glContext.LINEAR;
|
|
5203
5305
|
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MIN_FILTER, filter);
|
|
5204
5306
|
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MAG_FILTER, filter);
|
|
@@ -5314,8 +5416,6 @@ function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba=-1, rgba
|
|
|
5314
5416
|
* @namespace Engine
|
|
5315
5417
|
*/
|
|
5316
5418
|
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
5419
|
/** Name of engine
|
|
5320
5420
|
* @type {string}
|
|
5321
5421
|
* @default
|
|
@@ -5326,7 +5426,7 @@ const engineName = 'LittleJS';
|
|
|
5326
5426
|
* @type {string}
|
|
5327
5427
|
* @default
|
|
5328
5428
|
* @memberof Engine */
|
|
5329
|
-
const engineVersion = '1.
|
|
5429
|
+
const engineVersion = '1.12.6';
|
|
5330
5430
|
|
|
5331
5431
|
/** Frames per second to update
|
|
5332
5432
|
* @type {number}
|
|
@@ -5408,7 +5508,7 @@ function engineAddPlugin(updateFunction, renderFunction)
|
|
|
5408
5508
|
* @param {Array<string>} [imageSources=[]] - List of images to load
|
|
5409
5509
|
* @param {HTMLElement} [rootElement] - Root element to attach to, the document body by default
|
|
5410
5510
|
* @memberof Engine */
|
|
5411
|
-
function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, imageSources=[], rootElement=document.body)
|
|
5511
|
+
async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, imageSources=[], rootElement=document.body)
|
|
5412
5512
|
{
|
|
5413
5513
|
ASSERT(!mainContext, 'engine already initialized');
|
|
5414
5514
|
ASSERT(Array.isArray(imageSources), 'pass in images as array');
|
|
@@ -5565,16 +5665,14 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
5565
5665
|
mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
|
|
5566
5666
|
}
|
|
5567
5667
|
|
|
5568
|
-
|
|
5668
|
+
// wait for gameInit to load
|
|
5669
|
+
async function startEngine()
|
|
5569
5670
|
{
|
|
5570
|
-
|
|
5671
|
+
await gameInit();
|
|
5672
|
+
engineUpdate();
|
|
5571
5673
|
}
|
|
5572
|
-
|
|
5573
5674
|
if (headlessMode)
|
|
5574
|
-
|
|
5575
|
-
startEngine();
|
|
5576
|
-
return;
|
|
5577
|
-
}
|
|
5675
|
+
return startEngine();
|
|
5578
5676
|
|
|
5579
5677
|
// setup html
|
|
5580
5678
|
const styleRoot =
|
|
@@ -5650,8 +5748,9 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
5650
5748
|
}));
|
|
5651
5749
|
}
|
|
5652
5750
|
|
|
5653
|
-
//
|
|
5654
|
-
Promise.all(promises)
|
|
5751
|
+
// wait for all the promises to finish
|
|
5752
|
+
await Promise.all(promises);
|
|
5753
|
+
return startEngine();
|
|
5655
5754
|
}
|
|
5656
5755
|
|
|
5657
5756
|
/** Update each engine object, remove destroyed objects, and update time
|
|
@@ -5920,459 +6019,154 @@ function drawEngineSplashScreen(t)
|
|
|
5920
6019
|
x.restore();
|
|
5921
6020
|
}
|
|
5922
6021
|
|
|
5923
|
-
|
|
6022
|
+
/**
|
|
6023
|
+
* LittleJS Newgrounds API
|
|
6024
|
+
* - NewgroundsMedal extends Medal with Newgrounds API functionality
|
|
6025
|
+
* - Call new NewgroundsPlugin() to setup Newgrounds
|
|
6026
|
+
* - Uses CryptoJS for encryption if optional cipher is provided
|
|
6027
|
+
* - Keeps connection alive and logs views
|
|
6028
|
+
* - Functions to interact with scoreboards
|
|
6029
|
+
* - Functions to unlock medals
|
|
6030
|
+
*/
|
|
6031
|
+
|
|
6032
|
+
/** Global Newgrounds object
|
|
6033
|
+
* @type {NewgroundsPlugin}
|
|
6034
|
+
* @memberof Medal */
|
|
6035
|
+
let newgrounds;
|
|
6036
|
+
|
|
6037
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5924
6038
|
/**
|
|
5925
|
-
*
|
|
6039
|
+
* Newgrounds medal auto unlocks in newgrounds API
|
|
6040
|
+
* @extends Medal
|
|
5926
6041
|
*/
|
|
6042
|
+
class NewgroundsMedal extends Medal
|
|
6043
|
+
{
|
|
6044
|
+
/** Create a newgrounds medal object and adds it to the list of medals
|
|
6045
|
+
* @param {Number} id - The unique identifier of the medal
|
|
6046
|
+
* @param {String} name - Name of the medal
|
|
6047
|
+
* @param {String} [description] - Description of the medal
|
|
6048
|
+
* @param {String} [icon] - Icon for the medal
|
|
6049
|
+
* @param {String} [src] - Image location for the medal
|
|
6050
|
+
*/
|
|
6051
|
+
constructor(id, name, description, icon, src)
|
|
6052
|
+
{ super(id, name, description, icon, src); }
|
|
5927
6053
|
|
|
5928
|
-
|
|
6054
|
+
/** Unlocks a medal if not already unlocked */
|
|
6055
|
+
unlock()
|
|
6056
|
+
{
|
|
6057
|
+
super.unlock();
|
|
6058
|
+
newgrounds && newgrounds.unlockMedal(this.id);
|
|
6059
|
+
}
|
|
6060
|
+
}
|
|
5929
6061
|
|
|
5930
|
-
|
|
6062
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
6063
|
+
/**
|
|
6064
|
+
* Newgrounds API object
|
|
6065
|
+
*/
|
|
6066
|
+
class NewgroundsPlugin
|
|
5931
6067
|
{
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
engineObjectsDestroy,
|
|
5946
|
-
engineObjectsCollect,
|
|
5947
|
-
engineObjectsCallback,
|
|
5948
|
-
engineObjectsRaycast,
|
|
5949
|
-
engineAddPlugin,
|
|
6068
|
+
/** Create the global newgrounds object
|
|
6069
|
+
* @param {string} app_id - The newgrounds App ID
|
|
6070
|
+
* @param {string} [cipher] - The encryption Key (AES-128/Base64)
|
|
6071
|
+
* @param {Object} [cryptoJS] - An instance of CryptoJS, if there is a cipher
|
|
6072
|
+
* @example
|
|
6073
|
+
* // create the newgrounds object, replace the app id with your own
|
|
6074
|
+
* const app_id = 'your_app_id_here';
|
|
6075
|
+
* new NewgroundsPlugin(app_id);
|
|
6076
|
+
*/
|
|
6077
|
+
constructor(app_id, cipher, cryptoJS)
|
|
6078
|
+
{
|
|
6079
|
+
ASSERT(!newgrounds, 'there can only be one newgrounds object');
|
|
6080
|
+
ASSERT(!cipher || cryptoJS, 'must provide cryptojs if there is a cipher');
|
|
5950
6081
|
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
6082
|
+
newgrounds = this; // set global newgrounds object
|
|
6083
|
+
this.app_id = app_id;
|
|
6084
|
+
this.cipher = cipher;
|
|
6085
|
+
this.cryptoJS = cryptoJS;
|
|
6086
|
+
this.host = location ? location.hostname : '';
|
|
5955
6087
|
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
debugPoly,
|
|
5960
|
-
debugCircle,
|
|
5961
|
-
debugPoint,
|
|
5962
|
-
debugLine,
|
|
5963
|
-
debugOverlap,
|
|
5964
|
-
debugText,
|
|
5965
|
-
debugClear,
|
|
5966
|
-
debugScreenshot,
|
|
5967
|
-
debugSaveCanvas,
|
|
5968
|
-
debugSaveText,
|
|
5969
|
-
debugSaveDataURL,
|
|
5970
|
-
debugShowErrors,
|
|
5971
|
-
debugVideoCaptureIsActive,
|
|
5972
|
-
debugVideoCaptureStart,
|
|
5973
|
-
debugVideoCaptureStop,
|
|
6088
|
+
// get session id from url search params
|
|
6089
|
+
const url = new URL(location.href);
|
|
6090
|
+
this.session_id = url.searchParams.get('ngio_session_id');
|
|
5974
6091
|
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
cameraScale,
|
|
5978
|
-
canvasMaxSize,
|
|
5979
|
-
canvasFixedSize,
|
|
5980
|
-
canvasPixelated,
|
|
5981
|
-
tilesPixelated,
|
|
5982
|
-
fontDefault,
|
|
5983
|
-
showSplashScreen,
|
|
5984
|
-
headlessMode,
|
|
5985
|
-
tileSizeDefault,
|
|
5986
|
-
tileFixBleedScale,
|
|
5987
|
-
enablePhysicsSolver,
|
|
5988
|
-
objectDefaultMass,
|
|
5989
|
-
objectDefaultDamping,
|
|
5990
|
-
objectDefaultAngleDamping,
|
|
5991
|
-
objectDefaultElasticity,
|
|
5992
|
-
objectDefaultFriction,
|
|
5993
|
-
objectMaxSpeed,
|
|
5994
|
-
gravity,
|
|
5995
|
-
particleEmitRateScale,
|
|
5996
|
-
glEnable,
|
|
5997
|
-
glOverlay,
|
|
5998
|
-
gamepadsEnable,
|
|
5999
|
-
gamepadDirectionEmulateStick,
|
|
6000
|
-
inputWASDEmulateDirection,
|
|
6001
|
-
touchGamepadEnable,
|
|
6002
|
-
touchGamepadAnalog,
|
|
6003
|
-
touchGamepadSize,
|
|
6004
|
-
touchGamepadAlpha,
|
|
6005
|
-
vibrateEnable,
|
|
6006
|
-
soundEnable,
|
|
6007
|
-
soundVolume,
|
|
6008
|
-
soundDefaultRange,
|
|
6009
|
-
soundDefaultTaper,
|
|
6010
|
-
medalDisplayTime,
|
|
6011
|
-
medalDisplaySlideTime,
|
|
6012
|
-
medalDisplaySize,
|
|
6092
|
+
if (!this.session_id)
|
|
6093
|
+
return; // only use newgrounds when logged in
|
|
6013
6094
|
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
setObjectDefaultAngleDamping,
|
|
6032
|
-
setObjectDefaultElasticity,
|
|
6033
|
-
setObjectDefaultFriction,
|
|
6034
|
-
setObjectMaxSpeed,
|
|
6035
|
-
setGravity,
|
|
6036
|
-
setParticleEmitRateScale,
|
|
6037
|
-
setTouchInputEnable,
|
|
6038
|
-
setGamepadsEnable,
|
|
6039
|
-
setGamepadDirectionEmulateStick,
|
|
6040
|
-
setInputWASDEmulateDirection,
|
|
6041
|
-
setTouchGamepadEnable,
|
|
6042
|
-
setTouchGamepadAnalog,
|
|
6043
|
-
setTouchGamepadSize,
|
|
6044
|
-
setTouchGamepadAlpha,
|
|
6045
|
-
setVibrateEnable,
|
|
6046
|
-
setSoundEnable,
|
|
6047
|
-
setSoundVolume,
|
|
6048
|
-
setSoundDefaultRange,
|
|
6049
|
-
setSoundDefaultTaper,
|
|
6050
|
-
setMedalDisplayTime,
|
|
6051
|
-
setMedalDisplaySlideTime,
|
|
6052
|
-
setMedalDisplaySize,
|
|
6053
|
-
setMedalsPreventUnlock,
|
|
6054
|
-
setShowWatermark,
|
|
6055
|
-
setDebugKey,
|
|
6095
|
+
// get medals
|
|
6096
|
+
const medalsResult = this.call('Medal.getList');
|
|
6097
|
+
this.medals = medalsResult ? medalsResult.result.data['medals'] : [];
|
|
6098
|
+
debugMedals && console.log(this.medals);
|
|
6099
|
+
for (const newgroundsMedal of this.medals)
|
|
6100
|
+
{
|
|
6101
|
+
const medal = medals[newgroundsMedal['id']];
|
|
6102
|
+
if (medal)
|
|
6103
|
+
{
|
|
6104
|
+
// copy newgrounds medal data
|
|
6105
|
+
medal.image = new Image;
|
|
6106
|
+
medal.image.src = newgroundsMedal['icon'];
|
|
6107
|
+
medal.name = newgroundsMedal['name'];
|
|
6108
|
+
medal.description = newgroundsMedal['description'];
|
|
6109
|
+
medal.unlocked = newgroundsMedal['unlocked'];
|
|
6110
|
+
medal.difficulty = newgroundsMedal['difficulty'];
|
|
6111
|
+
medal.value = newgroundsMedal['value'];
|
|
6056
6112
|
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
distanceWrap,
|
|
6067
|
-
lerpWrap,
|
|
6068
|
-
distanceAngle,
|
|
6069
|
-
lerpAngle,
|
|
6070
|
-
lerp,
|
|
6071
|
-
smoothStep,
|
|
6072
|
-
nearestPowerOfTwo,
|
|
6073
|
-
isOverlapping,
|
|
6074
|
-
isIntersecting,
|
|
6075
|
-
wave,
|
|
6076
|
-
formatTime,
|
|
6113
|
+
if (medal.value) // add value to description
|
|
6114
|
+
medal.description = medal.description + ` (${ medal.value })`;
|
|
6115
|
+
}
|
|
6116
|
+
}
|
|
6117
|
+
|
|
6118
|
+
// get scoreboards
|
|
6119
|
+
const scoreboardResult = this.call('ScoreBoard.getBoards');
|
|
6120
|
+
this.scoreboards = scoreboardResult ? scoreboardResult.result.data.scoreboards : [];
|
|
6121
|
+
debugMedals && console.log(this.scoreboards);
|
|
6077
6122
|
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
randInCircle,
|
|
6083
|
-
randVector,
|
|
6084
|
-
randColor,
|
|
6123
|
+
// keep the session alive with a ping every minute
|
|
6124
|
+
const keepAliveMS = 60 * 1e3;
|
|
6125
|
+
setInterval(()=>this.call('Gateway.ping', 0, true), keepAliveMS);
|
|
6126
|
+
}
|
|
6085
6127
|
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
Color,
|
|
6090
|
-
Timer,
|
|
6091
|
-
vec2,
|
|
6092
|
-
rgb,
|
|
6093
|
-
hsl,
|
|
6094
|
-
isColor,
|
|
6128
|
+
/** Send message to unlock a medal by id
|
|
6129
|
+
* @param {number} id - The medal id */
|
|
6130
|
+
unlockMedal(id) { return this.call('Medal.unlock', {'id':id}, true); }
|
|
6095
6131
|
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
RED,
|
|
6101
|
-
ORANGE,
|
|
6102
|
-
YELLOW,
|
|
6103
|
-
GREEN,
|
|
6104
|
-
CYAN,
|
|
6105
|
-
BLUE,
|
|
6106
|
-
PURPLE,
|
|
6107
|
-
MAGENTA,
|
|
6132
|
+
/** Send message to post score
|
|
6133
|
+
* @param {number} id - The scoreboard id
|
|
6134
|
+
* @param {number} value - The score value */
|
|
6135
|
+
postScore(id, value) { return this.call('ScoreBoard.postScore', {'id':id, 'value':value}, true); }
|
|
6108
6136
|
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
screenToWorld,
|
|
6120
|
-
worldToScreen,
|
|
6121
|
-
drawTile,
|
|
6122
|
-
drawRect,
|
|
6123
|
-
drawLine,
|
|
6124
|
-
drawPoly,
|
|
6125
|
-
drawEllipse,
|
|
6126
|
-
drawCircle,
|
|
6127
|
-
drawCanvas2D,
|
|
6128
|
-
drawText,
|
|
6129
|
-
drawTextOverlay,
|
|
6130
|
-
drawTextScreen,
|
|
6131
|
-
setBlendMode,
|
|
6132
|
-
combineCanvases,
|
|
6133
|
-
engineFontImage,
|
|
6134
|
-
FontImage,
|
|
6135
|
-
isFullscreen,
|
|
6136
|
-
toggleFullscreen,
|
|
6137
|
-
setCursor,
|
|
6138
|
-
getCameraSize,
|
|
6137
|
+
/** Get scores from a scoreboard
|
|
6138
|
+
* @param {number} id - The scoreboard id
|
|
6139
|
+
* @param {string} [user] - A user's id or name
|
|
6140
|
+
* @param {number} [social] - If true, only social scores will be loaded
|
|
6141
|
+
* @param {number} [skip] - Number of scores to skip before start
|
|
6142
|
+
* @param {number} [limit] - Number of scores to include in the list
|
|
6143
|
+
* @return {Object} - The response JSON object
|
|
6144
|
+
*/
|
|
6145
|
+
getScores(id, user, social=0, skip=0, limit=10)
|
|
6146
|
+
{ return this.call('ScoreBoard.getScores', {'id':id, 'user':user, 'social':social, 'skip':skip, 'limit':limit}); }
|
|
6139
6147
|
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
glContext,
|
|
6143
|
-
glCompileShader,
|
|
6144
|
-
glCopyToContext,
|
|
6145
|
-
glCreateProgram,
|
|
6146
|
-
glCreateTexture,
|
|
6147
|
-
glSetTextureData,
|
|
6148
|
-
glDraw,
|
|
6149
|
-
glFlush,
|
|
6150
|
-
glSetTexture,
|
|
6151
|
-
glSetAntialias,
|
|
6152
|
-
glClearCanvas,
|
|
6153
|
-
glAntialias,
|
|
6154
|
-
glShader,
|
|
6155
|
-
glActiveTexture,
|
|
6156
|
-
glArrayBuffer,
|
|
6157
|
-
glGeometryBuffer,
|
|
6158
|
-
glPositionData,
|
|
6159
|
-
glColorData,
|
|
6160
|
-
glInstanceCount,
|
|
6161
|
-
glAdditive,
|
|
6162
|
-
glBatchAdditive,
|
|
6148
|
+
/** Send message to log a view */
|
|
6149
|
+
logView() { return this.call('App.logView', {'host':this.host}, true); }
|
|
6163
6150
|
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
gamepadsUpdate,
|
|
6184
|
-
vibrate,
|
|
6185
|
-
vibrateStop,
|
|
6186
|
-
isTouchDevice,
|
|
6187
|
-
|
|
6188
|
-
// Audio
|
|
6189
|
-
Sound,
|
|
6190
|
-
SoundWave,
|
|
6191
|
-
playAudioFile,
|
|
6192
|
-
speak,
|
|
6193
|
-
speakStop,
|
|
6194
|
-
getNoteFrequency,
|
|
6195
|
-
playSamples,
|
|
6196
|
-
zzfx,
|
|
6197
|
-
zzfxG,
|
|
6198
|
-
zzfxR,
|
|
6199
|
-
audioContext,
|
|
6200
|
-
|
|
6201
|
-
// Base Object
|
|
6202
|
-
EngineObject,
|
|
6203
|
-
|
|
6204
|
-
// Tiles
|
|
6205
|
-
tileCollision,
|
|
6206
|
-
tileCollisionSize,
|
|
6207
|
-
initTileCollision,
|
|
6208
|
-
setTileCollisionData,
|
|
6209
|
-
getTileCollisionData,
|
|
6210
|
-
tileCollisionTest,
|
|
6211
|
-
tileCollisionRaycast,
|
|
6212
|
-
TileLayerData,
|
|
6213
|
-
TileLayer,
|
|
6214
|
-
|
|
6215
|
-
// Particles
|
|
6216
|
-
ParticleEmitter,
|
|
6217
|
-
Particle,
|
|
6218
|
-
|
|
6219
|
-
// Medals
|
|
6220
|
-
medals,
|
|
6221
|
-
medalsPreventUnlock,
|
|
6222
|
-
medalsInit,
|
|
6223
|
-
Medal,
|
|
6224
|
-
};
|
|
6225
|
-
|
|
6226
|
-
/**
|
|
6227
|
-
* LittleJS Newgrounds API
|
|
6228
|
-
* - NewgroundsMedal extends Medal with Newgrounds API functionality
|
|
6229
|
-
* - Call new NewgroundsPlugin() to setup Newgrounds
|
|
6230
|
-
* - Uses CryptoJS for encryption if optional cipher is provided
|
|
6231
|
-
* - Keeps connection alive and logs views
|
|
6232
|
-
* - Functions to interact with scoreboards
|
|
6233
|
-
* - Functions to unlock medals
|
|
6234
|
-
*/
|
|
6235
|
-
|
|
6236
|
-
'use strict';
|
|
6237
|
-
|
|
6238
|
-
/** Global Newgrounds object
|
|
6239
|
-
* @type {NewgroundsPlugin}
|
|
6240
|
-
* @memberof Medal */
|
|
6241
|
-
let newgrounds;
|
|
6242
|
-
|
|
6243
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
6244
|
-
/**
|
|
6245
|
-
* Newgrounds medal auto unlocks in newgrounds API
|
|
6246
|
-
* @extends Medal
|
|
6247
|
-
*/
|
|
6248
|
-
class NewgroundsMedal extends Medal
|
|
6249
|
-
{
|
|
6250
|
-
/** Create a newgrounds medal object and adds it to the list of medals
|
|
6251
|
-
* @param {Number} id - The unique identifier of the medal
|
|
6252
|
-
* @param {String} name - Name of the medal
|
|
6253
|
-
* @param {String} [description] - Description of the medal
|
|
6254
|
-
* @param {String} [icon] - Icon for the medal
|
|
6255
|
-
* @param {String} [src] - Image location for the medal
|
|
6256
|
-
*/
|
|
6257
|
-
constructor(id, name, description, icon, src)
|
|
6258
|
-
{ super(id, name, description, icon, src); }
|
|
6259
|
-
|
|
6260
|
-
/** Unlocks a medal if not already unlocked */
|
|
6261
|
-
unlock()
|
|
6262
|
-
{
|
|
6263
|
-
super.unlock();
|
|
6264
|
-
newgrounds && newgrounds.unlockMedal(this.id);
|
|
6265
|
-
}
|
|
6266
|
-
}
|
|
6267
|
-
|
|
6268
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
6269
|
-
/**
|
|
6270
|
-
* Newgrounds API object
|
|
6271
|
-
*/
|
|
6272
|
-
class NewgroundsPlugin
|
|
6273
|
-
{
|
|
6274
|
-
/** Create the global newgrounds object
|
|
6275
|
-
* @param {string} app_id - The newgrounds App ID
|
|
6276
|
-
* @param {string} [cipher] - The encryption Key (AES-128/Base64)
|
|
6277
|
-
* @param {Object} [cryptoJS] - An instance of CryptoJS, if there is a cipher
|
|
6278
|
-
* @example
|
|
6279
|
-
* // create the newgrounds object, replace the app id with your own
|
|
6280
|
-
* const app_id = 'your_app_id_here';
|
|
6281
|
-
* new NewgroundsPlugin(app_id);
|
|
6282
|
-
*/
|
|
6283
|
-
constructor(app_id, cipher, cryptoJS)
|
|
6284
|
-
{
|
|
6285
|
-
ASSERT(!newgrounds, 'there can only be one newgrounds object');
|
|
6286
|
-
ASSERT(!cipher || cryptoJS, 'must provide cryptojs if there is a cipher');
|
|
6287
|
-
|
|
6288
|
-
newgrounds = this; // set global newgrounds object
|
|
6289
|
-
this.app_id = app_id;
|
|
6290
|
-
this.cipher = cipher;
|
|
6291
|
-
this.cryptoJS = cryptoJS;
|
|
6292
|
-
this.host = location ? location.hostname : '';
|
|
6293
|
-
|
|
6294
|
-
// get session id from url search params
|
|
6295
|
-
const url = new URL(location.href);
|
|
6296
|
-
this.session_id = url.searchParams.get('ngio_session_id');
|
|
6297
|
-
|
|
6298
|
-
if (!this.session_id)
|
|
6299
|
-
return; // only use newgrounds when logged in
|
|
6300
|
-
|
|
6301
|
-
// get medals
|
|
6302
|
-
const medalsResult = this.call('Medal.getList');
|
|
6303
|
-
this.medals = medalsResult ? medalsResult.result.data['medals'] : [];
|
|
6304
|
-
debugMedals && console.log(this.medals);
|
|
6305
|
-
for (const newgroundsMedal of this.medals)
|
|
6306
|
-
{
|
|
6307
|
-
const medal = medals[newgroundsMedal['id']];
|
|
6308
|
-
if (medal)
|
|
6309
|
-
{
|
|
6310
|
-
// copy newgrounds medal data
|
|
6311
|
-
medal.image = new Image;
|
|
6312
|
-
medal.image.src = newgroundsMedal['icon'];
|
|
6313
|
-
medal.name = newgroundsMedal['name'];
|
|
6314
|
-
medal.description = newgroundsMedal['description'];
|
|
6315
|
-
medal.unlocked = newgroundsMedal['unlocked'];
|
|
6316
|
-
medal.difficulty = newgroundsMedal['difficulty'];
|
|
6317
|
-
medal.value = newgroundsMedal['value'];
|
|
6318
|
-
|
|
6319
|
-
if (medal.value) // add value to description
|
|
6320
|
-
medal.description = medal.description + ` (${ medal.value })`;
|
|
6321
|
-
}
|
|
6322
|
-
}
|
|
6323
|
-
|
|
6324
|
-
// get scoreboards
|
|
6325
|
-
const scoreboardResult = this.call('ScoreBoard.getBoards');
|
|
6326
|
-
this.scoreboards = scoreboardResult ? scoreboardResult.result.data.scoreboards : [];
|
|
6327
|
-
debugMedals && console.log(this.scoreboards);
|
|
6328
|
-
|
|
6329
|
-
// keep the session alive with a ping every minute
|
|
6330
|
-
const keepAliveMS = 60 * 1e3;
|
|
6331
|
-
setInterval(()=>this.call('Gateway.ping', 0, true), keepAliveMS);
|
|
6332
|
-
}
|
|
6333
|
-
|
|
6334
|
-
/** Send message to unlock a medal by id
|
|
6335
|
-
* @param {number} id - The medal id */
|
|
6336
|
-
unlockMedal(id) { return this.call('Medal.unlock', {'id':id}, true); }
|
|
6337
|
-
|
|
6338
|
-
/** Send message to post score
|
|
6339
|
-
* @param {number} id - The scoreboard id
|
|
6340
|
-
* @param {number} value - The score value */
|
|
6341
|
-
postScore(id, value) { return this.call('ScoreBoard.postScore', {'id':id, 'value':value}, true); }
|
|
6342
|
-
|
|
6343
|
-
/** Get scores from a scoreboard
|
|
6344
|
-
* @param {number} id - The scoreboard id
|
|
6345
|
-
* @param {string} [user] - A user's id or name
|
|
6346
|
-
* @param {number} [social] - If true, only social scores will be loaded
|
|
6347
|
-
* @param {number} [skip] - Number of scores to skip before start
|
|
6348
|
-
* @param {number} [limit] - Number of scores to include in the list
|
|
6349
|
-
* @return {Object} - The response JSON object
|
|
6350
|
-
*/
|
|
6351
|
-
getScores(id, user, social=0, skip=0, limit=10)
|
|
6352
|
-
{ return this.call('ScoreBoard.getScores', {'id':id, 'user':user, 'social':social, 'skip':skip, 'limit':limit}); }
|
|
6353
|
-
|
|
6354
|
-
/** Send message to log a view */
|
|
6355
|
-
logView() { return this.call('App.logView', {'host':this.host}, true); }
|
|
6356
|
-
|
|
6357
|
-
/** Send a message to call a component of the Newgrounds API
|
|
6358
|
-
* @param {string} component - Name of the component
|
|
6359
|
-
* @param {Object} [parameters] - Parameters to use for call
|
|
6360
|
-
* @param {boolean} [async] - If true, don't wait for response before continuing
|
|
6361
|
-
* @return {Object} - The response JSON object
|
|
6362
|
-
*/
|
|
6363
|
-
call(component, parameters, async=false)
|
|
6364
|
-
{
|
|
6365
|
-
const call = {'component':component, 'parameters':parameters};
|
|
6366
|
-
if (this.cipher)
|
|
6367
|
-
{
|
|
6368
|
-
// encrypt using AES-128 Base64 with cryptoJS
|
|
6369
|
-
const cryptoJS = this.cryptoJS;
|
|
6370
|
-
const aesKey = cryptoJS['enc']['Base64']['parse'](this.cipher);
|
|
6371
|
-
const iv = cryptoJS['lib']['WordArray']['random'](16);
|
|
6372
|
-
const encrypted = cryptoJS['AES']['encrypt'](JSON.stringify(call), aesKey, {'iv':iv});
|
|
6373
|
-
call['secure'] = cryptoJS['enc']['Base64']['stringify'](iv.concat(encrypted['ciphertext']));
|
|
6374
|
-
call['parameters'] = 0;
|
|
6375
|
-
}
|
|
6151
|
+
/** Send a message to call a component of the Newgrounds API
|
|
6152
|
+
* @param {string} component - Name of the component
|
|
6153
|
+
* @param {Object} [parameters] - Parameters to use for call
|
|
6154
|
+
* @param {boolean} [async] - If true, don't wait for response before continuing
|
|
6155
|
+
* @return {Object} - The response JSON object
|
|
6156
|
+
*/
|
|
6157
|
+
call(component, parameters, async=false)
|
|
6158
|
+
{
|
|
6159
|
+
const call = {'component':component, 'parameters':parameters};
|
|
6160
|
+
if (this.cipher)
|
|
6161
|
+
{
|
|
6162
|
+
// encrypt using AES-128 Base64 with cryptoJS
|
|
6163
|
+
const cryptoJS = this.cryptoJS;
|
|
6164
|
+
const aesKey = cryptoJS['enc']['Base64']['parse'](this.cipher);
|
|
6165
|
+
const iv = cryptoJS['lib']['WordArray']['random'](16);
|
|
6166
|
+
const encrypted = cryptoJS['AES']['encrypt'](JSON.stringify(call), aesKey, {'iv':iv});
|
|
6167
|
+
call['secure'] = cryptoJS['enc']['Base64']['stringify'](iv.concat(encrypted['ciphertext']));
|
|
6168
|
+
call['parameters'] = 0;
|
|
6169
|
+
}
|
|
6376
6170
|
|
|
6377
6171
|
// build the input object
|
|
6378
6172
|
const input =
|
|
@@ -6408,8 +6202,6 @@ class NewgroundsPlugin
|
|
|
6408
6202
|
* - can be enabled to pass other canvases through a final shader
|
|
6409
6203
|
*/
|
|
6410
6204
|
|
|
6411
|
-
'use strict';
|
|
6412
|
-
|
|
6413
6205
|
///////////////////////////////////////////////////////////////////////////////
|
|
6414
6206
|
|
|
6415
6207
|
/** Global Post Process plugin object
|
|
@@ -6522,8 +6314,6 @@ class PostProcessPlugin
|
|
|
6522
6314
|
* LittleJS ZzFXM Plugin
|
|
6523
6315
|
*/
|
|
6524
6316
|
|
|
6525
|
-
'use strict';
|
|
6526
|
-
|
|
6527
6317
|
/**
|
|
6528
6318
|
* Music Object - Stores a zzfx music track for later use
|
|
6529
6319
|
*
|
|
@@ -6692,8 +6482,6 @@ function zzfxM(instruments, patterns, sequence, BPM = 125)
|
|
|
6692
6482
|
* - Images
|
|
6693
6483
|
*/
|
|
6694
6484
|
|
|
6695
|
-
'use strict';
|
|
6696
|
-
|
|
6697
6485
|
///////////////////////////////////////////////////////////////////////////////
|
|
6698
6486
|
|
|
6699
6487
|
/** Global UI system plugin object
|
|
@@ -6861,6 +6649,8 @@ class UIObject
|
|
|
6861
6649
|
this.lineWidth = uiSystem.defaultLineWidth;
|
|
6862
6650
|
/** @property {string} */
|
|
6863
6651
|
this.font = uiSystem.defaultFont;
|
|
6652
|
+
/** @property {number} - override for text height */
|
|
6653
|
+
this.textHeight = undefined;
|
|
6864
6654
|
/** @property {boolean} */
|
|
6865
6655
|
this.visible = true;
|
|
6866
6656
|
/** @property {Array<UIObject>} */
|
|
@@ -6971,7 +6761,8 @@ class UIText extends UIObject
|
|
|
6971
6761
|
}
|
|
6972
6762
|
render()
|
|
6973
6763
|
{
|
|
6974
|
-
|
|
6764
|
+
const textSize = vec2(this.size.x, this.textHeight || this.size.y);
|
|
6765
|
+
uiSystem.drawText(this.text, this.pos, textSize, this.textColor, this.lineWidth, this.lineColor, this.align, this.font);
|
|
6975
6766
|
}
|
|
6976
6767
|
}
|
|
6977
6768
|
|
|
@@ -7034,7 +6825,9 @@ class UIButton extends UIObject
|
|
|
7034
6825
|
const lineColor = this.mouseIsHeld ? this.color : this.lineColor;
|
|
7035
6826
|
const color = this.mouseIsOver? this.hoverColor : this.color;
|
|
7036
6827
|
uiSystem.drawRect(this.pos, this.size, color, this.lineWidth, lineColor);
|
|
7037
|
-
|
|
6828
|
+
|
|
6829
|
+
const textScale = .8; // scale text to fit in button
|
|
6830
|
+
const textSize = vec2(this.size.x, this.textHeight || this.size.y*textScale);
|
|
7038
6831
|
uiSystem.drawText(this.text, this.pos, textSize,
|
|
7039
6832
|
this.textColor, 0, undefined, this.align, this.font);
|
|
7040
6833
|
}
|
|
@@ -7131,7 +6924,8 @@ class UIScrollbar extends UIObject
|
|
|
7131
6924
|
const barColor = this.mouseIsHeld ? this.color : this.handleColor;
|
|
7132
6925
|
uiSystem.drawRect(handlePos, handleSize, barColor, this.lineWidth, this.lineColor);
|
|
7133
6926
|
|
|
7134
|
-
const
|
|
6927
|
+
const textScale = .8; // scale text to fit in scrollbar
|
|
6928
|
+
const textSize = vec2(this.size.x, this.textHeight || this.size.y*textScale);
|
|
7135
6929
|
uiSystem.drawText(this.text, this.pos, textSize,
|
|
7136
6930
|
this.textColor, 0, undefined, this.align, this.font);
|
|
7137
6931
|
}
|
|
@@ -7140,29 +6934,35 @@ class UIScrollbar extends UIObject
|
|
|
7140
6934
|
/**
|
|
7141
6935
|
* LittleJS Box2D Physics Plugin
|
|
7142
6936
|
* - Box2dObject extends EngineObject with Box2D physics
|
|
7143
|
-
* - Call
|
|
6937
|
+
* - Call box2dInit() before engineInit() to enable
|
|
7144
6938
|
* - You will also need to include box2d.wasm.js
|
|
7145
|
-
* - Uses
|
|
6939
|
+
* - Uses a super fast web assembly port of Box2D
|
|
7146
6940
|
* - More info: https://github.com/kripken/box2d.js
|
|
7147
|
-
* - Fully wraps everything in Box2d
|
|
7148
6941
|
* - Functions to create polygon, circle, and edge shapes
|
|
7149
|
-
* - Raycasting and querying
|
|
7150
|
-
* - Joint creation
|
|
7151
6942
|
* - Contact begin and end callbacks
|
|
6943
|
+
* - Wraps b2Vec2 type to/from Vector2
|
|
6944
|
+
* - Raycasting and querying
|
|
6945
|
+
* - Every type of joint
|
|
7152
6946
|
* - Debug physics drawing
|
|
6947
|
+
* @namespace Box2D
|
|
7153
6948
|
*/
|
|
7154
6949
|
|
|
7155
|
-
'use strict';
|
|
7156
|
-
|
|
7157
6950
|
/** Global Box2d Plugin object
|
|
7158
|
-
* @type {Box2dPlugin}
|
|
6951
|
+
* @type {Box2dPlugin}
|
|
6952
|
+
* @memberof Box2D */
|
|
7159
6953
|
let box2d;
|
|
7160
6954
|
|
|
7161
6955
|
/** Enable Box2D debug drawing
|
|
7162
6956
|
* @type {boolean}
|
|
7163
|
-
* @default
|
|
6957
|
+
* @default
|
|
6958
|
+
* @memberof Box2D */
|
|
7164
6959
|
let box2dDebug = false;
|
|
7165
6960
|
|
|
6961
|
+
/** Enable Box2D debug drawing
|
|
6962
|
+
* @param {boolean} enable
|
|
6963
|
+
* @memberof Box2D */
|
|
6964
|
+
function box2dSetDebug(enable) { box2dDebug = enable; }
|
|
6965
|
+
|
|
7166
6966
|
///////////////////////////////////////////////////////////////////////////////
|
|
7167
6967
|
/**
|
|
7168
6968
|
* Box2D Object - extend with your own custom physics objects
|
|
@@ -7262,7 +7062,7 @@ class Box2dObject extends EngineObject
|
|
|
7262
7062
|
* @param {number} [friction]
|
|
7263
7063
|
* @param {number} [restitution]
|
|
7264
7064
|
* @param {boolean} [isSensor] */
|
|
7265
|
-
addShape(shape, density=1, friction
|
|
7065
|
+
addShape(shape, density=1, friction=1, restitution=0, isSensor=false)
|
|
7266
7066
|
{
|
|
7267
7067
|
const fd = new box2d.instance.b2FixtureDef();
|
|
7268
7068
|
fd.set_shape(shape);
|
|
@@ -8566,7 +8366,7 @@ class Box2dPlugin
|
|
|
8566
8366
|
* @param {number} [frames] */
|
|
8567
8367
|
step(frames=1)
|
|
8568
8368
|
{
|
|
8569
|
-
box2d.world.SetGravity(box2d.vec2dTo(
|
|
8369
|
+
box2d.world.SetGravity(box2d.vec2dTo(gravity));
|
|
8570
8370
|
for (let i=frames; i--;)
|
|
8571
8371
|
box2d.world.Step(timeDelta, this.velocityIterations, this.positionIterations);
|
|
8572
8372
|
}
|
|
@@ -8707,8 +8507,8 @@ class Box2dPlugin
|
|
|
8707
8507
|
aabb.set_upperBound(box2d.vec2dTo(pos));
|
|
8708
8508
|
|
|
8709
8509
|
let queryObject;
|
|
8710
|
-
debugRaycast && debugRect(pos, vec2(), queryObject ? '#f00' : '#00f', .02);
|
|
8711
8510
|
box2d.world.QueryAABB(queryCallback, aabb);
|
|
8511
|
+
debugRaycast && debugRect(pos, vec2(), queryObject ? '#f00' : '#00f', .02);
|
|
8712
8512
|
return queryObject;
|
|
8713
8513
|
}
|
|
8714
8514
|
|
|
@@ -8839,176 +8639,464 @@ class Box2dPlugin
|
|
|
8839
8639
|
return new Vector2(v.get_x(), v.get_y());
|
|
8840
8640
|
}
|
|
8841
8641
|
|
|
8842
|
-
/** converts a box2d vec2 pointer to a Vector2
|
|
8843
|
-
* @param {Object} v */
|
|
8844
|
-
vec2FromPointer(v)
|
|
8845
|
-
{
|
|
8846
|
-
return box2d.vec2From(box2d.instance.wrapPointer(v, box2d.instance.b2Vec2));
|
|
8847
|
-
}
|
|
8642
|
+
/** converts a box2d vec2 pointer to a Vector2
|
|
8643
|
+
* @param {Object} v */
|
|
8644
|
+
vec2FromPointer(v)
|
|
8645
|
+
{
|
|
8646
|
+
return box2d.vec2From(box2d.instance.wrapPointer(v, box2d.instance.b2Vec2));
|
|
8647
|
+
}
|
|
8648
|
+
|
|
8649
|
+
/** converts a Vector2 to a box2 vec2
|
|
8650
|
+
* @param {Vector2} v */
|
|
8651
|
+
vec2dTo(v)
|
|
8652
|
+
{
|
|
8653
|
+
ASSERT(v instanceof Vector2);
|
|
8654
|
+
return new box2d.instance.b2Vec2(v.x, v.y);
|
|
8655
|
+
}
|
|
8656
|
+
|
|
8657
|
+
/** checks if a box2d object is null
|
|
8658
|
+
* @param {Object} o */
|
|
8659
|
+
isNull(o) { return !box2d.instance.getPointer(o); }
|
|
8660
|
+
|
|
8661
|
+
/** casts a box2d object to its correct type
|
|
8662
|
+
* @param {Object} o */
|
|
8663
|
+
castObjectType(o)
|
|
8664
|
+
{
|
|
8665
|
+
switch (o.GetType())
|
|
8666
|
+
{
|
|
8667
|
+
case box2d.instance.b2Shape.e_circle:
|
|
8668
|
+
return box2d.instance.castObject(o, box2d.instance.b2CircleShape);
|
|
8669
|
+
case box2d.instance.b2Shape.e_edge:
|
|
8670
|
+
return box2d.instance.castObject(o, box2d.instance.b2EdgeShape);
|
|
8671
|
+
case box2d.instance.b2Shape.e_polygon:
|
|
8672
|
+
return box2d.instance.castObject(o, box2d.instance.b2PolygonShape);
|
|
8673
|
+
case box2d.instance.b2Shape.e_chain:
|
|
8674
|
+
return box2d.instance.castObject(o, box2d.instance.b2ChainShape);
|
|
8675
|
+
case box2d.instance.e_revoluteJoint:
|
|
8676
|
+
return box2d.instance.castObject(o, box2d.instance.b2RevoluteJoint);
|
|
8677
|
+
case box2d.instance.e_prismaticJoint:
|
|
8678
|
+
return box2d.instance.castObject(o, box2d.instance.b2PrismaticJoint);
|
|
8679
|
+
case box2d.instance.e_distanceJoint:
|
|
8680
|
+
return box2d.instance.castObject(o, box2d.instance.b2DistanceJoint);
|
|
8681
|
+
case box2d.instance.e_pulleyJoint:
|
|
8682
|
+
return box2d.instance.castObject(o, box2d.instance.b2PulleyJoint);
|
|
8683
|
+
case box2d.instance.e_mouseJoint:
|
|
8684
|
+
return box2d.instance.castObject(o, box2d.instance.b2MouseJoint);
|
|
8685
|
+
case box2d.instance.e_gearJoint:
|
|
8686
|
+
return box2d.instance.castObject(o, box2d.instance.b2GearJoint);
|
|
8687
|
+
case box2d.instance.e_wheelJoint:
|
|
8688
|
+
return box2d.instance.castObject(o, box2d.instance.b2WheelJoint);
|
|
8689
|
+
case box2d.instance.e_weldJoint:
|
|
8690
|
+
return box2d.instance.castObject(o, box2d.instance.b2WeldJoint);
|
|
8691
|
+
case box2d.instance.e_frictionJoint:
|
|
8692
|
+
return box2d.instance.castObject(o, box2d.instance.b2FrictionJoint);
|
|
8693
|
+
case box2d.instance.e_ropeJoint:
|
|
8694
|
+
return box2d.instance.castObject(o, box2d.instance.b2RopeJoint);
|
|
8695
|
+
case box2d.instance.e_motorJoint:
|
|
8696
|
+
return box2d.instance.castObject(o, box2d.instance.b2MotorJoint);
|
|
8697
|
+
}
|
|
8698
|
+
|
|
8699
|
+
ASSERT(false, 'Unknown box2d object type');
|
|
8700
|
+
}
|
|
8701
|
+
}
|
|
8702
|
+
|
|
8703
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
8704
|
+
/** Box2d Init - Call with await before starting LittleJS to init box2d
|
|
8705
|
+
* @return {Promise<Box2dPlugin>}
|
|
8706
|
+
* @memberof Box2D */
|
|
8707
|
+
async function box2dInit()
|
|
8708
|
+
{
|
|
8709
|
+
// load box2d
|
|
8710
|
+
new Box2dPlugin(await Box2D());
|
|
8711
|
+
setupDebugDraw();
|
|
8712
|
+
engineAddPlugin(box2dUpdate, box2dRender);
|
|
8713
|
+
return box2d;
|
|
8714
|
+
|
|
8715
|
+
// add the box2d plugin to the engine
|
|
8716
|
+
function box2dUpdate()
|
|
8717
|
+
{
|
|
8718
|
+
if (!paused)
|
|
8719
|
+
box2d.step();
|
|
8720
|
+
}
|
|
8721
|
+
function box2dRender()
|
|
8722
|
+
{
|
|
8723
|
+
if (box2dDebug || debugPhysics && debugOverlay)
|
|
8724
|
+
box2d.world.DrawDebugData();
|
|
8725
|
+
}
|
|
8726
|
+
|
|
8727
|
+
// box2d debug drawing
|
|
8728
|
+
function setupDebugDraw()
|
|
8729
|
+
{
|
|
8730
|
+
// setup debug draw
|
|
8731
|
+
const debugDraw = new box2d.instance.JSDraw();
|
|
8732
|
+
const box2dColor = (c)=> new Color(c.get_r(), c.get_g(), c.get_b());
|
|
8733
|
+
const box2dColorPointer = (c)=>
|
|
8734
|
+
box2dColor(box2d.instance.wrapPointer(c, box2d.instance.b2Color));
|
|
8735
|
+
const getDebugColor = (color)=>box2dColorPointer(color).scale(1,.8);
|
|
8736
|
+
const getPointsList = (vertices, vertexCount) =>
|
|
8737
|
+
{
|
|
8738
|
+
const points = [];
|
|
8739
|
+
for (let i=vertexCount; i--;)
|
|
8740
|
+
points.push(box2d.vec2FromPointer(vertices+i*8));
|
|
8741
|
+
return points;
|
|
8742
|
+
}
|
|
8743
|
+
debugDraw.DrawSegment = function(point1, point2, color)
|
|
8744
|
+
{
|
|
8745
|
+
color = getDebugColor(color);
|
|
8746
|
+
point1 = box2d.vec2FromPointer(point1);
|
|
8747
|
+
point2 = box2d.vec2FromPointer(point2);
|
|
8748
|
+
box2d.drawLine(vec2(), 0, point1, point2, color, undefined, overlayContext);
|
|
8749
|
+
};
|
|
8750
|
+
debugDraw.DrawPolygon = function(vertices, vertexCount, color)
|
|
8751
|
+
{
|
|
8752
|
+
color = getDebugColor(color);
|
|
8753
|
+
const points = getPointsList(vertices, vertexCount);
|
|
8754
|
+
box2d.drawPoly(vec2(), 0, points, undefined, color, undefined, overlayContext);
|
|
8755
|
+
};
|
|
8756
|
+
debugDraw.DrawSolidPolygon = function(vertices, vertexCount, color)
|
|
8757
|
+
{
|
|
8758
|
+
color = getDebugColor(color);
|
|
8759
|
+
const points = getPointsList(vertices, vertexCount);
|
|
8760
|
+
box2d.drawPoly(vec2(), 0, points, color, color, undefined, overlayContext);
|
|
8761
|
+
};
|
|
8762
|
+
debugDraw.DrawCircle = function(center, radius, color)
|
|
8763
|
+
{
|
|
8764
|
+
color = getDebugColor(color);
|
|
8765
|
+
center = box2d.vec2FromPointer(center);
|
|
8766
|
+
box2d.drawCircle(center, radius, undefined, color, undefined, overlayContext);
|
|
8767
|
+
};
|
|
8768
|
+
debugDraw.DrawSolidCircle = function(center, radius, axis, color)
|
|
8769
|
+
{
|
|
8770
|
+
color = getDebugColor(color);
|
|
8771
|
+
center = box2d.vec2FromPointer(center);
|
|
8772
|
+
axis = box2d.vec2FromPointer(axis).scale(radius);
|
|
8773
|
+
box2d.drawCircle(center, radius, color, color, undefined, overlayContext);
|
|
8774
|
+
box2d.drawLine(center, 0, vec2(), axis, color, undefined, overlayContext);
|
|
8775
|
+
};
|
|
8776
|
+
debugDraw.DrawTransform = function(transform)
|
|
8777
|
+
{
|
|
8778
|
+
transform = box2d.instance.wrapPointer(transform, box2d.instance.b2Transform);
|
|
8779
|
+
const pos = vec2(transform.get_p());
|
|
8780
|
+
const angle = -transform.get_q().GetAngle();
|
|
8781
|
+
const p1 = vec2(1,0), c1 = rgb(.75,0,0,.8);
|
|
8782
|
+
const p2 = vec2(0,1), c2 = rgb(0,.75,0,.8);
|
|
8783
|
+
box2d.drawLine(pos, angle, vec2(), p1, c1, undefined, overlayContext);
|
|
8784
|
+
box2d.drawLine(pos, angle, vec2(), p2, c2, undefined, overlayContext);
|
|
8785
|
+
}
|
|
8786
|
+
|
|
8787
|
+
debugDraw.AppendFlags(box2d.instance.b2Draw.e_shapeBit);
|
|
8788
|
+
debugDraw.AppendFlags(box2d.instance.b2Draw.e_jointBit);
|
|
8789
|
+
//debugDraw.AppendFlags(box2d.instance.b2Draw.e_aabbBit);
|
|
8790
|
+
//debugDraw.AppendFlags(box2d.instance.b2Draw.e_pairBit);
|
|
8791
|
+
//debugDraw.AppendFlags(box2d.instance.b2Draw.e_centerOfMassBit);
|
|
8792
|
+
box2d.world.SetDebugDraw(debugDraw);
|
|
8793
|
+
}
|
|
8794
|
+
}
|
|
8795
|
+
|
|
8796
|
+
|
|
8797
|
+
/**
|
|
8798
|
+
* LittleJS Module Export
|
|
8799
|
+
*/
|
|
8800
|
+
|
|
8801
|
+
export
|
|
8802
|
+
{
|
|
8803
|
+
// Engine
|
|
8804
|
+
engineName,
|
|
8805
|
+
engineVersion,
|
|
8806
|
+
frameRate,
|
|
8807
|
+
timeDelta,
|
|
8808
|
+
engineObjects,
|
|
8809
|
+
frame,
|
|
8810
|
+
time,
|
|
8811
|
+
timeReal,
|
|
8812
|
+
paused,
|
|
8813
|
+
setPaused,
|
|
8814
|
+
engineInit,
|
|
8815
|
+
engineObjectsUpdate,
|
|
8816
|
+
engineObjectsDestroy,
|
|
8817
|
+
engineObjectsCollect,
|
|
8818
|
+
engineObjectsCallback,
|
|
8819
|
+
engineObjectsRaycast,
|
|
8820
|
+
engineAddPlugin,
|
|
8821
|
+
|
|
8822
|
+
// Globals
|
|
8823
|
+
debug,
|
|
8824
|
+
debugOverlay,
|
|
8825
|
+
showWatermark,
|
|
8826
|
+
|
|
8827
|
+
// Debug
|
|
8828
|
+
ASSERT,
|
|
8829
|
+
debugRect,
|
|
8830
|
+
debugPoly,
|
|
8831
|
+
debugCircle,
|
|
8832
|
+
debugPoint,
|
|
8833
|
+
debugLine,
|
|
8834
|
+
debugOverlap,
|
|
8835
|
+
debugText,
|
|
8836
|
+
debugClear,
|
|
8837
|
+
debugScreenshot,
|
|
8838
|
+
debugSaveCanvas,
|
|
8839
|
+
debugSaveText,
|
|
8840
|
+
debugSaveDataURL,
|
|
8841
|
+
debugShowErrors,
|
|
8842
|
+
debugVideoCaptureIsActive,
|
|
8843
|
+
debugVideoCaptureStart,
|
|
8844
|
+
debugVideoCaptureStop,
|
|
8845
|
+
|
|
8846
|
+
// Settings
|
|
8847
|
+
cameraPos,
|
|
8848
|
+
cameraScale,
|
|
8849
|
+
canvasMaxSize,
|
|
8850
|
+
canvasFixedSize,
|
|
8851
|
+
canvasPixelated,
|
|
8852
|
+
tilesPixelated,
|
|
8853
|
+
fontDefault,
|
|
8854
|
+
showSplashScreen,
|
|
8855
|
+
headlessMode,
|
|
8856
|
+
tileSizeDefault,
|
|
8857
|
+
tileFixBleedScale,
|
|
8858
|
+
enablePhysicsSolver,
|
|
8859
|
+
objectDefaultMass,
|
|
8860
|
+
objectDefaultDamping,
|
|
8861
|
+
objectDefaultAngleDamping,
|
|
8862
|
+
objectDefaultElasticity,
|
|
8863
|
+
objectDefaultFriction,
|
|
8864
|
+
objectMaxSpeed,
|
|
8865
|
+
gravity,
|
|
8866
|
+
particleEmitRateScale,
|
|
8867
|
+
glEnable,
|
|
8868
|
+
glOverlay,
|
|
8869
|
+
gamepadsEnable,
|
|
8870
|
+
gamepadDirectionEmulateStick,
|
|
8871
|
+
inputWASDEmulateDirection,
|
|
8872
|
+
touchGamepadEnable,
|
|
8873
|
+
touchGamepadAnalog,
|
|
8874
|
+
touchGamepadSize,
|
|
8875
|
+
touchGamepadAlpha,
|
|
8876
|
+
vibrateEnable,
|
|
8877
|
+
soundEnable,
|
|
8878
|
+
soundVolume,
|
|
8879
|
+
soundDefaultRange,
|
|
8880
|
+
soundDefaultTaper,
|
|
8881
|
+
medalDisplayTime,
|
|
8882
|
+
medalDisplaySlideTime,
|
|
8883
|
+
medalDisplaySize,
|
|
8884
|
+
|
|
8885
|
+
// Setters for globals
|
|
8886
|
+
setCameraPos,
|
|
8887
|
+
setCameraScale,
|
|
8888
|
+
setCanvasMaxSize,
|
|
8889
|
+
setCanvasFixedSize,
|
|
8890
|
+
setCanvasPixelated,
|
|
8891
|
+
setTilesPixelated,
|
|
8892
|
+
setFontDefault,
|
|
8893
|
+
setShowSplashScreen,
|
|
8894
|
+
setHeadlessMode,
|
|
8895
|
+
setGlEnable,
|
|
8896
|
+
setGlOverlay,
|
|
8897
|
+
setTileSizeDefault,
|
|
8898
|
+
setTileFixBleedScale,
|
|
8899
|
+
setEnablePhysicsSolver,
|
|
8900
|
+
setObjectDefaultMass,
|
|
8901
|
+
setObjectDefaultDamping,
|
|
8902
|
+
setObjectDefaultAngleDamping,
|
|
8903
|
+
setObjectDefaultElasticity,
|
|
8904
|
+
setObjectDefaultFriction,
|
|
8905
|
+
setObjectMaxSpeed,
|
|
8906
|
+
setGravity,
|
|
8907
|
+
setParticleEmitRateScale,
|
|
8908
|
+
setTouchInputEnable,
|
|
8909
|
+
setGamepadsEnable,
|
|
8910
|
+
setGamepadDirectionEmulateStick,
|
|
8911
|
+
setInputWASDEmulateDirection,
|
|
8912
|
+
setTouchGamepadEnable,
|
|
8913
|
+
setTouchGamepadAnalog,
|
|
8914
|
+
setTouchGamepadSize,
|
|
8915
|
+
setTouchGamepadAlpha,
|
|
8916
|
+
setVibrateEnable,
|
|
8917
|
+
setSoundEnable,
|
|
8918
|
+
setSoundVolume,
|
|
8919
|
+
setSoundDefaultRange,
|
|
8920
|
+
setSoundDefaultTaper,
|
|
8921
|
+
setMedalDisplayTime,
|
|
8922
|
+
setMedalDisplaySlideTime,
|
|
8923
|
+
setMedalDisplaySize,
|
|
8924
|
+
setMedalsPreventUnlock,
|
|
8925
|
+
setShowWatermark,
|
|
8926
|
+
setDebugKey,
|
|
8927
|
+
|
|
8928
|
+
// Utilities
|
|
8929
|
+
PI,
|
|
8930
|
+
abs,
|
|
8931
|
+
min,
|
|
8932
|
+
max,
|
|
8933
|
+
sign,
|
|
8934
|
+
mod,
|
|
8935
|
+
clamp,
|
|
8936
|
+
percent,
|
|
8937
|
+
distanceWrap,
|
|
8938
|
+
lerpWrap,
|
|
8939
|
+
distanceAngle,
|
|
8940
|
+
lerpAngle,
|
|
8941
|
+
lerp,
|
|
8942
|
+
smoothStep,
|
|
8943
|
+
nearestPowerOfTwo,
|
|
8944
|
+
isOverlapping,
|
|
8945
|
+
isIntersecting,
|
|
8946
|
+
wave,
|
|
8947
|
+
formatTime,
|
|
8948
|
+
fetchJSON,
|
|
8949
|
+
|
|
8950
|
+
// Random
|
|
8951
|
+
rand,
|
|
8952
|
+
randInt,
|
|
8953
|
+
randSign,
|
|
8954
|
+
randInCircle,
|
|
8955
|
+
randVector,
|
|
8956
|
+
randColor,
|
|
8957
|
+
|
|
8958
|
+
// Utility Classes
|
|
8959
|
+
RandomGenerator,
|
|
8960
|
+
Vector2,
|
|
8961
|
+
Color,
|
|
8962
|
+
Timer,
|
|
8963
|
+
vec2,
|
|
8964
|
+
rgb,
|
|
8965
|
+
hsl,
|
|
8966
|
+
isColor,
|
|
8967
|
+
|
|
8968
|
+
// Default Colors
|
|
8969
|
+
WHITE,
|
|
8970
|
+
BLACK,
|
|
8971
|
+
GRAY,
|
|
8972
|
+
RED,
|
|
8973
|
+
ORANGE,
|
|
8974
|
+
YELLOW,
|
|
8975
|
+
GREEN,
|
|
8976
|
+
CYAN,
|
|
8977
|
+
BLUE,
|
|
8978
|
+
PURPLE,
|
|
8979
|
+
MAGENTA,
|
|
8980
|
+
|
|
8981
|
+
// Draw
|
|
8982
|
+
textureInfos,
|
|
8983
|
+
tile,
|
|
8984
|
+
TileInfo,
|
|
8985
|
+
TextureInfo,
|
|
8986
|
+
mainCanvas,
|
|
8987
|
+
mainContext,
|
|
8988
|
+
overlayCanvas,
|
|
8989
|
+
overlayContext,
|
|
8990
|
+
mainCanvasSize,
|
|
8991
|
+
screenToWorld,
|
|
8992
|
+
worldToScreen,
|
|
8993
|
+
drawTile,
|
|
8994
|
+
drawRect,
|
|
8995
|
+
drawLine,
|
|
8996
|
+
drawPoly,
|
|
8997
|
+
drawEllipse,
|
|
8998
|
+
drawCircle,
|
|
8999
|
+
drawCanvas2D,
|
|
9000
|
+
drawText,
|
|
9001
|
+
drawTextOverlay,
|
|
9002
|
+
drawTextScreen,
|
|
9003
|
+
setBlendMode,
|
|
9004
|
+
combineCanvases,
|
|
9005
|
+
engineFontImage,
|
|
9006
|
+
FontImage,
|
|
9007
|
+
isFullscreen,
|
|
9008
|
+
toggleFullscreen,
|
|
9009
|
+
setCursor,
|
|
9010
|
+
getCameraSize,
|
|
8848
9011
|
|
|
8849
|
-
|
|
8850
|
-
|
|
8851
|
-
|
|
8852
|
-
|
|
8853
|
-
|
|
8854
|
-
|
|
8855
|
-
|
|
9012
|
+
// WebGL
|
|
9013
|
+
glCanvas,
|
|
9014
|
+
glContext,
|
|
9015
|
+
glCompileShader,
|
|
9016
|
+
glCopyToContext,
|
|
9017
|
+
glCreateProgram,
|
|
9018
|
+
glCreateTexture,
|
|
9019
|
+
glSetTextureData,
|
|
9020
|
+
glDraw,
|
|
9021
|
+
glFlush,
|
|
9022
|
+
glSetTexture,
|
|
9023
|
+
glSetAntialias,
|
|
9024
|
+
glClearCanvas,
|
|
9025
|
+
glAntialias,
|
|
9026
|
+
glShader,
|
|
9027
|
+
glActiveTexture,
|
|
9028
|
+
glArrayBuffer,
|
|
9029
|
+
glGeometryBuffer,
|
|
9030
|
+
glPositionData,
|
|
9031
|
+
glColorData,
|
|
9032
|
+
glInstanceCount,
|
|
9033
|
+
glAdditive,
|
|
9034
|
+
glBatchAdditive,
|
|
8856
9035
|
|
|
8857
|
-
|
|
8858
|
-
|
|
8859
|
-
|
|
9036
|
+
// Input
|
|
9037
|
+
keyIsDown,
|
|
9038
|
+
keyWasPressed,
|
|
9039
|
+
keyWasReleased,
|
|
9040
|
+
keyDirection,
|
|
9041
|
+
clearInput,
|
|
9042
|
+
mouseIsDown,
|
|
9043
|
+
mouseWasPressed,
|
|
9044
|
+
mouseWasReleased,
|
|
9045
|
+
mousePos,
|
|
9046
|
+
mousePosScreen,
|
|
9047
|
+
mouseWheel,
|
|
9048
|
+
isUsingGamepad,
|
|
9049
|
+
inputPreventDefault,
|
|
9050
|
+
setInputPreventDefault,
|
|
9051
|
+
gamepadIsDown,
|
|
9052
|
+
gamepadWasPressed,
|
|
9053
|
+
gamepadWasReleased,
|
|
9054
|
+
gamepadStick,
|
|
9055
|
+
gamepadsUpdate,
|
|
9056
|
+
vibrate,
|
|
9057
|
+
vibrateStop,
|
|
9058
|
+
isTouchDevice,
|
|
8860
9059
|
|
|
8861
|
-
|
|
8862
|
-
|
|
8863
|
-
|
|
8864
|
-
|
|
8865
|
-
|
|
8866
|
-
|
|
8867
|
-
|
|
8868
|
-
|
|
8869
|
-
|
|
8870
|
-
|
|
8871
|
-
|
|
8872
|
-
|
|
8873
|
-
case box2d.instance.b2Shape.e_chain:
|
|
8874
|
-
return box2d.instance.castObject(o, box2d.instance.b2ChainShape);
|
|
8875
|
-
case box2d.instance.e_revoluteJoint:
|
|
8876
|
-
return box2d.instance.castObject(o, box2d.instance.b2RevoluteJoint);
|
|
8877
|
-
case box2d.instance.e_prismaticJoint:
|
|
8878
|
-
return box2d.instance.castObject(o, box2d.instance.b2PrismaticJoint);
|
|
8879
|
-
case box2d.instance.e_distanceJoint:
|
|
8880
|
-
return box2d.instance.castObject(o, box2d.instance.b2DistanceJoint);
|
|
8881
|
-
case box2d.instance.e_pulleyJoint:
|
|
8882
|
-
return box2d.instance.castObject(o, box2d.instance.b2PulleyJoint);
|
|
8883
|
-
case box2d.instance.e_mouseJoint:
|
|
8884
|
-
return box2d.instance.castObject(o, box2d.instance.b2MouseJoint);
|
|
8885
|
-
case box2d.instance.e_gearJoint:
|
|
8886
|
-
return box2d.instance.castObject(o, box2d.instance.b2GearJoint);
|
|
8887
|
-
case box2d.instance.e_wheelJoint:
|
|
8888
|
-
return box2d.instance.castObject(o, box2d.instance.b2WheelJoint);
|
|
8889
|
-
case box2d.instance.e_weldJoint:
|
|
8890
|
-
return box2d.instance.castObject(o, box2d.instance.b2WeldJoint);
|
|
8891
|
-
case box2d.instance.e_frictionJoint:
|
|
8892
|
-
return box2d.instance.castObject(o, box2d.instance.b2FrictionJoint);
|
|
8893
|
-
case box2d.instance.e_ropeJoint:
|
|
8894
|
-
return box2d.instance.castObject(o, box2d.instance.b2RopeJoint);
|
|
8895
|
-
case box2d.instance.e_motorJoint:
|
|
8896
|
-
return box2d.instance.castObject(o, box2d.instance.b2MotorJoint);
|
|
8897
|
-
}
|
|
8898
|
-
|
|
8899
|
-
ASSERT(false, 'Unknown box2d object type');
|
|
8900
|
-
}
|
|
8901
|
-
}
|
|
9060
|
+
// Audio
|
|
9061
|
+
Sound,
|
|
9062
|
+
SoundWave,
|
|
9063
|
+
playAudioFile,
|
|
9064
|
+
speak,
|
|
9065
|
+
speakStop,
|
|
9066
|
+
getNoteFrequency,
|
|
9067
|
+
playSamples,
|
|
9068
|
+
zzfx,
|
|
9069
|
+
zzfxG,
|
|
9070
|
+
zzfxR,
|
|
9071
|
+
audioContext,
|
|
8902
9072
|
|
|
8903
|
-
|
|
8904
|
-
|
|
8905
|
-
* @param {Function|function():Promise} gameInit - Called once after the engine starts up
|
|
8906
|
-
* @param {Function} gameUpdate - Called every frame before objects are updated
|
|
8907
|
-
* @param {Function} gameUpdatePost - Called after physics and objects are updated, even when paused
|
|
8908
|
-
* @param {Function} gameRender - Called before objects are rendered, for drawing the background
|
|
8909
|
-
* @param {Function} gameRenderPost - Called after objects are rendered, useful for drawing UI
|
|
8910
|
-
* @param {Array<string>} [imageSources=[]] - List of images to load
|
|
8911
|
-
* @param {HTMLElement} [rootElement] - Root element to attach to, the document body by default */
|
|
8912
|
-
function box2dEngineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, imageSources, rootElement)
|
|
8913
|
-
{
|
|
8914
|
-
Box2D().then(box2dInstance=>
|
|
8915
|
-
{
|
|
8916
|
-
// create box2d object
|
|
8917
|
-
new Box2dPlugin(box2dInstance);
|
|
8918
|
-
setupDebugDraw();
|
|
9073
|
+
// Base Object
|
|
9074
|
+
EngineObject,
|
|
8919
9075
|
|
|
8920
|
-
|
|
8921
|
-
|
|
8922
|
-
|
|
8923
|
-
|
|
9076
|
+
// Tiles
|
|
9077
|
+
tileCollisionLayers,
|
|
9078
|
+
getTileCollisionData,
|
|
9079
|
+
tileCollisionTest,
|
|
9080
|
+
tileCollisionRaycast,
|
|
9081
|
+
TileLayerData,
|
|
9082
|
+
TileLayer,
|
|
9083
|
+
TileCollisionLayer,
|
|
8924
9084
|
|
|
8925
|
-
|
|
8926
|
-
|
|
8927
|
-
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
|
|
8931
|
-
|
|
8932
|
-
|
|
8933
|
-
|
|
8934
|
-
|
|
8935
|
-
}
|
|
8936
|
-
|
|
8937
|
-
// box2d debug drawing
|
|
8938
|
-
function setupDebugDraw()
|
|
8939
|
-
{
|
|
8940
|
-
// setup debug draw
|
|
8941
|
-
const debugDraw = new box2d.instance.JSDraw();
|
|
8942
|
-
const box2dColor = (c)=> new Color(c.get_r(), c.get_g(), c.get_b());
|
|
8943
|
-
const box2dColorPointer = (c)=>
|
|
8944
|
-
box2dColor(box2d.instance.wrapPointer(c, box2d.instance.b2Color));
|
|
8945
|
-
const getDebugColor = (color)=>box2dColorPointer(color).scale(1,.8);
|
|
8946
|
-
const getPointsList = (vertices, vertexCount) =>
|
|
8947
|
-
{
|
|
8948
|
-
const points = [];
|
|
8949
|
-
for (let i=vertexCount; i--;)
|
|
8950
|
-
points.push(box2d.vec2FromPointer(vertices+i*8));
|
|
8951
|
-
return points;
|
|
8952
|
-
}
|
|
8953
|
-
debugDraw.DrawSegment = function(point1, point2, color)
|
|
8954
|
-
{
|
|
8955
|
-
color = getDebugColor(color);
|
|
8956
|
-
point1 = box2d.vec2FromPointer(point1);
|
|
8957
|
-
point2 = box2d.vec2FromPointer(point2);
|
|
8958
|
-
box2d.drawLine(vec2(), 0, point1, point2, color, undefined, overlayContext);
|
|
8959
|
-
};
|
|
8960
|
-
debugDraw.DrawPolygon = function(vertices, vertexCount, color)
|
|
8961
|
-
{
|
|
8962
|
-
color = getDebugColor(color);
|
|
8963
|
-
const points = getPointsList(vertices, vertexCount);
|
|
8964
|
-
box2d.drawPoly(vec2(), 0, points, undefined, color, undefined, overlayContext);
|
|
8965
|
-
};
|
|
8966
|
-
debugDraw.DrawSolidPolygon = function(vertices, vertexCount, color)
|
|
8967
|
-
{
|
|
8968
|
-
color = getDebugColor(color);
|
|
8969
|
-
const points = getPointsList(vertices, vertexCount);
|
|
8970
|
-
box2d.drawPoly(vec2(), 0, points, color, color, undefined, overlayContext);
|
|
8971
|
-
};
|
|
8972
|
-
debugDraw.DrawCircle = function(center, radius, color)
|
|
8973
|
-
{
|
|
8974
|
-
color = getDebugColor(color);
|
|
8975
|
-
center = box2d.vec2FromPointer(center);
|
|
8976
|
-
box2d.drawCircle(center, radius, undefined, color, undefined, overlayContext);
|
|
8977
|
-
};
|
|
8978
|
-
debugDraw.DrawSolidCircle = function(center, radius, axis, color)
|
|
8979
|
-
{
|
|
8980
|
-
color = getDebugColor(color);
|
|
8981
|
-
center = box2d.vec2FromPointer(center);
|
|
8982
|
-
axis = box2d.vec2FromPointer(axis).scale(radius);
|
|
8983
|
-
box2d.drawCircle(center, radius, color, color, undefined, overlayContext);
|
|
8984
|
-
box2d.drawLine(center, 0, vec2(), axis, color, undefined, overlayContext);
|
|
8985
|
-
};
|
|
8986
|
-
debugDraw.DrawTransform = function(transform)
|
|
8987
|
-
{
|
|
8988
|
-
transform = box2d.instance.wrapPointer(transform, box2d.instance.b2Transform);
|
|
8989
|
-
const pos = vec2(transform.get_p());
|
|
8990
|
-
const angle = -transform.get_q().GetAngle();
|
|
8991
|
-
const p1 = vec2(1,0), c1 = rgb(.75,0,0,.8);
|
|
8992
|
-
const p2 = vec2(0,1), c2 = rgb(0,.75,0,.8);
|
|
8993
|
-
box2d.drawLine(pos, angle, vec2(), p1, c1, undefined, overlayContext);
|
|
8994
|
-
box2d.drawLine(pos, angle, vec2(), p2, c2, undefined, overlayContext);
|
|
8995
|
-
}
|
|
8996
|
-
|
|
8997
|
-
debugDraw.AppendFlags(box2d.instance.b2Draw.e_shapeBit);
|
|
8998
|
-
debugDraw.AppendFlags(box2d.instance.b2Draw.e_jointBit);
|
|
8999
|
-
//debugDraw.AppendFlags(box2d.instance.b2Draw.e_aabbBit);
|
|
9000
|
-
//debugDraw.AppendFlags(box2d.instance.b2Draw.e_pairBit);
|
|
9001
|
-
//debugDraw.AppendFlags(box2d.instance.b2Draw.e_centerOfMassBit);
|
|
9002
|
-
box2d.world.SetDebugDraw(debugDraw);
|
|
9003
|
-
}
|
|
9004
|
-
}
|
|
9085
|
+
// Particles
|
|
9086
|
+
ParticleEmitter,
|
|
9087
|
+
Particle,
|
|
9088
|
+
|
|
9089
|
+
// Medals
|
|
9090
|
+
medals,
|
|
9091
|
+
medalsPreventUnlock,
|
|
9092
|
+
medalsInit,
|
|
9093
|
+
Medal,
|
|
9094
|
+
};
|
|
9005
9095
|
|
|
9006
9096
|
/**
|
|
9007
9097
|
* LittleJS Module Plugins Export
|
|
9008
9098
|
*/
|
|
9009
9099
|
|
|
9010
|
-
'use strict';
|
|
9011
|
-
|
|
9012
9100
|
export
|
|
9013
9101
|
{
|
|
9014
9102
|
// Newgrounds
|
|
@@ -9036,7 +9124,8 @@ export
|
|
|
9036
9124
|
// Box2D Physics
|
|
9037
9125
|
box2d,
|
|
9038
9126
|
box2dDebug,
|
|
9039
|
-
|
|
9127
|
+
box2dSetDebug,
|
|
9128
|
+
box2dInit,
|
|
9040
9129
|
Box2dPlugin,
|
|
9041
9130
|
Box2dObject,
|
|
9042
9131
|
Box2dRaycastResult,
|