littlejsengine 1.9.0 → 1.9.2
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 +7 -7
- package/{build → dist}/littlejs.d.ts +84 -77
- package/{build → dist}/littlejs.esm.js +245 -143
- package/dist/littlejs.esm.min.js +1 -0
- package/{build → dist}/littlejs.js +245 -143
- package/dist/littlejs.min.js +1 -0
- package/{build → dist}/littlejs.release.js +239 -141
- package/examples/breakout/game.js +2 -2
- package/examples/breakout/gameObjects.js +3 -3
- package/examples/breakout/index.html +3 -3
- package/examples/breakoutTutorial/index.html +2 -2
- package/examples/electron/build.js +1 -1
- package/examples/electron/game.js +49 -38
- package/examples/electron/index.html +2 -2
- package/examples/electron/tiles.png +0 -0
- package/examples/empty/index.html +1 -1
- package/examples/js13k/build.js +2 -2
- package/examples/js13k/game.js +10 -9
- package/examples/js13k/index.html +13 -13
- package/examples/js13k/tiles.png +0 -0
- package/examples/module/game.js +45 -41
- package/examples/module/index.html +1 -1
- package/examples/module/tiles.png +0 -0
- package/examples/particles/index.html +1 -1
- package/examples/platformer/data/gameTileData.tmx +143 -0
- package/examples/platformer/data/gameTileData.tsx +4 -0
- package/examples/platformer/game.js +0 -1
- package/examples/platformer/gameCharacter.js +1 -1
- package/examples/platformer/gameEffects.js +42 -110
- package/examples/platformer/gameLevel.js +149 -183
- package/examples/platformer/gameObjects.js +61 -16
- package/examples/platformer/gamePlayer.js +3 -2
- package/examples/platformer/gameTileData.js +181 -0
- package/examples/platformer/index.html +8 -7
- package/examples/platformer/tiles.png +0 -0
- package/examples/platformer/tilesLevel.png +0 -0
- package/examples/puzzle/game.js +12 -12
- package/examples/puzzle/index.html +2 -2
- package/examples/starter/build.js +2 -2
- package/examples/starter/game.js +6 -6
- package/examples/starter/index.html +13 -13
- package/examples/starter/tiles.png +0 -0
- package/examples/stress/index.html +2 -2
- package/examples/typescript/build.bat +4 -1
- package/examples/typescript/game.js +34 -31
- package/examples/typescript/game.ts +40 -36
- package/examples/typescript/index.html +1 -1
- package/examples/typescript/tiles.png +0 -0
- package/package.json +3 -3
- package/src/engine.js +1 -1
- package/src/engineAudio.js +4 -10
- package/src/engineBuild.js +9 -2
- package/src/engineDebug.js +6 -2
- package/src/engineDraw.js +27 -27
- package/src/engineInput.js +7 -7
- package/src/engineMedals.js +2 -2
- package/src/engineObject.js +7 -7
- package/src/engineParticles.js +9 -9
- package/src/engineTileLayer.js +38 -33
- package/src/engineUtilities.js +136 -35
- package/src/engineWebGL.js +8 -10
- package/build/littlejs.esm.min.js +0 -1
- package/build/littlejs.min.js +0 -1
package/src/engineTileLayer.js
CHANGED
|
@@ -53,7 +53,7 @@ function getTileCollisionData(pos)
|
|
|
53
53
|
|
|
54
54
|
/** Check if collision with another object should occur
|
|
55
55
|
* @param {Vector2} pos
|
|
56
|
-
* @param {Vector2} [size=
|
|
56
|
+
* @param {Vector2} [size=(1,1)]
|
|
57
57
|
* @param {EngineObject} [object]
|
|
58
58
|
* @return {Boolean}
|
|
59
59
|
* @memberof TileCollision */
|
|
@@ -138,7 +138,7 @@ class TileLayerData
|
|
|
138
138
|
* @param {Number} [direction] - Integer direction of tile, in 90 degree increments
|
|
139
139
|
* @param {Boolean} [mirror] - If the tile should be mirrored along the x axis
|
|
140
140
|
* @param {Color} [color] - Color of the tile */
|
|
141
|
-
constructor(tile, direction=0, mirror=false, color=new Color
|
|
141
|
+
constructor(tile, direction=0, mirror=false, color=new Color)
|
|
142
142
|
{
|
|
143
143
|
/** @property {Number} - The tile to use, untextured if undefined */
|
|
144
144
|
this.tile = tile;
|
|
@@ -169,11 +169,11 @@ class TileLayerData
|
|
|
169
169
|
class TileLayer extends EngineObject
|
|
170
170
|
{
|
|
171
171
|
/** Create a tile layer object
|
|
172
|
-
* @param {Vector2} [position=
|
|
172
|
+
* @param {Vector2} [position=(0,0)] - World space position
|
|
173
173
|
* @param {Vector2} [size=tileCollisionSize] - World space size
|
|
174
|
-
* @param {TileInfo} [tileInfo]
|
|
175
|
-
* @param {Vector2} [scale=
|
|
176
|
-
* @param {Number} [renderOrder]
|
|
174
|
+
* @param {TileInfo} [tileInfo] - Tile info for layer
|
|
175
|
+
* @param {Vector2} [scale=(1,1)] - How much to scale this layer when rendered
|
|
176
|
+
* @param {Number} [renderOrder] - Objects are sorted by renderOrder
|
|
177
177
|
*/
|
|
178
178
|
constructor(position, size=tileCollisionSize, tileInfo=tile(), scale=vec2(1), renderOrder=0)
|
|
179
179
|
{
|
|
@@ -234,16 +234,18 @@ class TileLayer extends EngineObject
|
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
/** Draw all the tile data to an offscreen canvas
|
|
237
|
-
* - This may be slow in some browsers
|
|
238
|
-
*/
|
|
237
|
+
* - This may be slow in some browsers but only needs to be done once */
|
|
239
238
|
redraw()
|
|
240
239
|
{
|
|
241
240
|
this.redrawStart(true);
|
|
242
|
-
this.
|
|
241
|
+
for (let x = this.size.x; x--;)
|
|
242
|
+
for (let y = this.size.y; y--;)
|
|
243
|
+
this.drawTileData(vec2(x,y), false);
|
|
243
244
|
this.redrawEnd();
|
|
244
245
|
}
|
|
245
246
|
|
|
246
247
|
/** Call to start the redraw process
|
|
248
|
+
* - This can be used to manually update small parts of the level
|
|
247
249
|
* @param {Boolean} [clear] - Should it clear the canvas before drawing */
|
|
248
250
|
redrawStart(clear=false)
|
|
249
251
|
{
|
|
@@ -251,17 +253,19 @@ class TileLayer extends EngineObject
|
|
|
251
253
|
/** @type {[HTMLCanvasElement, CanvasRenderingContext2D, Vector2, Vector2, number]} */
|
|
252
254
|
this.savedRenderSettings = [mainCanvas, mainContext, mainCanvasSize, cameraPos, cameraScale];
|
|
253
255
|
|
|
254
|
-
//
|
|
256
|
+
// use webgl rendering system to render the tiles if enabled
|
|
257
|
+
// this works by temporally taking control of the rendering system
|
|
255
258
|
mainCanvas = this.canvas;
|
|
256
259
|
mainContext = this.context;
|
|
260
|
+
mainCanvasSize = this.size.multiply(this.tileInfo.size);
|
|
257
261
|
cameraPos = this.size.scale(.5);
|
|
258
262
|
cameraScale = this.tileInfo.size.x;
|
|
259
263
|
|
|
260
264
|
if (clear)
|
|
261
265
|
{
|
|
262
266
|
// clear and set size
|
|
263
|
-
mainCanvas.width =
|
|
264
|
-
mainCanvas.height =
|
|
267
|
+
mainCanvas.width = mainCanvasSize.x;
|
|
268
|
+
mainCanvas.height = mainCanvasSize.y;
|
|
265
269
|
}
|
|
266
270
|
|
|
267
271
|
// begin a new render for the tile canvas
|
|
@@ -279,32 +283,33 @@ class TileLayer extends EngineObject
|
|
|
279
283
|
[mainCanvas, mainContext, mainCanvasSize, cameraPos, cameraScale] = this.savedRenderSettings;
|
|
280
284
|
}
|
|
281
285
|
|
|
282
|
-
/** Draw the tile at a given position
|
|
283
|
-
*
|
|
284
|
-
|
|
286
|
+
/** Draw the tile at a given position in the tile grid
|
|
287
|
+
* This can be used to clear out tiles when they are destroyed
|
|
288
|
+
* Tiles can also be redrawn if isinde a redrawStart/End block
|
|
289
|
+
* @param {Vector2} layerPos
|
|
290
|
+
* @param {Boolean} [clear] - should the old tile be cleared out
|
|
291
|
+
*/
|
|
292
|
+
drawTileData(layerPos, clear=true)
|
|
285
293
|
{
|
|
286
|
-
//
|
|
287
|
-
const
|
|
288
|
-
|
|
294
|
+
// clear out where the tile was, for full opaque tiles this can be skipped
|
|
295
|
+
const s = this.tileInfo.size;
|
|
296
|
+
if (clear)
|
|
297
|
+
{
|
|
298
|
+
const pos = layerPos.multiply(s);
|
|
299
|
+
this.context.clearRect(pos.x, this.canvas.height-pos.y, s.x, -s.y);
|
|
300
|
+
}
|
|
289
301
|
|
|
290
302
|
// draw the tile if not undefined
|
|
291
303
|
const d = this.getData(layerPos);
|
|
292
304
|
if (d.tile != undefined)
|
|
293
305
|
{
|
|
306
|
+
const pos = this.pos.add(layerPos).add(vec2(.5));
|
|
294
307
|
ASSERT(mainContext == this.context, 'must call redrawStart() before drawing tiles');
|
|
295
|
-
const tileInfo = tile(d.tile,
|
|
308
|
+
const tileInfo = tile(d.tile, s, this.tileInfo.textureIndex);
|
|
296
309
|
drawTile(pos, vec2(1), tileInfo, d.color, d.direction*PI/2, d.mirror);
|
|
297
310
|
}
|
|
298
311
|
}
|
|
299
312
|
|
|
300
|
-
/** Draw all the tiles in this layer */
|
|
301
|
-
drawAllTileData()
|
|
302
|
-
{
|
|
303
|
-
for (let x = this.size.x; x--;)
|
|
304
|
-
for (let y = this.size.y; y--;)
|
|
305
|
-
this.drawTileData(vec2(x,y));
|
|
306
|
-
}
|
|
307
|
-
|
|
308
313
|
/** Draw directly to the 2D canvas in world space (bipass webgl)
|
|
309
314
|
* @param {Vector2} pos
|
|
310
315
|
* @param {Vector2} size
|
|
@@ -324,11 +329,11 @@ class TileLayer extends EngineObject
|
|
|
324
329
|
context.restore();
|
|
325
330
|
}
|
|
326
331
|
|
|
327
|
-
/** Draw a tile directly onto the layer canvas
|
|
332
|
+
/** Draw a tile directly onto the layer canvas in world space
|
|
328
333
|
* @param {Vector2} pos
|
|
329
|
-
* @param {Vector2} [size=
|
|
334
|
+
* @param {Vector2} [size=(1,1)]
|
|
330
335
|
* @param {TileInfo} [tileInfo]
|
|
331
|
-
* @param {Color} [color=
|
|
336
|
+
* @param {Color} [color=(1,1,1,1)]
|
|
332
337
|
* @param {Number} [angle=0]
|
|
333
338
|
* @param {Boolean} [mirror=0] */
|
|
334
339
|
drawTile(pos, size=vec2(1), tileInfo, color=new Color, angle, mirror)
|
|
@@ -353,10 +358,10 @@ class TileLayer extends EngineObject
|
|
|
353
358
|
});
|
|
354
359
|
}
|
|
355
360
|
|
|
356
|
-
/** Draw a rectangle directly onto the layer canvas
|
|
361
|
+
/** Draw a rectangle directly onto the layer canvas in world space
|
|
357
362
|
* @param {Vector2} pos
|
|
358
|
-
* @param {Vector2} [size=
|
|
359
|
-
* @param {Color} [color=
|
|
363
|
+
* @param {Vector2} [size=(1,1)]
|
|
364
|
+
* @param {Color} [color=(1,1,1,1)]
|
|
360
365
|
* @param {Number} [angle=0] */
|
|
361
366
|
drawRect(pos, size, color, angle)
|
|
362
367
|
{ this.drawTile(pos, size, undefined, color, angle); }
|
package/src/engineUtilities.js
CHANGED
|
@@ -121,13 +121,13 @@ function smoothStep(percent) { return percent * percent * (3 - 2 * percent); }
|
|
|
121
121
|
function nearestPowerOfTwo(value) { return 2**Math.ceil(Math.log2(value)); }
|
|
122
122
|
|
|
123
123
|
/** Returns true if two axis aligned bounding boxes are overlapping
|
|
124
|
-
* @param {Vector2} pointA
|
|
125
|
-
* @param {Vector2} sizeA
|
|
126
|
-
* @param {Vector2} pointB
|
|
127
|
-
* @param {Vector2} sizeB
|
|
128
|
-
* @return {Boolean}
|
|
124
|
+
* @param {Vector2} pointA - Center of box A
|
|
125
|
+
* @param {Vector2} sizeA - Size of box A
|
|
126
|
+
* @param {Vector2} pointB - Center of box B
|
|
127
|
+
* @param {Vector2} [sizeB=(0,0)] - Size of box B, a point if undefined
|
|
128
|
+
* @return {Boolean} - True if overlapping
|
|
129
129
|
* @memberof Utilities */
|
|
130
|
-
function isOverlapping(pointA, sizeA, pointB, sizeB)
|
|
130
|
+
function isOverlapping(pointA, sizeA, pointB, sizeB=vec2())
|
|
131
131
|
{
|
|
132
132
|
return abs(pointA.x - pointB.x)*2 < sizeA.x + sizeB.x
|
|
133
133
|
&& abs(pointA.y - pointB.y)*2 < sizeA.y + sizeB.y;
|
|
@@ -187,8 +187,8 @@ function randInCircle(radius=1, minRadius=0)
|
|
|
187
187
|
{ return radius > 0 ? randVector(radius * rand(minRadius / radius, 1)**.5) : new Vector2; }
|
|
188
188
|
|
|
189
189
|
/** Returns a random color between the two passed in colors, combine components if linear
|
|
190
|
-
* @param {Color} [colorA=
|
|
191
|
-
* @param {Color} [colorB=
|
|
190
|
+
* @param {Color} [colorA=(1,1,1,1)]
|
|
191
|
+
* @param {Color} [colorB=(0,0,0,1)]
|
|
192
192
|
* @param {Boolean} [linear]
|
|
193
193
|
* @return {Color}
|
|
194
194
|
* @memberof Random */
|
|
@@ -259,7 +259,11 @@ class RandomGenerator
|
|
|
259
259
|
* @memberof Utilities
|
|
260
260
|
*/
|
|
261
261
|
function vec2(x=0, y)
|
|
262
|
-
{
|
|
262
|
+
{
|
|
263
|
+
return typeof x === 'number' ?
|
|
264
|
+
new Vector2(x, y == undefined? x : y) :
|
|
265
|
+
new Vector2(x.x, x.y);
|
|
266
|
+
}
|
|
263
267
|
|
|
264
268
|
/**
|
|
265
269
|
* Check if object is a valid Vector2
|
|
@@ -267,7 +271,7 @@ function vec2(x=0, y)
|
|
|
267
271
|
* @return {Boolean}
|
|
268
272
|
* @memberof Utilities
|
|
269
273
|
*/
|
|
270
|
-
function isVector2(v) { return
|
|
274
|
+
function isVector2(v) { return v instanceof Vector2; }
|
|
271
275
|
|
|
272
276
|
/**
|
|
273
277
|
* 2D Vector object with vector math library
|
|
@@ -298,27 +302,47 @@ class Vector2
|
|
|
298
302
|
/** Returns a copy of this vector plus the vector passed in
|
|
299
303
|
* @param {Vector2} v - other vector
|
|
300
304
|
* @return {Vector2} */
|
|
301
|
-
add(v)
|
|
305
|
+
add(v)
|
|
306
|
+
{
|
|
307
|
+
ASSERT(isVector2(v));
|
|
308
|
+
return new Vector2(this.x + v.x, this.y + v.y);
|
|
309
|
+
}
|
|
302
310
|
|
|
303
311
|
/** Returns a copy of this vector minus the vector passed in
|
|
304
312
|
* @param {Vector2} v - other vector
|
|
305
313
|
* @return {Vector2} */
|
|
306
|
-
subtract(v)
|
|
314
|
+
subtract(v)
|
|
315
|
+
{
|
|
316
|
+
ASSERT(isVector2(v));
|
|
317
|
+
return new Vector2(this.x - v.x, this.y - v.y);
|
|
318
|
+
}
|
|
307
319
|
|
|
308
320
|
/** Returns a copy of this vector times the vector passed in
|
|
309
321
|
* @param {Vector2} v - other vector
|
|
310
322
|
* @return {Vector2} */
|
|
311
|
-
multiply(v)
|
|
323
|
+
multiply(v)
|
|
324
|
+
{
|
|
325
|
+
ASSERT(isVector2(v));
|
|
326
|
+
return new Vector2(this.x * v.x, this.y * v.y);
|
|
327
|
+
}
|
|
312
328
|
|
|
313
329
|
/** Returns a copy of this vector divided by the vector passed in
|
|
314
330
|
* @param {Vector2} v - other vector
|
|
315
331
|
* @return {Vector2} */
|
|
316
|
-
divide(v)
|
|
332
|
+
divide(v)
|
|
333
|
+
{
|
|
334
|
+
ASSERT(isVector2(v));
|
|
335
|
+
return new Vector2(this.x / v.x, this.y / v.y);
|
|
336
|
+
}
|
|
317
337
|
|
|
318
338
|
/** Returns a copy of this vector scaled by the vector passed in
|
|
319
339
|
* @param {Number} s - scale
|
|
320
340
|
* @return {Vector2} */
|
|
321
|
-
scale(s)
|
|
341
|
+
scale(s)
|
|
342
|
+
{
|
|
343
|
+
ASSERT(!isVector2(s));
|
|
344
|
+
return new Vector2(this.x * s, this.y * s);
|
|
345
|
+
}
|
|
322
346
|
|
|
323
347
|
/** Returns the length of this vector
|
|
324
348
|
* @return {Number} */
|
|
@@ -331,32 +355,56 @@ class Vector2
|
|
|
331
355
|
/** Returns the distance from this vector to vector passed in
|
|
332
356
|
* @param {Vector2} v - other vector
|
|
333
357
|
* @return {Number} */
|
|
334
|
-
distance(v)
|
|
358
|
+
distance(v)
|
|
359
|
+
{
|
|
360
|
+
ASSERT(isVector2(v));
|
|
361
|
+
return this.distanceSquared(v)**.5;
|
|
362
|
+
}
|
|
335
363
|
|
|
336
364
|
/** Returns the distance squared from this vector to vector passed in
|
|
337
365
|
* @param {Vector2} v - other vector
|
|
338
366
|
* @return {Number} */
|
|
339
|
-
distanceSquared(v)
|
|
367
|
+
distanceSquared(v)
|
|
368
|
+
{
|
|
369
|
+
ASSERT(isVector2(v));
|
|
370
|
+
return (this.x - v.x)**2 + (this.y - v.y)**2;
|
|
371
|
+
}
|
|
340
372
|
|
|
341
373
|
/** Returns a new vector in same direction as this one with the length passed in
|
|
342
374
|
* @param {Number} [length]
|
|
343
375
|
* @return {Vector2} */
|
|
344
|
-
normalize(length=1)
|
|
376
|
+
normalize(length=1)
|
|
377
|
+
{
|
|
378
|
+
const l = this.length();
|
|
379
|
+
return l ? this.scale(length/l) : new Vector2(0, length);
|
|
380
|
+
}
|
|
345
381
|
|
|
346
382
|
/** Returns a new vector clamped to length passed in
|
|
347
383
|
* @param {Number} [length]
|
|
348
384
|
* @return {Vector2} */
|
|
349
|
-
clampLength(length=1)
|
|
385
|
+
clampLength(length=1)
|
|
386
|
+
{
|
|
387
|
+
const l = this.length();
|
|
388
|
+
return l > length ? this.scale(length/l) : this;
|
|
389
|
+
}
|
|
350
390
|
|
|
351
391
|
/** Returns the dot product of this and the vector passed in
|
|
352
392
|
* @param {Vector2} v - other vector
|
|
353
393
|
* @return {Number} */
|
|
354
|
-
dot(v)
|
|
394
|
+
dot(v)
|
|
395
|
+
{
|
|
396
|
+
ASSERT(isVector2(v));
|
|
397
|
+
return this.x*v.x + this.y*v.y;
|
|
398
|
+
}
|
|
355
399
|
|
|
356
400
|
/** Returns the cross product of this and the vector passed in
|
|
357
401
|
* @param {Vector2} v - other vector
|
|
358
402
|
* @return {Number} */
|
|
359
|
-
cross(v)
|
|
403
|
+
cross(v)
|
|
404
|
+
{
|
|
405
|
+
ASSERT(isVector2(v));
|
|
406
|
+
return this.x*v.y - this.y*v.x;
|
|
407
|
+
}
|
|
360
408
|
|
|
361
409
|
/** Returns the angle of this vector, up is angle 0
|
|
362
410
|
* @return {Number} */
|
|
@@ -367,7 +415,11 @@ class Vector2
|
|
|
367
415
|
* @param {Number} [length]
|
|
368
416
|
* @return {Vector2} */
|
|
369
417
|
setAngle(angle=0, length=1)
|
|
370
|
-
{
|
|
418
|
+
{
|
|
419
|
+
this.x = length*Math.sin(angle);
|
|
420
|
+
this.y = length*Math.cos(angle);
|
|
421
|
+
return this;
|
|
422
|
+
}
|
|
371
423
|
|
|
372
424
|
/** Returns copy of this vector rotated by the angle passed in
|
|
373
425
|
* @param {Number} angle
|
|
@@ -378,9 +430,20 @@ class Vector2
|
|
|
378
430
|
return new Vector2(this.x*c - this.y*s, this.x*s + this.y*c);
|
|
379
431
|
}
|
|
380
432
|
|
|
433
|
+
/** Set the integer direction of this vector, corrosponding to multiples of 90 degree rotation (0-3)
|
|
434
|
+
* @param {Number} [direction]
|
|
435
|
+
* @param {Number} [length] */
|
|
436
|
+
setDirection(direction, length=1)
|
|
437
|
+
{
|
|
438
|
+
ASSERT(direction==0 || direction==1 || direction==2 || direction==3);
|
|
439
|
+
return vec2(direction%2 ? direction-1 ? -length : length : 0,
|
|
440
|
+
direction%2 ? 0 : direction ? -length : length);
|
|
441
|
+
}
|
|
442
|
+
|
|
381
443
|
/** Returns the integer direction of this vector, corrosponding to multiples of 90 degree rotation (0-3)
|
|
382
444
|
* @return {Number} */
|
|
383
|
-
direction()
|
|
445
|
+
direction()
|
|
446
|
+
{ return abs(this.x) > abs(this.y) ? this.x < 0 ? 3 : 1 : this.y < 0 ? 2 : 0; }
|
|
384
447
|
|
|
385
448
|
/** Returns a copy of this vector that has been inverted
|
|
386
449
|
* @return {Vector2} */
|
|
@@ -399,24 +462,34 @@ class Vector2
|
|
|
399
462
|
* @param {Number} percent
|
|
400
463
|
* @return {Vector2} */
|
|
401
464
|
lerp(v, percent)
|
|
402
|
-
{
|
|
465
|
+
{
|
|
466
|
+
ASSERT(isVector2(v));
|
|
467
|
+
return this.add(v.subtract(this).scale(clamp(percent)));
|
|
468
|
+
}
|
|
403
469
|
|
|
404
470
|
/** Returns true if this vector is within the bounds of an array size passed in
|
|
405
471
|
* @param {Vector2} arraySize
|
|
406
472
|
* @return {Boolean} */
|
|
407
|
-
arrayCheck(arraySize)
|
|
473
|
+
arrayCheck(arraySize)
|
|
474
|
+
{
|
|
475
|
+
ASSERT(isVector2(arraySize));
|
|
476
|
+
return this.x >= 0 && this.y >= 0 && this.x < arraySize.x && this.y < arraySize.y;
|
|
477
|
+
}
|
|
408
478
|
|
|
409
479
|
/** Returns this vector expressed as a string
|
|
410
480
|
* @param {Number} digits - precision to display
|
|
411
481
|
* @return {String} */
|
|
412
482
|
toString(digits=3)
|
|
413
|
-
{
|
|
483
|
+
{
|
|
484
|
+
if (debug)
|
|
485
|
+
return `(${(this.x<0?'':' ') + this.x.toFixed(digits)},${(this.y<0?'':' ') + this.y.toFixed(digits)} )`;
|
|
486
|
+
}
|
|
414
487
|
}
|
|
415
488
|
|
|
416
489
|
///////////////////////////////////////////////////////////////////////////////
|
|
417
490
|
|
|
418
491
|
/**
|
|
419
|
-
* Create a color object with RGBA values
|
|
492
|
+
* Create a color object with RGBA values, white by default
|
|
420
493
|
* @param {Number} [r=1] - red
|
|
421
494
|
* @param {Number} [g=1] - green
|
|
422
495
|
* @param {Number} [b=1] - blue
|
|
@@ -427,7 +500,7 @@ class Vector2
|
|
|
427
500
|
function rgb(r, g, b, a) { return new Color(r, g, b, a); }
|
|
428
501
|
|
|
429
502
|
/**
|
|
430
|
-
* Create a color object with HSLA values
|
|
503
|
+
* Create a color object with HSLA values, white by default
|
|
431
504
|
* @param {Number} [h=0] - hue
|
|
432
505
|
* @param {Number} [s=0] - saturation
|
|
433
506
|
* @param {Number} [l=1] - lightness
|
|
@@ -437,14 +510,22 @@ function rgb(r, g, b, a) { return new Color(r, g, b, a); }
|
|
|
437
510
|
*/
|
|
438
511
|
function hsl(h, s, l, a) { return new Color().setHSLA(h, s, l, a); }
|
|
439
512
|
|
|
513
|
+
/**
|
|
514
|
+
* Check if object is a valid Color
|
|
515
|
+
* @param {any} c
|
|
516
|
+
* @return {Boolean}
|
|
517
|
+
* @memberof Utilities
|
|
518
|
+
*/
|
|
519
|
+
function isColor(c) { return c instanceof Color; }
|
|
520
|
+
|
|
440
521
|
/**
|
|
441
522
|
* Color object (red, green, blue, alpha) with some helpful functions
|
|
442
523
|
* @example
|
|
443
524
|
* let a = new Color; // white
|
|
444
525
|
* let b = new Color(1, 0, 0); // red
|
|
445
526
|
* let c = new Color(0, 0, 0, 0); // transparent black
|
|
446
|
-
* let d =
|
|
447
|
-
* let e =
|
|
527
|
+
* let d = rgb(0, 0, 1); // blue using rgb color
|
|
528
|
+
* let e = hsl(.3, 1, .5); // green using hsl color
|
|
448
529
|
*/
|
|
449
530
|
class Color
|
|
450
531
|
{
|
|
@@ -472,22 +553,38 @@ class Color
|
|
|
472
553
|
/** Returns a copy of this color plus the color passed in
|
|
473
554
|
* @param {Color} c - other color
|
|
474
555
|
* @return {Color} */
|
|
475
|
-
add(c)
|
|
556
|
+
add(c)
|
|
557
|
+
{
|
|
558
|
+
ASSERT(isColor(c));
|
|
559
|
+
return new Color(this.r+c.r, this.g+c.g, this.b+c.b, this.a+c.a);
|
|
560
|
+
}
|
|
476
561
|
|
|
477
562
|
/** Returns a copy of this color minus the color passed in
|
|
478
563
|
* @param {Color} c - other color
|
|
479
564
|
* @return {Color} */
|
|
480
|
-
subtract(c)
|
|
565
|
+
subtract(c)
|
|
566
|
+
{
|
|
567
|
+
ASSERT(isColor(c));
|
|
568
|
+
return new Color(this.r-c.r, this.g-c.g, this.b-c.b, this.a-c.a);
|
|
569
|
+
}
|
|
481
570
|
|
|
482
571
|
/** Returns a copy of this color times the color passed in
|
|
483
572
|
* @param {Color} c - other color
|
|
484
573
|
* @return {Color} */
|
|
485
|
-
multiply(c)
|
|
574
|
+
multiply(c)
|
|
575
|
+
{
|
|
576
|
+
ASSERT(isColor(c));
|
|
577
|
+
return new Color(this.r*c.r, this.g*c.g, this.b*c.b, this.a*c.a);
|
|
578
|
+
}
|
|
486
579
|
|
|
487
580
|
/** Returns a copy of this color divided by the color passed in
|
|
488
581
|
* @param {Color} c - other color
|
|
489
582
|
* @return {Color} */
|
|
490
|
-
divide(c)
|
|
583
|
+
divide(c)
|
|
584
|
+
{
|
|
585
|
+
ASSERT(isColor(c));
|
|
586
|
+
return new Color(this.r/c.r, this.g/c.g, this.b/c.b, this.a/c.a);
|
|
587
|
+
}
|
|
491
588
|
|
|
492
589
|
/** Returns a copy of this color scaled by the value passed in, alpha can be scaled separately
|
|
493
590
|
* @param {Number} scale
|
|
@@ -504,7 +601,11 @@ class Color
|
|
|
504
601
|
* @param {Color} c - other color
|
|
505
602
|
* @param {Number} percent
|
|
506
603
|
* @return {Color} */
|
|
507
|
-
lerp(c, percent)
|
|
604
|
+
lerp(c, percent)
|
|
605
|
+
{
|
|
606
|
+
ASSERT(isColor(c));
|
|
607
|
+
return this.add(c.subtract(this).scale(clamp(percent)));
|
|
608
|
+
}
|
|
508
609
|
|
|
509
610
|
/** Sets this color given a hue, saturation, lightness, and alpha
|
|
510
611
|
* @param {Number} [h] - hue
|
package/src/engineWebGL.js
CHANGED
|
@@ -248,8 +248,10 @@ function glCopyToContext(context, forceDraw=false)
|
|
|
248
248
|
* @memberof WebGL */
|
|
249
249
|
function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba, rgbaAdditive=0)
|
|
250
250
|
{
|
|
251
|
+
ASSERT(typeof rgba == 'number' && typeof rgbaAdditive == 'number', 'invalid color');
|
|
252
|
+
|
|
251
253
|
// flush if there is not enough room or if different blend mode
|
|
252
|
-
if (glInstanceCount >= gl_MAX_INSTANCES
|
|
254
|
+
if (glInstanceCount >= gl_MAX_INSTANCES || glBatchAdditive != glAdditive)
|
|
253
255
|
glFlush();
|
|
254
256
|
|
|
255
257
|
let offset = glInstanceCount * gl_INDICIES_PER_INSTANCE;
|
|
@@ -276,7 +278,7 @@ let glPostShader, glPostArrayBuffer, glPostTexture, glPostIncludeOverlay;
|
|
|
276
278
|
* @param {String} shaderCode
|
|
277
279
|
* @param {Boolean} includeOverlay
|
|
278
280
|
* @memberof WebGL */
|
|
279
|
-
function glInitPostProcess(shaderCode, includeOverlay)
|
|
281
|
+
function glInitPostProcess(shaderCode, includeOverlay=false)
|
|
280
282
|
{
|
|
281
283
|
ASSERT(!glPostShader, 'can only have 1 post effects shader');
|
|
282
284
|
|
|
@@ -312,6 +314,8 @@ function glInitPostProcess(shaderCode, includeOverlay)
|
|
|
312
314
|
|
|
313
315
|
// hide the original 2d canvas
|
|
314
316
|
mainCanvas.style.visibility = 'hidden';
|
|
317
|
+
if (glPostIncludeOverlay)
|
|
318
|
+
overlayCanvas.style.visibility = 'hidden';
|
|
315
319
|
}
|
|
316
320
|
|
|
317
321
|
// Render the post processing shader, called automatically by the engine
|
|
@@ -332,14 +336,8 @@ function glRenderPostProcess()
|
|
|
332
336
|
glContext.viewport(0, 0, glCanvas.width = mainCanvas.width, glCanvas.height = mainCanvas.height);
|
|
333
337
|
}
|
|
334
338
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
// copy overlay canvas so it will be included in post processing
|
|
338
|
-
mainContext.drawImage(overlayCanvas, 0, 0);
|
|
339
|
-
|
|
340
|
-
// clear overlay canvas
|
|
341
|
-
overlayCanvas.width = mainCanvas.width;
|
|
342
|
-
}
|
|
339
|
+
// copy overlay canvas so it will be included in post processing
|
|
340
|
+
glPostIncludeOverlay && mainContext.drawImage(overlayCanvas, 0, 0);
|
|
343
341
|
|
|
344
342
|
// setup shader program to draw one triangle
|
|
345
343
|
glContext.useProgram(glPostShader);
|