littlejsengine 1.15.8 → 1.16.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 +87 -85
- package/dist/littlejs.esm.js +578 -532
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +562 -521
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +485 -444
- package/examples/box2d/game.js +2 -2
- package/examples/breakout/game.js +3 -3
- package/examples/electron/game.js +1 -2
- package/examples/electron/index.html +2 -2
- package/examples/htmlMenu/game.js +0 -1
- package/examples/index.html +1 -1
- package/examples/module/game.js +1 -2
- package/examples/particles/index.html +1 -1
- package/examples/platformer/game.js +11 -4
- package/examples/puzzle/game.js +2 -2
- package/examples/shorts/base.html +3 -4
- package/examples/shorts/box2dPool.js +2 -2
- package/examples/shorts/empty.js +1 -1
- package/examples/shorts/{systemFont.js → fontImage.js} +3 -3
- package/examples/shorts/fps.js +1 -1
- package/examples/shorts/helloWorld.js +2 -2
- package/examples/shorts/nineSlice.js +2 -2
- package/examples/shorts/slidingPuzzle.js +1 -1
- package/examples/shorts/uiSystem.js +1 -1
- package/examples/starter/game.js +1 -2
- package/examples/starter/index.html +2 -3
- package/examples/stress/index.html +1 -1
- package/examples/typescript/game.js +1 -2
- package/examples/typescript/game.ts +1 -2
- package/examples/uiSystem/game.js +4 -7
- package/package.json +1 -1
- package/plugins/box2d.js +8 -8
- package/plugins/drawUtilities.js +6 -6
- package/plugins/postProcess.js +13 -20
- package/plugins/uiSystem.js +15 -3
- package/reference.md +4 -6
- package/src/engine.js +240 -53
- package/src/engineAudio.js +3 -3
- package/src/engineBuild.js +0 -1
- package/src/engineDebug.js +78 -78
- package/src/engineDraw.js +107 -109
- package/src/engineExport.js +16 -11
- package/src/engineInput.js +14 -2
- package/src/engineMedals.js +3 -3
- package/src/engineObject.js +4 -2
- package/src/engineParticles.js +8 -6
- package/src/engineRelease.js +1 -1
- package/src/engineSettings.js +44 -30
- package/src/engineTileLayer.js +6 -6
- package/src/engineUtilities.js +2 -10
- package/src/engineWebGL.js +6 -5
- package/src/engineSplash.js +0 -173
package/src/engineSettings.js
CHANGED
|
@@ -48,6 +48,20 @@ let canvasClearColor = CLEAR_BLACK;
|
|
|
48
48
|
* @memberof Settings */
|
|
49
49
|
let canvasMaxSize = vec2(1920, 1080);
|
|
50
50
|
|
|
51
|
+
/** Minimum aspect ratio of the canvas (width/height), unused if 0
|
|
52
|
+
* Can be used with canvasMaxAspect to limit aspect ratio
|
|
53
|
+
* @type {number}
|
|
54
|
+
* @default
|
|
55
|
+
* @memberof Settings */
|
|
56
|
+
let canvasMinAspect = 0;
|
|
57
|
+
|
|
58
|
+
/** Maximum aspect ratio of the canvas (width/height), unused if 0
|
|
59
|
+
* Can be used with canvasMinAspect to limit aspect ratio
|
|
60
|
+
* @type {number}
|
|
61
|
+
* @default
|
|
62
|
+
* @memberof Settings */
|
|
63
|
+
let canvasMaxAspect = 0;
|
|
64
|
+
|
|
51
65
|
/** Fixed size of the canvas, if enabled canvas size never changes
|
|
52
66
|
* - you may also need to set mainCanvasSize if using screen space coords in startup
|
|
53
67
|
* @type {Vector2}
|
|
@@ -60,15 +74,7 @@ let canvasFixedSize = vec2();
|
|
|
60
74
|
* @type {boolean}
|
|
61
75
|
* @default
|
|
62
76
|
* @memberof Settings */
|
|
63
|
-
let canvasPixelated =
|
|
64
|
-
|
|
65
|
-
/** Use nearest canvas scaling for more pixelated look
|
|
66
|
-
* - If enabled sets css image-rendering:pixelated
|
|
67
|
-
* - This defaults to false because text looks better with smoothing
|
|
68
|
-
* @type {boolean}
|
|
69
|
-
* @default
|
|
70
|
-
* @memberof Settings */
|
|
71
|
-
let overlayCanvasPixelated = false;
|
|
77
|
+
let canvasPixelated = false;
|
|
72
78
|
|
|
73
79
|
/** Disables texture filtering for crisper pixel art
|
|
74
80
|
* @type {boolean}
|
|
@@ -116,13 +122,19 @@ let glCircleSides = 32;
|
|
|
116
122
|
* @type {Vector2}
|
|
117
123
|
* @default Vector2(16,16)
|
|
118
124
|
* @memberof Settings */
|
|
119
|
-
let
|
|
125
|
+
let tileDefaultSize = vec2(16);
|
|
120
126
|
|
|
121
|
-
/**
|
|
127
|
+
/** Default padding pixels around tiles
|
|
122
128
|
* @type {number}
|
|
123
129
|
* @default
|
|
124
130
|
* @memberof Settings */
|
|
125
|
-
let
|
|
131
|
+
let tileDefaultPadding = 0;
|
|
132
|
+
|
|
133
|
+
/** Default amount of pixels smaller to draw tiles to prevent neighbor bleeding
|
|
134
|
+
* @type {number}
|
|
135
|
+
* @default
|
|
136
|
+
* @memberof Settings */
|
|
137
|
+
let tileDefaultBleed = 0;
|
|
126
138
|
|
|
127
139
|
///////////////////////////////////////////////////////////////////////////////
|
|
128
140
|
// Object settings
|
|
@@ -344,13 +356,22 @@ function setCanvasClearColor(color) { canvasClearColor = color.copy(); }
|
|
|
344
356
|
* @memberof Settings */
|
|
345
357
|
function setCanvasMaxSize(size) { canvasMaxSize = size.copy(); }
|
|
346
358
|
|
|
359
|
+
/** Set minimum aspect ratio of the canvas (width/height), unused if 0
|
|
360
|
+
* @param {number} aspect
|
|
361
|
+
* @memberof Settings */
|
|
362
|
+
function setCanvasMinAspect(aspect) { canvasMinAspect = aspect; }
|
|
363
|
+
|
|
364
|
+
/** Set maximum aspect ratio of the canvas (width/height), unused if 0
|
|
365
|
+
* @param {number} aspect
|
|
366
|
+
* @memberof Settings */
|
|
367
|
+
function setCanvasMaxAspect(aspect) { canvasMaxAspect = aspect; }
|
|
368
|
+
|
|
347
369
|
/** Set fixed size of the canvas
|
|
348
370
|
* @param {Vector2} size
|
|
349
371
|
* @memberof Settings */
|
|
350
372
|
function setCanvasFixedSize(size) { canvasFixedSize = size.copy(); }
|
|
351
373
|
|
|
352
374
|
/** Use nearest scaling algorithm for canvas for more pixelated look
|
|
353
|
-
* - If enabled sets css image-rendering:pixelated
|
|
354
375
|
* @param {boolean} pixelated
|
|
355
376
|
* @memberof Settings */
|
|
356
377
|
function setCanvasPixelated(pixelated)
|
|
@@ -362,18 +383,6 @@ function setCanvasPixelated(pixelated)
|
|
|
362
383
|
glCanvas.style.imageRendering = pixelated ? 'pixelated' : '';
|
|
363
384
|
}
|
|
364
385
|
|
|
365
|
-
/** Use nearest scaling algorithm for canvas for more pixelated look
|
|
366
|
-
* - If enabled sets css image-rendering:pixelated
|
|
367
|
-
* - This defaults to false because text looks better with smoothing
|
|
368
|
-
* @param {boolean} pixelated
|
|
369
|
-
* @memberof Settings */
|
|
370
|
-
function setOverlayCanvasPixelated(pixelated)
|
|
371
|
-
{
|
|
372
|
-
overlayCanvasPixelated = pixelated;
|
|
373
|
-
if (overlayCanvas)
|
|
374
|
-
overlayCanvas.style.imageRendering = pixelated ? 'pixelated' : '';
|
|
375
|
-
}
|
|
376
|
-
|
|
377
386
|
/** Disables texture filtering for crisper pixel art
|
|
378
387
|
* @param {boolean} pixelated
|
|
379
388
|
* @memberof Settings */
|
|
@@ -417,12 +426,17 @@ function setGLCircleSides(sides) { glCircleSides = sides; }
|
|
|
417
426
|
/** Set default size of tiles in pixels
|
|
418
427
|
* @param {Vector2} size
|
|
419
428
|
* @memberof Settings */
|
|
420
|
-
function
|
|
429
|
+
function setTileDefaultSize(size) { tileDefaultSize = size.copy(); }
|
|
421
430
|
|
|
422
|
-
/**
|
|
423
|
-
* @param {number}
|
|
431
|
+
/** Default padding pixels around tiles
|
|
432
|
+
* @param {number} padding
|
|
433
|
+
* @memberof Settings */
|
|
434
|
+
function setTileDefaultPadding(padding) { tileDefaultPadding = padding; }
|
|
435
|
+
|
|
436
|
+
/** Default amount of pixels smaller to draw tiles to prevent neighbor bleeding
|
|
437
|
+
* @param {number} bleed
|
|
424
438
|
* @memberof Settings */
|
|
425
|
-
function
|
|
439
|
+
function setTileDefaultBleed(bleed) { tileDefaultBleed = bleed; }
|
|
426
440
|
|
|
427
441
|
/** Set if collisions between objects are enabled
|
|
428
442
|
* @param {boolean} enable
|
|
@@ -573,7 +587,7 @@ function setMedalsPreventUnlock(preventUnlock) { medalsPreventUnlock = preventUn
|
|
|
573
587
|
/** Set if watermark with FPS should be shown
|
|
574
588
|
* @param {boolean} show
|
|
575
589
|
* @memberof Debug */
|
|
576
|
-
function
|
|
590
|
+
function setDebugWatermark(show) { debugWatermark = show; }
|
|
577
591
|
|
|
578
592
|
/** Set key code used to toggle debug mode, Esc by default
|
|
579
593
|
* @param {string} key
|
package/src/engineTileLayer.js
CHANGED
|
@@ -211,8 +211,7 @@ class CanvasLayer extends EngineObject
|
|
|
211
211
|
/** Destroy this canvas layer */
|
|
212
212
|
destroy()
|
|
213
213
|
{
|
|
214
|
-
if (this.destroyed)
|
|
215
|
-
return;
|
|
214
|
+
if (this.destroyed) return;
|
|
216
215
|
|
|
217
216
|
this.textureInfo.destroyWebGLTexture();
|
|
218
217
|
super.destroy();
|
|
@@ -444,8 +443,8 @@ class TileLayer extends CanvasLayer
|
|
|
444
443
|
if (!this.context) return;
|
|
445
444
|
|
|
446
445
|
// save current render settings
|
|
447
|
-
/** @type {[HTMLCanvasElement|OffscreenCanvas, CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D, Vector2, Vector2, number]} */
|
|
448
|
-
this.savedRenderSettings = [drawCanvas, drawContext, mainCanvasSize, cameraPos, cameraScale];
|
|
446
|
+
/** @type {[HTMLCanvasElement|OffscreenCanvas, CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D, Vector2, Vector2, number, Color]} */
|
|
447
|
+
this.savedRenderSettings = [drawCanvas, drawContext, mainCanvasSize, cameraPos, cameraScale, canvasClearColor];
|
|
449
448
|
|
|
450
449
|
// set the draw canvas and context to this layer
|
|
451
450
|
// use camera settings to match this layer's canvas
|
|
@@ -454,6 +453,7 @@ class TileLayer extends CanvasLayer
|
|
|
454
453
|
cameraPos = this.size.scale(.5);
|
|
455
454
|
const tileSize = this.tileInfo ? this.tileInfo.size : vec2(1);
|
|
456
455
|
cameraScale = tileSize.x;
|
|
456
|
+
canvasClearColor = CLEAR_BLACK;
|
|
457
457
|
mainCanvasSize = this.size.multiply(tileSize);
|
|
458
458
|
if (clear)
|
|
459
459
|
{
|
|
@@ -463,7 +463,7 @@ class TileLayer extends CanvasLayer
|
|
|
463
463
|
}
|
|
464
464
|
|
|
465
465
|
// disable smoothing for pixel art
|
|
466
|
-
|
|
466
|
+
drawContext.imageSmoothingEnabled = !tilesPixelated;
|
|
467
467
|
|
|
468
468
|
// setup gl rendering if enabled
|
|
469
469
|
glPreRender();
|
|
@@ -479,7 +479,7 @@ class TileLayer extends CanvasLayer
|
|
|
479
479
|
//debugSaveCanvas(this.canvas);
|
|
480
480
|
|
|
481
481
|
// set stuff back to normal
|
|
482
|
-
[drawCanvas, drawContext, mainCanvasSize, cameraPos, cameraScale] = this.savedRenderSettings;
|
|
482
|
+
[drawCanvas, drawContext, mainCanvasSize, cameraPos, cameraScale, canvasClearColor] = this.savedRenderSettings;
|
|
483
483
|
}
|
|
484
484
|
|
|
485
485
|
/** Draw the tile at a given position in the tile grid
|
package/src/engineUtilities.js
CHANGED
|
@@ -126,11 +126,7 @@ function percent(value, valueA, valueB)
|
|
|
126
126
|
* @return {number}
|
|
127
127
|
* @memberof Utilities */
|
|
128
128
|
function lerp(valueA, valueB, percent)
|
|
129
|
-
{
|
|
130
|
-
if (valueA >= 0 && valueA <= 1 && ((valueB < 0 || valueB > 1) && (percent < 0 || percent > 1)))
|
|
131
|
-
console.warn('lerp() parameter order changed! use lerp(start, end, p)');
|
|
132
|
-
return valueA + clamp(percent) * (valueB-valueA);
|
|
133
|
-
}
|
|
129
|
+
{ return valueA + clamp(percent) * (valueB-valueA); }
|
|
134
130
|
|
|
135
131
|
/** Gets percent between percentA and percentB and linearly interpolates between lerpA and lerpB
|
|
136
132
|
* A shortcut for lerp(lerpA, lerpB, percent(value, percentA, percentB))
|
|
@@ -161,11 +157,7 @@ function distanceWrap(valueA, valueB, wrapSize=1)
|
|
|
161
157
|
* @return {number}
|
|
162
158
|
* @memberof Utilities */
|
|
163
159
|
function lerpWrap(valueA, valueB, percent, wrapSize=1)
|
|
164
|
-
{
|
|
165
|
-
if (valueA >= 0 && valueA <= 1 && ((valueB < 0 || valueB > 1) && (percent < 0 || percent > 1)))
|
|
166
|
-
console.warn('lerpWrap() parameter order changed! use lerpWrap(start, end, p)');
|
|
167
|
-
return valueA + clamp(percent) * distanceWrap(valueB, valueA, wrapSize);
|
|
168
|
-
}
|
|
160
|
+
{ return valueA + clamp(percent) * distanceWrap(valueB, valueA, wrapSize); }
|
|
169
161
|
|
|
170
162
|
/** Returns signed wrapped distance between the two angles passed in
|
|
171
163
|
* @param {number} angleA
|
package/src/engineWebGL.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
'use strict';
|
|
15
15
|
|
|
16
|
-
/** The WebGL canvas which appears
|
|
16
|
+
/** The WebGL canvas which appears below the main canvas
|
|
17
17
|
* @type {HTMLCanvasElement}
|
|
18
18
|
* @memberof WebGL */
|
|
19
19
|
let glCanvas;
|
|
@@ -43,7 +43,7 @@ const gl_MAX_POLY_VERTEXES = gl_ARRAY_BUFFER_SIZE / gl_POLY_VERTEX_BYTE_STRIDE |
|
|
|
43
43
|
///////////////////////////////////////////////////////////////////////////////
|
|
44
44
|
|
|
45
45
|
// Initialize WebGL, called automatically by the engine
|
|
46
|
-
function glInit()
|
|
46
|
+
function glInit(rootElement)
|
|
47
47
|
{
|
|
48
48
|
// keep set of texture infos so they can be restored if context is lost
|
|
49
49
|
glTextureInfos = new Set;
|
|
@@ -67,8 +67,7 @@ function glInit()
|
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
// attach the WebGL canvas
|
|
71
|
-
const rootElement = mainCanvas.parentElement;
|
|
70
|
+
// attach the WebGL canvas;
|
|
72
71
|
rootElement.appendChild(glCanvas);
|
|
73
72
|
|
|
74
73
|
// startup webgl
|
|
@@ -286,6 +285,9 @@ function glClearCanvas()
|
|
|
286
285
|
glCanvas.width = drawCanvas.width;
|
|
287
286
|
glCanvas.height = drawCanvas.height;
|
|
288
287
|
glContext.viewport(0, 0, glCanvas.width, glCanvas.height);
|
|
288
|
+
const color = canvasClearColor;
|
|
289
|
+
if (color.a > 0)
|
|
290
|
+
glContext.clearColor(color.r, color.g, color.b, color.a);
|
|
289
291
|
glContext.clear(glContext.COLOR_BUFFER_BIT);
|
|
290
292
|
}
|
|
291
293
|
|
|
@@ -515,7 +517,6 @@ function glDraw(x, y, sizeX, sizeY, angle=0, uv0X=0, uv0Y=0, uv1X=1, uv1Y=1, rgb
|
|
|
515
517
|
glFlush();
|
|
516
518
|
glSetInstancedMode();
|
|
517
519
|
|
|
518
|
-
glPolyMode = false;
|
|
519
520
|
let offset = glBatchCount++ * gl_INDICES_PER_INSTANCE;
|
|
520
521
|
glPositionData[offset++] = x;
|
|
521
522
|
glPositionData[offset++] = y;
|
package/src/engineSplash.js
DELETED
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LittleJS Engine Splash Screen
|
|
3
|
-
* @namespace Settings
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
'use strict';
|
|
7
|
-
|
|
8
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
9
|
-
// LittleJS splash screen and logo
|
|
10
|
-
|
|
11
|
-
function drawEngineSplashScreen(t)
|
|
12
|
-
{
|
|
13
|
-
const x = overlayContext;
|
|
14
|
-
const w = overlayCanvas.width = innerWidth;
|
|
15
|
-
const h = overlayCanvas.height = innerHeight;
|
|
16
|
-
|
|
17
|
-
{
|
|
18
|
-
// background
|
|
19
|
-
const p3 = percent(t, 1, .8);
|
|
20
|
-
const p4 = percent(t, 0, .5);
|
|
21
|
-
const g = x.createRadialGradient(w/2,h/2,0,w/2,h/2,hypot(w,h)*.7);
|
|
22
|
-
g.addColorStop(0,hsl(0,0,lerp(0,p3/2,p4),p3).toString());
|
|
23
|
-
g.addColorStop(1,hsl(0,0,0,p3).toString());
|
|
24
|
-
x.save();
|
|
25
|
-
x.fillStyle = g;
|
|
26
|
-
x.fillRect(0,0,w,h);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// draw LittleJS logo...
|
|
30
|
-
const rect = (X, Y, W, H, C)=>
|
|
31
|
-
{
|
|
32
|
-
x.beginPath();
|
|
33
|
-
x.rect(X,Y,W,C?H*p:H);
|
|
34
|
-
x.fillStyle = C;
|
|
35
|
-
C ? x.fill() : x.stroke();
|
|
36
|
-
};
|
|
37
|
-
const line = (X, Y, Z, W)=>
|
|
38
|
-
{
|
|
39
|
-
x.beginPath();
|
|
40
|
-
x.lineTo(X,Y);
|
|
41
|
-
x.lineTo(Z,W);
|
|
42
|
-
x.stroke();
|
|
43
|
-
};
|
|
44
|
-
const circle = (X, Y, R, A=0, B=2*PI, C, F)=>
|
|
45
|
-
{
|
|
46
|
-
const D = (A+B)/2, E = p*(B-A)/2;
|
|
47
|
-
x.beginPath();
|
|
48
|
-
F && x.lineTo(X,Y);
|
|
49
|
-
x.arc(X,Y,R,D-E,D+E);
|
|
50
|
-
x.fillStyle = C;
|
|
51
|
-
C ? x.fill() : x.stroke();
|
|
52
|
-
};
|
|
53
|
-
const color = (c=0, l=0) =>
|
|
54
|
-
hsl([.98,.3,.57,.14][c%4],.8,[0,.3,.5,.8,.9][l]).toString();
|
|
55
|
-
const alpha = wave(1,1,t);
|
|
56
|
-
const p = percent(alpha, .1, .5);
|
|
57
|
-
|
|
58
|
-
// setup
|
|
59
|
-
x.translate(w/2,h/2);
|
|
60
|
-
const size = min(6, min(w,h)/99); // fit to screen
|
|
61
|
-
x.scale(size,size);
|
|
62
|
-
x.translate(-40,-35);
|
|
63
|
-
x.lineJoin = x.lineCap = 'round';
|
|
64
|
-
x.lineWidth = .1 + p*1.9;
|
|
65
|
-
|
|
66
|
-
// drawing effect
|
|
67
|
-
const p2 = percent(alpha,.1,1);
|
|
68
|
-
x.setLineDash([99*p2,99]);
|
|
69
|
-
|
|
70
|
-
// cab top
|
|
71
|
-
rect(7,16,18,-8,color(2,2));
|
|
72
|
-
rect(7,8,18,4,color(2,3));
|
|
73
|
-
rect(25,8,8,8,color(2,1));
|
|
74
|
-
rect(25,8,-18,8);
|
|
75
|
-
rect(25,8,8,8);
|
|
76
|
-
|
|
77
|
-
// cab
|
|
78
|
-
rect(25,16,7,23,color());
|
|
79
|
-
rect(11,39,14,-23,color(1,1));
|
|
80
|
-
rect(11,16,14,18,color(1,2));
|
|
81
|
-
rect(11,16,14,8,color(1,3));
|
|
82
|
-
rect(25,16,-14,24);
|
|
83
|
-
|
|
84
|
-
// cab window
|
|
85
|
-
rect(15,29,6,-9,color(2,2));
|
|
86
|
-
circle(15,21,5,0,PI/2,color(2,4),1);
|
|
87
|
-
rect(21,21,-6,9);
|
|
88
|
-
|
|
89
|
-
// little stack
|
|
90
|
-
rect(37,14,9,6,color(3,2));
|
|
91
|
-
rect(37,14,4.5,6,color(3,3));
|
|
92
|
-
rect(37,14,9,6);
|
|
93
|
-
|
|
94
|
-
// big stack
|
|
95
|
-
rect(50,20,10,-8,color(0,1));
|
|
96
|
-
rect(50,20,6.5,-8,color(0,2));
|
|
97
|
-
rect(50,20,3.5,-8,color(0,3));
|
|
98
|
-
rect(50,20,10,-8);
|
|
99
|
-
circle(55,2,11.4,.5,PI-.5,color(3,3));
|
|
100
|
-
circle(55,2,11.4,.5,PI/2,color(3,2),1);
|
|
101
|
-
circle(55,2,11.4,.5,PI-.5);
|
|
102
|
-
rect(45,7,20,-7,color(0,2));
|
|
103
|
-
rect(45,-1,20,4,color(0,3));
|
|
104
|
-
rect(45,-1,20,8);
|
|
105
|
-
|
|
106
|
-
// engine
|
|
107
|
-
for (let i=5; i--;)
|
|
108
|
-
{
|
|
109
|
-
// stagger radius to fix slight seam
|
|
110
|
-
circle(60-i*6,30, 9.9,0,2*PI,color(i+2,3));
|
|
111
|
-
circle(60-i*6,30,10.0,-.5,PI+.5,color(i+2,2));
|
|
112
|
-
circle(60-i*6,30,10.1,.5,PI-.5,color(i+2,1));
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// engine outline
|
|
116
|
-
circle(36,30,10,PI/2,PI*3/2);
|
|
117
|
-
circle(48,30,10,PI/2,PI*3/2);
|
|
118
|
-
circle(60,30,10);
|
|
119
|
-
line(36,20,60,20);
|
|
120
|
-
|
|
121
|
-
// engine front light
|
|
122
|
-
circle(60,30,4,PI,3*PI,color(3,2));
|
|
123
|
-
circle(60,30,4,PI,2*PI,color(3,3));
|
|
124
|
-
circle(60,30,4,PI,3*PI);
|
|
125
|
-
|
|
126
|
-
// front brush
|
|
127
|
-
for (let i=6; i--;)
|
|
128
|
-
{
|
|
129
|
-
x.beginPath();
|
|
130
|
-
x.lineTo(53,54);
|
|
131
|
-
x.lineTo(53,40);
|
|
132
|
-
x.lineTo(53+(1+i*2.9)*p,40);
|
|
133
|
-
x.lineTo(53+(4+i*3.5)*p,54);
|
|
134
|
-
x.fillStyle = color(0,i%2+2);
|
|
135
|
-
x.fill();
|
|
136
|
-
i%2 && x.stroke();
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// wheels
|
|
140
|
-
rect(6,40,5,5);
|
|
141
|
-
rect(6,40,5,5,color());
|
|
142
|
-
rect(15,54,38,-14,color());
|
|
143
|
-
for (let i=3; i--;)
|
|
144
|
-
for (let j=2; j--;)
|
|
145
|
-
{
|
|
146
|
-
circle(15*i+15,47,j?7:1,PI,3*PI,color(i,3));
|
|
147
|
-
x.stroke();
|
|
148
|
-
circle(15*i+15,47,j?7:1,0,PI,color(i,2));
|
|
149
|
-
x.stroke();
|
|
150
|
-
}
|
|
151
|
-
line(6,40,68,40); // center
|
|
152
|
-
line(77,54,4,54); // bottom
|
|
153
|
-
|
|
154
|
-
// draw engine name
|
|
155
|
-
const s = engineName;
|
|
156
|
-
x.font = '900 16px arial';
|
|
157
|
-
x.textAlign = 'center';
|
|
158
|
-
x.textBaseline = 'top';
|
|
159
|
-
x.lineWidth = .1+p*3.9;
|
|
160
|
-
let w2 = 0;
|
|
161
|
-
for (let i=0; i<s.length; ++i)
|
|
162
|
-
w2 += x.measureText(s[i]).width;
|
|
163
|
-
for (let j=2; j--;)
|
|
164
|
-
for (let i=0, X=41-w2/2; i<s.length; ++i)
|
|
165
|
-
{
|
|
166
|
-
x.fillStyle = color(i,2);
|
|
167
|
-
const w = x.measureText(s[i]).width;
|
|
168
|
-
x[j?'strokeText':'fillText'](s[i],X+w/2,55.5,17*p);
|
|
169
|
-
X += w;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
x.restore();
|
|
173
|
-
}
|