littlejsengine 1.16.2 → 1.17.1
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 +200 -166
- package/dist/littlejs.esm.js +1231 -1086
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +888 -735
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +884 -731
- package/examples/box2d/gameObjects.js +1 -1
- package/examples/breakout/game.js +5 -6
- package/examples/electron/index.html +2 -2
- package/examples/electron/tiles.png +0 -0
- package/examples/htmlMenu/tiles.png +0 -0
- package/examples/index.html +1 -1
- package/examples/logo.png +0 -0
- package/examples/module/tiles.png +0 -0
- package/examples/platformer/gameEffects.js +23 -22
- package/examples/platformer/gameLevel.js +24 -25
- package/examples/shorts/base.html +1 -1
- package/examples/shorts/clock.js +3 -3
- package/examples/shorts/fontImage.js +4 -3
- package/examples/shorts/parallax.js +1 -1
- package/examples/shorts/sequencer.js +1 -1
- package/examples/shorts/shapes.js +1 -1
- package/examples/shorts/texture.js +10 -6
- package/examples/shorts/tiles.png +0 -0
- package/examples/shorts/tiltedView.js +2 -0
- package/examples/starter/index.html +2 -2
- package/examples/starter/tiles.png +0 -0
- package/examples/typescript/tiles.png +0 -0
- package/examples/uiSystem/game.js +1 -1
- package/examples/uiSystem/tiles.png +0 -0
- package/package.json +1 -1
- package/plugins/postProcess.js +47 -28
- package/plugins/uiSystem.js +15 -15
- package/reference.md +1 -1
- package/src/engine.js +174 -174
- package/src/engineAudio.js +4 -6
- package/src/engineDebug.js +4 -4
- package/src/engineDraw.js +179 -122
- package/src/engineExport.js +326 -334
- package/src/engineFont.png +0 -0
- package/src/engineInput.js +14 -20
- package/src/engineMath.js +15 -104
- package/src/engineObject.js +26 -25
- package/src/engineParticles.js +2 -2
- package/src/engineTileLayer.js +196 -170
- package/src/engineUtilities.js +100 -4
- package/src/engineWebGL.js +123 -72
package/src/engineDraw.js
CHANGED
|
@@ -77,10 +77,11 @@ let drawCount;
|
|
|
77
77
|
* Create a tile info object using a grid based system
|
|
78
78
|
* - This can take vecs or floats for easier use and conversion
|
|
79
79
|
* - If an index is passed in, the tile size and index will determine the position
|
|
80
|
-
* @param {Vector2|number} [
|
|
80
|
+
* @param {Vector2|number} [index=0] - Index of the tile in 1d or 2d form
|
|
81
81
|
* @param {Vector2|number} [size] - Size of tile in pixels
|
|
82
|
-
* @param {number} [
|
|
82
|
+
* @param {TextureInfo|number} [texture] - Texture index or info to use
|
|
83
83
|
* @param {number} [padding] - How many pixels padding around tiles
|
|
84
|
+
* @param {number} [bleed] - How many pixels smaller to draw tiles
|
|
84
85
|
* @return {TileInfo}
|
|
85
86
|
* @example
|
|
86
87
|
* tile(2) // a tile at index 2 using the default tile size of 16
|
|
@@ -88,36 +89,43 @@ let drawCount;
|
|
|
88
89
|
* tile(1, 16, 3) // a tile at index 1 of size 16 on texture 3
|
|
89
90
|
* tile(vec2(4,8), vec2(30,10)) // a tile at index (4,8) with a size of (30,10)
|
|
90
91
|
* @memberof Draw */
|
|
91
|
-
function tile(
|
|
92
|
+
function tile(index=new Vector2, size=tileDefaultSize, texture=0, padding=tileDefaultPadding, bleed=tileDefaultBleed)
|
|
92
93
|
{
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
ASSERT(isVector2(index) || typeof index === 'number', 'index must be a vec2 or number');
|
|
95
|
+
ASSERT(isVector2(size) || typeof size === 'number', 'size must be a vec2 or number');
|
|
96
|
+
ASSERT(isNumber(texture) || texture instanceof TextureInfo, 'texture must be a number or TextureInfo');
|
|
97
|
+
ASSERT(isNumber(padding), 'padding must be a number');
|
|
98
|
+
|
|
99
|
+
if (headlessMode) return new TileInfo;
|
|
95
100
|
|
|
96
|
-
// if size is a number, make it a vector
|
|
97
101
|
if (typeof size === 'number')
|
|
98
102
|
{
|
|
103
|
+
// if size is a number, make it a vector
|
|
99
104
|
ASSERT(size > 0);
|
|
100
105
|
size = new Vector2(size, size);
|
|
101
106
|
}
|
|
102
107
|
|
|
103
108
|
// create tile info object
|
|
104
|
-
const
|
|
109
|
+
const textureInfo = typeof texture === 'number' ?
|
|
110
|
+
textureInfos[texture] : texture;
|
|
105
111
|
|
|
106
112
|
// get the position of the tile
|
|
107
|
-
const textureInfo = textureInfos[textureIndex];
|
|
108
|
-
ASSERT(!!textureInfo, 'Texture not loaded');
|
|
109
113
|
const sizePaddedX = size.x + padding*2;
|
|
110
114
|
const sizePaddedY = size.y + padding*2;
|
|
111
|
-
|
|
115
|
+
let x, y;
|
|
116
|
+
if (typeof index === 'number')
|
|
112
117
|
{
|
|
113
118
|
const cols = textureInfo.size.x / sizePaddedX |0;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
tileInfo.pos.set(posX*sizePaddedX+padding, posY*sizePaddedY+padding);
|
|
119
|
+
x = index % cols;
|
|
120
|
+
y = index / cols |0;
|
|
117
121
|
}
|
|
118
122
|
else
|
|
119
|
-
|
|
120
|
-
|
|
123
|
+
{
|
|
124
|
+
x = index.x;
|
|
125
|
+
y = index.y;
|
|
126
|
+
}
|
|
127
|
+
const pos = new Vector2(x*sizePaddedX + padding, y*sizePaddedY + padding);
|
|
128
|
+
return new TileInfo(pos, size, textureInfo, padding, bleed);
|
|
121
129
|
}
|
|
122
130
|
|
|
123
131
|
/**
|
|
@@ -127,24 +135,22 @@ function tile(pos=new Vector2, size=tileDefaultSize, textureIndex=0, padding=til
|
|
|
127
135
|
class TileInfo
|
|
128
136
|
{
|
|
129
137
|
/** Create a tile info object
|
|
130
|
-
* @param {Vector2} [pos=(
|
|
138
|
+
* @param {Vector2} [pos=vec2()] - Top left corner of tile in pixels
|
|
131
139
|
* @param {Vector2} [size] - Size of tile in pixels
|
|
132
|
-
* @param {
|
|
133
|
-
* @param {number}
|
|
134
|
-
* @param {number}
|
|
140
|
+
* @param {TextureInfo} [textureInfo] - Texture info to use
|
|
141
|
+
* @param {number} [padding] - How many pixels padding around tiles
|
|
142
|
+
* @param {number} [bleed] - How many pixels smaller to draw tiles
|
|
135
143
|
*/
|
|
136
|
-
constructor(pos=vec2(), size=tileDefaultSize,
|
|
144
|
+
constructor(pos=vec2(), size=tileDefaultSize, textureInfo=textureInfos[0], padding=tileDefaultPadding, bleed=tileDefaultBleed)
|
|
137
145
|
{
|
|
138
146
|
/** @property {Vector2} - Top left corner of tile in pixels */
|
|
139
147
|
this.pos = pos.copy();
|
|
140
148
|
/** @property {Vector2} - Size of tile in pixels */
|
|
141
149
|
this.size = size.copy();
|
|
142
|
-
/** @property {number} - Texture index to use */
|
|
143
|
-
this.textureIndex = textureIndex;
|
|
144
150
|
/** @property {number} - How many pixels padding around tiles */
|
|
145
151
|
this.padding = padding;
|
|
146
152
|
/** @property {TextureInfo} - The texture info for this tile */
|
|
147
|
-
this.textureInfo =
|
|
153
|
+
this.textureInfo = textureInfo;
|
|
148
154
|
/** @property {number} - Shrinks tile by this many pixels to prevent neighbors bleeding */
|
|
149
155
|
this.bleed = bleed;
|
|
150
156
|
}
|
|
@@ -154,7 +160,7 @@ class TileInfo
|
|
|
154
160
|
* @return {TileInfo}
|
|
155
161
|
*/
|
|
156
162
|
offset(offset)
|
|
157
|
-
{ return new TileInfo(this.pos.add(offset), this.size, this.
|
|
163
|
+
{ return new TileInfo(this.pos.add(offset), this.size, this.textureInfo, this.padding, this.bleed); }
|
|
158
164
|
|
|
159
165
|
/** Returns a copy of this tile offset by a number of animation frames
|
|
160
166
|
* @param {number} frame - Offset to apply in animation frames
|
|
@@ -163,23 +169,33 @@ class TileInfo
|
|
|
163
169
|
frame(frame)
|
|
164
170
|
{
|
|
165
171
|
ASSERT(typeof frame === 'number');
|
|
166
|
-
|
|
172
|
+
const w = this.size.x + this.padding*2;
|
|
173
|
+
const x = frame*w;
|
|
174
|
+
ASSERT(x < this.textureInfo.size.x, 'frame extends beyond texture width!');
|
|
175
|
+
return this.offset(new Vector2(x));
|
|
167
176
|
}
|
|
168
177
|
|
|
169
178
|
/**
|
|
170
179
|
* Set this tile to use a full image in a texture info
|
|
171
|
-
* @param {TextureInfo} textureInfo
|
|
180
|
+
* @param {TextureInfo} [textureInfo]
|
|
172
181
|
* @return {TileInfo}
|
|
173
182
|
*/
|
|
174
|
-
setFullImage(textureInfo)
|
|
183
|
+
setFullImage(textureInfo=this.textureInfo)
|
|
175
184
|
{
|
|
185
|
+
this.textureInfo = textureInfo;
|
|
176
186
|
this.pos = new Vector2;
|
|
177
187
|
this.size = textureInfo.size.copy();
|
|
178
|
-
this.textureInfo = textureInfo;
|
|
179
|
-
// do not use padding or bleed
|
|
180
188
|
this.bleed = this.padding = 0;
|
|
181
189
|
return this;
|
|
182
190
|
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Returns a tile info for an index using this tile as refrence
|
|
194
|
+
* @param {Vector2|number} [index=0]
|
|
195
|
+
* @return {TileInfo}
|
|
196
|
+
*/
|
|
197
|
+
tile(index)
|
|
198
|
+
{ return tile(index, this.size, this.textureInfo, this.padding, this.bleed); }
|
|
183
199
|
}
|
|
184
200
|
|
|
185
201
|
/**
|
|
@@ -220,19 +236,19 @@ class TextureInfo
|
|
|
220
236
|
///////////////////////////////////////////////////////////////////////////////
|
|
221
237
|
// Drawing functions
|
|
222
238
|
|
|
223
|
-
/** Draw textured tile centered in world space
|
|
224
|
-
* @param {Vector2} pos
|
|
225
|
-
* @param {Vector2} [size=(1
|
|
226
|
-
* @param {TileInfo} [tileInfo]
|
|
227
|
-
* @param {Color} [color=
|
|
228
|
-
* @param {number} [angle]
|
|
229
|
-
* @param {boolean} [mirror]
|
|
230
|
-
* @param {Color} [additiveColor]
|
|
239
|
+
/** Draw textured tile centered in world space
|
|
240
|
+
* @param {Vector2} pos - Center of the tile in world space
|
|
241
|
+
* @param {Vector2} [size=vec2(1)] - Size of the tile in world space
|
|
242
|
+
* @param {TileInfo} [tileInfo] - Tile info to use, untextured if undefined
|
|
243
|
+
* @param {Color} [color=WHITE] - Color to modulate with
|
|
244
|
+
* @param {number} [angle] - Angle to rotate by
|
|
245
|
+
* @param {boolean} [mirror] - Is image flipped along the Y axis?
|
|
246
|
+
* @param {Color} [additiveColor] - Additive color to be applied if any
|
|
231
247
|
* @param {boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering?
|
|
232
248
|
* @param {boolean} [screenSpace=false] - Are the pos and size are in screen space?
|
|
233
249
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context] - Canvas 2D context to draw to
|
|
234
250
|
* @memberof Draw */
|
|
235
|
-
function drawTile(pos, size=
|
|
251
|
+
function drawTile(pos, size=vec2(1), tileInfo, color=WHITE,
|
|
236
252
|
angle=0, mirror, additiveColor, useWebGL=glEnable, screenSpace, context)
|
|
237
253
|
{
|
|
238
254
|
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
@@ -307,8 +323,8 @@ function drawTile(pos, size=new Vector2(1), tileInfo, color=WHITE,
|
|
|
307
323
|
|
|
308
324
|
/** Draw colored rect centered on pos
|
|
309
325
|
* @param {Vector2} pos
|
|
310
|
-
* @param {Vector2} [size=(1
|
|
311
|
-
* @param {Color} [color=
|
|
326
|
+
* @param {Vector2} [size=vec2(1)]
|
|
327
|
+
* @param {Color} [color=WHITE]
|
|
312
328
|
* @param {number} [angle]
|
|
313
329
|
* @param {boolean} [useWebGL=glEnable]
|
|
314
330
|
* @param {boolean} [screenSpace]
|
|
@@ -321,9 +337,9 @@ function drawRect(pos, size, color, angle, useWebGL, screenSpace, context)
|
|
|
321
337
|
|
|
322
338
|
/** Draw a rect centered on pos with a gradient from top to bottom
|
|
323
339
|
* @param {Vector2} pos
|
|
324
|
-
* @param {Vector2} [size=(1
|
|
325
|
-
* @param {Color} [colorTop=
|
|
326
|
-
* @param {Color} [colorBottom=
|
|
340
|
+
* @param {Vector2} [size=vec2(1)]
|
|
341
|
+
* @param {Color} [colorTop=WHITE]
|
|
342
|
+
* @param {Color} [colorBottom=BLACK]
|
|
327
343
|
* @param {number} [angle]
|
|
328
344
|
* @param {boolean} [useWebGL=glEnable]
|
|
329
345
|
* @param {boolean} [screenSpace]
|
|
@@ -385,9 +401,9 @@ function drawRectGradient(pos, size, colorTop=WHITE, colorBottom=BLACK, angle=0,
|
|
|
385
401
|
/** Draw connected lines between a series of points
|
|
386
402
|
* @param {Array<Vector2>} points
|
|
387
403
|
* @param {number} [width]
|
|
388
|
-
* @param {Color} [color=
|
|
404
|
+
* @param {Color} [color=WHITE]
|
|
389
405
|
* @param {boolean} [wrap] - Should the last point connect to the first?
|
|
390
|
-
* @param {Vector2} [pos=(
|
|
406
|
+
* @param {Vector2} [pos=vec2()] - Offset to apply
|
|
391
407
|
* @param {number} [angle] - Angle to rotate by
|
|
392
408
|
* @param {boolean} [useWebGL=glEnable]
|
|
393
409
|
* @param {boolean} [screenSpace]
|
|
@@ -422,13 +438,9 @@ function drawLineList(points, width=.1, color, wrap=false, pos=vec2(), angle=0,
|
|
|
422
438
|
for (let i=0; i<points.length; ++i)
|
|
423
439
|
{
|
|
424
440
|
const point = points[i];
|
|
425
|
-
|
|
426
|
-
context.lineTo(point.x, point.y);
|
|
427
|
-
else
|
|
428
|
-
context.moveTo(point.x, point.y);
|
|
441
|
+
context.lineTo(point.x, point.y);
|
|
429
442
|
}
|
|
430
|
-
|
|
431
|
-
context.closePath();
|
|
443
|
+
wrap && context.closePath();
|
|
432
444
|
context.stroke();
|
|
433
445
|
}, screenSpace, context);
|
|
434
446
|
}
|
|
@@ -438,8 +450,8 @@ function drawLineList(points, width=.1, color, wrap=false, pos=vec2(), angle=0,
|
|
|
438
450
|
* @param {Vector2} posA
|
|
439
451
|
* @param {Vector2} posB
|
|
440
452
|
* @param {number} [width]
|
|
441
|
-
* @param {Color} [color=
|
|
442
|
-
* @param {Vector2} [pos=(
|
|
453
|
+
* @param {Color} [color=WHITE]
|
|
454
|
+
* @param {Vector2} [pos=vec2()] - Offset to apply
|
|
443
455
|
* @param {number} [angle] - Angle to rotate by
|
|
444
456
|
* @param {boolean} [useWebGL=glEnable]
|
|
445
457
|
* @param {boolean} [screenSpace]
|
|
@@ -458,12 +470,12 @@ function drawLine(posA, posB, width=.1, color, pos=vec2(), angle=0, useWebGL, sc
|
|
|
458
470
|
|
|
459
471
|
/** Draw colored regular polygon using passed in number of sides
|
|
460
472
|
* @param {Vector2} pos
|
|
461
|
-
* @param {Vector2} [size=(1
|
|
473
|
+
* @param {Vector2} [size=vec2(1)]
|
|
462
474
|
* @param {number} [sides]
|
|
463
|
-
* @param {Color} [color=
|
|
475
|
+
* @param {Color} [color=WHITE]
|
|
464
476
|
* @param {number} [angle]
|
|
465
477
|
* @param {number} [lineWidth]
|
|
466
|
-
* @param {Color} [lineColor=
|
|
478
|
+
* @param {Color} [lineColor=BLACK]
|
|
467
479
|
* @param {boolean} [useWebGL=glEnable]
|
|
468
480
|
* @param {boolean} [screenSpace]
|
|
469
481
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
|
|
@@ -486,10 +498,10 @@ function drawRegularPoly(pos, size=vec2(1), sides=3, color=WHITE, lineWidth=0, l
|
|
|
486
498
|
|
|
487
499
|
/** Draw colored polygon using passed in points
|
|
488
500
|
* @param {Array<Vector2>} points - Array of Vector2 points
|
|
489
|
-
* @param {Color} [color=
|
|
501
|
+
* @param {Color} [color=WHITE]
|
|
490
502
|
* @param {number} [lineWidth]
|
|
491
|
-
* @param {Color} [lineColor=
|
|
492
|
-
* @param {Vector2} [pos=(
|
|
503
|
+
* @param {Color} [lineColor=BLACK]
|
|
504
|
+
* @param {Vector2} [pos=vec2()] - Offset to apply
|
|
493
505
|
* @param {number} [angle] - Angle to rotate by
|
|
494
506
|
* @param {boolean} [useWebGL=glEnable]
|
|
495
507
|
* @param {boolean} [screenSpace]
|
|
@@ -536,11 +548,11 @@ function drawPoly(points, color=WHITE, lineWidth=0, lineColor=BLACK, pos=vec2(),
|
|
|
536
548
|
|
|
537
549
|
/** Draw colored ellipse using passed in point
|
|
538
550
|
* @param {Vector2} pos
|
|
539
|
-
* @param {Vector2} [size=(1
|
|
540
|
-
* @param {Color} [color=
|
|
551
|
+
* @param {Vector2} [size=vec2(1)] - Width and height diameter
|
|
552
|
+
* @param {Color} [color=WHITE]
|
|
541
553
|
* @param {number} [angle]
|
|
542
554
|
* @param {number} [lineWidth]
|
|
543
|
-
* @param {Color} [lineColor=
|
|
555
|
+
* @param {Color} [lineColor=BLACK]
|
|
544
556
|
* @param {boolean} [useWebGL=glEnable]
|
|
545
557
|
* @param {boolean} [screenSpace]
|
|
546
558
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
|
|
@@ -582,9 +594,9 @@ function drawEllipse(pos, size=vec2(1), color=WHITE, angle=0, lineWidth=0, lineC
|
|
|
582
594
|
/** Draw colored circle using passed in point
|
|
583
595
|
* @param {Vector2} pos
|
|
584
596
|
* @param {number} [size=1] - Diameter
|
|
585
|
-
* @param {Color} [color=
|
|
597
|
+
* @param {Color} [color=WHITE]
|
|
586
598
|
* @param {number} [lineWidth=0]
|
|
587
|
-
* @param {Color} [lineColor=
|
|
599
|
+
* @param {Color} [lineColor=BLACK]
|
|
588
600
|
* @param {boolean} [useWebGL=glEnable]
|
|
589
601
|
* @param {boolean} [screenSpace]
|
|
590
602
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
|
|
@@ -639,9 +651,9 @@ function drawCanvas2D(pos, size, angle=0, mirror=false, drawFunction, screenSpac
|
|
|
639
651
|
* @param {string|number} text
|
|
640
652
|
* @param {Vector2} pos
|
|
641
653
|
* @param {number} [size]
|
|
642
|
-
* @param {Color} [color=
|
|
654
|
+
* @param {Color} [color=WHITE]
|
|
643
655
|
* @param {number} [lineWidth]
|
|
644
|
-
* @param {Color} [lineColor=
|
|
656
|
+
* @param {Color} [lineColor=BLACK]
|
|
645
657
|
* @param {CanvasTextAlign} [textAlign='center']
|
|
646
658
|
* @param {string} [font=fontDefault]
|
|
647
659
|
* @param {string} [fontStyle]
|
|
@@ -665,10 +677,10 @@ function drawText(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, f
|
|
|
665
677
|
* Automatically splits new lines into rows
|
|
666
678
|
* @param {string|number} text
|
|
667
679
|
* @param {Vector2} pos
|
|
668
|
-
* @param {number}
|
|
669
|
-
* @param {Color} [color=
|
|
680
|
+
* @param {number} size
|
|
681
|
+
* @param {Color} [color=WHITE]
|
|
670
682
|
* @param {number} [lineWidth]
|
|
671
|
-
* @param {Color} [lineColor=
|
|
683
|
+
* @param {Color} [lineColor=BLACK]
|
|
672
684
|
* @param {CanvasTextAlign} [textAlign]
|
|
673
685
|
* @param {string} [font=fontDefault]
|
|
674
686
|
* @param {string} [fontStyle]
|
|
@@ -676,7 +688,7 @@ function drawText(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, f
|
|
|
676
688
|
* @param {number} [angle]
|
|
677
689
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=drawContext]
|
|
678
690
|
* @memberof Draw */
|
|
679
|
-
function drawTextScreen(text, pos, size
|
|
691
|
+
function drawTextScreen(text, pos, size, color=WHITE, lineWidth=0, lineColor=BLACK, textAlign='center', font=fontDefault, fontStyle='', maxWidth, angle=0, context=drawContext)
|
|
680
692
|
{
|
|
681
693
|
ASSERT(isString(text), 'text must be a string');
|
|
682
694
|
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
@@ -800,7 +812,7 @@ function worldToScreenDelta(worldDelta)
|
|
|
800
812
|
|
|
801
813
|
/** Convert screen space transform to world space
|
|
802
814
|
* @param {Vector2} screenPos
|
|
803
|
-
* @param {Vector2} screenSize
|
|
815
|
+
* @param {Vector2} screenSize
|
|
804
816
|
* @param {number} [screenAngle]
|
|
805
817
|
* @return {[Vector2, Vector2, number]} - [pos, size, angle]
|
|
806
818
|
* @memberof Draw */
|
|
@@ -861,10 +873,9 @@ function isOnScreen(pos, size=0)
|
|
|
861
873
|
* @param {boolean} [additive]
|
|
862
874
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
|
|
863
875
|
* @memberof Draw */
|
|
864
|
-
function setBlendMode(additive=false, context)
|
|
876
|
+
function setBlendMode(additive=false, context=drawContext)
|
|
865
877
|
{
|
|
866
878
|
glAdditive = additive;
|
|
867
|
-
context ||= drawContext;
|
|
868
879
|
context.globalCompositeOperation = additive ? 'lighter' : 'source-over';
|
|
869
880
|
}
|
|
870
881
|
|
|
@@ -879,7 +890,6 @@ function combineCanvases()
|
|
|
879
890
|
workContext.fillRect(0,0,w,h); // remove background alpha
|
|
880
891
|
glCopyToContext(workContext);
|
|
881
892
|
workContext.drawImage(mainCanvas, 0, 0);
|
|
882
|
-
mainCanvas.width |= 0;
|
|
883
893
|
mainContext.drawImage(workCanvas, 0, 0);
|
|
884
894
|
}
|
|
885
895
|
|
|
@@ -984,17 +994,22 @@ function setCursor(cursorStyle = 'auto')
|
|
|
984
994
|
|
|
985
995
|
///////////////////////////////////////////////////////////////////////////////
|
|
986
996
|
|
|
997
|
+
/** Engine font image, 8x8 font provided by the engine
|
|
998
|
+
* @type {FontImage}
|
|
999
|
+
* @memberof Draw */
|
|
987
1000
|
let engineFontImage;
|
|
988
1001
|
|
|
989
1002
|
/**
|
|
990
|
-
* Font Image Object - Draw text
|
|
1003
|
+
* Font Image Object - Draw text by using tiles in an image
|
|
991
1004
|
* - 96 characters (from space to tilde) are stored in an image
|
|
992
|
-
* -
|
|
993
|
-
* -
|
|
1005
|
+
* - A 8x8 default engine font is supplied for general use
|
|
1006
|
+
* - This system is WebGL enabled for fast text rendering
|
|
1007
|
+
* - Fonts can also be colored and scaled along each axis
|
|
1008
|
+
*
|
|
994
1009
|
* @memberof Draw
|
|
995
1010
|
* @example
|
|
996
1011
|
* // use built in font
|
|
997
|
-
* const font =
|
|
1012
|
+
* const font = engineFontImage;
|
|
998
1013
|
*
|
|
999
1014
|
* // draw text
|
|
1000
1015
|
* font.drawTextScreen('LittleJS\nHello World!', vec2(200, 50));
|
|
@@ -1002,68 +1017,110 @@ let engineFontImage;
|
|
|
1002
1017
|
class FontImage
|
|
1003
1018
|
{
|
|
1004
1019
|
/** Create an image font
|
|
1005
|
-
* @param {
|
|
1006
|
-
* @param {Vector2} [tileSize=(8,8)] - Size of the font source tiles
|
|
1007
|
-
* @param {Vector2} [paddingSize=(0,1)] - How much space between characters
|
|
1020
|
+
* @param {TileInfo} tileInfo - Tile info of first characeter in font
|
|
1008
1021
|
*/
|
|
1009
|
-
constructor(
|
|
1022
|
+
constructor(tileInfo)
|
|
1010
1023
|
{
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
{
|
|
1014
|
-
|
|
1015
|
-
engineFontImage.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAAYAQAAAAA9+x6JAAAAAnRSTlMAAHaTzTgAAAGiSURBVHjaZZABhxxBEIUf6ECLBdFY+Q0PMNgf0yCgsSAGZcT9sgIPtBWwIA5wgAPEoHUyJeeSlW+gjK+fegWwtROWpVQEyWh2npdpBmTUFVhb29RINgLIukoXr5LIAvYQ5ve+1FqWEMqNKTX3FAJHyQDRZvmKWubAACcv5z5Gtg2oyCWE+Yk/8JZQX1jTTCpKAFGIgza+dJCNBF2UskRlsgwitHbSV0QLgt9sTPtsRlvJjEr8C/FARWA2bJ/TtJ7lko34dNDn6usJUMzuErP89UUBJbWeozrwLLncXczd508deAjLWipLO4Q5XGPcJvPu92cNDaN0P5G1FL0nSOzddZOrJ6rNhbXGmeDvO3TF7DeJWl4bvaYQTNHCTeuqKZmbjHaSOFes+IX/+IhHrnAkXOAsfn24EM68XieIECoccD4KZLk/odiwzeo2rovYdhvb2HYFgyznJyDpYJdYOmfXgVdJTaUi4xA2uWYNYec9BLeqdl9EsoTw582mSFDX2DxVLbNt9U3YYoeatBad1c2Tj8t2akrjaIGJNywKB/7h75/gN3vCMSaadIUTAAAAAElFTkSuQmCC';
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
this.image = image || engineFontImage;
|
|
1019
|
-
this.tileSize = tileSize;
|
|
1020
|
-
this.paddingSize = paddingSize;
|
|
1024
|
+
ASSERT(!!tileInfo, 'tileInfo is required for FontImage');
|
|
1025
|
+
|
|
1026
|
+
/** @property {TileInfo} - Tile info for the font */
|
|
1027
|
+
this.tileInfo = tileInfo.frame(0);
|
|
1021
1028
|
}
|
|
1022
1029
|
|
|
1023
1030
|
/** Draw text in world space using the image font
|
|
1024
|
-
* @param {string|number}
|
|
1031
|
+
* @param {string|number} text
|
|
1025
1032
|
* @param {Vector2} pos
|
|
1026
|
-
* @param {number}
|
|
1027
|
-
* @param {boolean} [center]
|
|
1028
|
-
* @param {
|
|
1033
|
+
* @param {Vector2|number} [size]
|
|
1034
|
+
* @param {boolean} [center=true]
|
|
1035
|
+
* @param {Color} [color=WHITE]
|
|
1036
|
+
* @param {boolean} [useWebGL=glEnable]
|
|
1037
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
|
|
1029
1038
|
*/
|
|
1030
|
-
drawText(text, pos,
|
|
1039
|
+
drawText(text, pos, size=1, center, color, useWebGL, context)
|
|
1031
1040
|
{
|
|
1032
|
-
|
|
1041
|
+
ASSERT(isVector2(size) || typeof size === 'number', 'size must be a vec2 or number');
|
|
1042
|
+
|
|
1043
|
+
if (typeof size === 'number')
|
|
1044
|
+
{
|
|
1045
|
+
// if size is a number, make it a vector
|
|
1046
|
+
ASSERT(size > 0);
|
|
1047
|
+
size *= cameraScale;
|
|
1048
|
+
size = new Vector2(size, size);
|
|
1049
|
+
}
|
|
1050
|
+
else
|
|
1051
|
+
size = size.scale(cameraScale);
|
|
1052
|
+
this.drawTextScreen(text, worldToScreen(pos), size, center, color, useWebGL, context);
|
|
1033
1053
|
}
|
|
1034
1054
|
|
|
1035
1055
|
/** Draw text in screen space using the image font
|
|
1036
|
-
* @param {string|number}
|
|
1056
|
+
* @param {string|number} text
|
|
1037
1057
|
* @param {Vector2} pos
|
|
1038
|
-
* @param {number}
|
|
1058
|
+
* @param {Vector2|number} size
|
|
1039
1059
|
* @param {boolean} [center]
|
|
1040
|
-
* @param {
|
|
1060
|
+
* @param {Color} [color=WHITE]
|
|
1061
|
+
* @param {boolean} [useWebGL=glEnable]
|
|
1062
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
|
|
1041
1063
|
*/
|
|
1042
|
-
drawTextScreen(text, pos,
|
|
1064
|
+
drawTextScreen(text, pos, size, center=true, color=WHITE, useWebGL=glEnable, context)
|
|
1043
1065
|
{
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1066
|
+
ASSERT(isString(text), 'text must be a string');
|
|
1067
|
+
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
1068
|
+
ASSERT(isVector2(size) || typeof size === 'number', 'size must be a vec2 or number');
|
|
1069
|
+
ASSERT(isColor(color), 'color must be a color');
|
|
1070
|
+
|
|
1071
|
+
// if size is a number, make it a vector
|
|
1072
|
+
size = typeof size === 'number' ? new Vector2(size, size) : size;
|
|
1073
|
+
|
|
1074
|
+
// precache objects for drawing
|
|
1075
|
+
const drawPos = new Vector2;
|
|
1076
|
+
const tileInfo = this.tileInfo;
|
|
1077
|
+
const padding = tileInfo.padding;
|
|
1078
|
+
const sizePaddedX = tileInfo.size.x + padding*2;
|
|
1079
|
+
const sizePaddedY = tileInfo.size.y + padding*2;
|
|
1080
|
+
const cols = tileInfo.textureInfo.size.x / sizePaddedX |0;
|
|
1081
|
+
|
|
1082
|
+
// draw each line of text
|
|
1083
|
+
(text+'').split('\n').forEach((line, j)=>
|
|
1049
1084
|
{
|
|
1050
|
-
const centerOffset = center ? line.length * size.x
|
|
1051
|
-
for (let
|
|
1085
|
+
const centerOffset = center ? (line.length-1) * size.x / 2 : 0;
|
|
1086
|
+
for (let i=line.length; i--;)
|
|
1052
1087
|
{
|
|
1053
|
-
//
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
charCode
|
|
1057
|
-
|
|
1058
|
-
// get the
|
|
1059
|
-
const
|
|
1060
|
-
const
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1088
|
+
// get the character index
|
|
1089
|
+
const charCode = line.charCodeAt(i);
|
|
1090
|
+
const index = charCode < 32 || charCode > 127 ?
|
|
1091
|
+
95 : charCode - 32; // handle out of range characters
|
|
1092
|
+
|
|
1093
|
+
// get the position of the tile
|
|
1094
|
+
const x = index % cols;
|
|
1095
|
+
const y = index / cols |0;
|
|
1096
|
+
tileInfo.pos.x = x*sizePaddedX + padding;
|
|
1097
|
+
tileInfo.pos.y = y*sizePaddedY + padding;
|
|
1098
|
+
|
|
1099
|
+
// draw the tile
|
|
1100
|
+
drawPos.x = pos.x + i * size.x - centerOffset |0;
|
|
1101
|
+
drawPos.y = pos.y + j * size.y |0;
|
|
1102
|
+
drawTile(drawPos, size, tileInfo, color, 0, false, undefined, useWebGL, true, context);
|
|
1065
1103
|
}
|
|
1066
1104
|
});
|
|
1067
|
-
context.restore();
|
|
1068
1105
|
}
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
// load engine font, called automatically on startup
|
|
1109
|
+
function fontImageInit()
|
|
1110
|
+
{
|
|
1111
|
+
return new Promise(resolve =>
|
|
1112
|
+
{
|
|
1113
|
+
// create the engine font
|
|
1114
|
+
const image = new Image;
|
|
1115
|
+
image.onerror = image.onload = ()=>
|
|
1116
|
+
{
|
|
1117
|
+
const tilePos=vec2(), tileSize=vec2(8), padding=1, bleed=0;
|
|
1118
|
+
const textureInfo = new TextureInfo(image);
|
|
1119
|
+
const tileInfo = new TileInfo(tilePos, tileSize, textureInfo, padding, bleed);
|
|
1120
|
+
engineFontImage = new FontImage(tileInfo);
|
|
1121
|
+
resolve();
|
|
1122
|
+
}
|
|
1123
|
+
image.crossOrigin = 'anonymous';
|
|
1124
|
+
image.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAAeAQMAAABnrVXaAAAABlBMVEUAAAD///+l2Z/dAAAAAXRSTlMAQObYZgAAAjpJREFUOMu9kzFu2zAUhn+CAROgqrk+B2l0BWYxMjlXeYaAtFtbdA1sGgHqRQfI0CNkSG5AwYB0BQ8d5Bsomwah6CPVeGg6tEPzAxLwyI+P78cP4u9lNO9OoMKnLMOobG5020/yaj/MrRcCGh1gBbyiLTPJEYaIiom5KM9Jq7KgynMGtb6L4GL4MF2H4LQKCXTvDVw2I4MsgZT7QLExdiutH+D08VOP3INXRrWX1/mmpbkNgAPYRVANb4xpcegYvhiNbIXauQICEjBuYLfMakaakWQeXxiZ0VDtuJCKs3ztMV59QtsHJNcRxDzfdL21ty3PrfIcXTN+E+GFAv6T5nbT9jd50/WFxb5ksdAv49qS6ouymG66ji08UMT6moykYLAo+V0j23GN4m829ZySAD5K7QsBfQTvOG8eE+gTeGYRAmnNAubN3hf5Zv9tJWDHp/VTuaSm7SN4fyINQqaNO3RMVxvpSPXnOChnRNvFcGY0gnwiPswYwTKVPE0zVtX3mTEIOoFzaqLrGuJaV+Uqumb71fVk/VoOH3cdLNQP/FHi8hV0CQNoqBZsUPlLPMsdCJro9QAaQQ0woDy9BJm0eTxCFnO9srcYlhNVlfR2EyTrph1uUtbUtAJifwRgrKuYdXVHeb0YI3QpawohQHkloI3J5FuVwI5ORxC9k2Tuz9Ir1IjgeIPGMHYkAZe2RuYkmWFmt3gGbTPOmBUWVTmRmHtGrfpzG/yuQNOKa6gBB/WA9khitPgl6/GP+gl2Af6tCbvaygAAAABJRU5ErkJggg==';
|
|
1125
|
+
});
|
|
1069
1126
|
}
|