littlejsengine 1.16.1 → 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 +287 -240
- package/dist/littlejs.esm.js +1419 -1259
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +1076 -910
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +977 -815
- package/examples/box2d/gameObjects.js +6 -6
- 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/logo2.png +0 -0
- package/examples/module/tiles.png +0 -0
- package/examples/platformer/gameEffects.js +24 -23
- package/examples/platformer/gameLevel.js +24 -25
- package/examples/shorts/base.html +2 -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 +3 -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 +16 -16
- package/reference.md +6 -6
- package/src/engine.js +186 -198
- package/src/engineAudio.js +6 -10
- package/src/engineBuild.js +1 -0
- package/src/engineDebug.js +100 -98
- package/src/engineDraw.js +185 -148
- package/src/engineExport.js +327 -333
- package/src/engineFont.png +0 -0
- package/src/engineInput.js +17 -26
- package/src/engineMath.js +1112 -0
- package/src/engineMedals.js +4 -4
- package/src/engineObject.js +27 -27
- package/src/engineParticles.js +2 -2
- package/src/engineRelease.js +1 -3
- package/src/engineSettings.js +2 -2
- package/src/engineTileLayer.js +200 -176
- package/src/engineUtilities.js +48 -1097
- package/src/engineWebGL.js +127 -79
package/src/engineDraw.js
CHANGED
|
@@ -31,11 +31,6 @@ let mainCanvas;
|
|
|
31
31
|
* @memberof Draw */
|
|
32
32
|
let mainContext;
|
|
33
33
|
|
|
34
|
-
/** The default canvas to use for drawing, usually mainCanvas
|
|
35
|
-
* @type {HTMLCanvasElement|OffscreenCanvas}
|
|
36
|
-
* @memberof Draw */
|
|
37
|
-
let drawCanvas;
|
|
38
|
-
|
|
39
34
|
/** The default 2d context to use for drawing, usually mainContext
|
|
40
35
|
* @type {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D}
|
|
41
36
|
* @memberof Draw */
|
|
@@ -82,10 +77,11 @@ let drawCount;
|
|
|
82
77
|
* Create a tile info object using a grid based system
|
|
83
78
|
* - This can take vecs or floats for easier use and conversion
|
|
84
79
|
* - If an index is passed in, the tile size and index will determine the position
|
|
85
|
-
* @param {Vector2|number} [
|
|
80
|
+
* @param {Vector2|number} [index=0] - Index of the tile in 1d or 2d form
|
|
86
81
|
* @param {Vector2|number} [size] - Size of tile in pixels
|
|
87
|
-
* @param {number} [
|
|
82
|
+
* @param {TextureInfo|number} [texture] - Texture index or info to use
|
|
88
83
|
* @param {number} [padding] - How many pixels padding around tiles
|
|
84
|
+
* @param {number} [bleed] - How many pixels smaller to draw tiles
|
|
89
85
|
* @return {TileInfo}
|
|
90
86
|
* @example
|
|
91
87
|
* tile(2) // a tile at index 2 using the default tile size of 16
|
|
@@ -93,36 +89,43 @@ let drawCount;
|
|
|
93
89
|
* tile(1, 16, 3) // a tile at index 1 of size 16 on texture 3
|
|
94
90
|
* tile(vec2(4,8), vec2(30,10)) // a tile at index (4,8) with a size of (30,10)
|
|
95
91
|
* @memberof Draw */
|
|
96
|
-
function tile(
|
|
92
|
+
function tile(index=new Vector2, size=tileDefaultSize, texture=0, padding=tileDefaultPadding, bleed=tileDefaultBleed)
|
|
97
93
|
{
|
|
98
|
-
|
|
99
|
-
|
|
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;
|
|
100
100
|
|
|
101
|
-
// if size is a number, make it a vector
|
|
102
101
|
if (typeof size === 'number')
|
|
103
102
|
{
|
|
103
|
+
// if size is a number, make it a vector
|
|
104
104
|
ASSERT(size > 0);
|
|
105
105
|
size = new Vector2(size, size);
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
// create tile info object
|
|
109
|
-
const
|
|
109
|
+
const textureInfo = typeof texture === 'number' ?
|
|
110
|
+
textureInfos[texture] : texture;
|
|
110
111
|
|
|
111
112
|
// get the position of the tile
|
|
112
|
-
const textureInfo = textureInfos[textureIndex];
|
|
113
|
-
ASSERT(!!textureInfo, 'Texture not loaded');
|
|
114
113
|
const sizePaddedX = size.x + padding*2;
|
|
115
114
|
const sizePaddedY = size.y + padding*2;
|
|
116
|
-
|
|
115
|
+
let x, y;
|
|
116
|
+
if (typeof index === 'number')
|
|
117
117
|
{
|
|
118
118
|
const cols = textureInfo.size.x / sizePaddedX |0;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
tileInfo.pos.set(posX*sizePaddedX+padding, posY*sizePaddedY+padding);
|
|
119
|
+
x = index % cols;
|
|
120
|
+
y = index / cols |0;
|
|
122
121
|
}
|
|
123
122
|
else
|
|
124
|
-
|
|
125
|
-
|
|
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);
|
|
126
129
|
}
|
|
127
130
|
|
|
128
131
|
/**
|
|
@@ -132,24 +135,22 @@ function tile(pos=new Vector2, size=tileDefaultSize, textureIndex=0, padding=til
|
|
|
132
135
|
class TileInfo
|
|
133
136
|
{
|
|
134
137
|
/** Create a tile info object
|
|
135
|
-
* @param {Vector2} [pos=(
|
|
138
|
+
* @param {Vector2} [pos=vec2()] - Top left corner of tile in pixels
|
|
136
139
|
* @param {Vector2} [size] - Size of tile in pixels
|
|
137
|
-
* @param {
|
|
138
|
-
* @param {number}
|
|
139
|
-
* @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
|
|
140
143
|
*/
|
|
141
|
-
constructor(pos=vec2(), size=tileDefaultSize,
|
|
144
|
+
constructor(pos=vec2(), size=tileDefaultSize, textureInfo=textureInfos[0], padding=tileDefaultPadding, bleed=tileDefaultBleed)
|
|
142
145
|
{
|
|
143
146
|
/** @property {Vector2} - Top left corner of tile in pixels */
|
|
144
147
|
this.pos = pos.copy();
|
|
145
148
|
/** @property {Vector2} - Size of tile in pixels */
|
|
146
149
|
this.size = size.copy();
|
|
147
|
-
/** @property {number} - Texture index to use */
|
|
148
|
-
this.textureIndex = textureIndex;
|
|
149
150
|
/** @property {number} - How many pixels padding around tiles */
|
|
150
151
|
this.padding = padding;
|
|
151
152
|
/** @property {TextureInfo} - The texture info for this tile */
|
|
152
|
-
this.textureInfo =
|
|
153
|
+
this.textureInfo = textureInfo;
|
|
153
154
|
/** @property {number} - Shrinks tile by this many pixels to prevent neighbors bleeding */
|
|
154
155
|
this.bleed = bleed;
|
|
155
156
|
}
|
|
@@ -159,7 +160,7 @@ class TileInfo
|
|
|
159
160
|
* @return {TileInfo}
|
|
160
161
|
*/
|
|
161
162
|
offset(offset)
|
|
162
|
-
{ 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); }
|
|
163
164
|
|
|
164
165
|
/** Returns a copy of this tile offset by a number of animation frames
|
|
165
166
|
* @param {number} frame - Offset to apply in animation frames
|
|
@@ -168,23 +169,33 @@ class TileInfo
|
|
|
168
169
|
frame(frame)
|
|
169
170
|
{
|
|
170
171
|
ASSERT(typeof frame === 'number');
|
|
171
|
-
|
|
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));
|
|
172
176
|
}
|
|
173
177
|
|
|
174
178
|
/**
|
|
175
179
|
* Set this tile to use a full image in a texture info
|
|
176
|
-
* @param {TextureInfo} textureInfo
|
|
180
|
+
* @param {TextureInfo} [textureInfo]
|
|
177
181
|
* @return {TileInfo}
|
|
178
182
|
*/
|
|
179
|
-
setFullImage(textureInfo)
|
|
183
|
+
setFullImage(textureInfo=this.textureInfo)
|
|
180
184
|
{
|
|
185
|
+
this.textureInfo = textureInfo;
|
|
181
186
|
this.pos = new Vector2;
|
|
182
187
|
this.size = textureInfo.size.copy();
|
|
183
|
-
this.textureInfo = textureInfo;
|
|
184
|
-
// do not use padding or bleed
|
|
185
188
|
this.bleed = this.padding = 0;
|
|
186
189
|
return this;
|
|
187
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); }
|
|
188
199
|
}
|
|
189
200
|
|
|
190
201
|
/**
|
|
@@ -225,19 +236,19 @@ class TextureInfo
|
|
|
225
236
|
///////////////////////////////////////////////////////////////////////////////
|
|
226
237
|
// Drawing functions
|
|
227
238
|
|
|
228
|
-
/** Draw textured tile centered in world space
|
|
229
|
-
* @param {Vector2} pos
|
|
230
|
-
* @param {Vector2} [size=(1
|
|
231
|
-
* @param {TileInfo} [tileInfo]
|
|
232
|
-
* @param {Color} [color=
|
|
233
|
-
* @param {number} [angle]
|
|
234
|
-
* @param {boolean} [mirror]
|
|
235
|
-
* @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
|
|
236
247
|
* @param {boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering?
|
|
237
248
|
* @param {boolean} [screenSpace=false] - Are the pos and size are in screen space?
|
|
238
249
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context] - Canvas 2D context to draw to
|
|
239
250
|
* @memberof Draw */
|
|
240
|
-
function drawTile(pos, size=
|
|
251
|
+
function drawTile(pos, size=vec2(1), tileInfo, color=WHITE,
|
|
241
252
|
angle=0, mirror, additiveColor, useWebGL=glEnable, screenSpace, context)
|
|
242
253
|
{
|
|
243
254
|
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
@@ -312,8 +323,8 @@ function drawTile(pos, size=new Vector2(1), tileInfo, color=WHITE,
|
|
|
312
323
|
|
|
313
324
|
/** Draw colored rect centered on pos
|
|
314
325
|
* @param {Vector2} pos
|
|
315
|
-
* @param {Vector2} [size=(1
|
|
316
|
-
* @param {Color} [color=
|
|
326
|
+
* @param {Vector2} [size=vec2(1)]
|
|
327
|
+
* @param {Color} [color=WHITE]
|
|
317
328
|
* @param {number} [angle]
|
|
318
329
|
* @param {boolean} [useWebGL=glEnable]
|
|
319
330
|
* @param {boolean} [screenSpace]
|
|
@@ -326,9 +337,9 @@ function drawRect(pos, size, color, angle, useWebGL, screenSpace, context)
|
|
|
326
337
|
|
|
327
338
|
/** Draw a rect centered on pos with a gradient from top to bottom
|
|
328
339
|
* @param {Vector2} pos
|
|
329
|
-
* @param {Vector2} [size=(1
|
|
330
|
-
* @param {Color} [colorTop=
|
|
331
|
-
* @param {Color} [colorBottom=
|
|
340
|
+
* @param {Vector2} [size=vec2(1)]
|
|
341
|
+
* @param {Color} [colorTop=WHITE]
|
|
342
|
+
* @param {Color} [colorBottom=BLACK]
|
|
332
343
|
* @param {number} [angle]
|
|
333
344
|
* @param {boolean} [useWebGL=glEnable]
|
|
334
345
|
* @param {boolean} [screenSpace]
|
|
@@ -390,9 +401,9 @@ function drawRectGradient(pos, size, colorTop=WHITE, colorBottom=BLACK, angle=0,
|
|
|
390
401
|
/** Draw connected lines between a series of points
|
|
391
402
|
* @param {Array<Vector2>} points
|
|
392
403
|
* @param {number} [width]
|
|
393
|
-
* @param {Color} [color=
|
|
404
|
+
* @param {Color} [color=WHITE]
|
|
394
405
|
* @param {boolean} [wrap] - Should the last point connect to the first?
|
|
395
|
-
* @param {Vector2} [pos=(
|
|
406
|
+
* @param {Vector2} [pos=vec2()] - Offset to apply
|
|
396
407
|
* @param {number} [angle] - Angle to rotate by
|
|
397
408
|
* @param {boolean} [useWebGL=glEnable]
|
|
398
409
|
* @param {boolean} [screenSpace]
|
|
@@ -427,13 +438,9 @@ function drawLineList(points, width=.1, color, wrap=false, pos=vec2(), angle=0,
|
|
|
427
438
|
for (let i=0; i<points.length; ++i)
|
|
428
439
|
{
|
|
429
440
|
const point = points[i];
|
|
430
|
-
|
|
431
|
-
context.lineTo(point.x, point.y);
|
|
432
|
-
else
|
|
433
|
-
context.moveTo(point.x, point.y);
|
|
441
|
+
context.lineTo(point.x, point.y);
|
|
434
442
|
}
|
|
435
|
-
|
|
436
|
-
context.closePath();
|
|
443
|
+
wrap && context.closePath();
|
|
437
444
|
context.stroke();
|
|
438
445
|
}, screenSpace, context);
|
|
439
446
|
}
|
|
@@ -443,8 +450,8 @@ function drawLineList(points, width=.1, color, wrap=false, pos=vec2(), angle=0,
|
|
|
443
450
|
* @param {Vector2} posA
|
|
444
451
|
* @param {Vector2} posB
|
|
445
452
|
* @param {number} [width]
|
|
446
|
-
* @param {Color} [color=
|
|
447
|
-
* @param {Vector2} [pos=(
|
|
453
|
+
* @param {Color} [color=WHITE]
|
|
454
|
+
* @param {Vector2} [pos=vec2()] - Offset to apply
|
|
448
455
|
* @param {number} [angle] - Angle to rotate by
|
|
449
456
|
* @param {boolean} [useWebGL=glEnable]
|
|
450
457
|
* @param {boolean} [screenSpace]
|
|
@@ -463,12 +470,12 @@ function drawLine(posA, posB, width=.1, color, pos=vec2(), angle=0, useWebGL, sc
|
|
|
463
470
|
|
|
464
471
|
/** Draw colored regular polygon using passed in number of sides
|
|
465
472
|
* @param {Vector2} pos
|
|
466
|
-
* @param {Vector2} [size=(1
|
|
473
|
+
* @param {Vector2} [size=vec2(1)]
|
|
467
474
|
* @param {number} [sides]
|
|
468
|
-
* @param {Color} [color=
|
|
475
|
+
* @param {Color} [color=WHITE]
|
|
469
476
|
* @param {number} [angle]
|
|
470
477
|
* @param {number} [lineWidth]
|
|
471
|
-
* @param {Color} [lineColor=
|
|
478
|
+
* @param {Color} [lineColor=BLACK]
|
|
472
479
|
* @param {boolean} [useWebGL=glEnable]
|
|
473
480
|
* @param {boolean} [screenSpace]
|
|
474
481
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
|
|
@@ -491,10 +498,10 @@ function drawRegularPoly(pos, size=vec2(1), sides=3, color=WHITE, lineWidth=0, l
|
|
|
491
498
|
|
|
492
499
|
/** Draw colored polygon using passed in points
|
|
493
500
|
* @param {Array<Vector2>} points - Array of Vector2 points
|
|
494
|
-
* @param {Color} [color=
|
|
501
|
+
* @param {Color} [color=WHITE]
|
|
495
502
|
* @param {number} [lineWidth]
|
|
496
|
-
* @param {Color} [lineColor=
|
|
497
|
-
* @param {Vector2} [pos=(
|
|
503
|
+
* @param {Color} [lineColor=BLACK]
|
|
504
|
+
* @param {Vector2} [pos=vec2()] - Offset to apply
|
|
498
505
|
* @param {number} [angle] - Angle to rotate by
|
|
499
506
|
* @param {boolean} [useWebGL=glEnable]
|
|
500
507
|
* @param {boolean} [screenSpace]
|
|
@@ -541,11 +548,11 @@ function drawPoly(points, color=WHITE, lineWidth=0, lineColor=BLACK, pos=vec2(),
|
|
|
541
548
|
|
|
542
549
|
/** Draw colored ellipse using passed in point
|
|
543
550
|
* @param {Vector2} pos
|
|
544
|
-
* @param {Vector2} [size=(1
|
|
545
|
-
* @param {Color} [color=
|
|
551
|
+
* @param {Vector2} [size=vec2(1)] - Width and height diameter
|
|
552
|
+
* @param {Color} [color=WHITE]
|
|
546
553
|
* @param {number} [angle]
|
|
547
554
|
* @param {number} [lineWidth]
|
|
548
|
-
* @param {Color} [lineColor=
|
|
555
|
+
* @param {Color} [lineColor=BLACK]
|
|
549
556
|
* @param {boolean} [useWebGL=glEnable]
|
|
550
557
|
* @param {boolean} [screenSpace]
|
|
551
558
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
|
|
@@ -587,9 +594,9 @@ function drawEllipse(pos, size=vec2(1), color=WHITE, angle=0, lineWidth=0, lineC
|
|
|
587
594
|
/** Draw colored circle using passed in point
|
|
588
595
|
* @param {Vector2} pos
|
|
589
596
|
* @param {number} [size=1] - Diameter
|
|
590
|
-
* @param {Color} [color=
|
|
597
|
+
* @param {Color} [color=WHITE]
|
|
591
598
|
* @param {number} [lineWidth=0]
|
|
592
|
-
* @param {Color} [lineColor=
|
|
599
|
+
* @param {Color} [lineColor=BLACK]
|
|
593
600
|
* @param {boolean} [useWebGL=glEnable]
|
|
594
601
|
* @param {boolean} [screenSpace]
|
|
595
602
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
|
|
@@ -623,7 +630,11 @@ function drawCanvas2D(pos, size, angle=0, mirror=false, drawFunction, screenSpac
|
|
|
623
630
|
ASSERT(typeof drawFunction === 'function', 'drawFunction must be a function');
|
|
624
631
|
|
|
625
632
|
if (!screenSpace)
|
|
626
|
-
|
|
633
|
+
{
|
|
634
|
+
pos = worldToScreen(pos);
|
|
635
|
+
size = size.scale(cameraScale);
|
|
636
|
+
angle -= cameraAngle;
|
|
637
|
+
}
|
|
627
638
|
context.save();
|
|
628
639
|
context.translate(pos.x+.5, pos.y+.5);
|
|
629
640
|
context.rotate(angle);
|
|
@@ -640,9 +651,9 @@ function drawCanvas2D(pos, size, angle=0, mirror=false, drawFunction, screenSpac
|
|
|
640
651
|
* @param {string|number} text
|
|
641
652
|
* @param {Vector2} pos
|
|
642
653
|
* @param {number} [size]
|
|
643
|
-
* @param {Color} [color=
|
|
654
|
+
* @param {Color} [color=WHITE]
|
|
644
655
|
* @param {number} [lineWidth]
|
|
645
|
-
* @param {Color} [lineColor=
|
|
656
|
+
* @param {Color} [lineColor=BLACK]
|
|
646
657
|
* @param {CanvasTextAlign} [textAlign='center']
|
|
647
658
|
* @param {string} [font=fontDefault]
|
|
648
659
|
* @param {string} [fontStyle]
|
|
@@ -666,18 +677,18 @@ function drawText(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, f
|
|
|
666
677
|
* Automatically splits new lines into rows
|
|
667
678
|
* @param {string|number} text
|
|
668
679
|
* @param {Vector2} pos
|
|
669
|
-
* @param {number}
|
|
670
|
-
* @param {Color} [color=
|
|
680
|
+
* @param {number} size
|
|
681
|
+
* @param {Color} [color=WHITE]
|
|
671
682
|
* @param {number} [lineWidth]
|
|
672
|
-
* @param {Color} [lineColor=
|
|
683
|
+
* @param {Color} [lineColor=BLACK]
|
|
673
684
|
* @param {CanvasTextAlign} [textAlign]
|
|
674
685
|
* @param {string} [font=fontDefault]
|
|
675
686
|
* @param {string} [fontStyle]
|
|
676
687
|
* @param {number} [maxWidth]
|
|
677
688
|
* @param {number} [angle]
|
|
678
|
-
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=
|
|
689
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=drawContext]
|
|
679
690
|
* @memberof Draw */
|
|
680
|
-
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)
|
|
681
692
|
{
|
|
682
693
|
ASSERT(isString(text), 'text must be a string');
|
|
683
694
|
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
@@ -801,7 +812,7 @@ function worldToScreenDelta(worldDelta)
|
|
|
801
812
|
|
|
802
813
|
/** Convert screen space transform to world space
|
|
803
814
|
* @param {Vector2} screenPos
|
|
804
|
-
* @param {Vector2} screenSize
|
|
815
|
+
* @param {Vector2} screenSize
|
|
805
816
|
* @param {number} [screenAngle]
|
|
806
817
|
* @return {[Vector2, Vector2, number]} - [pos, size, angle]
|
|
807
818
|
* @memberof Draw */
|
|
@@ -818,25 +829,6 @@ function screenToWorldTransform(screenPos, screenSize, screenAngle=0)
|
|
|
818
829
|
];
|
|
819
830
|
}
|
|
820
831
|
|
|
821
|
-
/** Convert world space transform to screen space
|
|
822
|
-
* @param {Vector2} worldPos
|
|
823
|
-
* @param {Vector2} worldSize
|
|
824
|
-
* @param {number} [worldAngle]
|
|
825
|
-
* @return {[Vector2, Vector2, number]} - [pos, size, angle]
|
|
826
|
-
* @memberof Draw */
|
|
827
|
-
function worldToScreenTransform(worldPos, worldSize, worldAngle=0)
|
|
828
|
-
{
|
|
829
|
-
ASSERT(isVector2(worldPos), 'worldPos must be a vec2');
|
|
830
|
-
ASSERT(isVector2(worldSize), 'worldSize must be a vec2');
|
|
831
|
-
ASSERT(isNumber(worldAngle), 'worldAngle must be a number');
|
|
832
|
-
|
|
833
|
-
return [
|
|
834
|
-
worldToScreen(worldPos),
|
|
835
|
-
worldSize.scale(cameraScale),
|
|
836
|
-
worldAngle - cameraAngle
|
|
837
|
-
];
|
|
838
|
-
}
|
|
839
|
-
|
|
840
832
|
/** Get the size of the camera window in world space
|
|
841
833
|
* @return {Vector2}
|
|
842
834
|
* @memberof Draw */
|
|
@@ -881,10 +873,9 @@ function isOnScreen(pos, size=0)
|
|
|
881
873
|
* @param {boolean} [additive]
|
|
882
874
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
|
|
883
875
|
* @memberof Draw */
|
|
884
|
-
function setBlendMode(additive=false, context)
|
|
876
|
+
function setBlendMode(additive=false, context=drawContext)
|
|
885
877
|
{
|
|
886
878
|
glAdditive = additive;
|
|
887
|
-
context ||= drawContext;
|
|
888
879
|
context.globalCompositeOperation = additive ? 'lighter' : 'source-over';
|
|
889
880
|
}
|
|
890
881
|
|
|
@@ -899,7 +890,6 @@ function combineCanvases()
|
|
|
899
890
|
workContext.fillRect(0,0,w,h); // remove background alpha
|
|
900
891
|
glCopyToContext(workContext);
|
|
901
892
|
workContext.drawImage(mainCanvas, 0, 0);
|
|
902
|
-
mainCanvas.width |= 0;
|
|
903
893
|
mainContext.drawImage(workCanvas, 0, 0);
|
|
904
894
|
}
|
|
905
895
|
|
|
@@ -1004,17 +994,22 @@ function setCursor(cursorStyle = 'auto')
|
|
|
1004
994
|
|
|
1005
995
|
///////////////////////////////////////////////////////////////////////////////
|
|
1006
996
|
|
|
997
|
+
/** Engine font image, 8x8 font provided by the engine
|
|
998
|
+
* @type {FontImage}
|
|
999
|
+
* @memberof Draw */
|
|
1007
1000
|
let engineFontImage;
|
|
1008
1001
|
|
|
1009
1002
|
/**
|
|
1010
|
-
* Font Image Object - Draw text
|
|
1003
|
+
* Font Image Object - Draw text by using tiles in an image
|
|
1011
1004
|
* - 96 characters (from space to tilde) are stored in an image
|
|
1012
|
-
* -
|
|
1013
|
-
* -
|
|
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
|
+
*
|
|
1014
1009
|
* @memberof Draw
|
|
1015
1010
|
* @example
|
|
1016
1011
|
* // use built in font
|
|
1017
|
-
* const font =
|
|
1012
|
+
* const font = engineFontImage;
|
|
1018
1013
|
*
|
|
1019
1014
|
* // draw text
|
|
1020
1015
|
* font.drawTextScreen('LittleJS\nHello World!', vec2(200, 50));
|
|
@@ -1022,68 +1017,110 @@ let engineFontImage;
|
|
|
1022
1017
|
class FontImage
|
|
1023
1018
|
{
|
|
1024
1019
|
/** Create an image font
|
|
1025
|
-
* @param {
|
|
1026
|
-
* @param {Vector2} [tileSize=(8,8)] - Size of the font source tiles
|
|
1027
|
-
* @param {Vector2} [paddingSize=(0,1)] - How much space between characters
|
|
1020
|
+
* @param {TileInfo} tileInfo - Tile info of first characeter in font
|
|
1028
1021
|
*/
|
|
1029
|
-
constructor(
|
|
1022
|
+
constructor(tileInfo)
|
|
1030
1023
|
{
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
{
|
|
1034
|
-
|
|
1035
|
-
engineFontImage.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAAYAQAAAAA9+x6JAAAAAnRSTlMAAHaTzTgAAAGiSURBVHjaZZABhxxBEIUf6ECLBdFY+Q0PMNgf0yCgsSAGZcT9sgIPtBWwIA5wgAPEoHUyJeeSlW+gjK+fegWwtROWpVQEyWh2npdpBmTUFVhb29RINgLIukoXr5LIAvYQ5ve+1FqWEMqNKTX3FAJHyQDRZvmKWubAACcv5z5Gtg2oyCWE+Yk/8JZQX1jTTCpKAFGIgza+dJCNBF2UskRlsgwitHbSV0QLgt9sTPtsRlvJjEr8C/FARWA2bJ/TtJ7lko34dNDn6usJUMzuErP89UUBJbWeozrwLLncXczd508deAjLWipLO4Q5XGPcJvPu92cNDaN0P5G1FL0nSOzddZOrJ6rNhbXGmeDvO3TF7DeJWl4bvaYQTNHCTeuqKZmbjHaSOFes+IX/+IhHrnAkXOAsfn24EM68XieIECoccD4KZLk/odiwzeo2rovYdhvb2HYFgyznJyDpYJdYOmfXgVdJTaUi4xA2uWYNYec9BLeqdl9EsoTw582mSFDX2DxVLbNt9U3YYoeatBad1c2Tj8t2akrjaIGJNywKB/7h75/gN3vCMSaadIUTAAAAAElFTkSuQmCC';
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
this.image = image || engineFontImage;
|
|
1039
|
-
this.tileSize = tileSize;
|
|
1040
|
-
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);
|
|
1041
1028
|
}
|
|
1042
1029
|
|
|
1043
1030
|
/** Draw text in world space using the image font
|
|
1044
|
-
* @param {string|number}
|
|
1031
|
+
* @param {string|number} text
|
|
1045
1032
|
* @param {Vector2} pos
|
|
1046
|
-
* @param {number}
|
|
1047
|
-
* @param {boolean} [center]
|
|
1048
|
-
* @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]
|
|
1049
1038
|
*/
|
|
1050
|
-
drawText(text, pos,
|
|
1039
|
+
drawText(text, pos, size=1, center, color, useWebGL, context)
|
|
1051
1040
|
{
|
|
1052
|
-
|
|
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);
|
|
1053
1053
|
}
|
|
1054
1054
|
|
|
1055
1055
|
/** Draw text in screen space using the image font
|
|
1056
|
-
* @param {string|number}
|
|
1056
|
+
* @param {string|number} text
|
|
1057
1057
|
* @param {Vector2} pos
|
|
1058
|
-
* @param {number}
|
|
1058
|
+
* @param {Vector2|number} size
|
|
1059
1059
|
* @param {boolean} [center]
|
|
1060
|
-
* @param {
|
|
1060
|
+
* @param {Color} [color=WHITE]
|
|
1061
|
+
* @param {boolean} [useWebGL=glEnable]
|
|
1062
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
|
|
1061
1063
|
*/
|
|
1062
|
-
drawTextScreen(text, pos,
|
|
1064
|
+
drawTextScreen(text, pos, size, center=true, color=WHITE, useWebGL=glEnable, context)
|
|
1063
1065
|
{
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
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)=>
|
|
1069
1084
|
{
|
|
1070
|
-
const centerOffset = center ? line.length * size.x
|
|
1071
|
-
for (let
|
|
1085
|
+
const centerOffset = center ? (line.length-1) * size.x / 2 : 0;
|
|
1086
|
+
for (let i=line.length; i--;)
|
|
1072
1087
|
{
|
|
1073
|
-
//
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
charCode
|
|
1077
|
-
|
|
1078
|
-
// get the
|
|
1079
|
-
const
|
|
1080
|
-
const
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
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);
|
|
1085
1103
|
}
|
|
1086
1104
|
});
|
|
1087
|
-
context.restore();
|
|
1088
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
|
+
});
|
|
1089
1126
|
}
|