littlejsengine 1.14.11 → 1.14.16
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/littlejs.d.ts +252 -109
- package/dist/littlejs.esm.js +559 -252
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +557 -251
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +482 -206
- package/examples/box2d/gameObjects.js +2 -2
- package/examples/breakout/gameObjects.js +2 -2
- package/examples/breakoutTutorial/README.md +32 -32
- package/examples/breakoutTutorial/game.js +1 -1
- package/examples/electron/game.js +3 -3
- package/examples/electron/index.html +2 -2
- package/examples/electron/package.json +1 -8
- package/examples/index.html +10 -7
- package/examples/module/game.js +3 -3
- package/examples/platformer/gameEffects.js +4 -4
- package/examples/platformer/gameLevel.js +1 -1
- package/examples/platformer/gameObjects.js +4 -4
- package/examples/puzzle/game.js +1 -1
- package/examples/shorts/animation.js +1 -1
- package/examples/shorts/base.html +1 -1
- package/examples/shorts/blending.js +8 -14
- package/examples/shorts/box2d.js +7 -3
- package/examples/shorts/box2dCar.js +2 -1
- package/examples/shorts/empty.js +30 -0
- package/examples/shorts/helloWorld.js +1 -1
- package/examples/shorts/hillGlideGame.js +10 -4
- package/examples/shorts/landerGame.js +11 -8
- package/examples/shorts/medals.js +4 -4
- package/examples/shorts/music.js +29 -56
- package/examples/shorts/musicPlayer.js +134 -0
- package/examples/shorts/nineSlice.js +34 -15
- package/examples/shorts/parallax.js +4 -3
- package/examples/shorts/particles.js +15 -15
- package/examples/shorts/piano.js +15 -21
- package/examples/shorts/pongGame.js +6 -4
- package/examples/shorts/raycasting.js +9 -4
- package/examples/shorts/sequencer.js +122 -0
- package/examples/shorts/shapes.js +7 -4
- package/examples/shorts/slidingPuzzle.js +4 -2
- package/examples/shorts/sound.js +18 -9
- package/examples/shorts/spaceGame.js +12 -8
- package/examples/shorts/spriteAtlas.js +7 -7
- package/examples/shorts/starfield.js +1 -1
- package/examples/shorts/systemFont.js +2 -2
- package/examples/shorts/texture.js +2 -2
- package/examples/shorts/tileLayer.js +10 -10
- package/examples/shorts/tiltedView.js +14 -3
- package/examples/shorts/timers.js +10 -0
- package/examples/shorts/topDown.js +4 -1
- package/examples/shorts/uiSystem.js +8 -5
- package/examples/starter/game.js +3 -3
- package/examples/starter/index.html +2 -2
- package/examples/typescript/game.js +3 -3
- package/examples/typescript/game.ts +3 -3
- package/examples/uiSystem/game.js +3 -3
- package/package.json +4 -2
- package/plugins/box2d.js +17 -2
- package/plugins/newgrounds.js +7 -5
- package/plugins/postProcess.js +5 -2
- package/plugins/uiSystem.js +120 -34
- package/plugins/zzfxm.js +5 -1
- package/reference.md +1 -1
- package/src/engine.js +35 -12
- package/src/engineAudio.js +31 -14
- package/src/engineDebug.js +75 -45
- package/src/engineDraw.js +60 -31
- package/src/engineExport.js +2 -1
- package/src/engineMedals.js +10 -2
- package/src/engineObject.js +14 -10
- package/src/engineParticles.js +59 -46
- package/src/engineSettings.js +7 -7
- package/src/engineTileLayer.js +45 -20
- package/src/engineUtilities.js +67 -20
package/dist/littlejs.release.js
CHANGED
|
@@ -33,7 +33,7 @@ const engineName = 'LittleJS';
|
|
|
33
33
|
* @type {string}
|
|
34
34
|
* @default
|
|
35
35
|
* @memberof Engine */
|
|
36
|
-
const engineVersion = '1.14.
|
|
36
|
+
const engineVersion = '1.14.16';
|
|
37
37
|
|
|
38
38
|
/** Frames per second to update
|
|
39
39
|
* @type {number}
|
|
@@ -96,9 +96,14 @@ let frameTimeLastMS = 0, frameTimeBufferMS = 0, averageFPS = 0;
|
|
|
96
96
|
|
|
97
97
|
const pluginUpdateList = [], pluginRenderList = [];
|
|
98
98
|
|
|
99
|
+
/**
|
|
100
|
+
* @callback PluginCallback - Update or render function for a plugin
|
|
101
|
+
* @memberof Engine
|
|
102
|
+
*/
|
|
103
|
+
|
|
99
104
|
/** Add a new update function for a plugin
|
|
100
|
-
* @param {
|
|
101
|
-
* @param {
|
|
105
|
+
* @param {PluginCallback} [updateFunction]
|
|
106
|
+
* @param {PluginCallback} [renderFunction]
|
|
102
107
|
* @memberof Engine */
|
|
103
108
|
function engineAddPlugin(updateFunction, renderFunction)
|
|
104
109
|
{
|
|
@@ -111,12 +116,22 @@ function engineAddPlugin(updateFunction, renderFunction)
|
|
|
111
116
|
///////////////////////////////////////////////////////////////////////////////
|
|
112
117
|
// Main Engine Functions
|
|
113
118
|
|
|
119
|
+
/**
|
|
120
|
+
* @callback GameInitCallback - Called after the engine starts, can be async
|
|
121
|
+
* @returns {void|Promise<void>}
|
|
122
|
+
* @memberof Engine
|
|
123
|
+
*/
|
|
124
|
+
/**
|
|
125
|
+
* @callback GameCallback - Update or render function for the game
|
|
126
|
+
* @memberof Engine
|
|
127
|
+
*/
|
|
128
|
+
|
|
114
129
|
/** Startup LittleJS engine with your callback functions
|
|
115
|
-
* @param {
|
|
116
|
-
* @param {
|
|
117
|
-
* @param {
|
|
118
|
-
* @param {
|
|
119
|
-
* @param {
|
|
130
|
+
* @param {GameInitCallback} gameInit - Called once after the engine starts up, can be async for loading
|
|
131
|
+
* @param {GameCallback} gameUpdate - Called every frame before objects are updated (60fps), use for game logic
|
|
132
|
+
* @param {GameCallback} gameUpdatePost - Called after physics and objects are updated, even when paused, use for UI updates
|
|
133
|
+
* @param {GameCallback} gameRender - Called before objects are rendered, use for drawing backgrounds/world elements
|
|
134
|
+
* @param {GameCallback} gameRenderPost - Called after objects are rendered, use for drawing UI/overlays
|
|
120
135
|
* @param {Array<string>} [imageSources=[]] - List of image file paths to preload (e.g., ['player.png', 'tiles.png'])
|
|
121
136
|
* @param {HTMLElement} [rootElement] - Root DOM element to attach canvas to, defaults to document.body
|
|
122
137
|
* @example
|
|
@@ -368,6 +383,8 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
|
|
|
368
383
|
const promises = imageSources.map((src, textureIndex)=>
|
|
369
384
|
new Promise(resolve =>
|
|
370
385
|
{
|
|
386
|
+
ASSERT(isString(src), 'imageSources must be an array of strings');
|
|
387
|
+
|
|
371
388
|
const image = new Image;
|
|
372
389
|
image.onerror = image.onload = ()=>
|
|
373
390
|
{
|
|
@@ -399,7 +416,7 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
|
|
|
399
416
|
promises.push(new Promise(resolve =>
|
|
400
417
|
{
|
|
401
418
|
let t = 0;
|
|
402
|
-
|
|
419
|
+
console.log(`${engineName} Engine v${engineVersion}`);
|
|
403
420
|
updateSplash();
|
|
404
421
|
function updateSplash()
|
|
405
422
|
{
|
|
@@ -483,10 +500,16 @@ function engineObjectsCollect(pos, size, objects=engineObjects)
|
|
|
483
500
|
return collectedObjects;
|
|
484
501
|
}
|
|
485
502
|
|
|
503
|
+
/**
|
|
504
|
+
* @callback ObjectCallbackFunction - Function that processes an object
|
|
505
|
+
* @param {EngineObject} uiObjects
|
|
506
|
+
* @memberof Engine
|
|
507
|
+
*/
|
|
508
|
+
|
|
486
509
|
/** Triggers a callback for each object within a given area
|
|
487
|
-
* @param {Vector2} [pos]
|
|
488
|
-
* @param {Vector2|number} [size]
|
|
489
|
-
* @param {
|
|
510
|
+
* @param {Vector2} [pos] - Center of test area, or undefined for all objects
|
|
511
|
+
* @param {Vector2|number} [size] - Radius of circle if float, rectangle size if Vector2
|
|
512
|
+
* @param {ObjectCallbackFunction} [callbackFunction] - Calls this function on every object that passes the test
|
|
490
513
|
* @param {Array<EngineObject>} [objects=engineObjects] - List of objects to check
|
|
491
514
|
* @memberof Engine */
|
|
492
515
|
function engineObjectsCallback(pos, size, callbackFunction, objects=engineObjects)
|
|
@@ -950,6 +973,8 @@ function formatTime(t)
|
|
|
950
973
|
async function fetchJSON(url)
|
|
951
974
|
{
|
|
952
975
|
const response = await fetch(url);
|
|
976
|
+
if (!response.ok)
|
|
977
|
+
throw new Error(`Failed to fetch JSON from ${url}: ${response.status} ${response.statusText}`);
|
|
953
978
|
return response.json();
|
|
954
979
|
}
|
|
955
980
|
|
|
@@ -960,6 +985,13 @@ async function fetchJSON(url)
|
|
|
960
985
|
* @memberof Utilities */
|
|
961
986
|
function isNumber(n) { return typeof n === 'number' && !isNaN(n); }
|
|
962
987
|
|
|
988
|
+
/**
|
|
989
|
+
* Check if object is a valid string or can be converted to one
|
|
990
|
+
* @param {any} s
|
|
991
|
+
* @return {boolean}
|
|
992
|
+
* @memberof Utilities */
|
|
993
|
+
function isString(s) { return s !== undefined && s !== null && typeof s.toString() === 'string'; }
|
|
994
|
+
|
|
963
995
|
///////////////////////////////////////////////////////////////////////////////
|
|
964
996
|
|
|
965
997
|
/** Random global functions
|
|
@@ -1022,6 +1054,7 @@ function randColor(colorA=new Color, colorB=new Color(0,0,0,1), linear=false)
|
|
|
1022
1054
|
/**
|
|
1023
1055
|
* Seeded random number generator
|
|
1024
1056
|
* - Can be used to create a deterministic random number sequence
|
|
1057
|
+
* @memberof Engine
|
|
1025
1058
|
* @example
|
|
1026
1059
|
* let r = new RandomGenerator(123); // random number generator with seed 123
|
|
1027
1060
|
* let a = r.float(); // random value between 0 and 1
|
|
@@ -1118,6 +1151,7 @@ function ASSERT_VECTOR2_NORMAL(v)
|
|
|
1118
1151
|
/**
|
|
1119
1152
|
* 2D Vector object with vector math library
|
|
1120
1153
|
* - Functions do not change this so they can be chained together
|
|
1154
|
+
* @memberof Engine
|
|
1121
1155
|
* @example
|
|
1122
1156
|
* let a = new Vector2(2, 3); // vector with coordinates (2, 3)
|
|
1123
1157
|
* let b = new Vector2; // vector with coordinates (0, 0)
|
|
@@ -1258,9 +1292,10 @@ class Vector2
|
|
|
1258
1292
|
return new Vector2(this.x*c - this.y*s, this.x*s + this.y*c);
|
|
1259
1293
|
}
|
|
1260
1294
|
|
|
1261
|
-
/**
|
|
1295
|
+
/** Sets this this vector to point in the specified integer direction (0-3), corresponding to multiples of 90 degree rotation
|
|
1262
1296
|
* @param {number} [direction]
|
|
1263
|
-
* @param {number} [length]
|
|
1297
|
+
* @param {number} [length]
|
|
1298
|
+
* @return {Vector2} */
|
|
1264
1299
|
setDirection(direction, length=1)
|
|
1265
1300
|
{
|
|
1266
1301
|
ASSERT_NUMBER_VALID(direction);
|
|
@@ -1268,8 +1303,10 @@ class Vector2
|
|
|
1268
1303
|
direction = mod(direction, 4);
|
|
1269
1304
|
ASSERT(direction===0 || direction===1 || direction===2 || direction===3,
|
|
1270
1305
|
'Vector2.setDirection() direction must be an integer between 0 and 3.');
|
|
1271
|
-
|
|
1272
|
-
|
|
1306
|
+
|
|
1307
|
+
this.x = direction%2 ? direction-1 ? -length : length : 0;
|
|
1308
|
+
this.y = direction%2 ? 0 : direction ? -length : length;
|
|
1309
|
+
return this;
|
|
1273
1310
|
}
|
|
1274
1311
|
|
|
1275
1312
|
/** Returns the integer direction of this vector, corresponding to multiples of 90 degree rotation (0-3)
|
|
@@ -1365,6 +1402,7 @@ function ASSERT_COLOR_VALID(c) { ASSERT(isColor(c), 'Color is invalid.', c); }
|
|
|
1365
1402
|
|
|
1366
1403
|
/**
|
|
1367
1404
|
* Color object (red, green, blue, alpha) with some helpful functions
|
|
1405
|
+
* @memberof Engine
|
|
1368
1406
|
* @example
|
|
1369
1407
|
* let a = new Color; // white
|
|
1370
1408
|
* let b = new Color(1, 0, 0); // red
|
|
@@ -1542,7 +1580,8 @@ class Color
|
|
|
1542
1580
|
* @return {Color} */
|
|
1543
1581
|
setHex(hex)
|
|
1544
1582
|
{
|
|
1545
|
-
ASSERT(
|
|
1583
|
+
ASSERT(isString(hex), 'Color hex code must be a string');
|
|
1584
|
+
ASSERT(hex[0] === '#', 'Color hex code must start with #');
|
|
1546
1585
|
ASSERT([4,5,7,9].includes(hex.length), 'Invalid hex');
|
|
1547
1586
|
|
|
1548
1587
|
if (hex.length < 6)
|
|
@@ -1584,77 +1623,78 @@ class Color
|
|
|
1584
1623
|
}
|
|
1585
1624
|
|
|
1586
1625
|
///////////////////////////////////////////////////////////////////////////////
|
|
1587
|
-
//
|
|
1626
|
+
// Default Colors
|
|
1588
1627
|
|
|
1589
1628
|
/** Color - White #ffffff
|
|
1590
1629
|
* @type {Color}
|
|
1591
1630
|
* @memberof Utilities */
|
|
1592
|
-
const WHITE = rgb();
|
|
1631
|
+
const WHITE = protectEngineConstant(rgb());
|
|
1593
1632
|
|
|
1594
|
-
/** Color - Clear White #
|
|
1633
|
+
/** Color - Clear White #757474ff with 0 alpha
|
|
1595
1634
|
* @type {Color}
|
|
1596
1635
|
* @memberof Utilities */
|
|
1597
|
-
const CLEAR_WHITE = rgb(1,1,1,0);
|
|
1636
|
+
const CLEAR_WHITE = protectEngineConstant(rgb(1,1,1,0));
|
|
1598
1637
|
|
|
1599
1638
|
/** Color - Black #000000
|
|
1600
1639
|
* @type {Color}
|
|
1601
1640
|
* @memberof Utilities */
|
|
1602
|
-
const BLACK = rgb(0,0,0);
|
|
1641
|
+
const BLACK = protectEngineConstant(rgb(0,0,0));
|
|
1603
1642
|
|
|
1604
1643
|
/** Color - Clear Black #000000 with 0 alpha
|
|
1605
1644
|
* @type {Color}
|
|
1606
1645
|
* @memberof Utilities */
|
|
1607
|
-
const CLEAR_BLACK = rgb(0,0,0,0);
|
|
1646
|
+
const CLEAR_BLACK = protectEngineConstant(rgb(0,0,0,0));
|
|
1608
1647
|
|
|
1609
1648
|
/** Color - Gray #808080
|
|
1610
1649
|
* @type {Color}
|
|
1611
1650
|
* @memberof Utilities */
|
|
1612
|
-
const GRAY = rgb(.5,.5,.5);
|
|
1651
|
+
const GRAY = protectEngineConstant(rgb(.5,.5,.5));
|
|
1613
1652
|
|
|
1614
1653
|
/** Color - Red #ff0000
|
|
1615
1654
|
* @type {Color}
|
|
1616
1655
|
* @memberof Utilities */
|
|
1617
|
-
const RED = rgb(1,0,0);
|
|
1656
|
+
const RED = protectEngineConstant(rgb(1,0,0));
|
|
1618
1657
|
|
|
1619
1658
|
/** Color - Orange #ff8000
|
|
1620
1659
|
* @type {Color}
|
|
1621
1660
|
* @memberof Utilities */
|
|
1622
|
-
const ORANGE = rgb(1,.5,0);
|
|
1661
|
+
const ORANGE = protectEngineConstant(rgb(1,.5,0));
|
|
1623
1662
|
|
|
1624
1663
|
/** Color - Yellow #ffff00
|
|
1625
1664
|
* @type {Color}
|
|
1626
1665
|
* @memberof Utilities */
|
|
1627
|
-
const YELLOW = rgb(1,1,0);
|
|
1666
|
+
const YELLOW = protectEngineConstant(rgb(1,1,0));
|
|
1628
1667
|
|
|
1629
1668
|
/** Color - Green #00ff00
|
|
1630
1669
|
* @type {Color}
|
|
1631
1670
|
* @memberof Utilities */
|
|
1632
|
-
const GREEN = rgb(0,1,0);
|
|
1671
|
+
const GREEN = protectEngineConstant(rgb(0,1,0));
|
|
1633
1672
|
|
|
1634
1673
|
/** Color - Cyan #00ffff
|
|
1635
1674
|
* @type {Color}
|
|
1636
1675
|
* @memberof Utilities */
|
|
1637
|
-
const CYAN = rgb(0,1,1);
|
|
1676
|
+
const CYAN = protectEngineConstant(rgb(0,1,1));
|
|
1638
1677
|
|
|
1639
1678
|
/** Color - Blue #0000ff
|
|
1640
1679
|
* @type {Color}
|
|
1641
1680
|
* @memberof Utilities */
|
|
1642
|
-
const BLUE = rgb(0,0,1);
|
|
1681
|
+
const BLUE = protectEngineConstant(rgb(0,0,1));
|
|
1643
1682
|
|
|
1644
1683
|
/** Color - Purple #8000ff
|
|
1645
1684
|
* @type {Color}
|
|
1646
1685
|
* @memberof Utilities */
|
|
1647
|
-
const PURPLE = rgb(.5,0,1);
|
|
1686
|
+
const PURPLE = protectEngineConstant(rgb(.5,0,1));
|
|
1648
1687
|
|
|
1649
1688
|
/** Color - Magenta #ff00ff
|
|
1650
1689
|
* @type {Color}
|
|
1651
1690
|
* @memberof Utilities */
|
|
1652
|
-
const MAGENTA = rgb(1,0,1);
|
|
1691
|
+
const MAGENTA = protectEngineConstant(rgb(1,0,1));
|
|
1653
1692
|
|
|
1654
1693
|
///////////////////////////////////////////////////////////////////////////////
|
|
1655
1694
|
|
|
1656
1695
|
/**
|
|
1657
1696
|
* Timer object tracks how long has passed since it was set
|
|
1697
|
+
* @memberof Engine
|
|
1658
1698
|
* @example
|
|
1659
1699
|
* let a = new Timer; // creates a timer that is not set
|
|
1660
1700
|
* a.set(3); // sets the timer to 3 seconds
|
|
@@ -1716,6 +1756,36 @@ class Timer
|
|
|
1716
1756
|
/** Get how long since elapsed, returns 0 if not set (returns negative if currently active)
|
|
1717
1757
|
* @return {number} */
|
|
1718
1758
|
valueOf() { return this.get(); }
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
1762
|
+
// Helper functions used by the engine
|
|
1763
|
+
|
|
1764
|
+
// make color constants immutable with debug assertions
|
|
1765
|
+
function protectEngineConstant(obj)
|
|
1766
|
+
{
|
|
1767
|
+
if (debug)
|
|
1768
|
+
{
|
|
1769
|
+
// get properties and store original values
|
|
1770
|
+
const props = Object.keys(obj), values = {};
|
|
1771
|
+
props.forEach(prop => values[prop] = obj[prop]);
|
|
1772
|
+
|
|
1773
|
+
// replace with getters/setters that assert
|
|
1774
|
+
props.forEach(prop =>
|
|
1775
|
+
{
|
|
1776
|
+
Object.defineProperty(obj, prop, {
|
|
1777
|
+
get: () => values[prop],
|
|
1778
|
+
set: (value) =>
|
|
1779
|
+
{
|
|
1780
|
+
ASSERT(false, `Cannot modify engine constant. Attempted to set constant (${obj}) property '${prop}' to '${value}'.`);
|
|
1781
|
+
},
|
|
1782
|
+
enumerable: true
|
|
1783
|
+
});
|
|
1784
|
+
});
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
// freeze the object to prevent adding new properties
|
|
1788
|
+
return Object.freeze(obj);
|
|
1719
1789
|
}
|
|
1720
1790
|
/**
|
|
1721
1791
|
* LittleJS Engine Settings
|
|
@@ -2023,7 +2093,7 @@ let medalsPreventUnlock = false;
|
|
|
2023
2093
|
/** Set position of camera in world space
|
|
2024
2094
|
* @param {Vector2} pos
|
|
2025
2095
|
* @memberof Settings */
|
|
2026
|
-
function setCameraPos(pos) { cameraPos = pos; }
|
|
2096
|
+
function setCameraPos(pos) { cameraPos = pos.copy(); }
|
|
2027
2097
|
|
|
2028
2098
|
/** Set angle of camera in world space
|
|
2029
2099
|
* @param {number} angle
|
|
@@ -2046,17 +2116,17 @@ function setCanvasColorTiles(colorTiles) { canvasColorTiles = colorTiles; }
|
|
|
2046
2116
|
/** Set color to clear the canvas to before render
|
|
2047
2117
|
* @param {Color} color
|
|
2048
2118
|
* @memberof Settings */
|
|
2049
|
-
function setCanvasClearColor(color) { canvasClearColor = color; }
|
|
2119
|
+
function setCanvasClearColor(color) { canvasClearColor = color.copy(); }
|
|
2050
2120
|
|
|
2051
2121
|
/** Set max size of the canvas
|
|
2052
2122
|
* @param {Vector2} size
|
|
2053
2123
|
* @memberof Settings */
|
|
2054
|
-
function setCanvasMaxSize(size) { canvasMaxSize = size; }
|
|
2124
|
+
function setCanvasMaxSize(size) { canvasMaxSize = size.copy(); }
|
|
2055
2125
|
|
|
2056
2126
|
/** Set fixed size of the canvas
|
|
2057
2127
|
* @param {Vector2} size
|
|
2058
2128
|
* @memberof Settings */
|
|
2059
|
-
function setCanvasFixedSize(size) { canvasFixedSize = size; }
|
|
2129
|
+
function setCanvasFixedSize(size) { canvasFixedSize = size.copy(); }
|
|
2060
2130
|
|
|
2061
2131
|
/** Use nearest scaling algorithm for canvas for more pixelated look
|
|
2062
2132
|
* - If enabled sets css image-rendering:pixelated
|
|
@@ -2121,7 +2191,7 @@ function setGLCircleSides(sides) { glCircleSides = sides; }
|
|
|
2121
2191
|
/** Set default size of tiles in pixels
|
|
2122
2192
|
* @param {Vector2} size
|
|
2123
2193
|
* @memberof Settings */
|
|
2124
|
-
function setTileSizeDefault(size) { tileSizeDefault = size; }
|
|
2194
|
+
function setTileSizeDefault(size) { tileSizeDefault = size.copy(); }
|
|
2125
2195
|
|
|
2126
2196
|
/** Set to prevent tile bleeding from neighbors in pixels
|
|
2127
2197
|
* @param {number} scale
|
|
@@ -2166,7 +2236,7 @@ function setObjectMaxSpeed(speed) { objectMaxSpeed = speed; }
|
|
|
2166
2236
|
/** Set how much gravity to apply to objects
|
|
2167
2237
|
* @param {Vector2} newGravity
|
|
2168
2238
|
* @memberof Settings */
|
|
2169
|
-
function setGravity(newGravity) { gravity = newGravity; }
|
|
2239
|
+
function setGravity(newGravity) { gravity = newGravity.copy(); }
|
|
2170
2240
|
|
|
2171
2241
|
/** Set to scales emit rate of particles
|
|
2172
2242
|
* @param {number} scale
|
|
@@ -2256,7 +2326,7 @@ function setMedalDisplaySlideTime(time) { medalDisplaySlideTime = time; }
|
|
|
2256
2326
|
/** Set size of medal display
|
|
2257
2327
|
* @param {Vector2} size
|
|
2258
2328
|
* @memberof Settings */
|
|
2259
|
-
function setMedalDisplaySize(size) { medalDisplaySize = size; }
|
|
2329
|
+
function setMedalDisplaySize(size) { medalDisplaySize = size.copy(); }
|
|
2260
2330
|
|
|
2261
2331
|
/** Set to stop medals from being unlockable
|
|
2262
2332
|
* @param {boolean} preventUnlock
|
|
@@ -2296,6 +2366,7 @@ function setDebugKey(key) { debugKey = key; }
|
|
|
2296
2366
|
* - Collision for objects can be set to be solid to block other objects
|
|
2297
2367
|
* - Objects may get pushed into overlapping other solid objects, if so they will push away
|
|
2298
2368
|
* - Solid objects are more performance intensive and should be used sparingly
|
|
2369
|
+
* @memberof Engine
|
|
2299
2370
|
* @example
|
|
2300
2371
|
* // create an engine object, normally you would first extend the class with your own
|
|
2301
2372
|
* const pos = vec2(2,3);
|
|
@@ -2304,18 +2375,18 @@ function setDebugKey(key) { debugKey = key; }
|
|
|
2304
2375
|
class EngineObject
|
|
2305
2376
|
{
|
|
2306
2377
|
/** Create an engine object and adds it to the list of objects
|
|
2307
|
-
* @param {Vector2} [pos=(0,0)]
|
|
2308
|
-
* @param {Vector2} [size=(1,1)]
|
|
2309
|
-
* @param {TileInfo} [tileInfo]
|
|
2310
|
-
* @param {number} [angle]
|
|
2311
|
-
* @param {Color} [color=
|
|
2312
|
-
* @param {number} [renderOrder]
|
|
2378
|
+
* @param {Vector2} [pos=(0,0)] - World space position of the object
|
|
2379
|
+
* @param {Vector2} [size=(1,1)] - World space size of the object
|
|
2380
|
+
* @param {TileInfo} [tileInfo] - Tile info to render object (undefined is untextured)
|
|
2381
|
+
* @param {number} [angle] - Angle the object is rotated by
|
|
2382
|
+
* @param {Color} [color=WHITE] - Color to apply to tile when rendered
|
|
2383
|
+
* @param {number} [renderOrder] - Objects sorted by renderOrder before being rendered
|
|
2313
2384
|
*/
|
|
2314
|
-
constructor(pos=vec2(), size=vec2(1), tileInfo, angle=0, color=
|
|
2385
|
+
constructor(pos=vec2(), size=vec2(1), tileInfo, angle=0, color=WHITE, renderOrder=0)
|
|
2315
2386
|
{
|
|
2316
2387
|
// check passed in params
|
|
2317
|
-
ASSERT(isVector2(pos), 'object pos
|
|
2318
|
-
ASSERT(isVector2(size), 'object size
|
|
2388
|
+
ASSERT(isVector2(pos), 'object pos must be a vec2');
|
|
2389
|
+
ASSERT(isVector2(size), 'object size must be a vec2');
|
|
2319
2390
|
ASSERT(!tileInfo || tileInfo instanceof TileInfo, 'object tileInfo should be a TileInfo or undefined');
|
|
2320
2391
|
ASSERT(typeof angle === 'number' && isFinite(angle), 'object angle should be a number');
|
|
2321
2392
|
ASSERT(isColor(color), 'object color should be a valid rgba color');
|
|
@@ -2600,7 +2671,7 @@ class EngineObject
|
|
|
2600
2671
|
drawTile(this.pos, this.drawSize || this.size, this.tileInfo, this.color, this.angle, this.mirror, this.additiveColor);
|
|
2601
2672
|
}
|
|
2602
2673
|
|
|
2603
|
-
/** Destroy this object, destroy its children, detach
|
|
2674
|
+
/** Destroy this object, destroy its children, detach its parent, and mark it for removal */
|
|
2604
2675
|
destroy()
|
|
2605
2676
|
{
|
|
2606
2677
|
if (this.destroyed)
|
|
@@ -2674,6 +2745,8 @@ class EngineObject
|
|
|
2674
2745
|
addChild(child, localPos=vec2(), localAngle=0)
|
|
2675
2746
|
{
|
|
2676
2747
|
ASSERT(!child.parent && !this.children.includes(child));
|
|
2748
|
+
ASSERT(child instanceof EngineObject, 'child must be an EngineObject');
|
|
2749
|
+
ASSERT(child !== this, 'cannot add self as child');
|
|
2677
2750
|
this.children.push(child);
|
|
2678
2751
|
child.parent = this;
|
|
2679
2752
|
child.localPos = localPos.copy();
|
|
@@ -2685,6 +2758,7 @@ class EngineObject
|
|
|
2685
2758
|
removeChild(child)
|
|
2686
2759
|
{
|
|
2687
2760
|
ASSERT(child.parent === this && this.children.includes(child));
|
|
2761
|
+
ASSERT(child instanceof EngineObject, 'child must be an EngineObject');
|
|
2688
2762
|
this.children.splice(this.children.indexOf(child), 1);
|
|
2689
2763
|
child.parent = 0;
|
|
2690
2764
|
}
|
|
@@ -2823,7 +2897,7 @@ let drawCount;
|
|
|
2823
2897
|
* Create a tile info object using a grid based system
|
|
2824
2898
|
* - This can take vecs or floats for easier use and conversion
|
|
2825
2899
|
* - If an index is passed in, the tile size and index will determine the position
|
|
2826
|
-
* @param {Vector2|number} [pos=0] -
|
|
2900
|
+
* @param {Vector2|number} [pos=0] - Position of the tile in pixels, or tile index
|
|
2827
2901
|
* @param {Vector2|number} [size=tileSizeDefault] - Size of tile in pixels
|
|
2828
2902
|
* @param {number} [textureIndex] - Texture index to use
|
|
2829
2903
|
* @param {number} [padding] - How many pixels padding around tiles
|
|
@@ -2868,6 +2942,7 @@ function tile(pos=new Vector2, size=tileSizeDefault, textureIndex=0, padding=0)
|
|
|
2868
2942
|
|
|
2869
2943
|
/**
|
|
2870
2944
|
* Tile Info - Stores info about how to draw a tile
|
|
2945
|
+
* @memberof Draw
|
|
2871
2946
|
*/
|
|
2872
2947
|
class TileInfo
|
|
2873
2948
|
{
|
|
@@ -2928,7 +3003,10 @@ class TileInfo
|
|
|
2928
3003
|
}
|
|
2929
3004
|
}
|
|
2930
3005
|
|
|
2931
|
-
/**
|
|
3006
|
+
/**
|
|
3007
|
+
* Tile Info - Stores info about each texture
|
|
3008
|
+
* @memberof Draw
|
|
3009
|
+
*/
|
|
2932
3010
|
class TextureInfo
|
|
2933
3011
|
{
|
|
2934
3012
|
/**
|
|
@@ -2974,10 +3052,11 @@ class TextureInfo
|
|
|
2974
3052
|
function drawTile(pos, size=new Vector2(1), tileInfo, color=WHITE,
|
|
2975
3053
|
angle=0, mirror, additiveColor, useWebGL=glEnable, screenSpace, context)
|
|
2976
3054
|
{
|
|
2977
|
-
ASSERT(isVector2(pos), '
|
|
2978
|
-
ASSERT(isVector2(size), '
|
|
2979
|
-
ASSERT(isColor(color)
|
|
2980
|
-
ASSERT(isNumber(angle), '
|
|
3055
|
+
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
3056
|
+
ASSERT(isVector2(size), 'size must be a vec2');
|
|
3057
|
+
ASSERT(isColor(color), 'color is invalid');
|
|
3058
|
+
ASSERT(isNumber(angle), 'angle must be a number');
|
|
3059
|
+
ASSERT(!additiveColor || isColor(additiveColor), 'additiveColor must be a color');
|
|
2981
3060
|
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
2982
3061
|
|
|
2983
3062
|
const textureInfo = tileInfo && tileInfo.textureInfo;
|
|
@@ -3072,10 +3151,10 @@ function drawRect(pos, size, color, angle, useWebGL, screenSpace, context)
|
|
|
3072
3151
|
* @memberof Draw */
|
|
3073
3152
|
function drawRectGradient(pos, size, colorTop=WHITE, colorBottom=BLACK, angle=0, useWebGL=glEnable, screenSpace=false, context)
|
|
3074
3153
|
{
|
|
3075
|
-
ASSERT(isVector2(pos), '
|
|
3076
|
-
ASSERT(isVector2(size), '
|
|
3077
|
-
ASSERT(isColor(colorTop) && isColor(colorBottom), '
|
|
3078
|
-
ASSERT(isNumber(angle), '
|
|
3154
|
+
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
3155
|
+
ASSERT(isVector2(size), 'size must be a vec2');
|
|
3156
|
+
ASSERT(isColor(colorTop) && isColor(colorBottom), 'color is invalid');
|
|
3157
|
+
ASSERT(isNumber(angle), 'angle must be a number');
|
|
3079
3158
|
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
3080
3159
|
if (useWebGL)
|
|
3081
3160
|
{
|
|
@@ -3133,11 +3212,11 @@ function drawRectGradient(pos, size, colorTop=WHITE, colorBottom=BLACK, angle=0,
|
|
|
3133
3212
|
* @memberof Draw */
|
|
3134
3213
|
function drawLineList(points, width=.1, color, wrap=false, pos=vec2(), angle=0, useWebGL=glEnable, screenSpace, context)
|
|
3135
3214
|
{
|
|
3136
|
-
ASSERT(Array.isArray(points), '
|
|
3137
|
-
ASSERT(isNumber(width), '
|
|
3138
|
-
ASSERT(isColor(color), '
|
|
3139
|
-
ASSERT(isVector2(pos), '
|
|
3140
|
-
ASSERT(isNumber(angle), '
|
|
3215
|
+
ASSERT(Array.isArray(points), 'points must be an array');
|
|
3216
|
+
ASSERT(isNumber(width), 'width must be a number');
|
|
3217
|
+
ASSERT(isColor(color), 'color is invalid');
|
|
3218
|
+
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
3219
|
+
ASSERT(isNumber(angle), 'angle must be a number');
|
|
3141
3220
|
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
3142
3221
|
if (useWebGL)
|
|
3143
3222
|
{
|
|
@@ -3208,8 +3287,8 @@ function drawLine(posA, posB, width=.1, color, pos=vec2(), angle=0, useWebGL, sc
|
|
|
3208
3287
|
* @memberof Draw */
|
|
3209
3288
|
function drawRegularPoly(pos, size=vec2(1), sides=3, color=WHITE, lineWidth=0, lineColor=BLACK, angle=0, useWebGL=glEnable, screenSpace=false, context)
|
|
3210
3289
|
{
|
|
3211
|
-
ASSERT(isVector2(size), '
|
|
3212
|
-
ASSERT(isNumber(sides), '
|
|
3290
|
+
ASSERT(isVector2(size), 'size must be a vec2');
|
|
3291
|
+
ASSERT(isNumber(sides), 'sides must be a number');
|
|
3213
3292
|
|
|
3214
3293
|
// build regular polygon points
|
|
3215
3294
|
const points = [];
|
|
@@ -3235,12 +3314,13 @@ function drawRegularPoly(pos, size=vec2(1), sides=3, color=WHITE, lineWidth=0, l
|
|
|
3235
3314
|
* @memberof Draw */
|
|
3236
3315
|
function drawPoly(points, color=WHITE, lineWidth=0, lineColor=BLACK, pos=vec2(), angle=0, useWebGL=glEnable, screenSpace=false, context=undefined)
|
|
3237
3316
|
{
|
|
3238
|
-
ASSERT(isVector2(pos), '
|
|
3239
|
-
ASSERT(Array.isArray(points), '
|
|
3240
|
-
ASSERT(isColor(color) && isColor(lineColor), '
|
|
3241
|
-
ASSERT(isNumber(lineWidth), '
|
|
3242
|
-
ASSERT(isNumber(angle), '
|
|
3317
|
+
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
3318
|
+
ASSERT(Array.isArray(points), 'points must be an array');
|
|
3319
|
+
ASSERT(isColor(color) && isColor(lineColor), 'color is invalid');
|
|
3320
|
+
ASSERT(isNumber(lineWidth), 'lineWidth must be a number');
|
|
3321
|
+
ASSERT(isNumber(angle), 'angle must be a number');
|
|
3243
3322
|
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
3323
|
+
|
|
3244
3324
|
if (useWebGL)
|
|
3245
3325
|
{
|
|
3246
3326
|
let scale = 1;
|
|
@@ -3287,13 +3367,14 @@ function drawPoly(points, color=WHITE, lineWidth=0, lineColor=BLACK, pos=vec2(),
|
|
|
3287
3367
|
* @memberof Draw */
|
|
3288
3368
|
function drawEllipse(pos, size=vec2(1), color=WHITE, angle=0, lineWidth=0, lineColor=BLACK, useWebGL=glEnable, screenSpace=false, context)
|
|
3289
3369
|
{
|
|
3290
|
-
ASSERT(isVector2(pos), '
|
|
3291
|
-
ASSERT(isVector2(size), '
|
|
3292
|
-
ASSERT(isColor(color) && isColor(lineColor), '
|
|
3293
|
-
ASSERT(isNumber(angle), '
|
|
3294
|
-
ASSERT(isNumber(lineWidth), '
|
|
3295
|
-
ASSERT(lineWidth >= 0 && lineWidth < size.x && lineWidth < size.y, '
|
|
3370
|
+
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
3371
|
+
ASSERT(isVector2(size), 'size must be a vec2');
|
|
3372
|
+
ASSERT(isColor(color) && isColor(lineColor), 'color is invalid');
|
|
3373
|
+
ASSERT(isNumber(angle), 'angle must be a number');
|
|
3374
|
+
ASSERT(isNumber(lineWidth), 'lineWidth must be a number');
|
|
3375
|
+
ASSERT(lineWidth >= 0 && lineWidth < size.x && lineWidth < size.y, 'invalid lineWidth');
|
|
3296
3376
|
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
3377
|
+
|
|
3297
3378
|
if (useWebGL)
|
|
3298
3379
|
{
|
|
3299
3380
|
// draw as a regular polygon
|
|
@@ -3330,21 +3411,32 @@ function drawEllipse(pos, size=vec2(1), color=WHITE, angle=0, lineWidth=0, lineC
|
|
|
3330
3411
|
* @memberof Draw */
|
|
3331
3412
|
function drawCircle(pos, size=1, color=WHITE, lineWidth=0, lineColor=BLACK, useWebGL=glEnable, screenSpace=false, context)
|
|
3332
3413
|
{
|
|
3333
|
-
ASSERT(isNumber(size), '
|
|
3414
|
+
ASSERT(isNumber(size), 'size must be a number');
|
|
3334
3415
|
drawEllipse(pos, vec2(size), color, 0, lineWidth, lineColor, useWebGL, screenSpace, context);
|
|
3335
3416
|
}
|
|
3336
3417
|
|
|
3418
|
+
/**
|
|
3419
|
+
* @callback Canvas2DDrawFunction - A function that draws to a 2D canvas context
|
|
3420
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} context
|
|
3421
|
+
* @memberof Draw
|
|
3422
|
+
*/
|
|
3423
|
+
|
|
3337
3424
|
/** Draw directly to a 2d canvas context in world space
|
|
3338
3425
|
* @param {Vector2} pos
|
|
3339
3426
|
* @param {Vector2} size
|
|
3340
3427
|
* @param {number} angle
|
|
3341
3428
|
* @param {boolean} [mirror]
|
|
3342
|
-
* @param {
|
|
3429
|
+
* @param {Canvas2DDrawFunction} [drawFunction]
|
|
3343
3430
|
* @param {boolean} [screenSpace=false]
|
|
3344
3431
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=drawContext]
|
|
3345
3432
|
* @memberof Draw */
|
|
3346
3433
|
function drawCanvas2D(pos, size, angle=0, mirror=false, drawFunction, screenSpace=false, context=drawContext)
|
|
3347
3434
|
{
|
|
3435
|
+
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
3436
|
+
ASSERT(isVector2(size), 'size must be a vec2');
|
|
3437
|
+
ASSERT(isNumber(angle), 'angle must be a number');
|
|
3438
|
+
ASSERT(typeof drawFunction === 'function', 'drawFunction must be a function');
|
|
3439
|
+
|
|
3348
3440
|
if (!screenSpace)
|
|
3349
3441
|
{
|
|
3350
3442
|
// transform from world space to screen space
|
|
@@ -3412,6 +3504,16 @@ function drawTextOverlay(text, pos, size=1, color, lineWidth=0, lineColor, textA
|
|
|
3412
3504
|
* @memberof Draw */
|
|
3413
3505
|
function drawTextScreen(text, pos, size=1, color=WHITE, lineWidth=0, lineColor=BLACK, textAlign='center', font=fontDefault, maxWidth, context=overlayContext)
|
|
3414
3506
|
{
|
|
3507
|
+
ASSERT(isString(text), 'text must be a string');
|
|
3508
|
+
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
3509
|
+
ASSERT(isNumber(size), 'size must be a number');
|
|
3510
|
+
ASSERT(isColor(color), 'color must be a color');
|
|
3511
|
+
ASSERT(isNumber(lineWidth), 'lineWidth must be a number');
|
|
3512
|
+
ASSERT(isColor(lineColor), 'lineColor must be a color');
|
|
3513
|
+
ASSERT(isColor(lineColor), 'lineColor must be a color');
|
|
3514
|
+
ASSERT(['left','center','right'].includes(textAlign), 'align must be left, center, or right');
|
|
3515
|
+
ASSERT(isString(font), 'font must be a string');
|
|
3516
|
+
|
|
3415
3517
|
context.fillStyle = color.toString();
|
|
3416
3518
|
context.strokeStyle = lineColor.toString();
|
|
3417
3519
|
context.lineWidth = lineWidth;
|
|
@@ -3613,6 +3715,7 @@ let engineFontImage;
|
|
|
3613
3715
|
* - 96 characters (from space to tilde) are stored in an image
|
|
3614
3716
|
* - Uses a default 8x8 font if none is supplied
|
|
3615
3717
|
* - You can also use fonts from the main tile sheet
|
|
3718
|
+
* @memberof Draw
|
|
3616
3719
|
* @example
|
|
3617
3720
|
* // use built in font
|
|
3618
3721
|
* const font = new FontImage;
|
|
@@ -3669,7 +3772,7 @@ class FontImage
|
|
|
3669
3772
|
* @param {boolean} [center]
|
|
3670
3773
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=drawContext]
|
|
3671
3774
|
*/
|
|
3672
|
-
drawTextScreen(text, pos, scale=4, center, context=overlayContext)
|
|
3775
|
+
drawTextScreen(text, pos, scale=4, center=true, context=overlayContext)
|
|
3673
3776
|
{
|
|
3674
3777
|
context.save();
|
|
3675
3778
|
const size = this.tileSize;
|
|
@@ -4363,6 +4466,7 @@ function audioInit()
|
|
|
4363
4466
|
* Sound Object - Stores a sound for later use and can be played positionally
|
|
4364
4467
|
*
|
|
4365
4468
|
* <a href=https://killedbyapixel.github.io/ZzFX/>Create sounds using the ZzFX Sound Designer.</a>
|
|
4469
|
+
* @memberof Audio
|
|
4366
4470
|
* @example
|
|
4367
4471
|
* // create a sound
|
|
4368
4472
|
* const sound_example = new Sound([.5,.5]);
|
|
@@ -4457,12 +4561,12 @@ class Sound
|
|
|
4457
4561
|
|
|
4458
4562
|
/** Play the sound as a musical note with a semitone offset
|
|
4459
4563
|
* This can be used to play music with chromatic scales
|
|
4460
|
-
* @param {number} semitoneOffset - How many semitones to offset pitch
|
|
4564
|
+
* @param {number} [semitoneOffset=0] - How many semitones to offset pitch
|
|
4461
4565
|
* @param {Vector2} [pos] - World space position to play the sound if any
|
|
4462
4566
|
* @param {number} [volume=1] - How much to scale volume by
|
|
4463
4567
|
* @return {SoundInstance} - The audio source node
|
|
4464
4568
|
*/
|
|
4465
|
-
playNote(semitoneOffset, pos, volume)
|
|
4569
|
+
playNote(semitoneOffset=0, pos, volume)
|
|
4466
4570
|
{
|
|
4467
4571
|
const pitch = getNoteFrequency(semitoneOffset, 1);
|
|
4468
4572
|
return this.play(pos, volume, pitch, 0);
|
|
@@ -4485,6 +4589,8 @@ class Sound
|
|
|
4485
4589
|
/**
|
|
4486
4590
|
* Sound Wave Object - Stores a wave sound for later use and can be played positionally
|
|
4487
4591
|
* - this can be used to play wave, mp3, and ogg files
|
|
4592
|
+
* @extends Sound
|
|
4593
|
+
* @memberof Audio
|
|
4488
4594
|
* @example
|
|
4489
4595
|
* // create a sound
|
|
4490
4596
|
* const sound_example = new SoundWave('sound.mp3');
|
|
@@ -4494,22 +4600,29 @@ class Sound
|
|
|
4494
4600
|
*/
|
|
4495
4601
|
class SoundWave extends Sound
|
|
4496
4602
|
{
|
|
4603
|
+
/**
|
|
4604
|
+
* @callback SoundLoadCallback - Function called when sound is loaded
|
|
4605
|
+
* @param {SoundWave} sound
|
|
4606
|
+
* @memberof Audio
|
|
4607
|
+
*/
|
|
4608
|
+
|
|
4497
4609
|
/** Create a sound object and cache the wave file for later use
|
|
4498
4610
|
* @param {string} filename - Filename of audio file to load
|
|
4499
4611
|
* @param {number} [randomness] - How much to randomize frequency each time sound plays
|
|
4500
4612
|
* @param {number} [range=soundDefaultRange] - World space max range of sound
|
|
4501
4613
|
* @param {number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering
|
|
4502
|
-
* @param {
|
|
4614
|
+
* @param {SoundLoadCallback} [onloadCallback] - callback function to call when sound is loaded
|
|
4503
4615
|
*/
|
|
4504
4616
|
constructor(filename, randomness=0, range, taper, onloadCallback)
|
|
4505
4617
|
{
|
|
4506
4618
|
super(undefined, range, taper);
|
|
4507
4619
|
if (!soundEnable || headlessMode) return;
|
|
4620
|
+
ASSERT(!filename || isString(filename), 'filename must be a string');
|
|
4508
4621
|
|
|
4509
|
-
/** @property {
|
|
4622
|
+
/** @property {SoundLoadCallback} - callback function to call when sound is loaded */
|
|
4510
4623
|
this.onloadCallback = onloadCallback;
|
|
4511
4624
|
this.randomness = randomness;
|
|
4512
|
-
this.loadSound(filename);
|
|
4625
|
+
filename && this.loadSound(filename);
|
|
4513
4626
|
}
|
|
4514
4627
|
|
|
4515
4628
|
/** Loads a sound from a URL and decodes it into sample data. Must be used with await!
|
|
@@ -4518,6 +4631,8 @@ class SoundWave extends Sound
|
|
|
4518
4631
|
async loadSound(filename)
|
|
4519
4632
|
{
|
|
4520
4633
|
const response = await fetch(filename);
|
|
4634
|
+
if (!response.ok)
|
|
4635
|
+
throw new Error(`Failed to load sound from ${filename}: ${response.status} ${response.statusText}`);
|
|
4521
4636
|
const arrayBuffer = await response.arrayBuffer();
|
|
4522
4637
|
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
|
|
4523
4638
|
|
|
@@ -4553,7 +4668,7 @@ class SoundWave extends Sound
|
|
|
4553
4668
|
this.sampleChannels = sampleChannels;
|
|
4554
4669
|
this.loadedPercent = 1;
|
|
4555
4670
|
if (this.onloadCallback)
|
|
4556
|
-
this.onloadCallback();
|
|
4671
|
+
this.onloadCallback(this);
|
|
4557
4672
|
}
|
|
4558
4673
|
}
|
|
4559
4674
|
|
|
@@ -4562,6 +4677,7 @@ class SoundWave extends Sound
|
|
|
4562
4677
|
/**
|
|
4563
4678
|
* Sound Instance - Wraps an AudioBufferSourceNode for individual sound control
|
|
4564
4679
|
* Represents a single playing instance of a sound with pause/resume capabilities
|
|
4680
|
+
* @memberof Audio
|
|
4565
4681
|
* @example
|
|
4566
4682
|
* // Play a sound and get an instance for control
|
|
4567
4683
|
* const jumpSound = new Sound([.5,.5,220]);
|
|
@@ -4761,6 +4877,12 @@ function getNoteFrequency(semitoneOffset, rootFrequency=220)
|
|
|
4761
4877
|
|
|
4762
4878
|
///////////////////////////////////////////////////////////////////////////////
|
|
4763
4879
|
|
|
4880
|
+
/**
|
|
4881
|
+
* @callback AudioEndedCallback - Function called when a sound ends
|
|
4882
|
+
* @param {AudioBufferSourceNode} source
|
|
4883
|
+
* @memberof Audio
|
|
4884
|
+
*/
|
|
4885
|
+
|
|
4764
4886
|
/** Play cached audio samples with given settings
|
|
4765
4887
|
* @param {Array} sampleChannels - Array of arrays of samples to play (for stereo playback)
|
|
4766
4888
|
* @param {number} [volume] - How much to scale volume by
|
|
@@ -4770,7 +4892,7 @@ function getNoteFrequency(semitoneOffset, rootFrequency=220)
|
|
|
4770
4892
|
* @param {number} [sampleRate=44100] - Sample rate for the sound
|
|
4771
4893
|
* @param {GainNode} [gainNode] - Optional gain node for volume control while playing
|
|
4772
4894
|
* @param {number} [offset] - Offset in seconds to start playback from
|
|
4773
|
-
* @param {
|
|
4895
|
+
* @param {AudioEndedCallback} [onended] - Callback for when the sound ends
|
|
4774
4896
|
* @return {AudioBufferSourceNode} - The audio node of the sound played
|
|
4775
4897
|
* @memberof Audio */
|
|
4776
4898
|
function playSamples(sampleChannels, volume=1, rate=1, pan=0, loop=false, sampleRate=audioDefaultSampleRate, gainNode, offset=0, onended)
|
|
@@ -4802,16 +4924,14 @@ function playSamples(sampleChannels, volume=1, rate=1, pan=0, loop=false, sample
|
|
|
4802
4924
|
if (onended)
|
|
4803
4925
|
source.addEventListener('ended', ()=> onended(source));
|
|
4804
4926
|
|
|
4927
|
+
const startOffset = offset * rate;
|
|
4805
4928
|
if (!audioIsRunning())
|
|
4806
4929
|
{
|
|
4807
|
-
// fix stalled audio
|
|
4808
|
-
audioContext.resume();
|
|
4809
|
-
return;
|
|
4930
|
+
// fix stalled audio and start
|
|
4931
|
+
audioContext.resume().then(()=>source.start(0, startOffset));
|
|
4810
4932
|
}
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
const startOffset = offset * rate;
|
|
4814
|
-
source.start(0, startOffset);
|
|
4933
|
+
else
|
|
4934
|
+
source.start(0, startOffset);
|
|
4815
4935
|
return source;
|
|
4816
4936
|
}
|
|
4817
4937
|
|
|
@@ -4976,7 +5096,7 @@ function zzfxG
|
|
|
4976
5096
|
* - Unlimited numbers of layers, allocates canvases as needed
|
|
4977
5097
|
* - Tile layers can be drawn to using their context with canvas2d
|
|
4978
5098
|
* - Tile layers can also have collision with EngineObjects
|
|
4979
|
-
* @namespace
|
|
5099
|
+
* @namespace TileLayers
|
|
4980
5100
|
*/
|
|
4981
5101
|
|
|
4982
5102
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -4984,13 +5104,13 @@ function zzfxG
|
|
|
4984
5104
|
|
|
4985
5105
|
/** Keep track of all tile layers with collision
|
|
4986
5106
|
* @type {Array<TileCollisionLayer>}
|
|
4987
|
-
* @memberof
|
|
5107
|
+
* @memberof TileLayers */
|
|
4988
5108
|
const tileCollisionLayers = [];
|
|
4989
5109
|
|
|
4990
5110
|
/** Get tile collision data for a given cell in the grid
|
|
4991
5111
|
* @param {Vector2} pos
|
|
4992
5112
|
* @return {number}
|
|
4993
|
-
* @memberof
|
|
5113
|
+
* @memberof TileLayers */
|
|
4994
5114
|
function tileCollisionGetData(pos)
|
|
4995
5115
|
{
|
|
4996
5116
|
// check all tile collision layers
|
|
@@ -5006,7 +5126,7 @@ function tileCollisionGetData(pos)
|
|
|
5006
5126
|
* @param {EngineObject} [object] - An object or undefined for generic test
|
|
5007
5127
|
* @param {boolean} [solidOnly] - Only check solid layers if true
|
|
5008
5128
|
* @return {TileCollisionLayer}
|
|
5009
|
-
* @memberof
|
|
5129
|
+
* @memberof TileLayers */
|
|
5010
5130
|
function tileCollisionTest(pos, size=vec2(), object, solidOnly=true)
|
|
5011
5131
|
{
|
|
5012
5132
|
for (const layer of tileCollisionLayers)
|
|
@@ -5024,7 +5144,7 @@ function tileCollisionTest(pos, size=vec2(), object, solidOnly=true)
|
|
|
5024
5144
|
* @param {EngineObject} [object] - An object or undefined for generic test
|
|
5025
5145
|
* @param {boolean} [solidOnly=true] - Only check solid layers if true
|
|
5026
5146
|
* @return {Vector2}
|
|
5027
|
-
* @memberof
|
|
5147
|
+
* @memberof TileLayers */
|
|
5028
5148
|
function tileCollisionRaycast(posStart, posEnd, object, solidOnly=true)
|
|
5029
5149
|
{
|
|
5030
5150
|
for (const layer of tileCollisionLayers)
|
|
@@ -5047,8 +5167,8 @@ function tileCollisionRaycast(posStart, posEnd, object, solidOnly=true)
|
|
|
5047
5167
|
* @param {number} [collisionLayer] - Layer to use for collision if any
|
|
5048
5168
|
* @param {boolean} [draw] - Should the layer be drawn automatically
|
|
5049
5169
|
* @return {Array<TileCollisionLayer>}
|
|
5050
|
-
* @memberof
|
|
5051
|
-
function
|
|
5170
|
+
* @memberof TileLayers */
|
|
5171
|
+
function tileLayersLoad(tileMapData, tileInfo=tile(), renderOrder=0, collisionLayer, draw=true)
|
|
5052
5172
|
{
|
|
5053
5173
|
if (!tileMapData)
|
|
5054
5174
|
{
|
|
@@ -5079,9 +5199,9 @@ function tileCollisionLoad(tileMapData, tileInfo=tile(), renderOrder=0, collisio
|
|
|
5079
5199
|
tileLayers[layerIndex] = tileLayer;
|
|
5080
5200
|
|
|
5081
5201
|
// apply layer color
|
|
5082
|
-
const layerColor = dataLayer.
|
|
5083
|
-
|
|
5084
|
-
|
|
5202
|
+
const layerColor = dataLayer.tintcolor ?
|
|
5203
|
+
new Color().setHex(dataLayer.tintcolor) :
|
|
5204
|
+
dataLayer.color || WHITE;
|
|
5085
5205
|
ASSERT(isColor(layerColor), 'layer color is not a color');
|
|
5086
5206
|
|
|
5087
5207
|
for (let x=levelSize.x; x--;)
|
|
@@ -5108,6 +5228,7 @@ function tileCollisionLoad(tileMapData, tileInfo=tile(), renderOrder=0, collisio
|
|
|
5108
5228
|
///////////////////////////////////////////////////////////////////////////////
|
|
5109
5229
|
/**
|
|
5110
5230
|
* Tile layer data object stores info about how to draw a tile
|
|
5231
|
+
* @memberof TileLayers
|
|
5111
5232
|
* @example
|
|
5112
5233
|
* // create tile layer data with tile index 0 and random orientation and color
|
|
5113
5234
|
* const tileIndex = 0;
|
|
@@ -5145,6 +5266,7 @@ class TileLayerData
|
|
|
5145
5266
|
* - Contains an offscreen canvas that can be rendered to
|
|
5146
5267
|
* - WebGL rendering is optional, call useWebGL to enable
|
|
5147
5268
|
* @extends EngineObject
|
|
5269
|
+
* @memberof TileLayers
|
|
5148
5270
|
* @example
|
|
5149
5271
|
* const canvasLayer = new CanvasLayer(vec2(), vec2(200,100));
|
|
5150
5272
|
*/
|
|
@@ -5159,6 +5281,7 @@ class CanvasLayer extends EngineObject
|
|
|
5159
5281
|
*/
|
|
5160
5282
|
constructor(position, size, angle=0, renderOrder=0, canvasSize=vec2(512))
|
|
5161
5283
|
{
|
|
5284
|
+
ASSERT(isVector2(canvasSize), 'canvasSize must be a Vector2');
|
|
5162
5285
|
super(position, size, undefined, angle, WHITE, renderOrder);
|
|
5163
5286
|
|
|
5164
5287
|
/** @property {HTMLCanvasElement} - The canvas used by this layer */
|
|
@@ -5206,12 +5329,18 @@ class CanvasLayer extends EngineObject
|
|
|
5206
5329
|
drawTile(pos, size, tileInfo, color, angle, mirror, additiveColor, useWebGL, screenSpace, context);
|
|
5207
5330
|
}
|
|
5208
5331
|
|
|
5332
|
+
/**
|
|
5333
|
+
* @callback Canvas2DDrawCallback - Function that draws to a canvas 2D context
|
|
5334
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} context
|
|
5335
|
+
* @memberof TileLayers
|
|
5336
|
+
*/
|
|
5337
|
+
|
|
5209
5338
|
/** Draw onto the layer canvas in world space (bypass WebGL)
|
|
5210
5339
|
* @param {Vector2} pos
|
|
5211
5340
|
* @param {Vector2} size
|
|
5212
5341
|
* @param {number} angle
|
|
5213
5342
|
* @param {boolean} mirror
|
|
5214
|
-
* @param {
|
|
5343
|
+
* @param {Canvas2DDrawCallback} drawFunction */
|
|
5215
5344
|
drawCanvas2D(pos, size, angle, mirror, drawFunction)
|
|
5216
5345
|
{
|
|
5217
5346
|
const context = this.context;
|
|
@@ -5248,7 +5377,7 @@ class CanvasLayer extends EngineObject
|
|
|
5248
5377
|
else
|
|
5249
5378
|
{
|
|
5250
5379
|
// untextured
|
|
5251
|
-
context.fillStyle = color;
|
|
5380
|
+
context.fillStyle = color.toString();
|
|
5252
5381
|
context.fillRect(-.5, -.5, 1, 1);
|
|
5253
5382
|
}
|
|
5254
5383
|
});
|
|
@@ -5285,7 +5414,9 @@ class CanvasLayer extends EngineObject
|
|
|
5285
5414
|
* - To allow dynamic modifications, layers are rendered using canvas 2d
|
|
5286
5415
|
* - Some devices like mobile phones are limited to 4k texture resolution
|
|
5287
5416
|
* - For with 16x16 tiles this limits layers to 256x256 on mobile devices
|
|
5417
|
+
* - Tile layers are centered on their corner, so normal levels are at (0,0)
|
|
5288
5418
|
* @extends CanvasLayer
|
|
5419
|
+
* @memberof TileLayers
|
|
5289
5420
|
* @example
|
|
5290
5421
|
* const tileLayer = new TileLayer(vec2(), vec2(200,100));
|
|
5291
5422
|
*/
|
|
@@ -5295,15 +5426,14 @@ class TileLayer extends CanvasLayer
|
|
|
5295
5426
|
* @param {Vector2} position - World space position
|
|
5296
5427
|
* @param {Vector2} size - World space size
|
|
5297
5428
|
* @param {TileInfo} [tileInfo] - Default tile info for layer (used for size and texture)
|
|
5298
|
-
* @param {Vector2} [scale=(1,1)] - How much to scale this layer when rendered
|
|
5299
5429
|
* @param {number} [renderOrder] - Objects are sorted by renderOrder
|
|
5300
5430
|
* @param {boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering
|
|
5301
5431
|
*/
|
|
5302
|
-
constructor(position, size, tileInfo=tile(),
|
|
5432
|
+
constructor(position, size, tileInfo=tile(), renderOrder=0, useWebGL=glEnable)
|
|
5303
5433
|
{
|
|
5304
5434
|
super(position, size, 0, renderOrder, size);
|
|
5435
|
+
|
|
5305
5436
|
this.tileInfo = tileInfo;
|
|
5306
|
-
|
|
5307
5437
|
const canvasSize = size.multiply(tileInfo.size);
|
|
5308
5438
|
/** @property {HTMLCanvasElement} - The canvas used by this tile layer */
|
|
5309
5439
|
this.canvas = new OffscreenCanvas(canvasSize.x, canvasSize.y);
|
|
@@ -5340,6 +5470,8 @@ class TileLayer extends CanvasLayer
|
|
|
5340
5470
|
* @param {boolean} [redraw] - Force the tile to redraw if true */
|
|
5341
5471
|
setData(layerPos, data, redraw=false)
|
|
5342
5472
|
{
|
|
5473
|
+
ASSERT(isVector2(layerPos), 'layerPos must be a Vector2');
|
|
5474
|
+
ASSERT(data instanceof TileLayerData, 'data must be a TileLayerData');
|
|
5343
5475
|
if (layerPos.arrayCheck(this.size))
|
|
5344
5476
|
{
|
|
5345
5477
|
this.data[(layerPos.y|0)*this.size.x+layerPos.x|0] = data;
|
|
@@ -5351,7 +5483,10 @@ class TileLayer extends CanvasLayer
|
|
|
5351
5483
|
* @param {Vector2} layerPos - Local position in array
|
|
5352
5484
|
* @return {TileLayerData} */
|
|
5353
5485
|
getData(layerPos)
|
|
5354
|
-
{
|
|
5486
|
+
{
|
|
5487
|
+
ASSERT(isVector2(layerPos), 'layerPos must be a Vector2');
|
|
5488
|
+
return layerPos.arrayCheck(this.size) && this.data[(layerPos.y|0)*this.size.x+layerPos.x|0];
|
|
5489
|
+
}
|
|
5355
5490
|
|
|
5356
5491
|
// Render the tile layer, called automatically by the engine
|
|
5357
5492
|
render()
|
|
@@ -5360,9 +5495,10 @@ class TileLayer extends CanvasLayer
|
|
|
5360
5495
|
|
|
5361
5496
|
// draw the tile layer as a single tile
|
|
5362
5497
|
const tileInfo = new TileInfo().setFullImage(this.canvas, this.glTexture);
|
|
5363
|
-
const
|
|
5498
|
+
const size = this.drawSize || this.size;
|
|
5499
|
+
const pos = this.pos.add(size.scale(.5));
|
|
5364
5500
|
const useWebGL = glEnable && this.glTexture !== undefined;
|
|
5365
|
-
drawTile(pos,
|
|
5501
|
+
drawTile(pos, size, tileInfo, WHITE, 0, false, CLEAR_BLACK, useWebGL);
|
|
5366
5502
|
}
|
|
5367
5503
|
|
|
5368
5504
|
/** Draw all the tile data to an offscreen canvas
|
|
@@ -5454,6 +5590,7 @@ class TileLayer extends CanvasLayer
|
|
|
5454
5590
|
* - there can be multiple tile collision layers
|
|
5455
5591
|
* - tile collision layers should not overlap each other
|
|
5456
5592
|
* @extends TileLayer
|
|
5593
|
+
* @memberof TileLayers
|
|
5457
5594
|
*/
|
|
5458
5595
|
class TileCollisionLayer extends TileLayer
|
|
5459
5596
|
{
|
|
@@ -5466,8 +5603,7 @@ class TileCollisionLayer extends TileLayer
|
|
|
5466
5603
|
*/
|
|
5467
5604
|
constructor(position, size, tileInfo=tile(), renderOrder=0, useWebGL=glEnable)
|
|
5468
5605
|
{
|
|
5469
|
-
|
|
5470
|
-
super(position, size.floor(), tileInfo, scale, renderOrder, useWebGL);
|
|
5606
|
+
super(position, size.floor(), tileInfo, renderOrder, useWebGL);
|
|
5471
5607
|
|
|
5472
5608
|
/** @property {Array<number>} - The tile collision grid */
|
|
5473
5609
|
this.collisionData = [];
|
|
@@ -5497,6 +5633,7 @@ class TileCollisionLayer extends TileLayer
|
|
|
5497
5633
|
* @param {Vector2} size - width and height of tile collision 2d grid */
|
|
5498
5634
|
initCollision(size)
|
|
5499
5635
|
{
|
|
5636
|
+
ASSERT(isVector2(size), 'size must be a Vector2');
|
|
5500
5637
|
this.size = size.floor();
|
|
5501
5638
|
this.collisionData = [];
|
|
5502
5639
|
this.collisionData.length = size.area();
|
|
@@ -5508,6 +5645,7 @@ class TileCollisionLayer extends TileLayer
|
|
|
5508
5645
|
* @param {number} [data] */
|
|
5509
5646
|
setCollisionData(gridPos, data=1)
|
|
5510
5647
|
{
|
|
5648
|
+
ASSERT(isVector2(gridPos), 'gridPos must be a Vector2');
|
|
5511
5649
|
const i = (gridPos.y|0)*this.size.x + gridPos.x|0;
|
|
5512
5650
|
gridPos.arrayCheck(this.size) && (this.collisionData[i] = data);
|
|
5513
5651
|
}
|
|
@@ -5517,6 +5655,7 @@ class TileCollisionLayer extends TileLayer
|
|
|
5517
5655
|
* @return {number} */
|
|
5518
5656
|
getCollisionData(gridPos)
|
|
5519
5657
|
{
|
|
5658
|
+
ASSERT(isVector2(gridPos), 'gridPos must be a Vector2');
|
|
5520
5659
|
const i = (gridPos.y|0)*this.size.x + gridPos.x|0;
|
|
5521
5660
|
return gridPos.arrayCheck(this.size) ? this.collisionData[i] : 0;
|
|
5522
5661
|
}
|
|
@@ -5528,6 +5667,9 @@ class TileCollisionLayer extends TileLayer
|
|
|
5528
5667
|
* @return {boolean} */
|
|
5529
5668
|
collisionTest(pos, size=new Vector2, object)
|
|
5530
5669
|
{
|
|
5670
|
+
ASSERT(isVector2(pos) && isVector2(size), 'pos and size must be Vector2s');
|
|
5671
|
+
ASSERT(!object || object instanceof EngineObject, 'object must be an EngineObject');
|
|
5672
|
+
|
|
5531
5673
|
// transform to local layer space
|
|
5532
5674
|
const posX = pos.x - this.pos.x;
|
|
5533
5675
|
const posY = pos.y - this.pos.y;
|
|
@@ -5558,6 +5700,9 @@ class TileCollisionLayer extends TileLayer
|
|
|
5558
5700
|
* @return {Vector2} */
|
|
5559
5701
|
collisionRaycast(posStart, posEnd, object)
|
|
5560
5702
|
{
|
|
5703
|
+
ASSERT(isVector2(posStart) && isVector2(posEnd), 'positions must be Vector2s');
|
|
5704
|
+
ASSERT(!object || object instanceof EngineObject, 'object must be an EngineObject');
|
|
5705
|
+
|
|
5561
5706
|
// transform to local layer space
|
|
5562
5707
|
const posStartX = posStart.x - this.pos.x;
|
|
5563
5708
|
const posStartY = posStart.y - this.pos.y;
|
|
@@ -5607,9 +5752,16 @@ class TileCollisionLayer extends TileLayer
|
|
|
5607
5752
|
* LittleJS Particle System
|
|
5608
5753
|
*/
|
|
5609
5754
|
|
|
5755
|
+
/**
|
|
5756
|
+
* @callback ParticleCallbackFunction - Function that processes a particle
|
|
5757
|
+
* @param {Particle} particle
|
|
5758
|
+
* @memberof Engine
|
|
5759
|
+
*/
|
|
5760
|
+
|
|
5610
5761
|
/**
|
|
5611
5762
|
* Particle Emitter - Spawns particles with the given settings
|
|
5612
5763
|
* @extends EngineObject
|
|
5764
|
+
* @memberof Engine
|
|
5613
5765
|
* @example
|
|
5614
5766
|
* // create a particle emitter
|
|
5615
5767
|
* let pos = vec2(2,3);
|
|
@@ -5634,10 +5786,10 @@ class ParticleEmitter extends EngineObject
|
|
|
5634
5786
|
* @param {number} [emitRate] - How many particles per second to spawn, does not emit if 0
|
|
5635
5787
|
* @param {number} [emitConeAngle=PI] - Local angle to apply velocity to particles from emitter
|
|
5636
5788
|
* @param {TileInfo} [tileInfo] - Tile info to render particles (undefined is untextured)
|
|
5637
|
-
* @param {Color} [colorStartA=
|
|
5638
|
-
* @param {Color} [colorStartB=
|
|
5639
|
-
* @param {Color} [colorEndA=
|
|
5640
|
-
* @param {Color} [colorEndB=
|
|
5789
|
+
* @param {Color} [colorStartA=WHITE] - Color at start of life 1, randomized between start colors
|
|
5790
|
+
* @param {Color} [colorStartB=WHITE] - Color at start of life 2, randomized between start colors
|
|
5791
|
+
* @param {Color} [colorEndA=CLEAR_WHITE] - Color at end of life 1, randomized between end colors
|
|
5792
|
+
* @param {Color} [colorEndB=CLEAR_WHITE] - Color at end of life 2, randomized between end colors
|
|
5641
5793
|
* @param {number} [particleTime] - How long particles live
|
|
5642
5794
|
* @param {number} [sizeStart] - How big are particles at start
|
|
5643
5795
|
* @param {number} [sizeEnd] - How big are particles at end
|
|
@@ -5664,10 +5816,10 @@ class ParticleEmitter extends EngineObject
|
|
|
5664
5816
|
emitRate = 100,
|
|
5665
5817
|
emitConeAngle = PI,
|
|
5666
5818
|
tileInfo,
|
|
5667
|
-
colorStartA =
|
|
5668
|
-
colorStartB =
|
|
5669
|
-
colorEndA =
|
|
5670
|
-
colorEndB =
|
|
5819
|
+
colorStartA = WHITE,
|
|
5820
|
+
colorStartB = WHITE,
|
|
5821
|
+
colorEndA = CLEAR_WHITE,
|
|
5822
|
+
colorEndB = CLEAR_WHITE,
|
|
5671
5823
|
particleTime = .5,
|
|
5672
5824
|
sizeStart = .1,
|
|
5673
5825
|
sizeEnd = 1,
|
|
@@ -5690,7 +5842,8 @@ class ParticleEmitter extends EngineObject
|
|
|
5690
5842
|
|
|
5691
5843
|
// emitter settings
|
|
5692
5844
|
/** @property {number|Vector2} - World space size of the emitter (float for circle diameter, vec2 for rect) */
|
|
5693
|
-
this.emitSize = emitSize
|
|
5845
|
+
this.emitSize = emitSize instanceof Vector2 ?
|
|
5846
|
+
emitSize.copy() : emitSize;
|
|
5694
5847
|
/** @property {number} - How long to stay alive (0 is forever) */
|
|
5695
5848
|
this.emitTime = emitTime;
|
|
5696
5849
|
/** @property {number} - How many particles per second to spawn, does not emit if 0 */
|
|
@@ -5700,13 +5853,13 @@ class ParticleEmitter extends EngineObject
|
|
|
5700
5853
|
|
|
5701
5854
|
// color settings
|
|
5702
5855
|
/** @property {Color} - Color at start of life 1, randomized between start colors */
|
|
5703
|
-
this.colorStartA = colorStartA;
|
|
5856
|
+
this.colorStartA = colorStartA.copy();
|
|
5704
5857
|
/** @property {Color} - Color at start of life 2, randomized between start colors */
|
|
5705
|
-
this.colorStartB = colorStartB;
|
|
5858
|
+
this.colorStartB = colorStartB.copy();
|
|
5706
5859
|
/** @property {Color} - Color at end of life 1, randomized between end colors */
|
|
5707
|
-
this.colorEndA = colorEndA;
|
|
5860
|
+
this.colorEndA = colorEndA.copy();
|
|
5708
5861
|
/** @property {Color} - Color at end of life 2, randomized between end colors */
|
|
5709
|
-
this.colorEndB = colorEndB;
|
|
5862
|
+
this.colorEndB = colorEndB.copy();
|
|
5710
5863
|
/** @property {boolean} - Should color be randomized linearly or across each component */
|
|
5711
5864
|
this.randomColorLinear = randomColorLinear;
|
|
5712
5865
|
|
|
@@ -5741,9 +5894,9 @@ class ParticleEmitter extends EngineObject
|
|
|
5741
5894
|
this.localSpace = localSpace;
|
|
5742
5895
|
/** @property {number} - If non zero the particle is drawn as a trail, stretched in the direction of velocity */
|
|
5743
5896
|
this.trailScale = 0;
|
|
5744
|
-
/** @property {
|
|
5897
|
+
/** @property {ParticleCallbackFunction} - Callback when particle is destroyed */
|
|
5745
5898
|
this.particleDestroyCallback = undefined;
|
|
5746
|
-
/** @property {
|
|
5899
|
+
/** @property {ParticleCallbackFunction} - Callback when particle is created */
|
|
5747
5900
|
this.particleCreateCallback = undefined;
|
|
5748
5901
|
/** @property {number} - Track particle emit time */
|
|
5749
5902
|
this.emitTimeBuffer = 0;
|
|
@@ -5844,6 +5997,7 @@ class ParticleEmitter extends EngineObject
|
|
|
5844
5997
|
/**
|
|
5845
5998
|
* Particle Object - Created automatically by Particle Emitters
|
|
5846
5999
|
* @extends EngineObject
|
|
6000
|
+
* @memberof Engine
|
|
5847
6001
|
*/
|
|
5848
6002
|
class Particle extends EngineObject
|
|
5849
6003
|
{
|
|
@@ -5862,7 +6016,7 @@ class Particle extends EngineObject
|
|
|
5862
6016
|
* @param {boolean} additive - Does it use additive blend mode
|
|
5863
6017
|
* @param {number} trailScale - If a trail, how long to make it
|
|
5864
6018
|
* @param {ParticleEmitter} [localSpaceEmitter] - Parent emitter if local space
|
|
5865
|
-
* @param {
|
|
6019
|
+
* @param {ParticleCallbackFunction} [destroyCallback] - Callback when particle dies
|
|
5866
6020
|
*/
|
|
5867
6021
|
constructor(position, tileInfo, angle, colorStart, colorEnd, lifeTime, sizeStart, sizeEnd, fadeRate, additive, trailScale, localSpaceEmitter, destroyCallback
|
|
5868
6022
|
)
|
|
@@ -5871,14 +6025,14 @@ class Particle extends EngineObject
|
|
|
5871
6025
|
|
|
5872
6026
|
/** @property {Color} - Color at start of life */
|
|
5873
6027
|
this.colorStart = colorStart;
|
|
5874
|
-
/** @property {Color} -
|
|
5875
|
-
this.
|
|
6028
|
+
/** @property {Color} - Color at end of life */
|
|
6029
|
+
this.colorEnd = colorEnd;
|
|
5876
6030
|
/** @property {number} - How long to live for */
|
|
5877
6031
|
this.lifeTime = lifeTime;
|
|
5878
6032
|
/** @property {number} - Size at start of life */
|
|
5879
6033
|
this.sizeStart = sizeStart;
|
|
5880
|
-
/** @property {number} -
|
|
5881
|
-
this.
|
|
6034
|
+
/** @property {number} - Size at end of life */
|
|
6035
|
+
this.sizeEnd = sizeEnd;
|
|
5882
6036
|
/** @property {number} - How quick to fade in/out */
|
|
5883
6037
|
this.fadeRate = fadeRate;
|
|
5884
6038
|
/** @property {boolean} - Is it additive */
|
|
@@ -5887,7 +6041,7 @@ class Particle extends EngineObject
|
|
|
5887
6041
|
this.trailScale = trailScale;
|
|
5888
6042
|
/** @property {ParticleEmitter} - Parent emitter if local space */
|
|
5889
6043
|
this.localSpaceEmitter = localSpaceEmitter;
|
|
5890
|
-
/** @property {
|
|
6044
|
+
/** @property {ParticleCallbackFunction} - Called when particle dies */
|
|
5891
6045
|
this.destroyCallback = destroyCallback;
|
|
5892
6046
|
// particles do not clamp speed by default
|
|
5893
6047
|
this.clampSpeed = false;
|
|
@@ -5914,54 +6068,58 @@ class Particle extends EngineObject
|
|
|
5914
6068
|
/** Render the particle, automatically called each frame, sorted by renderOrder */
|
|
5915
6069
|
render()
|
|
5916
6070
|
{
|
|
5917
|
-
//
|
|
5918
|
-
const
|
|
5919
|
-
const radius = this.sizeStart +
|
|
5920
|
-
|
|
6071
|
+
// lerp color and size
|
|
6072
|
+
const p1 = this.lifeTime > 0 ? min((time - this.spawnTime) / this.lifeTime, 1) : 1, p2 = 1-p1;
|
|
6073
|
+
const radius = p2 * this.sizeStart + p1 * this.sizeEnd;
|
|
6074
|
+
this.size.x = this.size.y = radius;
|
|
6075
|
+
this.color.r = p2 * this.colorStart.r + p1 * this.colorEnd.r;
|
|
6076
|
+
this.color.g = p2 * this.colorStart.g + p1 * this.colorEnd.g;
|
|
6077
|
+
this.color.b = p2 * this.colorStart.b + p1 * this.colorEnd.b;
|
|
6078
|
+
this.color.a = p2 * this.colorStart.a + p1 * this.colorEnd.a;
|
|
6079
|
+
|
|
6080
|
+
// fade alpha
|
|
5921
6081
|
const fadeRate = this.fadeRate/2;
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
this.colorStart.g + p * this.colorEndDelta.g,
|
|
5925
|
-
this.colorStart.b + p * this.colorEndDelta.b,
|
|
5926
|
-
(this.colorStart.a + p * this.colorEndDelta.a) *
|
|
5927
|
-
(p < fadeRate ? p/fadeRate : p > 1-fadeRate ? (1-p)/fadeRate : 1)); // fade alpha
|
|
6082
|
+
this.color.a *= p1 < fadeRate ? p1/fadeRate :
|
|
6083
|
+
p1 > 1-fadeRate ? (1-p1)/fadeRate : 1;
|
|
5928
6084
|
|
|
5929
6085
|
// draw the particle
|
|
5930
6086
|
this.additive && setBlendMode(true);
|
|
5931
6087
|
|
|
6088
|
+
// update the position and angle for drawing
|
|
5932
6089
|
let pos = this.pos, angle = this.angle;
|
|
5933
6090
|
if (this.localSpaceEmitter)
|
|
5934
6091
|
{
|
|
5935
6092
|
// in local space of emitter
|
|
5936
|
-
|
|
6093
|
+
const a = this.localSpaceEmitter.angle;
|
|
6094
|
+
const c = Math.cos(a), s = Math.sin(a);
|
|
6095
|
+
pos = this.localSpaceEmitter.pos.add(
|
|
6096
|
+
new Vector2(pos.x*c - pos.y*s, pos.x*s + pos.y*c));
|
|
5937
6097
|
angle += this.localSpaceEmitter.angle;
|
|
5938
6098
|
}
|
|
5939
6099
|
if (this.trailScale)
|
|
5940
6100
|
{
|
|
5941
6101
|
// trail style particles
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
const speed =
|
|
6102
|
+
const direction = this.localSpaceEmitter ?
|
|
6103
|
+
this.velocity.rotate(-this.localSpaceEmitter.angle) :
|
|
6104
|
+
this.velocity;
|
|
6105
|
+
const speed = direction.length();
|
|
5946
6106
|
if (speed)
|
|
5947
6107
|
{
|
|
5948
|
-
|
|
6108
|
+
// stretch in direction of motion
|
|
5949
6109
|
const trailLength = speed * this.trailScale;
|
|
5950
|
-
size.y = max(size.x, trailLength);
|
|
5951
|
-
angle = direction.
|
|
5952
|
-
drawTile(pos
|
|
6110
|
+
this.size.y = max(this.size.x, trailLength);
|
|
6111
|
+
angle = Math.atan2(direction.x, direction.y);
|
|
6112
|
+
drawTile(pos, this.size, this.tileInfo, this.color, angle, this.mirror);
|
|
5953
6113
|
}
|
|
5954
6114
|
}
|
|
5955
6115
|
else
|
|
5956
|
-
drawTile(pos, size, this.tileInfo, color, angle, this.mirror);
|
|
6116
|
+
drawTile(pos, this.size, this.tileInfo, this.color, angle, this.mirror);
|
|
5957
6117
|
this.additive && setBlendMode();
|
|
5958
|
-
debugParticles && debugRect(pos, size, '#f005', 0, angle);
|
|
6118
|
+
debugParticles && debugRect(pos, this.size, '#f005', 0, angle);
|
|
5959
6119
|
|
|
5960
|
-
if (
|
|
6120
|
+
if (p1 === 1)
|
|
5961
6121
|
{
|
|
5962
|
-
// destroy particle when
|
|
5963
|
-
this.color = color;
|
|
5964
|
-
this.size = size;
|
|
6122
|
+
// destroy particle when its time runs out
|
|
5965
6123
|
this.destroyCallback && this.destroyCallback(this);
|
|
5966
6124
|
this.destroyed = 1;
|
|
5967
6125
|
}
|
|
@@ -6026,8 +6184,14 @@ function medalsInit(saveName)
|
|
|
6026
6184
|
}
|
|
6027
6185
|
}
|
|
6028
6186
|
|
|
6187
|
+
/**
|
|
6188
|
+
* @callback MedalCallbackFunction - Function that processes a medal
|
|
6189
|
+
* @param {Medal} medal
|
|
6190
|
+
* @memberof Medals
|
|
6191
|
+
*/
|
|
6192
|
+
|
|
6029
6193
|
/** Calls a function for each medal
|
|
6030
|
-
* @param {
|
|
6194
|
+
* @param {MedalCallbackFunction} callback
|
|
6031
6195
|
* @memberof Medals */
|
|
6032
6196
|
function medalsForEach(callback)
|
|
6033
6197
|
{ Object.values(medals).forEach(medal=>callback(medal)); }
|
|
@@ -6036,6 +6200,7 @@ function medalsForEach(callback)
|
|
|
6036
6200
|
|
|
6037
6201
|
/**
|
|
6038
6202
|
* Medal - Tracks an unlockable medal
|
|
6203
|
+
* @memberof Medals
|
|
6039
6204
|
* @example
|
|
6040
6205
|
* // create a medal
|
|
6041
6206
|
* const medal_example = new Medal(0, 'Example Medal', 'More info about the medal goes here.', '🎖️');
|
|
@@ -6104,11 +6269,12 @@ class Medal
|
|
|
6104
6269
|
const height = medalDisplaySize.y;
|
|
6105
6270
|
const x = overlayCanvas.width - width;
|
|
6106
6271
|
const y = -height*hidePercent;
|
|
6272
|
+
const backgroundColor = hsl(0,0,.9);
|
|
6107
6273
|
|
|
6108
6274
|
// draw containing rect and clip to that region
|
|
6109
6275
|
context.save();
|
|
6110
6276
|
context.beginPath();
|
|
6111
|
-
context.fillStyle =
|
|
6277
|
+
context.fillStyle = backgroundColor.toString();
|
|
6112
6278
|
context.strokeStyle = BLACK.toString();
|
|
6113
6279
|
context.lineWidth = 3;
|
|
6114
6280
|
context.rect(x, y, width, height);
|
|
@@ -6910,24 +7076,25 @@ function glPolyStrip(points)
|
|
|
6910
7076
|
return strip;
|
|
6911
7077
|
}
|
|
6912
7078
|
/**
|
|
6913
|
-
* LittleJS Newgrounds
|
|
7079
|
+
* LittleJS Newgrounds Plugin
|
|
6914
7080
|
* - NewgroundsMedal extends Medal with Newgrounds API functionality
|
|
6915
|
-
* - Call new NewgroundsPlugin() to setup Newgrounds
|
|
7081
|
+
* - Call new NewgroundsPlugin(app_id) to setup Newgrounds
|
|
6916
7082
|
* - Uses CryptoJS for encryption if optional cipher is provided
|
|
7083
|
+
* - provides functions to interact with medals scoreboards
|
|
6917
7084
|
* - Keeps connection alive and logs views
|
|
6918
|
-
*
|
|
6919
|
-
* - Functions to unlock medals
|
|
7085
|
+
* @namespace Newgrounds
|
|
6920
7086
|
*/
|
|
6921
7087
|
|
|
6922
7088
|
/** Global Newgrounds object
|
|
6923
7089
|
* @type {NewgroundsPlugin}
|
|
6924
|
-
* @memberof
|
|
7090
|
+
* @memberof Newgrounds */
|
|
6925
7091
|
let newgrounds;
|
|
6926
7092
|
|
|
6927
7093
|
///////////////////////////////////////////////////////////////////////////////
|
|
6928
7094
|
/**
|
|
6929
7095
|
* Newgrounds medal auto unlocks in newgrounds API
|
|
6930
7096
|
* @extends Medal
|
|
7097
|
+
* @memberof Newgrounds
|
|
6931
7098
|
*/
|
|
6932
7099
|
class NewgroundsMedal extends Medal
|
|
6933
7100
|
{
|
|
@@ -6952,6 +7119,7 @@ class NewgroundsMedal extends Medal
|
|
|
6952
7119
|
///////////////////////////////////////////////////////////////////////////////
|
|
6953
7120
|
/**
|
|
6954
7121
|
* Newgrounds API object
|
|
7122
|
+
* @memberof Newgrounds
|
|
6955
7123
|
*/
|
|
6956
7124
|
class NewgroundsPlugin
|
|
6957
7125
|
{
|
|
@@ -7087,19 +7255,22 @@ class NewgroundsPlugin
|
|
|
7087
7255
|
/**
|
|
7088
7256
|
* LittleJS Post Processing Plugin
|
|
7089
7257
|
* - Supports shadertoy style post processing shaders
|
|
7090
|
-
* - call new
|
|
7258
|
+
* - call new PostProcessPlugin() to setup post processing
|
|
7091
7259
|
* - can be enabled to pass other canvases through a final shader
|
|
7260
|
+
* @namespace PostProcess
|
|
7092
7261
|
*/
|
|
7093
7262
|
|
|
7094
7263
|
///////////////////////////////////////////////////////////////////////////////
|
|
7095
7264
|
|
|
7096
7265
|
/** Global Post Process plugin object
|
|
7097
|
-
* @type {PostProcessPlugin}
|
|
7266
|
+
* @type {PostProcessPlugin}
|
|
7267
|
+
* @memberof PostProcess */
|
|
7098
7268
|
let postProcess;
|
|
7099
7269
|
|
|
7100
7270
|
/////////////////////////////////////////////////////////////////////////
|
|
7101
7271
|
/**
|
|
7102
7272
|
* UI System Global Object
|
|
7273
|
+
* @memberof PostProcess
|
|
7103
7274
|
*/
|
|
7104
7275
|
class PostProcessPlugin
|
|
7105
7276
|
{
|
|
@@ -7207,12 +7378,15 @@ class PostProcessPlugin
|
|
|
7207
7378
|
}
|
|
7208
7379
|
/**
|
|
7209
7380
|
* LittleJS ZzFXM Plugin
|
|
7381
|
+
* @namespace ZzFXM
|
|
7210
7382
|
*/
|
|
7211
7383
|
|
|
7212
7384
|
/**
|
|
7213
7385
|
* Music Object - Stores a zzfx music track for later use
|
|
7214
7386
|
*
|
|
7215
7387
|
* <a href=https://keithclark.github.io/ZzFXM/>Create music with the ZzFXM tracker.</a>
|
|
7388
|
+
* @extends Sound
|
|
7389
|
+
* @memberof ZzFXM
|
|
7216
7390
|
* @example
|
|
7217
7391
|
* // create some music
|
|
7218
7392
|
* const music_example = new Music(
|
|
@@ -7271,7 +7445,8 @@ class ZzFXMusic extends Sound
|
|
|
7271
7445
|
* @param {Array} patterns - Array of pattern data
|
|
7272
7446
|
* @param {Array} sequence - Array of pattern indexes
|
|
7273
7447
|
* @param {number} [BPM] - Playback speed of the song in BPM
|
|
7274
|
-
* @return {Array} - Left and right channel sample data
|
|
7448
|
+
* @return {Array} - Left and right channel sample data
|
|
7449
|
+
* @memberof ZzFXM */
|
|
7275
7450
|
function zzfxM(instruments, patterns, sequence, BPM = 125)
|
|
7276
7451
|
{
|
|
7277
7452
|
let i, j, k;
|
|
@@ -7374,17 +7549,20 @@ function zzfxM(instruments, patterns, sequence, BPM = 125)
|
|
|
7374
7549
|
* - Buttons
|
|
7375
7550
|
* - Checkboxes
|
|
7376
7551
|
* - Images
|
|
7552
|
+
* @namespace UISystem
|
|
7377
7553
|
*/
|
|
7378
7554
|
|
|
7379
7555
|
///////////////////////////////////////////////////////////////////////////////
|
|
7380
7556
|
|
|
7381
7557
|
/** Global UI system plugin object
|
|
7382
|
-
* @type {UISystemPlugin}
|
|
7558
|
+
* @type {UISystemPlugin}
|
|
7559
|
+
* @memberof UISystem */
|
|
7383
7560
|
let uiSystem;
|
|
7384
7561
|
|
|
7385
7562
|
///////////////////////////////////////////////////////////////////////////////
|
|
7386
7563
|
/**
|
|
7387
7564
|
* UI System Global Object
|
|
7565
|
+
* @memberof UISystem
|
|
7388
7566
|
*/
|
|
7389
7567
|
class UISystemPlugin
|
|
7390
7568
|
{
|
|
@@ -7429,10 +7607,12 @@ class UISystemPlugin
|
|
|
7429
7607
|
this.uiObjects = [];
|
|
7430
7608
|
/** @property {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} - Context to render UI elements to */
|
|
7431
7609
|
this.uiContext = context;
|
|
7432
|
-
/** @property {UIObject} - Top most object user is over */
|
|
7433
|
-
this.hoverObject = undefined;
|
|
7434
7610
|
/** @property {UIObject} - Object user is currently interacting with */
|
|
7435
7611
|
this.activeObject = undefined;
|
|
7612
|
+
/** @property {UIObject} - Top most object user is over */
|
|
7613
|
+
this.hoverObject = undefined;
|
|
7614
|
+
/** @property {UIObject} - Hover object at start of update */
|
|
7615
|
+
this.lastHoverObject = undefined;
|
|
7436
7616
|
|
|
7437
7617
|
engineAddPlugin(uiUpdate, uiRender);
|
|
7438
7618
|
|
|
@@ -7463,6 +7643,7 @@ class UISystemPlugin
|
|
|
7463
7643
|
updateInvisibleObject(o);
|
|
7464
7644
|
}
|
|
7465
7645
|
// reset hover object at start of update
|
|
7646
|
+
uiSystem.lastHoverObject = uiSystem.hoverObject;
|
|
7466
7647
|
uiSystem.hoverObject = undefined;
|
|
7467
7648
|
for (let i = uiSystem.uiObjects.length; i--;)
|
|
7468
7649
|
{
|
|
@@ -7495,6 +7676,13 @@ class UISystemPlugin
|
|
|
7495
7676
|
* @param {number} [cornerRadius=uiSystem.defaultCornerRadius] */
|
|
7496
7677
|
drawRect(pos, size, color=uiSystem.defaultColor, lineWidth=uiSystem.defaultLineWidth, lineColor=uiSystem.defaultLineColor, cornerRadius=uiSystem.defaultCornerRadius)
|
|
7497
7678
|
{
|
|
7679
|
+
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
7680
|
+
ASSERT(isVector2(size), 'size must be a vec2');
|
|
7681
|
+
ASSERT(isColor(color), 'color must be a color');
|
|
7682
|
+
ASSERT(isNumber(lineWidth), 'lineWidth must be a number');
|
|
7683
|
+
ASSERT(isColor(lineColor), 'lineColor must be a color');
|
|
7684
|
+
ASSERT(isNumber(cornerRadius), 'cornerRadius must be a number');
|
|
7685
|
+
|
|
7498
7686
|
const context = uiSystem.uiContext;
|
|
7499
7687
|
context.fillStyle = color.toString();
|
|
7500
7688
|
context.beginPath();
|
|
@@ -7518,6 +7706,11 @@ class UISystemPlugin
|
|
|
7518
7706
|
* @param {Color} [lineColor=uiSystem.defaultLineColor] */
|
|
7519
7707
|
drawLine(posA, posB, lineWidth=uiSystem.defaultLineWidth, lineColor=uiSystem.defaultLineColor)
|
|
7520
7708
|
{
|
|
7709
|
+
ASSERT(isVector2(posA), 'posA must be a vec2');
|
|
7710
|
+
ASSERT(isVector2(posB), 'posB must be a vec2');
|
|
7711
|
+
ASSERT(isNumber(lineWidth), 'lineWidth must be a number');
|
|
7712
|
+
ASSERT(isColor(lineColor), 'lineColor must be a color');
|
|
7713
|
+
|
|
7521
7714
|
const context = uiSystem.uiContext;
|
|
7522
7715
|
context.strokeStyle = lineColor.toString();
|
|
7523
7716
|
context.lineWidth = lineWidth;
|
|
@@ -7553,12 +7746,37 @@ class UISystemPlugin
|
|
|
7553
7746
|
{
|
|
7554
7747
|
drawTextScreen(text, pos, size.y, color, lineWidth, lineColor, align, font, applyMaxWidth ? size.x : undefined, uiSystem.uiContext);
|
|
7555
7748
|
}
|
|
7749
|
+
|
|
7750
|
+
/**
|
|
7751
|
+
* @callback DragAndDropCallback - Callback for drag and drop events
|
|
7752
|
+
* @param {DragEvent} event - The drag event
|
|
7753
|
+
* @memberof UISystem
|
|
7754
|
+
*/
|
|
7755
|
+
|
|
7756
|
+
/** Setup drag and drop event handlers
|
|
7757
|
+
* Automatically prevents defaults and calls the given functions
|
|
7758
|
+
* @param {DragAndDropCallback} [onDrop] - when a file is dropped
|
|
7759
|
+
* @param {DragAndDropCallback} [onDragEnter] - when a file is dragged onto the window
|
|
7760
|
+
* @param {DragAndDropCallback} [onDragLeave] - when a file is dragged off the window
|
|
7761
|
+
* @param {DragAndDropCallback} [onDragOver] - continously when dragging over */
|
|
7762
|
+
setupDragAndDrop(onDrop, onDragEnter, onDragLeave, onDragOver)
|
|
7763
|
+
{
|
|
7764
|
+
function setCallback(callback, listenerType)
|
|
7765
|
+
{
|
|
7766
|
+
function listener(e) { e.preventDefault(); callback && callback(e); }
|
|
7767
|
+
document.addEventListener(listenerType, listener);
|
|
7768
|
+
}
|
|
7769
|
+
setCallback(onDrop, 'drop');
|
|
7770
|
+
setCallback(onDragEnter, 'dragenter');
|
|
7771
|
+
setCallback(onDragLeave, 'dragleave');
|
|
7772
|
+
setCallback(onDragOver, 'dragover');
|
|
7773
|
+
}
|
|
7556
7774
|
}
|
|
7557
7775
|
|
|
7558
7776
|
///////////////////////////////////////////////////////////////////////////////
|
|
7559
7777
|
/**
|
|
7560
7778
|
* UI Object - Base level object for all UI elements
|
|
7561
|
-
*/
|
|
7779
|
+
* @memberof UISystem */
|
|
7562
7780
|
class UIObject
|
|
7563
7781
|
{
|
|
7564
7782
|
/** Create a UIObject
|
|
@@ -7567,6 +7785,9 @@ class UIObject
|
|
|
7567
7785
|
*/
|
|
7568
7786
|
constructor(pos=vec2(), size=vec2())
|
|
7569
7787
|
{
|
|
7788
|
+
ASSERT(isVector2(pos), 'ui object pos must be a vec2');
|
|
7789
|
+
ASSERT(isVector2(size), 'ui object size must be a vec2');
|
|
7790
|
+
|
|
7570
7791
|
/** @property {Vector2} - Local position of the object */
|
|
7571
7792
|
this.localPos = pos.copy();
|
|
7572
7793
|
/** @property {Vector2} - Screen space position of the object */
|
|
@@ -7574,21 +7795,21 @@ class UIObject
|
|
|
7574
7795
|
/** @property {Vector2} - Screen space size of the object */
|
|
7575
7796
|
this.size = size.copy();
|
|
7576
7797
|
/** @property {Color} - Color of the object */
|
|
7577
|
-
this.color = uiSystem.defaultColor;
|
|
7798
|
+
this.color = uiSystem.defaultColor.copy();
|
|
7578
7799
|
/** @property {Color} - Color of the object when active, uses color if undefined */
|
|
7579
7800
|
this.activeColor = undefined;
|
|
7580
7801
|
/** @property {string} - Text for this ui object */
|
|
7581
7802
|
this.text = undefined;
|
|
7582
7803
|
/** @property {Color} - Color when disabled */
|
|
7583
|
-
this.disabledColor = uiSystem.defaultDisabledColor;
|
|
7804
|
+
this.disabledColor = uiSystem.defaultDisabledColor.copy();
|
|
7584
7805
|
/** @property {boolean} - Is this object disabled? */
|
|
7585
7806
|
this.disabled = false;
|
|
7586
7807
|
/** @property {Color} - Color for text */
|
|
7587
|
-
this.textColor = uiSystem.defaultTextColor
|
|
7808
|
+
this.textColor = uiSystem.defaultTextColor.copy()
|
|
7588
7809
|
/** @property {Color} - Color used when hovering over the object */
|
|
7589
|
-
this.hoverColor = uiSystem.defaultHoverColor
|
|
7810
|
+
this.hoverColor = uiSystem.defaultHoverColor.copy()
|
|
7590
7811
|
/** @property {Color} - Color for line drawing */
|
|
7591
|
-
this.lineColor = uiSystem.defaultLineColor
|
|
7812
|
+
this.lineColor = uiSystem.defaultLineColor.copy()
|
|
7592
7813
|
/** @property {number} - Width for line drawing */
|
|
7593
7814
|
this.lineWidth = uiSystem.defaultLineWidth;
|
|
7594
7815
|
/** @property {number} - Corner radius for rounded rects */
|
|
@@ -7645,7 +7866,7 @@ class UIObject
|
|
|
7645
7866
|
/** Update the object, called automatically by plugin once each frame */
|
|
7646
7867
|
update()
|
|
7647
7868
|
{
|
|
7648
|
-
const wasHover = this
|
|
7869
|
+
const wasHover = uiSystem.lastHoverObject === this;
|
|
7649
7870
|
const isActive = this.isActiveObject();
|
|
7650
7871
|
const mouseDown = mouseIsDown(0);
|
|
7651
7872
|
const mousePress = this.dragActivate ? mouseDown : mouseWasPressed(0);
|
|
@@ -7658,15 +7879,14 @@ class UIObject
|
|
|
7658
7879
|
}
|
|
7659
7880
|
if (this.isHoverObject())
|
|
7660
7881
|
{
|
|
7661
|
-
if (mousePress)
|
|
7662
|
-
inputClearKey(0,0,0,1,0); // clear mouse was pressed state
|
|
7663
7882
|
if (!this.disabled)
|
|
7664
7883
|
{
|
|
7665
7884
|
if (mousePress)
|
|
7666
7885
|
{
|
|
7667
7886
|
if (this.interactive)
|
|
7668
7887
|
{
|
|
7669
|
-
this.
|
|
7888
|
+
if (!this.dragActivate || (!wasHover || mouseWasPressed(0)))
|
|
7889
|
+
this.onPress();
|
|
7670
7890
|
if (this.soundPress)
|
|
7671
7891
|
this.soundPress.play();
|
|
7672
7892
|
if (uiSystem.activeObject && !isActive)
|
|
@@ -7674,13 +7894,15 @@ class UIObject
|
|
|
7674
7894
|
uiSystem.activeObject = this;
|
|
7675
7895
|
}
|
|
7676
7896
|
}
|
|
7677
|
-
if (!mouseDown &&
|
|
7897
|
+
if (!mouseDown && this.isActiveObject() && this.interactive)
|
|
7678
7898
|
{
|
|
7679
7899
|
this.onClick();
|
|
7680
7900
|
if (this.soundClick)
|
|
7681
7901
|
this.soundClick.play();
|
|
7682
7902
|
}
|
|
7683
7903
|
}
|
|
7904
|
+
// clear mouse was pressed state even when disabled
|
|
7905
|
+
mousePress && inputClearKey(0,0,0,1,0);
|
|
7684
7906
|
}
|
|
7685
7907
|
if (isActive)
|
|
7686
7908
|
if (!mouseDown || (this.dragActivate && !this.isHoverObject()))
|
|
@@ -7691,6 +7913,7 @@ class UIObject
|
|
|
7691
7913
|
uiSystem.activeObject = undefined;
|
|
7692
7914
|
}
|
|
7693
7915
|
|
|
7916
|
+
// call enter/leave events
|
|
7694
7917
|
if (this.isHoverObject() !== wasHover)
|
|
7695
7918
|
this.isHoverObject() ? this.onEnter() : this.onLeave();
|
|
7696
7919
|
}
|
|
@@ -7701,7 +7924,7 @@ class UIObject
|
|
|
7701
7924
|
if (!this.size.x || !this.size.y) return;
|
|
7702
7925
|
|
|
7703
7926
|
const lineColor = this.interactive && this.isActiveObject() && !this.disabled ? this.color : this.lineColor;
|
|
7704
|
-
const color = this.
|
|
7927
|
+
const color = this.disabled ? this.disabledColor : this.interactive ? this.isActiveObject() ? this.activeColor || this.color : this.isHoverObject() ? this.hoverColor : this.color : this.color;
|
|
7705
7928
|
uiSystem.drawRect(this.pos, this.size, color, this.lineWidth, lineColor, this.cornerRadius);
|
|
7706
7929
|
}
|
|
7707
7930
|
|
|
@@ -7752,6 +7975,7 @@ class UIObject
|
|
|
7752
7975
|
/**
|
|
7753
7976
|
* UIText - A UI object that displays text
|
|
7754
7977
|
* @extends UIObject
|
|
7978
|
+
* @memberof UISystem
|
|
7755
7979
|
*/
|
|
7756
7980
|
class UIText extends UIObject
|
|
7757
7981
|
{
|
|
@@ -7766,6 +7990,10 @@ class UIText extends UIObject
|
|
|
7766
7990
|
{
|
|
7767
7991
|
super(pos, size);
|
|
7768
7992
|
|
|
7993
|
+
ASSERT(isString(text), 'ui text must be a string');
|
|
7994
|
+
ASSERT(['left','center','right'].includes(align), 'ui text align must be left, center, or right');
|
|
7995
|
+
ASSERT(isString(font), 'ui text font must be a string');
|
|
7996
|
+
|
|
7769
7997
|
// set properties
|
|
7770
7998
|
this.text = text;
|
|
7771
7999
|
this.align = align;
|
|
@@ -7785,6 +8013,7 @@ class UIText extends UIObject
|
|
|
7785
8013
|
/**
|
|
7786
8014
|
* UITile - A UI object that displays a tile image
|
|
7787
8015
|
* @extends UIObject
|
|
8016
|
+
* @memberof UISystem
|
|
7788
8017
|
*/
|
|
7789
8018
|
class UITile extends UIObject
|
|
7790
8019
|
{
|
|
@@ -7799,15 +8028,19 @@ class UITile extends UIObject
|
|
|
7799
8028
|
constructor(pos, size, tileInfo, color=WHITE, angle=0, mirror=false)
|
|
7800
8029
|
{
|
|
7801
8030
|
super(pos, size);
|
|
8031
|
+
|
|
8032
|
+
ASSERT(tileInfo instanceof TileInfo, 'ui tile tileInfo must be a TileInfo');
|
|
8033
|
+
ASSERT(isColor(color), 'ui tile color must be a color');
|
|
8034
|
+
ASSERT(isNumber(angle), 'ui tile angle must be a number');
|
|
8035
|
+
|
|
7802
8036
|
/** @property {TileInfo} - Tile image to use */
|
|
7803
8037
|
this.tileInfo = tileInfo;
|
|
7804
8038
|
/** @property {number} - Angle to rotate in radians */
|
|
7805
8039
|
this.angle = angle;
|
|
7806
8040
|
/** @property {boolean} - Should it be mirrored? */
|
|
7807
8041
|
this.mirror = mirror;
|
|
7808
|
-
|
|
7809
8042
|
// set properties
|
|
7810
|
-
this.color = color;
|
|
8043
|
+
this.color = color.copy();
|
|
7811
8044
|
}
|
|
7812
8045
|
render()
|
|
7813
8046
|
{
|
|
@@ -7819,6 +8052,7 @@ class UITile extends UIObject
|
|
|
7819
8052
|
/**
|
|
7820
8053
|
* UIButton - A UI object that acts as a button
|
|
7821
8054
|
* @extends UIObject
|
|
8055
|
+
* @memberof UISystem
|
|
7822
8056
|
*/
|
|
7823
8057
|
class UIButton extends UIObject
|
|
7824
8058
|
{
|
|
@@ -7832,9 +8066,12 @@ class UIButton extends UIObject
|
|
|
7832
8066
|
{
|
|
7833
8067
|
super(pos, size);
|
|
7834
8068
|
|
|
8069
|
+
ASSERT(isString(text), 'ui button must be a string');
|
|
8070
|
+
ASSERT(isColor(color), 'ui button color must be a color');
|
|
8071
|
+
|
|
7835
8072
|
// set properties
|
|
7836
8073
|
this.text = text;
|
|
7837
|
-
this.color = color
|
|
8074
|
+
this.color = color.copy()
|
|
7838
8075
|
this.interactive = true;
|
|
7839
8076
|
}
|
|
7840
8077
|
render()
|
|
@@ -7852,6 +8089,7 @@ class UIButton extends UIObject
|
|
|
7852
8089
|
/**
|
|
7853
8090
|
* UICheckbox - A UI object that acts as a checkbox
|
|
7854
8091
|
* @extends UIObject
|
|
8092
|
+
* @memberof UISystem
|
|
7855
8093
|
*/
|
|
7856
8094
|
class UICheckbox extends UIObject
|
|
7857
8095
|
{
|
|
@@ -7865,12 +8103,15 @@ class UICheckbox extends UIObject
|
|
|
7865
8103
|
constructor(pos, size, checked=false, text='', color=uiSystem.defaultButtonColor)
|
|
7866
8104
|
{
|
|
7867
8105
|
super(pos, size);
|
|
8106
|
+
|
|
8107
|
+
ASSERT(isString(text), 'ui checkbox must be a string');
|
|
8108
|
+
ASSERT(isColor(color), 'ui checkbox color must be a color');
|
|
8109
|
+
|
|
7868
8110
|
/** @property {boolean} - Current percentage value of this scrollbar 0-1 */
|
|
7869
8111
|
this.checked = checked;
|
|
7870
|
-
|
|
7871
8112
|
// set properties
|
|
7872
8113
|
this.text = text;
|
|
7873
|
-
this.color = color;
|
|
8114
|
+
this.color = color.copy();
|
|
7874
8115
|
this.interactive = true;
|
|
7875
8116
|
}
|
|
7876
8117
|
onClick()
|
|
@@ -7902,6 +8143,7 @@ class UICheckbox extends UIObject
|
|
|
7902
8143
|
/**
|
|
7903
8144
|
* UIScrollbar - A UI object that acts as a scrollbar
|
|
7904
8145
|
* @extends UIObject
|
|
8146
|
+
* @memberof UISystem
|
|
7905
8147
|
*/
|
|
7906
8148
|
class UIScrollbar extends UIObject
|
|
7907
8149
|
{
|
|
@@ -7917,14 +8159,19 @@ class UIScrollbar extends UIObject
|
|
|
7917
8159
|
{
|
|
7918
8160
|
super(pos, size);
|
|
7919
8161
|
|
|
8162
|
+
ASSERT(isNumber(value), 'ui scrollbar value must be a number');
|
|
8163
|
+
ASSERT(isString(text), 'ui scrollbar must be a string');
|
|
8164
|
+
ASSERT(isColor(color), 'ui scrollbar color must be a color');
|
|
8165
|
+
ASSERT(isColor(handleColor), 'ui scrollbar handleColor must be a color');
|
|
8166
|
+
|
|
7920
8167
|
/** @property {number} - Current percentage value of this scrollbar 0-1 */
|
|
7921
8168
|
this.value = value;
|
|
7922
8169
|
/** @property {Color} - Color for the handle part of the scrollbar */
|
|
7923
|
-
this.handleColor = handleColor;
|
|
8170
|
+
this.handleColor = handleColor.copy();
|
|
7924
8171
|
|
|
7925
8172
|
// set properties
|
|
7926
8173
|
this.text = text;
|
|
7927
|
-
this.color = color;
|
|
8174
|
+
this.color = color.copy();
|
|
7928
8175
|
this.interactive = true;
|
|
7929
8176
|
}
|
|
7930
8177
|
update()
|
|
@@ -7932,29 +8179,43 @@ class UIScrollbar extends UIObject
|
|
|
7932
8179
|
super.update();
|
|
7933
8180
|
if (this.isActiveObject() && this.interactive)
|
|
7934
8181
|
{
|
|
8182
|
+
// handle horizontal or vertical scrollbar
|
|
8183
|
+
const isHorizontal = this.size.x > this.size.y;
|
|
8184
|
+
const handleSize = isHorizontal ? this.size.y : this.size.x;
|
|
8185
|
+
const barSize = isHorizontal ? this.size.x : this.size.y;
|
|
8186
|
+
const centerPos = isHorizontal ? this.pos.x : this.pos.y;
|
|
8187
|
+
|
|
7935
8188
|
// check if value changed
|
|
7936
|
-
const
|
|
7937
|
-
const
|
|
7938
|
-
const
|
|
7939
|
-
const p2 = this.pos.x + handleWidth/2;
|
|
8189
|
+
const handleWidth = barSize - handleSize;
|
|
8190
|
+
const p1 = centerPos - handleWidth/2;
|
|
8191
|
+
const p2 = centerPos + handleWidth/2;
|
|
7940
8192
|
const oldValue = this.value;
|
|
7941
|
-
this.value =
|
|
8193
|
+
this.value = isHorizontal ?
|
|
8194
|
+
percent(mousePosScreen.x, p1, p2) :
|
|
8195
|
+
percent(mousePosScreen.y, p2, p1);
|
|
7942
8196
|
this.value === oldValue || this.onChange();
|
|
7943
8197
|
}
|
|
7944
8198
|
}
|
|
7945
8199
|
render()
|
|
7946
8200
|
{
|
|
7947
8201
|
super.render();
|
|
7948
|
-
|
|
8202
|
+
|
|
8203
|
+
// handle horizontal or vertical scrollbar
|
|
8204
|
+
const isHorizontal = this.size.x > this.size.y;
|
|
8205
|
+
const handleSize = isHorizontal ? this.size.y : this.size.x;
|
|
8206
|
+
const barSize = isHorizontal ? this.size.x : this.size.y;
|
|
8207
|
+
const centerPos = isHorizontal ? this.pos.x : this.pos.y;
|
|
8208
|
+
|
|
7949
8209
|
// draw the scrollbar handle
|
|
7950
|
-
const
|
|
7951
|
-
const
|
|
7952
|
-
const
|
|
7953
|
-
const
|
|
7954
|
-
|
|
8210
|
+
const handleWidth = barSize - handleSize;
|
|
8211
|
+
const p1 = centerPos - handleWidth/2;
|
|
8212
|
+
const p2 = centerPos + handleWidth/2;
|
|
8213
|
+
const handlePos = isHorizontal ?
|
|
8214
|
+
vec2(lerp(p1, p2, this.value), this.pos.y) :
|
|
8215
|
+
vec2(this.pos.x, lerp(p2, p1, this.value))
|
|
7955
8216
|
const handleColor = this.disabled ? this.disabledColor :
|
|
7956
8217
|
this.interactive && this.isActiveObject() ? this.color : this.handleColor;
|
|
7957
|
-
uiSystem.drawRect(handlePos, handleSize, handleColor, this.lineWidth, this.lineColor, this.cornerRadius);
|
|
8218
|
+
uiSystem.drawRect(handlePos, vec2(handleSize), handleColor, this.lineWidth, this.lineColor, this.cornerRadius);
|
|
7958
8219
|
|
|
7959
8220
|
// draw the text scaled to fit on the scrollbar
|
|
7960
8221
|
const textSize = this.getTextSize();
|
|
@@ -8001,6 +8262,7 @@ function box2dSetDebug(enable) { box2dDebug = enable; }
|
|
|
8001
8262
|
* - Each object has a Box2D body which can have multiple fixtures and joints
|
|
8002
8263
|
* - Provides interface for Box2D body and fixture functions
|
|
8003
8264
|
* @extends EngineObject
|
|
8265
|
+
* @memberof Box2D
|
|
8004
8266
|
*/
|
|
8005
8267
|
class Box2dObject extends EngineObject
|
|
8006
8268
|
{
|
|
@@ -8012,7 +8274,7 @@ class Box2dObject extends EngineObject
|
|
|
8012
8274
|
* @param {Color} [color]
|
|
8013
8275
|
* @param {number} [bodyType]
|
|
8014
8276
|
* @param {number} [renderOrder] */
|
|
8015
|
-
constructor(pos
|
|
8277
|
+
constructor(pos, size, tileInfo, angle=0, color, bodyType=box2d.bodyTypeDynamic, renderOrder=0)
|
|
8016
8278
|
{
|
|
8017
8279
|
super(pos, size, tileInfo, angle, color, renderOrder);
|
|
8018
8280
|
|
|
@@ -8026,7 +8288,7 @@ class Box2dObject extends EngineObject
|
|
|
8026
8288
|
this.lineColor = BLACK;
|
|
8027
8289
|
}
|
|
8028
8290
|
|
|
8029
|
-
/** Destroy this object and
|
|
8291
|
+
/** Destroy this object and its physics body */
|
|
8030
8292
|
destroy()
|
|
8031
8293
|
{
|
|
8032
8294
|
// destroy physics body, fixtures, and joints
|
|
@@ -8510,6 +8772,7 @@ class Box2dRaycastResult
|
|
|
8510
8772
|
* Box2D Joint
|
|
8511
8773
|
* - Base class for Box2D joints
|
|
8512
8774
|
* - A joint is used to connect objects together
|
|
8775
|
+
* @memberof Box2D
|
|
8513
8776
|
*/
|
|
8514
8777
|
class Box2dJoint
|
|
8515
8778
|
{
|
|
@@ -8565,6 +8828,7 @@ class Box2dJoint
|
|
|
8565
8828
|
* - This a soft constraint with a max force
|
|
8566
8829
|
* - This allows the constraint to stretch and without applying huge forces
|
|
8567
8830
|
* @extends Box2dJoint
|
|
8831
|
+
* @memberof Box2D
|
|
8568
8832
|
*/
|
|
8569
8833
|
class Box2dTargetJoint extends Box2dJoint
|
|
8570
8834
|
{
|
|
@@ -8614,6 +8878,7 @@ class Box2dTargetJoint extends Box2dJoint
|
|
|
8614
8878
|
* - Constrains two points on two objects to remain at a fixed distance
|
|
8615
8879
|
* - You can view this as a massless, rigid rod
|
|
8616
8880
|
* @extends Box2dJoint
|
|
8881
|
+
* @memberof Box2D
|
|
8617
8882
|
*/
|
|
8618
8883
|
class Box2dDistanceJoint extends Box2dJoint
|
|
8619
8884
|
{
|
|
@@ -8677,6 +8942,7 @@ class Box2dDistanceJoint extends Box2dJoint
|
|
|
8677
8942
|
* Box2D Pin Joint
|
|
8678
8943
|
* - Pins two objects together at a point
|
|
8679
8944
|
* @extends Box2dDistanceJoint
|
|
8945
|
+
* @memberof Box2D
|
|
8680
8946
|
*/
|
|
8681
8947
|
class Box2dPinJoint extends Box2dDistanceJoint
|
|
8682
8948
|
{
|
|
@@ -8696,6 +8962,7 @@ class Box2dPinJoint extends Box2dDistanceJoint
|
|
|
8696
8962
|
* Box2D Rope Joint
|
|
8697
8963
|
* - Enforces a maximum distance between two points on two objects
|
|
8698
8964
|
* @extends Box2dJoint
|
|
8965
|
+
* @memberof Box2D
|
|
8699
8966
|
*/
|
|
8700
8967
|
class Box2dRopeJoint extends Box2dJoint
|
|
8701
8968
|
{
|
|
@@ -8748,6 +9015,7 @@ class Box2dRopeJoint extends Box2dJoint
|
|
|
8748
9015
|
* - You can use a motor to drive the relative rotation about the shared point
|
|
8749
9016
|
* - A maximum motor torque is provided so that infinite forces are not generated
|
|
8750
9017
|
* @extends Box2dJoint
|
|
9018
|
+
* @memberof Box2D
|
|
8751
9019
|
*/
|
|
8752
9020
|
class Box2dRevoluteJoint extends Box2dJoint
|
|
8753
9021
|
{
|
|
@@ -8849,6 +9117,7 @@ class Box2dRevoluteJoint extends Box2dJoint
|
|
|
8849
9117
|
* - Either joint can be a revolute or prismatic joint
|
|
8850
9118
|
* - You specify a gear ratio to bind the motions together
|
|
8851
9119
|
* @extends Box2dJoint
|
|
9120
|
+
* @memberof Box2D
|
|
8852
9121
|
*/
|
|
8853
9122
|
class Box2dGearJoint extends Box2dJoint
|
|
8854
9123
|
{
|
|
@@ -8897,6 +9166,7 @@ class Box2dGearJoint extends Box2dJoint
|
|
|
8897
9166
|
* - You can use a joint limit to restrict the range of motion
|
|
8898
9167
|
* - You can use a joint motor to drive the motion or to model joint friction
|
|
8899
9168
|
* @extends Box2dJoint
|
|
9169
|
+
* @memberof Box2D
|
|
8900
9170
|
*/
|
|
8901
9171
|
class Box2dPrismaticJoint extends Box2dJoint
|
|
8902
9172
|
{
|
|
@@ -9006,6 +9276,7 @@ class Box2dPrismaticJoint extends Box2dJoint
|
|
|
9006
9276
|
* - You can use a joint motor to drive the motion or to model joint friction
|
|
9007
9277
|
* - This joint is designed for vehicle suspensions
|
|
9008
9278
|
* @extends Box2dJoint
|
|
9279
|
+
* @memberof Box2D
|
|
9009
9280
|
*/
|
|
9010
9281
|
class Box2dWheelJoint extends Box2dJoint
|
|
9011
9282
|
{
|
|
@@ -9101,6 +9372,7 @@ class Box2dWheelJoint extends Box2dJoint
|
|
|
9101
9372
|
* Box2D Weld Joint
|
|
9102
9373
|
* - Glues two objects together
|
|
9103
9374
|
* @extends Box2dJoint
|
|
9375
|
+
* @memberof Box2D
|
|
9104
9376
|
*/
|
|
9105
9377
|
class Box2dWeldJoint extends Box2dJoint
|
|
9106
9378
|
{
|
|
@@ -9159,6 +9431,7 @@ class Box2dWeldJoint extends Box2dJoint
|
|
|
9159
9431
|
* - Used to apply top-down friction
|
|
9160
9432
|
* - Provides 2D translational friction and angular friction
|
|
9161
9433
|
* @extends Box2dJoint
|
|
9434
|
+
* @memberof Box2D
|
|
9162
9435
|
*/
|
|
9163
9436
|
class Box2dFrictionJoint extends Box2dJoint
|
|
9164
9437
|
{
|
|
@@ -9213,6 +9486,7 @@ class Box2dFrictionJoint extends Box2dJoint
|
|
|
9213
9486
|
* - The pulley supports a ratio such that: length1 + ratio * length2 <= constant
|
|
9214
9487
|
* - The force transmitted is scaled by the ratio
|
|
9215
9488
|
* @extends Box2dJoint
|
|
9489
|
+
* @memberof Box2D
|
|
9216
9490
|
*/
|
|
9217
9491
|
class Box2dPulleyJoint extends Box2dJoint
|
|
9218
9492
|
{
|
|
@@ -9280,6 +9554,7 @@ class Box2dPulleyJoint extends Box2dJoint
|
|
|
9280
9554
|
* - Controls the relative motion between two objects
|
|
9281
9555
|
* - Typical usage is to control the movement of a object with respect to the ground
|
|
9282
9556
|
* @extends Box2dJoint
|
|
9557
|
+
* @memberof Box2D
|
|
9283
9558
|
*/
|
|
9284
9559
|
class Box2dMotorJoint extends Box2dJoint
|
|
9285
9560
|
{
|
|
@@ -9343,6 +9618,7 @@ class Box2dMotorJoint extends Box2dJoint
|
|
|
9343
9618
|
/**
|
|
9344
9619
|
* Box2D Global Object
|
|
9345
9620
|
* - Wraps Box2d world and provides global functions
|
|
9621
|
+
* @memberof Box2D
|
|
9346
9622
|
*/
|
|
9347
9623
|
class Box2dPlugin
|
|
9348
9624
|
{
|