littlejsengine 1.11.17 → 1.12.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/box2d.wasm.js +630 -0
- package/dist/box2d.wasm.wasm +0 -0
- package/dist/littlejs.d.ts +158 -81
- package/dist/littlejs.esm.js +882 -793
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +3048 -175
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +3047 -172
- package/examples/box2d/game.js +82 -56
- package/examples/box2d/gameObjects.js +114 -107
- package/examples/box2d/index.html +2 -7
- package/examples/box2d/scenes.js +72 -78
- package/examples/box2d/tiles.png +0 -0
- package/examples/breakout/game.js +63 -28
- package/examples/breakout/gameObjects.js +45 -47
- package/examples/breakout/index.html +1 -5
- package/examples/breakoutTutorial/game.js +36 -29
- package/examples/breakoutTutorial/index.html +1 -3
- package/examples/empty/game.js +5 -2
- package/examples/empty/index.html +1 -3
- package/examples/htmlMenu/game.js +24 -15
- package/examples/htmlMenu/index.html +5 -7
- package/examples/index.html +24 -17
- package/examples/module/game.js +32 -34
- package/examples/module/index.html +1 -1
- package/examples/particles/index.html +27 -22
- package/examples/platformer/game.js +62 -45
- package/examples/platformer/gameCharacter.js +42 -34
- package/examples/platformer/gameEffects.js +82 -75
- package/examples/platformer/gameLevel.js +67 -38
- package/examples/platformer/{gameLevelData.js → gameLevelData.json} +1 -11
- package/examples/platformer/gameObjects.js +70 -64
- package/examples/platformer/gamePlayer.js +12 -7
- package/examples/platformer/index.html +1 -9
- package/examples/puzzle/game.js +59 -40
- package/examples/puzzle/index.html +1 -3
- package/examples/shorts/base.html +3 -2
- package/examples/shorts/box2d.js +46 -0
- package/examples/shorts/box2dCar.js +49 -0
- package/examples/shorts/particles.js +1 -1
- package/examples/shorts/platformer.js +1 -1
- package/examples/shorts/postProcess.js +45 -0
- package/examples/shorts/tileLayer.js +5 -6
- package/examples/shorts/tiles.png +0 -0
- package/examples/shorts/uiSystem.js +39 -0
- package/examples/starter/game.js +9 -10
- package/examples/starter/index.html +13 -13
- package/examples/stress/index.html +44 -44
- package/examples/typescript/build.js +17 -18
- package/examples/typescript/game.js +32 -34
- package/examples/typescript/game.ts +32 -34
- package/examples/typescript/index.html +1 -1
- package/examples/uiSystem/game.js +34 -31
- package/examples/uiSystem/index.html +1 -5
- package/package.json +1 -1
- package/plugins/box2d.js +28 -30
- package/plugins/pluginExport.js +2 -3
- package/plugins/uiSystem.js +9 -3
- package/reference.md +29 -27
- package/src/engine.js +10 -11
- package/src/engineAudio.js +24 -15
- package/src/engineBuild.js +25 -8
- package/src/engineDebug.js +1 -3
- package/src/engineExport.js +3 -6
- package/src/engineInput.js +6 -4
- package/src/engineObject.js +18 -14
- package/src/engineSettings.js +6 -6
- package/src/engineTileLayer.js +179 -96
- package/src/engineUtilities.js +16 -0
- package/src/engineWebGL.js +13 -1
- package/examples/typescript/build/dist/littlejs.esm.js +0 -4834
- package/examples/typescript/build/examples/typescript/build.js +0 -24
- package/examples/typescript/build/examples/typescript/game.js +0 -102
package/src/engineTileLayer.js
CHANGED
|
@@ -2,75 +2,47 @@
|
|
|
2
2
|
* LittleJS Tile Layer System
|
|
3
3
|
* - Caches arrays of tiles to off screen canvas for fast rendering
|
|
4
4
|
* - Unlimited numbers of layers, allocates canvases as needed
|
|
5
|
-
* - Interfaces with EngineObject for collision
|
|
6
|
-
* - Collision layer is separate from visible layers
|
|
7
|
-
* - It is recommended to have a visible layer that matches the collision
|
|
8
5
|
* - Tile layers can be drawn to using their context with canvas2d
|
|
9
6
|
* - Drawn directly to the main canvas without using WebGL
|
|
7
|
+
* - Tile layers can also have collision with EngineObjects
|
|
10
8
|
* @namespace TileCollision
|
|
11
9
|
*/
|
|
12
10
|
|
|
13
11
|
'use strict';
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
* @memberof TileCollision */
|
|
18
|
-
let tileCollision = [];
|
|
19
|
-
|
|
20
|
-
/** Size of the tile collision layer 2d grid
|
|
21
|
-
* @type {Vector2}
|
|
22
|
-
* @memberof TileCollision */
|
|
23
|
-
let tileCollisionSize = vec2();
|
|
13
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
14
|
+
// Tile Layer System
|
|
24
15
|
|
|
25
|
-
/**
|
|
26
|
-
* @
|
|
16
|
+
/** Keep track of all tile layers with collision
|
|
17
|
+
* @type {Array<TileCollisionLayer>}
|
|
27
18
|
* @memberof TileCollision */
|
|
28
|
-
|
|
29
|
-
{
|
|
30
|
-
tileCollisionSize = size;
|
|
31
|
-
tileCollision = [];
|
|
32
|
-
for (let i=tileCollision.length = tileCollisionSize.area(); i--;)
|
|
33
|
-
tileCollision[i] = 0;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** Set tile collision data for a given cell in the grid
|
|
37
|
-
* @param {Vector2} pos
|
|
38
|
-
* @param {number} [data]
|
|
39
|
-
* @memberof TileCollision */
|
|
40
|
-
function setTileCollisionData(pos, data=0)
|
|
41
|
-
{
|
|
42
|
-
pos.arrayCheck(tileCollisionSize) && (tileCollision[(pos.y|0)*tileCollisionSize.x+pos.x|0] = data);
|
|
43
|
-
}
|
|
19
|
+
let tileCollisionLayers = [];
|
|
44
20
|
|
|
45
21
|
/** Get tile collision data for a given cell in the grid
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
22
|
+
* @param {Vector2} pos
|
|
23
|
+
* @return {number}
|
|
24
|
+
* @memberof TileCollision */
|
|
49
25
|
function getTileCollisionData(pos)
|
|
50
26
|
{
|
|
51
|
-
|
|
27
|
+
// check all tile collision layers
|
|
28
|
+
for (const layer of tileCollisionLayers)
|
|
29
|
+
if (pos.arrayCheck(layer.size))
|
|
30
|
+
return layer.getCollisionData(pos);
|
|
31
|
+
return 0;
|
|
52
32
|
}
|
|
53
33
|
|
|
54
|
-
/** Check if
|
|
34
|
+
/** Check if a tile layer collides with another object
|
|
55
35
|
* @param {Vector2} pos
|
|
56
36
|
* @param {Vector2} [size=(0,0)]
|
|
57
37
|
* @param {EngineObject} [object]
|
|
58
|
-
* @return {
|
|
38
|
+
* @return {TileCollisionLayer}
|
|
59
39
|
* @memberof TileCollision */
|
|
60
40
|
function tileCollisionTest(pos, size=vec2(), object)
|
|
61
41
|
{
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
for (let y = minY; y < maxY; ++y)
|
|
67
|
-
for (let x = minX; x < maxX; ++x)
|
|
68
|
-
{
|
|
69
|
-
const tileData = tileCollision[y*tileCollisionSize.x+x];
|
|
70
|
-
if (tileData && (!object || object.collideWithTile(tileData, vec2(x, y))))
|
|
71
|
-
return true;
|
|
72
|
-
}
|
|
73
|
-
return false;
|
|
42
|
+
// check all tile collision layers
|
|
43
|
+
for (const layer of tileCollisionLayers)
|
|
44
|
+
if (layer.collisionTest(pos, size, object))
|
|
45
|
+
return layer;
|
|
74
46
|
}
|
|
75
47
|
|
|
76
48
|
/** Return the center of first tile hit, undefined if nothing was hit.
|
|
@@ -82,49 +54,17 @@ function tileCollisionTest(pos, size=vec2(), object)
|
|
|
82
54
|
* @memberof TileCollision */
|
|
83
55
|
function tileCollisionRaycast(posStart, posEnd, object)
|
|
84
56
|
{
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
const delta = posEnd.subtract(posStart);
|
|
88
|
-
const totalLength = delta.length();
|
|
89
|
-
const normalizedDelta = delta.normalize();
|
|
90
|
-
const unit = vec2(abs(1/normalizedDelta.x), abs(1/normalizedDelta.y));
|
|
91
|
-
const flooredPosStart = posStart.floor();
|
|
92
|
-
|
|
93
|
-
// setup iteration variables
|
|
94
|
-
let pos = flooredPosStart;
|
|
95
|
-
let xi = unit.x * (delta.x < 0 ? posStart.x - pos.x : pos.x - posStart.x + 1);
|
|
96
|
-
let yi = unit.y * (delta.y < 0 ? posStart.y - pos.y : pos.y - posStart.y + 1);
|
|
97
|
-
|
|
98
|
-
while (true)
|
|
57
|
+
// check all tile collision layers
|
|
58
|
+
for (const layer of tileCollisionLayers)
|
|
99
59
|
{
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
{
|
|
104
|
-
debugRaycast && debugLine(posStart, posEnd, '#f00', .02);
|
|
105
|
-
debugRaycast && debugPoint(pos.add(vec2(.5)), '#ff0');
|
|
106
|
-
return pos.add(vec2(.5));
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// check if past the end
|
|
110
|
-
if (xi > totalLength && yi > totalLength)
|
|
111
|
-
break;
|
|
112
|
-
|
|
113
|
-
// get coordinates of the next tile to check
|
|
114
|
-
if (xi > yi)
|
|
115
|
-
pos.y += sign(delta.y), yi += unit.y;
|
|
116
|
-
else
|
|
117
|
-
pos.x += sign(delta.x), xi += unit.x;
|
|
60
|
+
const hitPos = layer.collisionRaycast(posStart, posEnd, object)
|
|
61
|
+
if (hitPos)
|
|
62
|
+
return hitPos;
|
|
118
63
|
}
|
|
119
|
-
|
|
120
|
-
debugRaycast && debugLine(posStart, posEnd, '#00f', .02);
|
|
121
64
|
}
|
|
122
65
|
|
|
123
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
124
|
-
// Tile Layer Rendering System
|
|
125
|
-
|
|
126
66
|
/**
|
|
127
|
-
* Tile layer data object stores info about how to
|
|
67
|
+
* Tile layer data object stores info about how to draw a tile
|
|
128
68
|
* @example
|
|
129
69
|
* // create tile layer data with tile index 0 and random orientation and color
|
|
130
70
|
* const tileIndex = 0;
|
|
@@ -156,28 +96,27 @@ class TileLayerData
|
|
|
156
96
|
clear() { this.tile = this.direction = 0; this.mirror = false; this.color = new Color; }
|
|
157
97
|
}
|
|
158
98
|
|
|
99
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
159
100
|
/**
|
|
160
101
|
* Tile Layer - cached rendering system for tile layers
|
|
161
102
|
* - Each Tile layer is rendered to an off screen canvas
|
|
162
103
|
* - To allow dynamic modifications, layers are rendered using canvas 2d
|
|
163
104
|
* - Some devices like mobile phones are limited to 4k texture resolution
|
|
164
|
-
* -
|
|
105
|
+
* - For with 16x16 tiles this limits layers to 256x256 on mobile devices
|
|
165
106
|
* @extends EngineObject
|
|
166
107
|
* @example
|
|
167
|
-
*
|
|
168
|
-
* initTileCollision(vec2(200,100));
|
|
169
|
-
* const tileLayer = new TileLayer();
|
|
108
|
+
* const tileLayer = new TileLayer(vec2(), vec2(200,100));
|
|
170
109
|
*/
|
|
171
110
|
class TileLayer extends EngineObject
|
|
172
111
|
{
|
|
173
112
|
/** Create a tile layer object
|
|
174
|
-
* @param {Vector2} [position=(0,0)]
|
|
175
|
-
* @param {Vector2} [size=
|
|
176
|
-
* @param {TileInfo} [tileInfo]
|
|
177
|
-
* @param {Vector2} [scale=(1,1)]
|
|
178
|
-
* @param {number} [renderOrder]
|
|
113
|
+
* @param {Vector2} [position=(0,0)] - World space position
|
|
114
|
+
* @param {Vector2} [size=(1,1)] - World space size
|
|
115
|
+
* @param {TileInfo} [tileInfo] - Tile info for layer
|
|
116
|
+
* @param {Vector2} [scale=(1,1)] - How much to scale this layer when rendered
|
|
117
|
+
* @param {number} [renderOrder] - Objects are sorted by renderOrder
|
|
179
118
|
*/
|
|
180
|
-
constructor(position, size
|
|
119
|
+
constructor(position, size, tileInfo=tile(), scale=vec2(1), renderOrder=0)
|
|
181
120
|
{
|
|
182
121
|
super(position, size, tileInfo, 0, undefined, renderOrder);
|
|
183
122
|
|
|
@@ -189,6 +128,10 @@ class TileLayer extends EngineObject
|
|
|
189
128
|
this.scale = scale;
|
|
190
129
|
/** @property {boolean} - If true this layer will render to overlay canvas and appear above all objects */
|
|
191
130
|
this.isOverlay = false;
|
|
131
|
+
// set no friction by default, applied friction is max of both objects
|
|
132
|
+
this.friction = 0;
|
|
133
|
+
// set no elasticity by default, applied elasticity is max of both objects
|
|
134
|
+
this.elasticity = 0;
|
|
192
135
|
|
|
193
136
|
// init tile data
|
|
194
137
|
this.data = [];
|
|
@@ -385,4 +328,144 @@ class TileLayer extends EngineObject
|
|
|
385
328
|
* @param {number} [angle=0] */
|
|
386
329
|
drawRect(pos, size, color, angle)
|
|
387
330
|
{ this.drawTile(pos, size, undefined, color, angle); }
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
334
|
+
/**
|
|
335
|
+
* Tile Collision Layer - a tile layer with collision
|
|
336
|
+
* - adds collision data and functions to TileLayer
|
|
337
|
+
* - there can be multiple tile collision layers
|
|
338
|
+
* - tile collison layers should not overlap each other
|
|
339
|
+
* @extends TileLayer
|
|
340
|
+
*/
|
|
341
|
+
class TileCollisionLayer extends TileLayer
|
|
342
|
+
{
|
|
343
|
+
/** Create a tile layer object
|
|
344
|
+
* @param {Vector2} [position=(0,0)] - World space position
|
|
345
|
+
* @param {Vector2} [size=(0,0)] - World space size
|
|
346
|
+
* @param {TileInfo} [tileInfo] - Tile info for layer
|
|
347
|
+
* @param {number} [renderOrder] - Objects are sorted by renderOrder
|
|
348
|
+
*/
|
|
349
|
+
constructor(position, size, tileInfo=tile(), renderOrder=0)
|
|
350
|
+
{
|
|
351
|
+
const scale = vec2(1); // collision layers are not scaled
|
|
352
|
+
super(position, size.floor(), tileInfo, scale, renderOrder);
|
|
353
|
+
|
|
354
|
+
/** @property {Array<number>} - The tile collision grid */
|
|
355
|
+
this.collisionData = [];
|
|
356
|
+
this.initCollision(this.size);
|
|
357
|
+
|
|
358
|
+
// keep track of all collision layers
|
|
359
|
+
tileCollisionLayers.push(this);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/** Destroy this collision layer */
|
|
363
|
+
destroy()
|
|
364
|
+
{
|
|
365
|
+
if (this.destroyed)
|
|
366
|
+
return;
|
|
367
|
+
|
|
368
|
+
// remove from collision layers array and destroy
|
|
369
|
+
const index = tileCollisionLayers.indexOf(this);
|
|
370
|
+
ASSERT(index >= 0, 'tile collision layer not found in array');
|
|
371
|
+
tileCollisionLayers.splice(index, 1);
|
|
372
|
+
super.destroy();
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/** Clear and initialize tile collision to new size
|
|
376
|
+
* @param {Vector2} size - width and height of tile collision 2d grid */
|
|
377
|
+
initCollision(size)
|
|
378
|
+
{
|
|
379
|
+
this.size = size.floor();
|
|
380
|
+
this.collisionData = [];
|
|
381
|
+
this.collisionData.length = size.area();
|
|
382
|
+
this.collisionData.fill(0);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/** Set tile collision data for a given cell in the grid
|
|
386
|
+
* @param {Vector2} pos
|
|
387
|
+
* @param {number} [data] */
|
|
388
|
+
setCollisionData(pos, data=1)
|
|
389
|
+
{
|
|
390
|
+
const i = (pos.y|0)*this.size.x + pos.x|0;
|
|
391
|
+
pos.arrayCheck(this.size) && (this.collisionData[i] = data);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/** Get tile collision data for a given cell in the grid
|
|
395
|
+
* @param {Vector2} pos
|
|
396
|
+
* @return {number} */
|
|
397
|
+
getCollisionData(pos)
|
|
398
|
+
{
|
|
399
|
+
const i = (pos.y|0)*this.size.x + pos.x|0;
|
|
400
|
+
return pos.arrayCheck(this.size) ? this.collisionData[i] : 0;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/** Check if collision with another object should occur
|
|
404
|
+
* @param {Vector2} pos
|
|
405
|
+
* @param {Vector2} [size=(0,0)]
|
|
406
|
+
* @param {EngineObject} [object]
|
|
407
|
+
* @return {boolean} */
|
|
408
|
+
collisionTest(pos, size=vec2(), object)
|
|
409
|
+
{
|
|
410
|
+
const minX = max(pos.x - size.x/2|0, 0);
|
|
411
|
+
const minY = max(pos.y - size.y/2|0, 0);
|
|
412
|
+
const maxX = min(pos.x + size.x/2, this.size.x);
|
|
413
|
+
const maxY = min(pos.y + size.y/2, this.size.y);
|
|
414
|
+
for (let y = minY; y < maxY; ++y)
|
|
415
|
+
for (let x = minX; x < maxX; ++x)
|
|
416
|
+
{
|
|
417
|
+
// check if the object should collide with this tile
|
|
418
|
+
const tileData = this.collisionData[y*this.size.x+x];
|
|
419
|
+
if (tileData && (!object || object.collideWithTile(tileData, vec2(x, y))))
|
|
420
|
+
return true;
|
|
421
|
+
}
|
|
422
|
+
return false;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/** Return the center of first tile hit, undefined if nothing was hit.
|
|
426
|
+
* This does not return the exact intersection, but the center of the tile hit.
|
|
427
|
+
* @param {Vector2} posStart
|
|
428
|
+
* @param {Vector2} posEnd
|
|
429
|
+
* @param {EngineObject} [object]
|
|
430
|
+
* @return {Vector2} */
|
|
431
|
+
collisionRaycast(posStart, posEnd, object)
|
|
432
|
+
{
|
|
433
|
+
// test if a ray collides with tiles from start to end
|
|
434
|
+
// todo: a way to get the exact hit point, it must still be inside the hit tile
|
|
435
|
+
const delta = posEnd.subtract(posStart);
|
|
436
|
+
const totalLength = delta.length();
|
|
437
|
+
const normalizedDelta = delta.normalize();
|
|
438
|
+
const unit = vec2(abs(1/normalizedDelta.x), abs(1/normalizedDelta.y));
|
|
439
|
+
const flooredPosStart = posStart.floor();
|
|
440
|
+
|
|
441
|
+
// setup iteration variables
|
|
442
|
+
let pos = flooredPosStart;
|
|
443
|
+
let xi = unit.x * (delta.x < 0 ? posStart.x - pos.x : pos.x - posStart.x + 1);
|
|
444
|
+
let yi = unit.y * (delta.y < 0 ? posStart.y - pos.y : pos.y - posStart.y + 1);
|
|
445
|
+
|
|
446
|
+
// use line drawing algorithm to test for collisions
|
|
447
|
+
while (true)
|
|
448
|
+
{
|
|
449
|
+
// check for tile collision
|
|
450
|
+
const tileData = this.getCollisionData(pos);
|
|
451
|
+
if (tileData && (!object || object.collideWithTile(tileData, pos)))
|
|
452
|
+
{
|
|
453
|
+
debugRaycast && debugLine(posStart, posEnd, '#f00', .02);
|
|
454
|
+
debugRaycast && debugPoint(pos.add(vec2(.5)), '#ff0');
|
|
455
|
+
return pos.add(vec2(.5));
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// check if past the end
|
|
459
|
+
if (xi > totalLength && yi > totalLength)
|
|
460
|
+
break;
|
|
461
|
+
|
|
462
|
+
// get coordinates of next tile to check
|
|
463
|
+
if (xi > yi)
|
|
464
|
+
pos.y += sign(delta.y), yi += unit.y;
|
|
465
|
+
else
|
|
466
|
+
pos.x += sign(delta.x), xi += unit.x;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
debugRaycast && debugLine(posStart, posEnd, '#00f', .02);
|
|
470
|
+
}
|
|
388
471
|
}
|
package/src/engineUtilities.js
CHANGED
|
@@ -189,6 +189,16 @@ function wave(frequency=1, amplitude=1, t=time)
|
|
|
189
189
|
* @memberof Utilities */
|
|
190
190
|
function formatTime(t) { return (t/60|0) + ':' + (t%60<10?'0':'') + (t%60|0); }
|
|
191
191
|
|
|
192
|
+
/** Fetches a JSON file from a URL and returns the parsed JSON object. Must be used with await!
|
|
193
|
+
* @param {string} url - URL of JSON file
|
|
194
|
+
* @return {Promise<object>}
|
|
195
|
+
* @memberof Utilities */
|
|
196
|
+
async function fetchJSON(url)
|
|
197
|
+
{
|
|
198
|
+
const response = await fetch(url);
|
|
199
|
+
return response.json();
|
|
200
|
+
}
|
|
201
|
+
|
|
192
202
|
///////////////////////////////////////////////////////////////////////////////
|
|
193
203
|
|
|
194
204
|
/** Random global functions
|
|
@@ -284,6 +294,12 @@ class RandomGenerator
|
|
|
284
294
|
/** Randomly returns either -1 or 1 deterministically
|
|
285
295
|
* @return {number} */
|
|
286
296
|
sign() { return this.float() > .5 ? 1 : -1; }
|
|
297
|
+
|
|
298
|
+
/** Returns a seeded random value between the two values passed in with a random sign
|
|
299
|
+
* @param {number} [valueA]
|
|
300
|
+
* @param {number} [valueB]
|
|
301
|
+
* @return {number} */
|
|
302
|
+
floatSign(valueA=1, valueB=0) { return this.float(valueA, valueB) * this.sign(); }
|
|
287
303
|
}
|
|
288
304
|
|
|
289
305
|
///////////////////////////////////////////////////////////////////////////////
|
package/src/engineWebGL.js
CHANGED
|
@@ -210,7 +210,19 @@ function glCreateTexture(image)
|
|
|
210
210
|
const texture = glContext.createTexture();
|
|
211
211
|
glContext.bindTexture(glContext.TEXTURE_2D, texture);
|
|
212
212
|
if (image && image.width)
|
|
213
|
+
{
|
|
213
214
|
glSetTextureData(texture, image);
|
|
215
|
+
|
|
216
|
+
const isPowerOfTwo = (value)=> !(value & (value - 1));
|
|
217
|
+
if (!tilesPixelated && isPowerOfTwo(image.width) && isPowerOfTwo(image.height))
|
|
218
|
+
{
|
|
219
|
+
// use mipmap filtering
|
|
220
|
+
glContext.generateMipmap(glContext.TEXTURE_2D);
|
|
221
|
+
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MIN_FILTER, glContext.LINEAR_MIPMAP_LINEAR);
|
|
222
|
+
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MAG_FILTER, glContext.LINEAR);
|
|
223
|
+
return texture;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
214
226
|
else
|
|
215
227
|
{
|
|
216
228
|
// create a white texture
|
|
@@ -218,7 +230,7 @@ function glCreateTexture(image)
|
|
|
218
230
|
glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, 1, 1, 0, glContext.RGBA, glContext.UNSIGNED_BYTE, whitePixel);
|
|
219
231
|
}
|
|
220
232
|
|
|
221
|
-
//
|
|
233
|
+
// set texture filtering
|
|
222
234
|
const filter = tilesPixelated ? glContext.NEAREST : glContext.LINEAR;
|
|
223
235
|
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MIN_FILTER, filter);
|
|
224
236
|
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MAG_FILTER, filter);
|