littlejsengine 1.1.2 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -0
- package/build.bat +2 -1
- package/engine/engine.all.js +1320 -930
- package/engine/engine.all.min.js +1 -1
- package/engine/engine.all.release.js +965 -601
- package/engine/engine.js +71 -60
- package/engine/engineAudio.js +80 -22
- package/engine/engineBuild.bat +2 -2
- package/engine/engineDebug.js +65 -36
- package/engine/engineDraw.js +71 -56
- package/engine/engineInput.js +178 -28
- package/engine/engineMedals.js +66 -58
- package/engine/engineObject.js +86 -71
- package/engine/engineParticles.js +101 -63
- package/engine/engineRelease.js +4 -1
- package/engine/engineSettings.js +62 -53
- package/engine/engineTileLayer.js +99 -83
- package/engine/engineUtilities.js +95 -59
- package/engine/engineWebGL.js +53 -48
- package/examples/breakout/game.js +1 -1
- package/examples/breakout/gameObjects.js +2 -2
- package/examples/breakout/index.html +7 -5
- package/examples/platformer/game.js +7 -4
- package/examples/platformer/gameEffects.js +8 -11
- package/examples/platformer/gameLevel.js +15 -8
- package/examples/platformer/gameObjects.js +2 -2
- package/examples/platformer/gamePlayer.js +6 -6
- package/examples/platformer/index.html +10 -8
- package/examples/puzzle/game.js +3 -3
- package/examples/puzzle/index.html +6 -4
- package/examples/stress/index.html +7 -5
- package/game.js +10 -10
- package/index.html +17 -15
- package/package.json +4 -7
- package/tiles.png +0 -0
- package/LittleJS.zip +0 -0
- package/docs/Audio.html +0 -2264
- package/docs/Color.html +0 -2506
- package/docs/Debug.html +0 -2929
- package/docs/Draw.html +0 -3854
- package/docs/EngineObject.html +0 -2506
- package/docs/Input.html +0 -2478
- package/docs/Medal.html +0 -992
- package/docs/Medals.html +0 -624
- package/docs/Music.html +0 -569
- package/docs/Newgrounds.html +0 -1384
- package/docs/Particle.html +0 -567
- package/docs/ParticleEmitter.html +0 -1537
- package/docs/Random.html +0 -1770
- package/docs/Settings.html +0 -2885
- package/docs/Sound.html +0 -998
- package/docs/TileLayer.html +0 -3211
- package/docs/TileLayerData.html +0 -569
- package/docs/Timer.html +0 -1168
- package/docs/Utilities.html +0 -3266
- package/docs/Vector2.html +0 -3956
- package/docs/WebGL.html +0 -1842
- package/docs/engine.js.html +0 -428
- package/docs/engineAudio.js.html +0 -567
- package/docs/engineDebug.js.html +0 -721
- package/docs/engineDraw.js.html +0 -409
- package/docs/engineInput.js.html +0 -397
- package/docs/engineMedals.js.html +0 -445
- package/docs/engineObject.js.html +0 -492
- package/docs/engineParticles.js.html +0 -399
- package/docs/engineSettings.js.html +0 -358
- package/docs/engineTileLayer.js.html +0 -482
- package/docs/engineUtilities.js.html +0 -600
- package/docs/engineWebGL.js.html +0 -507
- package/docs/fonts/MavenPro-Regular.ttf +0 -0
- package/docs/fonts/Montserrat-Regular.ttf +0 -0
- package/docs/fonts/Muli-Black.ttf +0 -0
- package/docs/fonts/OFL-hind.txt +0 -93
- package/docs/fonts/OFL-montserrat.txt +0 -93
- package/docs/global.html +0 -1635
- package/docs/index.html +0 -243
- package/docs/scripts/fix-code-block.js +0 -53
- package/docs/scripts/fix-navbar.js +0 -25
- package/docs/scripts/linenumber.js +0 -25
- package/docs/scripts/misc.js +0 -217
- package/docs/scripts/resize.js +0 -85
- package/docs/scripts/search.js +0 -83
- package/docs/scripts/third-party/Apache-License-2.0.txt +0 -202
- package/docs/scripts/third-party/fuse.js +0 -9
- package/docs/scripts/third-party/lang-css.js +0 -2
- package/docs/scripts/third-party/prettify.js +0 -28
- package/docs/static/favicon.png +0 -0
- package/docs/styles/clean-jsdoc-theme-base.css +0 -393
- package/docs/styles/clean-jsdoc-theme-dark.css +0 -324
- package/docs/styles/clean-jsdoc-theme-light.css +0 -319
- package/docs/styles/reset.css +0 -346
- package/docs/styles/third-party/ionicons.min.css +0 -11
- package/docs/styles/third-party/prettify-jsdoc.css +0 -111
- package/docs/styles/third-party/prettify-tomorrow.css +0 -5
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
2
|
+
* LittleJS Tile Layer System
|
|
3
|
+
* <br> - Caches arrays of tiles to off screen canvas for fast rendering
|
|
4
|
+
* <br> - Unlimted numbers of layers, allocates canvases as needed
|
|
5
|
+
* <br> - Interfaces with EngineObject for collision
|
|
6
|
+
* <br> - Collision layer is separate from visible layers
|
|
7
|
+
* <br> - It is recommended to have a visible layer that matches the collision
|
|
8
|
+
* <br> - Tile layers can be drawn to using their context with canvas2d
|
|
9
|
+
* <br> - Drawn directly to the main canvas without using WebGL
|
|
10
|
+
* @namespace TileCollision
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
13
|
'use strict';
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
/** The tile collision layer array, use setTileCollisionData and getTileCollisionData to access
|
|
16
|
+
* @memberof TileCollision */
|
|
17
|
+
let tileCollision = [];
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
/** Size of the tile collision layer
|
|
20
|
+
* @type {Vector2}
|
|
21
|
+
* @memberof TileCollision */
|
|
22
|
+
let tileCollisionSize = vec2();
|
|
19
23
|
|
|
20
24
|
/** Clear and initialize tile collision
|
|
21
25
|
* @param {Vector2} size
|
|
22
|
-
* @memberof
|
|
26
|
+
* @memberof TileCollision */
|
|
23
27
|
function initTileCollision(size)
|
|
24
28
|
{
|
|
25
29
|
tileCollisionSize = size;
|
|
@@ -31,14 +35,14 @@ function initTileCollision(size)
|
|
|
31
35
|
/** Set tile collision data
|
|
32
36
|
* @param {Vector2} pos
|
|
33
37
|
* @param {Number} [data=0]
|
|
34
|
-
* @memberof
|
|
38
|
+
* @memberof TileCollision */
|
|
35
39
|
const setTileCollisionData = (pos, data=0)=>
|
|
36
40
|
pos.arrayCheck(tileCollisionSize) && (tileCollision[(pos.y|0)*tileCollisionSize.x+pos.x|0] = data);
|
|
37
41
|
|
|
38
42
|
/** Get tile collision data
|
|
39
43
|
* @param {Vector2} pos
|
|
40
44
|
* @return {Number}
|
|
41
|
-
* @memberof
|
|
45
|
+
* @memberof TileCollision */
|
|
42
46
|
const getTileCollisionData = (pos)=>
|
|
43
47
|
pos.arrayCheck(tileCollisionSize) ? tileCollision[(pos.y|0)*tileCollisionSize.x+pos.x|0] : 0;
|
|
44
48
|
|
|
@@ -47,13 +51,13 @@ const getTileCollisionData = (pos)=>
|
|
|
47
51
|
* @param {Vector2} [size=new Vector2(1,1)]
|
|
48
52
|
* @param {EngineObject} [object]
|
|
49
53
|
* @return {Boolean}
|
|
50
|
-
* @memberof
|
|
54
|
+
* @memberof TileCollision */
|
|
51
55
|
function tileCollisionTest(pos, size=vec2(), object)
|
|
52
56
|
{
|
|
53
|
-
const minX = max(
|
|
54
|
-
const minY = max(
|
|
55
|
-
const maxX = min(pos.x + size.x/2, tileCollisionSize.x
|
|
56
|
-
const maxY = min(pos.y + size.y/2, tileCollisionSize.y
|
|
57
|
+
const minX = max(pos.x - size.x/2|0, 0);
|
|
58
|
+
const minY = max(pos.y - size.y/2|0, 0);
|
|
59
|
+
const maxX = min(pos.x + size.x/2, tileCollisionSize.x);
|
|
60
|
+
const maxY = min(pos.y + size.y/2, tileCollisionSize.y);
|
|
57
61
|
for (let y = minY; y < maxY; ++y)
|
|
58
62
|
for (let x = minX; x < maxX; ++x)
|
|
59
63
|
{
|
|
@@ -68,7 +72,7 @@ function tileCollisionTest(pos, size=vec2(), object)
|
|
|
68
72
|
* @param {Vector2} posEnd
|
|
69
73
|
* @param {EngineObject} [object]
|
|
70
74
|
* @return {Vector2}
|
|
71
|
-
* @memberof
|
|
75
|
+
* @memberof TileCollision */
|
|
72
76
|
function tileCollisionRaycast(posStart, posEnd, object)
|
|
73
77
|
{
|
|
74
78
|
// test if a ray collides with tiles from start to end
|
|
@@ -102,23 +106,32 @@ function tileCollisionRaycast(posStart, posEnd, object)
|
|
|
102
106
|
///////////////////////////////////////////////////////////////////////////////
|
|
103
107
|
// Tile Layer Rendering System
|
|
104
108
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Tile layer data object stores info about how to render a tile
|
|
111
|
+
* @example
|
|
112
|
+
* // create tile layer data with tile index 0 and random orientation and color
|
|
113
|
+
* const tileIndex = 0;
|
|
114
|
+
* const direction = randInt(4)
|
|
115
|
+
* const mirror = randInt(2);
|
|
116
|
+
* const color = randColor();
|
|
117
|
+
* const data = new TileLayerData(tileIndex, direction, mirror, color);
|
|
118
|
+
*/
|
|
109
119
|
class TileLayerData
|
|
110
120
|
{
|
|
111
|
-
/** Create a tile layer data object
|
|
112
|
-
* @param {Number} [tile]
|
|
113
|
-
* @param {Number} [direction=0]
|
|
114
|
-
* @param {Boolean} [mirror=0]
|
|
115
|
-
* @param {Color} [color=new Color(1,1,1)] - Color of the tile
|
|
116
|
-
*/
|
|
121
|
+
/** Create a tile layer data object, one for each tile in a TileLayer
|
|
122
|
+
* @param {Number} [tile] - The tile to use, untextured if undefined
|
|
123
|
+
* @param {Number} [direction=0] - Integer direction of tile, in 90 degree increments
|
|
124
|
+
* @param {Boolean} [mirror=0] - If the tile should be mirrored along the x axis
|
|
125
|
+
* @param {Color} [color=new Color(1,1,1)] - Color of the tile */
|
|
117
126
|
constructor(tile, direction=0, mirror=0, color=new Color)
|
|
118
127
|
{
|
|
128
|
+
/** @property {Number} - The tile to use, untextured if undefined */
|
|
119
129
|
this.tile = tile;
|
|
130
|
+
/** @property {Number} - Integer direction of tile, in 90 degree increments */
|
|
120
131
|
this.direction = direction;
|
|
132
|
+
/** @property {Boolean} - If the tile should be mirrored along the x axis */
|
|
121
133
|
this.mirror = mirror;
|
|
134
|
+
/** @property {Color} - Color of the tile */
|
|
122
135
|
this.color = color;
|
|
123
136
|
}
|
|
124
137
|
|
|
@@ -126,44 +139,49 @@ class TileLayerData
|
|
|
126
139
|
clear() { this.tile = this.direction = this.mirror = 0; color = new Color; }
|
|
127
140
|
}
|
|
128
141
|
|
|
129
|
-
/**
|
|
142
|
+
/**
|
|
143
|
+
* Tile layer object - cached rendering system for tile layers
|
|
144
|
+
* <br> - Each Tile layer is rendered to an off screen canvas
|
|
145
|
+
* <br> - To allow dynamic modifications, layers are rendered using canvas 2d
|
|
146
|
+
* <br> - Some devices like mobile phones are limited to 4k texture resolution
|
|
147
|
+
* <br> - So with 16x16 tiles this limits layers to 256x256 on mobile devices
|
|
148
|
+
* @extends EngineObject
|
|
149
|
+
* @example
|
|
150
|
+
* // create tile collision and visible tile layer
|
|
151
|
+
* initTileCollision(vec2(200,100));
|
|
152
|
+
* const tileLayer = new TileLayer();
|
|
153
|
+
*/
|
|
130
154
|
class TileLayer extends EngineObject
|
|
131
155
|
{
|
|
132
|
-
/** Create a tile layer
|
|
156
|
+
/** Create a tile layer object
|
|
133
157
|
* @param {Vector2} [position=new Vector2(0,0)] - World space position
|
|
134
|
-
* @param {Vector2} [size=
|
|
135
|
-
* @param {Vector2} [
|
|
136
|
-
* @param {
|
|
158
|
+
* @param {Vector2} [size=objectDefaultSize] - World space size
|
|
159
|
+
* @param {Vector2} [tileSize=tileSizeDefault] - Size of tiles in source pixels
|
|
160
|
+
* @param {Vector2} [scale=new Vector2(1,1)] - How much to scale this layer when rendered
|
|
161
|
+
* @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
|
|
137
162
|
*/
|
|
138
|
-
constructor(pos, size, scale=vec2(1), renderOrder=0)
|
|
163
|
+
constructor(pos, size=tileCollisionSize, tileSize=tileSizeDefault, scale=vec2(1), renderOrder=0)
|
|
139
164
|
{
|
|
140
|
-
super(pos, size);
|
|
165
|
+
super(pos, size, -1, tileSize, 0, undefined, renderOrder);
|
|
141
166
|
|
|
142
|
-
|
|
143
|
-
this.canvas =
|
|
167
|
+
/** @property {HTMLCanvasElement} - The canvas used by this tile layer */
|
|
168
|
+
this.canvas = document.createElement('canvas');
|
|
169
|
+
/** @property {CanvasRenderingContext2D} - The 2D canvas context used by this tile layer */
|
|
144
170
|
this.context = this.canvas.getContext('2d');
|
|
171
|
+
/** @property {Vector2} - How much to scale this layer when rendered */
|
|
145
172
|
this.scale = scale;
|
|
146
|
-
|
|
147
|
-
this.
|
|
148
|
-
this.flushGLBeforeRender = 1;
|
|
173
|
+
/** @property {Boolean} [isOverlay=0] - If true this layer will render to overlay canvas and appear above all objects */
|
|
174
|
+
this.isOverlay;
|
|
149
175
|
|
|
150
176
|
// init tile data
|
|
151
177
|
this.data = [];
|
|
152
178
|
for (let j = this.size.area(); j--;)
|
|
153
179
|
this.data.push(new TileLayerData());
|
|
154
180
|
}
|
|
155
|
-
|
|
156
|
-
/** Destroy this tile layer */
|
|
157
|
-
destroy()
|
|
158
|
-
{
|
|
159
|
-
// add canvas back to the cache
|
|
160
|
-
tileLayerCanvasCache.push(this.canvas);
|
|
161
|
-
super.destroy();
|
|
162
|
-
}
|
|
163
181
|
|
|
164
182
|
/** Set data at a given position in the array
|
|
165
|
-
* @param {Vector2} position
|
|
166
|
-
* @param {TileLayerData} data
|
|
183
|
+
* @param {Vector2} position - Local position in array
|
|
184
|
+
* @param {TileLayerData} data - Data to set
|
|
167
185
|
* @param {Boolean} [redraw=0] - Force the tile to redraw if true */
|
|
168
186
|
setData(layerPos, data, redraw)
|
|
169
187
|
{
|
|
@@ -188,50 +206,48 @@ class TileLayer extends EngineObject
|
|
|
188
206
|
{
|
|
189
207
|
ASSERT(mainContext != this.context); // must call redrawEnd() after drawing tiles
|
|
190
208
|
|
|
191
|
-
// flush and copy gl canvas because tile canvas does not use
|
|
192
|
-
|
|
209
|
+
// flush and copy gl canvas because tile canvas does not use webgl
|
|
210
|
+
glEnable && !glOverlay && !this.isOverlay && glCopyToContext(mainContext);
|
|
193
211
|
|
|
194
|
-
// draw the entire cached level onto the
|
|
212
|
+
// draw the entire cached level onto the canvas
|
|
195
213
|
const pos = worldToScreen(this.pos.add(vec2(0,this.size.y*this.scale.y)));
|
|
196
|
-
mainContext.drawImage
|
|
214
|
+
(this.isOverlay ? overlayContext : mainContext).drawImage
|
|
197
215
|
(
|
|
198
216
|
this.canvas, pos.x, pos.y,
|
|
199
217
|
cameraScale*this.size.x*this.scale.x, cameraScale*this.size.y*this.scale.y
|
|
200
218
|
);
|
|
201
219
|
}
|
|
202
220
|
|
|
203
|
-
/** Draw all the tile data to an offscreen canvas
|
|
221
|
+
/** Draw all the tile data to an offscreen canvas
|
|
222
|
+
* - This may be slow in some browsers
|
|
223
|
+
*/
|
|
204
224
|
redraw()
|
|
205
225
|
{
|
|
206
|
-
this.redrawStart();
|
|
226
|
+
this.redrawStart(1);
|
|
207
227
|
this.drawAllTileData();
|
|
208
228
|
this.redrawEnd();
|
|
209
229
|
}
|
|
210
230
|
|
|
211
231
|
/** Call to start the redraw process
|
|
212
|
-
* @param {Boolean} [clear=
|
|
213
|
-
redrawStart(clear =
|
|
232
|
+
* @param {Boolean} [clear=0] - Should it clear the canvas before drawing */
|
|
233
|
+
redrawStart(clear = 0)
|
|
214
234
|
{
|
|
215
|
-
// clear and set size
|
|
216
|
-
const width = this.size.x * this.tileSize.x;
|
|
217
|
-
const height = this.size.y * this.tileSize.y;
|
|
218
235
|
if (clear)
|
|
219
236
|
{
|
|
220
|
-
|
|
221
|
-
this.canvas.
|
|
237
|
+
// clear and set size
|
|
238
|
+
this.canvas.width = this.size.x * this.tileSize.x;
|
|
239
|
+
this.canvas.height = this.size.y * this.tileSize.y;
|
|
222
240
|
}
|
|
223
241
|
|
|
224
242
|
// save current render settings
|
|
225
|
-
this.savedRenderSettings = [
|
|
243
|
+
this.savedRenderSettings = [mainCanvas, mainContext, cameraPos, cameraScale];
|
|
226
244
|
|
|
227
|
-
//
|
|
228
|
-
cameraScale = this.tileSize.x;
|
|
229
|
-
cameraPos = this.size.scale(.5);
|
|
245
|
+
// use normal rendering system to render the tiles
|
|
230
246
|
mainCanvas = this.canvas;
|
|
231
247
|
mainContext = this.context;
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
248
|
+
cameraPos = this.size.scale(.5);
|
|
249
|
+
cameraScale = this.tileSize.x;
|
|
250
|
+
enginePreRender();
|
|
235
251
|
}
|
|
236
252
|
|
|
237
253
|
/** Call to end the redraw process */
|
|
@@ -242,7 +258,7 @@ class TileLayer extends EngineObject
|
|
|
242
258
|
//debugSaveCanvas(this.canvas);
|
|
243
259
|
|
|
244
260
|
// set stuff back to normal
|
|
245
|
-
[
|
|
261
|
+
[mainCanvas, mainContext, cameraPos, cameraScale] = this.savedRenderSettings;
|
|
246
262
|
}
|
|
247
263
|
|
|
248
264
|
/** Draw the tile at a given position
|
|
@@ -270,13 +286,13 @@ class TileLayer extends EngineObject
|
|
|
270
286
|
this.drawTileData(vec2(x,y));
|
|
271
287
|
}
|
|
272
288
|
|
|
273
|
-
/** Draw directly to the
|
|
289
|
+
/** Draw directly to the 2D canvas in world space (bipass webgl)
|
|
274
290
|
* @param {Vector2} pos
|
|
275
291
|
* @param {Vector2} size
|
|
276
|
-
* @param {Number} angle
|
|
277
|
-
* @param {Boolean} mirror
|
|
292
|
+
* @param {Number} [angle=0]
|
|
293
|
+
* @param {Boolean} [mirror=0]
|
|
278
294
|
* @param {Function} drawFunction */
|
|
279
|
-
drawCanvas2D(pos, size, angle, mirror, drawFunction)
|
|
295
|
+
drawCanvas2D(pos, size, angle=0, mirror, drawFunction)
|
|
280
296
|
{
|
|
281
297
|
const context = this.context;
|
|
282
298
|
context.save();
|
|
@@ -284,7 +300,7 @@ class TileLayer extends EngineObject
|
|
|
284
300
|
size = size.multiply(this.tileSize);
|
|
285
301
|
context.translate(pos.x, this.canvas.height - pos.y);
|
|
286
302
|
context.rotate(angle);
|
|
287
|
-
context.scale(mirror
|
|
303
|
+
context.scale(mirror ? -size.x : size.x, size.y);
|
|
288
304
|
drawFunction(context);
|
|
289
305
|
context.restore();
|
|
290
306
|
}
|
|
@@ -293,11 +309,11 @@ class TileLayer extends EngineObject
|
|
|
293
309
|
* @param {Vector2} pos
|
|
294
310
|
* @param {Vector2} [size=new Vector2(1,1)]
|
|
295
311
|
* @param {Number} [tileIndex=-1]
|
|
296
|
-
* @param {Vector2} [tileSize=
|
|
312
|
+
* @param {Vector2} [tileSize=tileSizeDefault]
|
|
297
313
|
* @param {Color} [color=new Color(1,1,1)]
|
|
298
314
|
* @param {Number} [angle=0]
|
|
299
315
|
* @param {Boolean} [mirror=0] */
|
|
300
|
-
drawTile(pos, size=vec2(1), tileIndex=-1, tileSize=
|
|
316
|
+
drawTile(pos, size=vec2(1), tileIndex=-1, tileSize=tileSizeDefault, color=new Color, angle, mirror)
|
|
301
317
|
{
|
|
302
318
|
this.drawCanvas2D(pos, size, angle, mirror, (context)=>
|
|
303
319
|
{
|
|
@@ -310,7 +326,7 @@ class TileLayer extends EngineObject
|
|
|
310
326
|
else
|
|
311
327
|
{
|
|
312
328
|
const cols = tileImage.width/tileSize.x;
|
|
313
|
-
context.globalAlpha = color.a; //
|
|
329
|
+
context.globalAlpha = color.a; // only alpha, no color, is supported in this mode
|
|
314
330
|
context.drawImage(tileImage,
|
|
315
331
|
(tileIndex%cols)*tileSize.x, (tileIndex/cols|0)*tileSize.x,
|
|
316
332
|
tileSize.x, tileSize.y, -.5, -.5, 1, 1);
|
|
@@ -323,5 +339,5 @@ class TileLayer extends EngineObject
|
|
|
323
339
|
* @param {Vector2} [size=new Vector2(1,1)]
|
|
324
340
|
* @param {Color} [color=new Color(1,1,1)]
|
|
325
341
|
* @param {Number} [angle=0] */
|
|
326
|
-
drawRect(pos, size, color, angle) { this.drawTile(pos, size, -1, 0, color, angle
|
|
342
|
+
drawRect(pos, size, color, angle) { this.drawTile(pos, size, -1, 0, color, angle); }
|
|
327
343
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
2
|
+
* LittleJS Utility Classes and Functions
|
|
3
|
+
* <br> - General purpose math library
|
|
4
|
+
* <br> - Vector2 - fast, simple, easy 2D vector class
|
|
5
|
+
* <br> - Color - holds a rgba color with some math functions
|
|
6
|
+
* <br> - Timer - tracks time automatically
|
|
7
|
+
* @namespace Utilities
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -14,23 +14,12 @@
|
|
|
14
14
|
* @memberof Utilities */
|
|
15
15
|
const PI = Math.PI;
|
|
16
16
|
|
|
17
|
-
/** True if running a Chromium based browser
|
|
18
|
-
* @const
|
|
19
|
-
* @memberof Utilities */
|
|
20
|
-
const isChrome = window['chrome'];
|
|
21
|
-
|
|
22
17
|
/** Returns absoulte value of value passed in
|
|
23
18
|
* @param {Number} value
|
|
24
19
|
* @return {Number}
|
|
25
20
|
* @memberof Utilities */
|
|
26
21
|
const abs = (a)=> a < 0 ? -a : a;
|
|
27
22
|
|
|
28
|
-
/** Returns the sign of value passed in
|
|
29
|
-
* @param {Number} value
|
|
30
|
-
* @return {Number}
|
|
31
|
-
* @memberof Utilities */
|
|
32
|
-
const sign = (a)=> a < 0 ? -1 : 1;
|
|
33
|
-
|
|
34
23
|
/** Returns lowest of two values passed in
|
|
35
24
|
* @param {Number} valueA
|
|
36
25
|
* @param {Number} valueB
|
|
@@ -45,54 +34,54 @@ const min = (a, b)=> a < b ? a : b;
|
|
|
45
34
|
* @memberof Utilities */
|
|
46
35
|
const max = (a, b)=> a > b ? a : b;
|
|
47
36
|
|
|
37
|
+
/** Returns the sign of value passed in (also returns 1 if 0)
|
|
38
|
+
* @param {Number} value
|
|
39
|
+
* @return {Number}
|
|
40
|
+
* @memberof Utilities */
|
|
41
|
+
const sign = (a)=> a < 0 ? -1 : 1;
|
|
42
|
+
|
|
48
43
|
/** Returns first parm modulo the second param, but adjusted so negative numbers work as expected
|
|
49
44
|
* @param {Number} dividend
|
|
50
|
-
* @param {Number} divisor
|
|
45
|
+
* @param {Number} [divisor=1]
|
|
51
46
|
* @return {Number}
|
|
52
47
|
* @memberof Utilities */
|
|
53
|
-
const mod = (a, b)=> ((a % b) + b) % b;
|
|
48
|
+
const mod = (a, b=1)=> ((a % b) + b) % b;
|
|
54
49
|
|
|
55
50
|
/** Clamps the value beween max and min
|
|
56
51
|
* @param {Number} value
|
|
57
|
-
* @param {Number} [max=1]
|
|
58
52
|
* @param {Number} [min=0]
|
|
53
|
+
* @param {Number} [max=1]
|
|
59
54
|
* @return {Number}
|
|
60
55
|
* @memberof Utilities */
|
|
61
|
-
const clamp = (v,
|
|
56
|
+
const clamp = (v, min=0, max=1)=> v < min ? min : v > max ? max : v;
|
|
62
57
|
|
|
63
58
|
/** Returns what percentage the value is between max and min
|
|
64
59
|
* @param {Number} value
|
|
65
|
-
* @param {Number} [max=1]
|
|
66
60
|
* @param {Number} [min=0]
|
|
61
|
+
* @param {Number} [max=1]
|
|
67
62
|
* @return {Number}
|
|
68
63
|
* @memberof Utilities */
|
|
69
|
-
const percent = (v,
|
|
64
|
+
const percent = (v, min=0, max=1)=> max-min ? clamp((v-min) / (max-min)) : 0;
|
|
70
65
|
|
|
71
66
|
/** Linearly interpolates the percent value between max and min
|
|
72
67
|
* @param {Number} percent
|
|
73
|
-
* @param {Number} [max=1]
|
|
74
68
|
* @param {Number} [min=0]
|
|
69
|
+
* @param {Number} [max=1]
|
|
75
70
|
* @return {Number}
|
|
76
71
|
* @memberof Utilities */
|
|
77
|
-
const lerp = (p,
|
|
72
|
+
const lerp = (p, min=0, max=1)=> min + clamp(p) * (max-min);
|
|
78
73
|
|
|
79
|
-
/**
|
|
80
|
-
* @param {Number} t - time in seconds
|
|
81
|
-
* @return {String}
|
|
82
|
-
* @memberof Utilities */
|
|
83
|
-
const formatTime = (t)=> (t/60|0)+':'+(t%60<10?'0':'')+(t%60|0);
|
|
84
|
-
|
|
85
|
-
/** Returns the nearest power of two not less then the value
|
|
74
|
+
/** Applies smoothstep function to the percentage value
|
|
86
75
|
* @param {Number} value
|
|
87
76
|
* @return {Number}
|
|
88
77
|
* @memberof Utilities */
|
|
89
|
-
const
|
|
78
|
+
const smoothStep = (p)=> p * p * (3 - 2 * p);
|
|
90
79
|
|
|
91
|
-
/**
|
|
80
|
+
/** Returns the nearest power of two not less then the value
|
|
92
81
|
* @param {Number} value
|
|
93
82
|
* @return {Number}
|
|
94
83
|
* @memberof Utilities */
|
|
95
|
-
const
|
|
84
|
+
const nearestPowerOfTwo = (v)=> 2**Math.ceil(Math.log2(v));
|
|
96
85
|
|
|
97
86
|
/** Returns true if two axis aligned bounding boxes are overlapping
|
|
98
87
|
* @param {Vector2} pointA - Center of box A
|
|
@@ -111,6 +100,12 @@ const isOverlapping = (pA, sA, pB, sB)=> abs(pA.x - pB.x)*2 < sA.x + sB.x & abs(
|
|
|
111
100
|
* @memberof Utilities */
|
|
112
101
|
const wave = (frequency=1, amplitude=1, t=time)=> amplitude/2 * (1 - Math.cos(t*frequency*2*PI));
|
|
113
102
|
|
|
103
|
+
/** Formats seconds to mm:ss style for display purposes
|
|
104
|
+
* @param {Number} t - time in seconds
|
|
105
|
+
* @return {String}
|
|
106
|
+
* @memberof Utilities */
|
|
107
|
+
const formatTime = (t)=> (t/60|0)+':'+(t%60<10?'0':'')+(t%60|0);
|
|
108
|
+
|
|
114
109
|
///////////////////////////////////////////////////////////////////////////////
|
|
115
110
|
|
|
116
111
|
/** Random global functions
|
|
@@ -133,7 +128,7 @@ const randInt = (a=1, b=0)=> rand(a,b)|0;
|
|
|
133
128
|
/** Randomly returns either -1 or 1
|
|
134
129
|
* @return {Number}
|
|
135
130
|
* @memberof Random */
|
|
136
|
-
const randSign = ()=> (rand(2)|0)*2-1;
|
|
131
|
+
const randSign = ()=> (rand(2)|0) * 2 - 1;
|
|
137
132
|
|
|
138
133
|
/** Returns a random Vector2 within a circular shape
|
|
139
134
|
* @param {Number} [radius=1]
|
|
@@ -169,25 +164,46 @@ let randSeed = 1;
|
|
|
169
164
|
const randSeeded = (a=1, b=0)=>
|
|
170
165
|
{
|
|
171
166
|
randSeed ^= randSeed << 13; randSeed ^= randSeed >>> 17; randSeed ^= randSeed << 5; // xorshift
|
|
172
|
-
return b + (a-b)*abs(randSeed % 1e9)/1e9;
|
|
167
|
+
return b + (a-b) * abs(randSeed % 1e9) / 1e9;
|
|
173
168
|
}
|
|
174
169
|
|
|
175
170
|
///////////////////////////////////////////////////////////////////////////////
|
|
176
171
|
|
|
177
|
-
/**
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
172
|
+
/**
|
|
173
|
+
* Create a 2d vector, can take another Vector2 to copy, 2 scalars, or 1 scalar
|
|
174
|
+
* @param {Number} [x=0]
|
|
175
|
+
* @param {Number} [y=0]
|
|
176
|
+
* @return {Vector2}
|
|
177
|
+
* @example
|
|
178
|
+
* let a = vec2(0, 1); // vector with coordinates (0, 1)
|
|
179
|
+
* let b = vec2(a); // copy a into b
|
|
180
|
+
* a = vec2(5); // set a to (5, 5)
|
|
181
|
+
* b = vec2(); // set b to (0, 0)
|
|
182
|
+
* @memberof Utilities
|
|
183
|
+
*/
|
|
182
184
|
const vec2 = (x=0, y)=> x.x == undefined ? new Vector2(x, y == undefined? x : y) : new Vector2(x.x, x.y);
|
|
183
185
|
|
|
184
|
-
/**
|
|
186
|
+
/**
|
|
187
|
+
* 2D Vector object with vector math library
|
|
188
|
+
* <br> - Functions do not change this so they can be chained together
|
|
189
|
+
* @example
|
|
190
|
+
* let a = new Vector2(2, 3); // vector with coordinates (2, 3)
|
|
191
|
+
* let b = new Vector2; // vector with coordinates (0, 0)
|
|
192
|
+
* let c = vec2(4, 2); // use the vec2 function to make a Vector2
|
|
193
|
+
* let d = a.add(b).scale(5); // operators can be chained
|
|
194
|
+
*/
|
|
185
195
|
class Vector2
|
|
186
196
|
{
|
|
187
197
|
/** Create a 2D vector with the x and y passed in, can also be created with vec2()
|
|
188
|
-
* @param {Number} [x=0] -
|
|
189
|
-
* @param {Number} [y=0] -
|
|
190
|
-
constructor(x=0, y=0)
|
|
198
|
+
* @param {Number} [x=0] - X axis location
|
|
199
|
+
* @param {Number} [y=0] - Y axis location */
|
|
200
|
+
constructor(x=0, y=0)
|
|
201
|
+
{
|
|
202
|
+
/** @property {Number} - X axis location */
|
|
203
|
+
this.x = x;
|
|
204
|
+
/** @property {Number} - Y axis location */
|
|
205
|
+
this.y = y;
|
|
206
|
+
}
|
|
191
207
|
|
|
192
208
|
/** Returns a new vector that is a copy of this
|
|
193
209
|
* @return {Vector2} */
|
|
@@ -278,10 +294,6 @@ class Vector2
|
|
|
278
294
|
* @return {Vector2} */
|
|
279
295
|
invert() { return new Vector2(this.y, -this.x); }
|
|
280
296
|
|
|
281
|
-
/** Returns a copy of this vector with the axies flipped
|
|
282
|
-
* @return {Vector2} */
|
|
283
|
-
flip() { return new Vector2(this.y, this.x); }
|
|
284
|
-
|
|
285
297
|
/** Returns a copy of this vector with each axis floored
|
|
286
298
|
* @return {Vector2} */
|
|
287
299
|
floor() { return new Vector2(Math.floor(this.x), Math.floor(this.y)); }
|
|
@@ -304,15 +316,31 @@ class Vector2
|
|
|
304
316
|
|
|
305
317
|
///////////////////////////////////////////////////////////////////////////////
|
|
306
318
|
|
|
307
|
-
/**
|
|
319
|
+
/**
|
|
320
|
+
* Color object (red, green, blue, alpha) with some helpful functions
|
|
321
|
+
* @example
|
|
322
|
+
* let a = new Color; // white
|
|
323
|
+
* let b = new Color(1, 0, 0); // red
|
|
324
|
+
* let c = new Color(0, 0, 0, 0); // transparent black
|
|
325
|
+
*/
|
|
308
326
|
class Color
|
|
309
327
|
{
|
|
310
328
|
/** Create a color with the components passed in, white by default
|
|
311
|
-
* @param {Number} [
|
|
312
|
-
* @param {Number} [
|
|
313
|
-
* @param {Number} [
|
|
314
|
-
* @param {Number} [
|
|
315
|
-
constructor(r=1, g=1, b=1, a=1)
|
|
329
|
+
* @param {Number} [red=1]
|
|
330
|
+
* @param {Number} [green=1]
|
|
331
|
+
* @param {Number} [blue=1]
|
|
332
|
+
* @param {Number} [alpha=1] */
|
|
333
|
+
constructor(r=1, g=1, b=1, a=1)
|
|
334
|
+
{
|
|
335
|
+
/** @property {Number} - Red */
|
|
336
|
+
this.r = r;
|
|
337
|
+
/** @property {Number} - Green */
|
|
338
|
+
this.g = g;
|
|
339
|
+
/** @property {Number} - Blue */
|
|
340
|
+
this.b = b;
|
|
341
|
+
/** @property {Number} - Alpha */
|
|
342
|
+
this.a = a;
|
|
343
|
+
}
|
|
316
344
|
|
|
317
345
|
/** Returns a new color that is a copy of this
|
|
318
346
|
* @return {Color} */
|
|
@@ -409,7 +437,15 @@ class Color
|
|
|
409
437
|
|
|
410
438
|
///////////////////////////////////////////////////////////////////////////////
|
|
411
439
|
|
|
412
|
-
/**
|
|
440
|
+
/**
|
|
441
|
+
* Timer object tracks how long has passed since it was set
|
|
442
|
+
* @example
|
|
443
|
+
* let a = new Timer; // creates a timer that is not set
|
|
444
|
+
* a.set(3); // sets the timer to 3 seconds
|
|
445
|
+
*
|
|
446
|
+
* let b = new Timer(1); // creates a timer with 1 second left
|
|
447
|
+
* b.unset(); // unsets the timer
|
|
448
|
+
*/
|
|
413
449
|
class Timer
|
|
414
450
|
{
|
|
415
451
|
/** Create a timer object set time passed in
|
|
@@ -435,11 +471,11 @@ class Timer
|
|
|
435
471
|
* @return {Boolean} */
|
|
436
472
|
elapsed() { return time > this.time; }
|
|
437
473
|
|
|
438
|
-
/** Get how long since elapsed, returns 0 if not set
|
|
474
|
+
/** Get how long since elapsed, returns 0 if not set (returns negative if currently active)
|
|
439
475
|
* @return {Number} */
|
|
440
476
|
get() { return this.isSet()? time - this.time : 0; }
|
|
441
477
|
|
|
442
478
|
/** Get percentage elapsed based on time it was set to, returns 0 if not set
|
|
443
479
|
* @return {Number} */
|
|
444
|
-
getPercent() { return this.isSet()? percent(this.time - time,
|
|
480
|
+
getPercent() { return this.isSet()? percent(this.time - time, this.setTime, 0) : 0; }
|
|
445
481
|
}
|