littlejsengine 1.2.0 → 1.3.0

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/engine/index.d.ts CHANGED
@@ -60,7 +60,19 @@ declare function drawCanvas2D(pos: Vector2, size: Vector2, angle: number, mirror
60
60
  * @param {Boolean} [useWebGL=glEnable]
61
61
  * @memberof Draw */
62
62
  declare function setBlendMode(additive?: boolean, useWebGL?: boolean): void;
63
+ /** Draw text on overlay canvas in screen space
64
+ * Automatically splits new lines into rows
65
+ * @param {String} text
66
+ * @param {Vector2} pos
67
+ * @param {Number} [size=1]
68
+ * @param {Color} [color=new Color(1,1,1)]
69
+ * @param {Number} [lineWidth=0]
70
+ * @param {Color} [lineColor=new Color(0,0,0)]
71
+ * @param {String} [textAlign='center']
72
+ * @memberof Draw */
73
+ declare function drawTextScreen(text: string, pos: Vector2, size?: number, color?: Color, lineWidth?: number, lineColor?: Color, textAlign?: string, font?: string): void;
63
74
  /** Draw text on overlay canvas in world space
75
+ * Automatically splits new lines into rows
64
76
  * @param {String} text
65
77
  * @param {Vector2} pos
66
78
  * @param {Number} [size=1]
@@ -69,7 +81,7 @@ declare function setBlendMode(additive?: boolean, useWebGL?: boolean): void;
69
81
  * @param {Color} [lineColor=new Color(0,0,0)]
70
82
  * @param {String} [textAlign='center']
71
83
  * @memberof Draw */
72
- declare function drawText(text: string, pos: Vector2, size?: number, color?: Color, lineWidth?: number, lineColor?: Color, textAlign?: string, font?: string): void;
84
+ declare function drawText(text: string, pos: Vector2, size?: number, color?: Color, lineWidth?: number, lineColor?: Color, textAlign?: string, font: any): void;
73
85
  /** Toggle fullsceen mode
74
86
  * @memberof Draw */
75
87
  declare function toggleFullscreen(): void;
@@ -551,6 +563,10 @@ declare class Vector2 {
551
563
  * @param {Vector2} arraySize
552
564
  * @return {Boolean} */
553
565
  arrayCheck(arraySize: Vector2): boolean;
566
+ /** Returns this vector expressed as a string
567
+ * @param {float} digits - precision to display
568
+ * @return {String} */
569
+ toString(digits?: float): string;
554
570
  }
555
571
  /**
556
572
  * Color object (red, green, blue, alpha) with some helpful functions
@@ -606,7 +622,7 @@ declare class Color {
606
622
  * @param {Number} percent
607
623
  * @return {Color} */
608
624
  lerp(c: any, p: any): Color;
609
- /** Sets this color given a hue, saturation, lightness , and alpha
625
+ /** Sets this color given a hue, saturation, lightness, and alpha
610
626
  * @param {Number} [hue=0]
611
627
  * @param {Number} [saturation=0]
612
628
  * @param {Number} [lightness=1]
@@ -618,12 +634,19 @@ declare class Color {
618
634
  * @param {Number} [alphaAmount=0]
619
635
  * @return {Color} */
620
636
  mutate(amount?: number, alphaAmount?: number): Color;
621
- /** Returns this color expressed as an rgba string
637
+ /** Returns this color expressed as an CSS color value
622
638
  * @return {String} */
623
- rgba(): string;
624
- /** Returns this color expressed as 32 bit integer value
639
+ toString(): string;
640
+ /** Returns this color expressed as 32 bit integer RGBA value
625
641
  * @return {Number} */
626
642
  rgbaInt(): number;
643
+ /** Returns this color expressed as a hex code
644
+ * @return {String} */
645
+ hex(): string;
646
+ /** Set this color from a hex code
647
+ * @param {String} hex - html hex code
648
+ * @return {Color} */
649
+ setHex(hex: string): Color;
627
650
  }
628
651
  /**
629
652
  * Timer object tracks how long has passed since it was set
@@ -660,6 +683,9 @@ declare class Timer {
660
683
  /** Get percentage elapsed based on time it was set to, returns 0 if not set
661
684
  * @return {Number} */
662
685
  getPercent(): number;
686
+ /** Returns this timer expressed as a string
687
+ * @return {String} */
688
+ toString(): string;
663
689
  }
664
690
  /** The max size of the canvas, centered if window is larger
665
691
  * @type {Vector2}
@@ -760,6 +786,10 @@ declare let inputWASDEmulateDirection: number;
760
786
  * @default
761
787
  * @memberof Settings */
762
788
  declare let touchGamepadEnable: number;
789
+ /** True if touch gamepad should be analog stick or false to use if 8 way dpad
790
+ * @default
791
+ * @memberof Settings */
792
+ declare let touchGamepadAnalog: number;
763
793
  /** Size of virutal gamepad for touch devices in pixels
764
794
  * @default
765
795
  * @memberof Settings */
@@ -839,7 +869,7 @@ declare class EngineObject {
839
869
  * @param {Vector2} [size=objectDefaultSize] - World space size of the object
840
870
  * @param {Number} [tileIndex=-1] - Tile to use to render object, untextured if -1
841
871
  * @param {Vector2} [tileSize=tileSizeDefault] - Size of tile in source pixels
842
- * @param {Number} [angle=0] - Angle to rotate the object
872
+ * @param {Number} [angle=0] - Angle the object is rotated by
843
873
  * @param {Color} [color] - Color to apply to tile when rendered
844
874
  * @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
845
875
  */
@@ -927,6 +957,7 @@ declare class EngineObject {
927
957
  setCollision(collideSolidObjects?: boolean, isSolid?: boolean, collideTiles?: boolean): void;
928
958
  collideSolidObjects: boolean;
929
959
  isSolid: boolean;
960
+ toString(): string;
930
961
  }
931
962
  /** Tile sheet for batch rendering system
932
963
  * @type {Image}
@@ -974,6 +1005,7 @@ declare function worldToScreen(worldPos: Vector2): Vector2;
974
1005
  * // draw text
975
1006
  * font.drawTextScreen("LittleJS\nHello World!", vec2(200, 50));
976
1007
  */
1008
+ declare let engineFontImage: any;
977
1009
  declare class FontImage {
978
1010
  /** Create an image font
979
1011
  * @param {Image} [image] - The image the font is stored in, if undefined the default font is used
@@ -983,7 +1015,7 @@ declare class FontImage {
983
1015
  * @param {CanvasRenderingContext2D} [context=overlayContext] - context to draw to
984
1016
  */
985
1017
  constructor(image?: new (width?: number, height?: number) => HTMLImageElement, tileSize?: Vector2, paddingSize?: Vector2, startTileIndex?: number, context?: CanvasRenderingContext2D);
986
- image: new (width?: number, height?: number) => HTMLImageElement;
1018
+ image: any;
987
1019
  tileSize: Vector2;
988
1020
  paddingSize: Vector2;
989
1021
  startTileIndex: number;
@@ -1102,7 +1134,6 @@ declare const isTouchDevice: boolean;
1102
1134
  declare let touchGamepadTimer: Timer;
1103
1135
  declare let touchGamepadButtons: any[];
1104
1136
  declare let touchGamepadStick: Vector2;
1105
- declare let touchGamepadAnalog: number;
1106
1137
  /**
1107
1138
  * Sound Object - Stores a zzfx sound for later use and can be played positionally
1108
1139
  * <br>
@@ -1268,12 +1299,12 @@ declare class TileLayerData {
1268
1299
  */
1269
1300
  declare class TileLayer extends EngineObject {
1270
1301
  /** Create a tile layer object
1271
- * @param {Vector2} [position=new Vector2()] - World space position
1272
- * @param {Vector2} [size=objectDefaultSize] - World space size
1273
- * @param {Vector2} [tileSize=tileSizeDefault] - Size of tiles in source pixels
1274
- * @param {Vector2} [scale=new Vector2(1,1)] - How much to scale this layer when rendered
1275
- * @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
1276
- */
1302
+ * @param {Vector2} [position=new Vector2()] - World space position
1303
+ * @param {Vector2} [size=tileCollisionSize] - World space size
1304
+ * @param {Vector2} [tileSize=tileSizeDefault] - Size of tiles in source pixels
1305
+ * @param {Vector2} [scale=new Vector2(1,1)] - How much to scale this layer when rendered
1306
+ * @param {Number} [renderOrder=0] - Objects sorted by renderOrder before being rendered
1307
+ */
1277
1308
  constructor(pos: any, size?: Vector2, tileSize?: Vector2, scale?: Vector2, renderOrder?: number);
1278
1309
  /** @property {HTMLCanvasElement} - The canvas used by this tile layer */
1279
1310
  canvas: HTMLCanvasElement;
@@ -1337,9 +1368,9 @@ declare class TileLayer extends EngineObject {
1337
1368
  * let pos = vec2(2,3);
1338
1369
  * let particleEmiter = new ParticleEmitter
1339
1370
  * (
1340
- * pos, 1, 0, 500, PI, // pos, emitSize, emitTime, emitRate, emiteCone
1371
+ * pos, 0, 1, 0, 500, PI, // pos, angle, emitSize, emitTime, emitRate, emiteCone
1341
1372
  * 0, vec2(16), // tileIndex, tileSize
1342
- * new Color, new Color(0,0,0), // colorStartA, colorStartB
1373
+ * new Color(1,1,1), new Color(0,0,0), // colorStartA, colorStartB
1343
1374
  * new Color(1,1,1,0), new Color(0,0,0,0), // colorEndA, colorEndB
1344
1375
  * 2, .2, .2, .1, .05, // particleTime, sizeStart, sizeEnd, particleSpeed, particleAngleSpeed
1345
1376
  * .99, 1, 1, PI, .05, // damping, angleDamping, gravityScale, particleCone, fadeRate,
@@ -1349,6 +1380,7 @@ declare class TileLayer extends EngineObject {
1349
1380
  declare class ParticleEmitter extends EngineObject {
1350
1381
  /** Create a particle system with the given settings
1351
1382
  * @param {Vector2} position - World space position of the emitter
1383
+ * @param {Number} [angle=0] - Angle to emit the particles
1352
1384
  * @param {Number} [emitSize=0] - World space size of the emitter (float for circle diameter, vec2 for rect)
1353
1385
  * @param {Number} [emitTime=0] - How long to stay alive (0 is forever)
1354
1386
  * @param {Number} [emitRate=100] - How many particles per second to spawn, does not emit if 0
@@ -1375,7 +1407,7 @@ declare class ParticleEmitter extends EngineObject {
1375
1407
  * @param {Boolean} [randomColorLinear=1] - Should color be randomized linearly or across each component
1376
1408
  * @param {Number} [renderOrder=0] - Render order for particles (additive is above other stuff by default)
1377
1409
  */
1378
- constructor(pos: any, emitSize?: number, emitTime?: number, emitRate?: number, emitConeAngle?: number, tileIndex?: number, tileSize?: number, colorStartA?: Color, colorStartB?: Color, colorEndA?: Color, colorEndB?: Color, particleTime?: number, sizeStart?: number, sizeEnd?: number, speed?: number, angleSpeed?: number, damping?: number, angleDamping?: number, gravityScale?: number, particleConeAngle?: number, fadeRate?: number, randomness?: number, collideTiles?: boolean, additive?: boolean, randomColorLinear?: boolean, renderOrder?: number);
1410
+ constructor(pos: any, angle?: number, emitSize?: number, emitTime?: number, emitRate?: number, emitConeAngle?: number, tileIndex?: number, tileSize?: number, colorStartA?: Color, colorStartB?: Color, colorEndA?: Color, colorEndB?: Color, particleTime?: number, sizeStart?: number, sizeEnd?: number, speed?: number, angleSpeed?: number, damping?: number, angleDamping?: number, gravityScale?: number, particleConeAngle?: number, fadeRate?: number, randomness?: number, collideTiles?: boolean, additive?: boolean, randomColorLinear?: boolean, renderOrder?: number);
1379
1411
  /** @property {Number} - World space size of the emitter (float for circle diameter, vec2 for rect) */
1380
1412
  emitSize: number;
1381
1413
  /** @property {Number} - How long to stay alive (0 is forever) */
@@ -1410,6 +1442,8 @@ declare class ParticleEmitter extends EngineObject {
1410
1442
  fadeRate: number;
1411
1443
  /** @property {Number} - Apply extra randomness percent */
1412
1444
  randomness: number;
1445
+ /** @property {Number} - Do particles collide against tiles */
1446
+ collideTiles: boolean;
1413
1447
  /** @property {Number} - Should particles use addtive blend */
1414
1448
  additive: boolean;
1415
1449
  /** @property {Number} - If set the partile is drawn as a trail, stretched in the drection of velocity */
@@ -1514,8 +1548,6 @@ declare class Newgrounds {
1514
1548
  * @param {Number} id - The scoreboard id
1515
1549
  * @param {Number} value - The score value */
1516
1550
  postScore(id: number, value: number): any;
1517
- /** Send message to log a view */
1518
- logView(): any;
1519
1551
  /** Get scores from a scoreboard
1520
1552
  * @param {Number} id - The scoreboard id
1521
1553
  * @param {String} [user=0] - A user's id or name
@@ -1525,6 +1557,8 @@ declare class Newgrounds {
1525
1557
  * @return {Object} - The response JSON object
1526
1558
  */
1527
1559
  getScores(id: number, user?: string, social?: number, skip?: number, limit?: number): any;
1560
+ /** Send message to log a view */
1561
+ logView(): any;
1528
1562
  /** Send a message to call a component of the Newgrounds API
1529
1563
  * @param {String} component - Name of the component
1530
1564
  * @param {Object} [parameters=0] - Parameters to use for call
@@ -1583,7 +1617,7 @@ declare const gl_VERTEX_BYTE_STRIDE: number;
1583
1617
  /** Name of engine */
1584
1618
  declare const engineName: "LittleJS";
1585
1619
  /** Version of engine */
1586
- declare const engineVersion: "1.2.0";
1620
+ declare const engineVersion: "1.3.0";
1587
1621
  /** Frames per second to update objects
1588
1622
  * @default */
1589
1623
  declare const frameRate: 60;
@@ -1609,4 +1643,4 @@ declare let tileImageFixBleed: any;
1609
1643
  declare let averageFPS: any;
1610
1644
  declare let drawCount: any;
1611
1645
  declare const styleBody: string;
1612
- declare const styleCanvas: "position:absolute";
1646
+ declare const styleCanvas: "position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)";
@@ -56,11 +56,11 @@ class Block extends EngineObject
56
56
  const color1 = this.color;
57
57
  const color2 = color1.lerp(new Color, .5);
58
58
  new ParticleEmitter(
59
- this.pos, this.size, .1, 200, PI, // pos, emitSize, emitTime, emitRate, emiteCone
59
+ this.pos, 0, this.size, .1, 200, PI, // pos, angle, emitSize, emitTime, emitRate, emiteCone
60
60
  0, vec2(16), // tileIndex, tileSize
61
61
  color1, color2, // colorStartA, colorStartB
62
62
  color1.scale(1,0), color2.scale(1,0), // colorEndA, colorEndB
63
- .2, 1, 1, .1, .05, // particleTime, sizeStart, sizeEnd, particleSpeed, particleAngleSpeed
63
+ .2, 1, 1, .1, .05, // particleTime, sizeStart, sizeEnd, particleSpeed, particleAngleSpeed
64
64
  .99, .95, .4, PI, .1, // damping, angleDamping, gravityScale, particleCone, fadeRate,
65
65
  1, 0, 1 // randomness, collide, additive, randomColorLinear, renderOrder
66
66
  );
@@ -5,6 +5,6 @@
5
5
  <link rel=icon type=image/png href=../../favicon.png>
6
6
  </head><body>
7
7
 
8
- <script src=../../engine/engine.all.js?97></script>
9
- <script src=game.js?97></script>
10
- <script src=gameObjects.js?97></script>
8
+ <script src=../../engine/engine.all.js?104></script>
9
+ <script src=game.js?104></script>
10
+ <script src=gameObjects.js?104></script>
@@ -0,0 +1,366 @@
1
+ <html><head><meta charset=utf-8>
2
+ <meta name=viewport content=width=device-width,height=device-height,initial-scale=1,maximum-scale=1>
3
+ <meta name=apple-mobile-web-app-capable content=yes>
4
+ <meta name=mobile-web-app-capable content=yes>
5
+ <link rel=icon type=image/png href=favicon.png>
6
+ <style>
7
+ input
8
+ {
9
+ width:99px;
10
+ }
11
+ button
12
+ {
13
+ margin:1px;
14
+ }
15
+ </style>
16
+ </head><body>
17
+
18
+ <script src=../../engine/engineDebug.js?104></script>
19
+ <script src=../../engine/engineUtilities.js?104></script>
20
+ <script src=../../engine/engineSettings.js?104></script>
21
+ <script src=../../engine/engineObject.js?104></script>
22
+ <script src=../../engine/engineDraw.js?104></script>
23
+ <script src=../../engine/engineInput.js?104></script>
24
+ <script src=../../engine/engineAudio.js?104></script>
25
+ <script src=../../engine/engineTileLayer.js?104></script>
26
+ <script src=../../engine/engineParticles.js?104></script>
27
+ <script src=../../engine/engineMedals.js?104></script>
28
+ <script src=../../engine/engineWebGL.js?104></script>
29
+ <script src=../../engine/engine.js?104></script>
30
+ <script>
31
+
32
+ 'use strict';
33
+
34
+ let particleEditor = 0, particleSystem, particleSystemDiv, particleSystemCode;
35
+ let inputCondense;
36
+ let restartTimer = new Timer();
37
+ const storagePrefix = 'particles_';
38
+
39
+ const particleSettings = [];
40
+ function addSetting(name, type, min, max, step, description)
41
+ {
42
+ particleSettings.push({name, type:type||'number', min, max, step, description});
43
+ }
44
+
45
+ addSetting('emitSize', '', 0, 1e9, .1);
46
+ addSetting('emitTime', '', 0, 1e9, .1);
47
+ addSetting('emitRate', '', 0, 1e9, 1);
48
+ addSetting('emitConeAngle', '', 0, 1e9, .01);
49
+ addSetting('tileIndex', '', -1, 1e9, 1);
50
+ addSetting('tileSizeX', '', 0, 1e9, 1);
51
+ addSetting('tileSizeY', '', 0, 1e9, 1);
52
+ addSetting('colorStartA', 'color');
53
+ addSetting('colorStartB', 'color');
54
+ addSetting('colorEndA', 'color');
55
+ addSetting('colorEndB', 'color');
56
+ addSetting('colorAlphaStartA', 'alpha', 0, 1, .01);
57
+ addSetting('colorAlphaStartB', 'alpha', 0, 1, .01);
58
+ addSetting('colorAlphaEndA', 'alpha', 0, 1, .01);
59
+ addSetting('colorAlphaEndB', 'alpha', 0, 1, .01);
60
+ addSetting('particleTime', '', 0, 1e9, .1);
61
+ addSetting('sizeStart', '', 0, 1e9, .01);
62
+ addSetting('sizeEnd', '', 0, 1e9, .01);
63
+ addSetting('speed', '', 0, 1e9, .01);
64
+ addSetting('angleSpeed', '', 0, 1e9, .01);
65
+ addSetting('damping', '', 0, 1, .01);
66
+ addSetting('angleDamping', '', 0, 1, .01);
67
+ addSetting('gravityScale', '', -1e9, 1e9, .1);
68
+ addSetting('particleConeAngle','', 0, 1e9, .1);
69
+ addSetting('fadeRate', '', 0, 1, .01);
70
+ addSetting('randomness', '', 0, 1, .01);
71
+ addSetting('collideTiles', 'checkbox');
72
+ addSetting('additive', 'checkbox');
73
+ addSetting('randomColorLinear','checkbox');
74
+
75
+ function makeEmitter()
76
+ {
77
+ particleSystem = new ParticleEmitter(cameraPos);
78
+ particleSystem.emitConeAngle =
79
+ particleSystem.particleConeAngle = 3.14;
80
+ }
81
+
82
+ ///////////////////////////////////////////////////////////////////////////////
83
+ function gameInit()
84
+ {
85
+ makeEmitter();
86
+ gravity = -.01;
87
+ cameraScale = 50;
88
+
89
+ const div = particleSystemDiv = document.createElement('div');
90
+ div.innerHTML = '<big><b>LittleJS Particle Tool';
91
+ div.style = 'position:absolute;top:10;left:10;color:#fff';
92
+ document.body.appendChild(div);
93
+
94
+ for (const setting of particleSettings)
95
+ {
96
+ const input = setting.input = document.createElement('input');
97
+ const name = setting.name;
98
+ input.oninput = (e)=> updateParticles();
99
+ input.type = setting.type == 'alpha' ? 'number' : setting.type;
100
+ if (setting.min !== undefined)
101
+ input.min = setting.min;
102
+ if (setting.max !== undefined)
103
+ input.max = setting.max;
104
+ if (setting.step !== undefined)
105
+ input.step = setting.step;
106
+ if (name == 'emitConeAngle' || name == 'particleConeAngle')
107
+ particleSystem[name] = 3.14; // simplify pi
108
+
109
+ div.appendChild(document.createElement('br'));
110
+ div.appendChild(input);
111
+ div.appendChild(document.createTextNode(' ' + name));
112
+ }
113
+
114
+ div.appendChild(document.createElement('br'));
115
+ div.appendChild(document.createElement('br'));
116
+
117
+ {
118
+ const button = document.createElement('button')
119
+ div.appendChild(button);
120
+ button.innerHTML = 'Copy To Clipboard';
121
+ button.onclick = (e)=> navigator.clipboard.writeText(particleSystemCode.value);
122
+ }
123
+ {
124
+ const button = document.createElement('button');
125
+ div.appendChild(button);
126
+ button.innerHTML = 'Reset';
127
+ button.onclick = (e)=>
128
+ {
129
+ if (!confirm('Reset to default?'))
130
+ return;
131
+ particleSystem.destroy();
132
+ makeEmitter();
133
+ updateInputs(0);
134
+ cameraScale = 50;
135
+ }
136
+ }
137
+ {
138
+ inputCondense = document.createElement('input');
139
+ div.appendChild(inputCondense);
140
+ inputCondense.checked = 'true';
141
+ inputCondense.type = 'checkbox';
142
+ inputCondense.style.width = 'initial';
143
+ inputCondense.oninput = (e)=> updateParticles();
144
+ div.appendChild(document.createTextNode(' Condense'));
145
+ }
146
+
147
+ //div.appendChild(document.createTextNode('JavaScript Code... '));
148
+ div.appendChild(document.createElement('br'));
149
+ div.appendChild(particleSystemCode = document.createElement('textarea'));
150
+ particleSystemCode.style.width = 500;
151
+ particleSystemCode.style.height = 100;
152
+ particleSystemCode.disabled = true;
153
+
154
+ updateInputs(0);
155
+
156
+ // load from storage
157
+ for (const setting of particleSettings)
158
+ {
159
+ const type = setting.type;
160
+ const storageName = storagePrefix + setting.name;
161
+ const savedValue = localStorage[storageName];
162
+ if (savedValue == undefined)
163
+ continue;
164
+
165
+ if (type == 'checkbox')
166
+ setting.input.checked = savedValue == 'true';
167
+ else
168
+ setting.input.value = savedValue;
169
+ }
170
+
171
+ updateParticles();
172
+ }
173
+
174
+ function updateParticles()
175
+ {
176
+ for (const setting of particleSettings)
177
+ {
178
+ const input = setting.input;
179
+ const name = setting.name;
180
+ const type = setting.type;
181
+ const inputFloat = parseFloat(input.value) || 0;
182
+ if (type == 'color')
183
+ {
184
+ const color = new Color().setHex(input.value);
185
+ particleSystem[name].r = color.r;
186
+ particleSystem[name].g = color.g;
187
+ particleSystem[name].b = color.b;
188
+ }
189
+ else if (type == 'alpha')
190
+ {
191
+ if (name == 'colorAlphaStartA')
192
+ particleSystem.colorStartA.a = clamp(inputFloat);
193
+ else if (name == 'colorAlphaStartB')
194
+ particleSystem.colorStartB.a = clamp(inputFloat);
195
+ else if (name == 'colorAlphaEndA')
196
+ particleSystem.colorEndA.a = clamp(inputFloat);
197
+ else if (name == 'colorAlphaEndB')
198
+ particleSystem.colorEndB.a = clamp(inputFloat);
199
+ }
200
+ else if (name == 'tileSizeX')
201
+ {
202
+ particleSystem.tileSize = vec2(parseInt(input.value), particleSystem.tileSize.y);
203
+ }
204
+ else if (name == 'tileSizeY')
205
+ {
206
+ particleSystem.tileSize = vec2(particleSystem.tileSize.x, parseInt(input.value));
207
+ }
208
+ else if (type == 'checkbox')
209
+ particleSystem[name] = input.checked ? 1 : 0;
210
+ else if (name == 'emitRate')
211
+ particleSystem[name] = min(inputFloat,1e3);
212
+ else
213
+ particleSystem[name] = clamp(inputFloat, setting.min, setting.max);
214
+ }
215
+ updateInputs();
216
+ }
217
+
218
+ function updateInputs(save=1)
219
+ {
220
+ for (const setting of particleSettings)
221
+ {
222
+ const input = setting.input;
223
+ const name = setting.name;
224
+ const type = setting.type;
225
+
226
+ if (type == 'color')
227
+ {
228
+ const color = particleSystem[name];
229
+ input.value = color.hex();
230
+ }
231
+ else if (type == 'alpha')
232
+ {
233
+ if (name == 'colorAlphaStartA')
234
+ input.value = particleSystem.colorStartA.a;
235
+ else if (name == 'colorAlphaStartB')
236
+ input.value = particleSystem.colorStartB.a;
237
+ else if (name == 'colorAlphaEndA')
238
+ input.value = particleSystem.colorEndA.a;
239
+ else if (name == 'colorAlphaEndB')
240
+ input.value = particleSystem.colorEndB.a;
241
+ }
242
+ else if (name == 'tileSizeX')
243
+ input.value = particleSystem.tileSize.x;
244
+ else if (name == 'tileSizeY')
245
+ input.value = particleSystem.tileSize.y;
246
+ else if (type == 'checkbox')
247
+ input.checked = particleSystem[name];
248
+ else
249
+ input.value = particleSystem[name] || '0';
250
+
251
+ if (save)
252
+ {
253
+ const storageName = storagePrefix + setting.name;
254
+ localStorage[storageName] = type == 'checkbox' ?
255
+ input.checked : input.value;
256
+ }
257
+ }
258
+ particleSystemCode.value = getCode();
259
+ }
260
+
261
+ function getCode()
262
+ {
263
+ const condense = inputCondense.checked;
264
+ let code = '';
265
+
266
+ // https://www.codingem.com/javascript-how-to-limit-decimal-places/
267
+ Number.prototype.round = function(n) {
268
+ const d = Math.pow(10, n);
269
+ return Math.round((this + Number.EPSILON) * d) / d;
270
+ }
271
+
272
+ code = 'new ParticleEmitter(';
273
+ if (condense)
274
+ code += 'vec2(), 0, ';
275
+ else
276
+ code += '\n vec2(), 0,\t//position, angle\n';
277
+
278
+ let count = 0;
279
+ for (const setting of particleSettings)
280
+ {
281
+ const name = setting.name;
282
+ const type = setting.type;
283
+ let value;
284
+ if (name == 'tileSizeX' || type == 'alpha')
285
+ continue;
286
+
287
+ if (name == 'tileSizeY')
288
+ value = `vec2(${particleSystem.tileSize.x}, ${particleSystem.tileSize.y})`;
289
+ else if (type == 'color')
290
+ {
291
+ const c = particleSystem[name];
292
+ const p = 3;
293
+ value = `new Color(${c.r.round(p)}, ${c.g.round(p)}, ${c.b.round(p)}, ${c.a.round(p)})`;
294
+ }
295
+ else if (type == 'checkbox')
296
+ value = particleSystem[name] ? 1 : 0;
297
+ else
298
+ value = particleSystem[name].round(3);
299
+ if (!condense)
300
+ code += ' ';
301
+ code += value;
302
+
303
+ const isEnd = name == 'randomColorLinear';
304
+ if (!condense)
305
+ {
306
+ code += ',\t// ' + name;
307
+ if (!isEnd)
308
+ code += '\n';
309
+ }
310
+ else if (!isEnd)
311
+ code += ', ';
312
+ }
313
+
314
+
315
+ if (condense)
316
+ code += ');';
317
+ else
318
+ code += '\n); // particle emitter';
319
+
320
+ return code;
321
+ }
322
+
323
+ ///////////////////////////////////////////////////////////////////////////////
324
+ function gameUpdate()
325
+ {
326
+ if (!restartTimer.isSet() && particleSystem.destroyed)
327
+ restartTimer.set(1);
328
+ else if (restartTimer.elapsed())
329
+ {
330
+ restartTimer.unset()
331
+ makeEmitter();
332
+ updateParticles();
333
+ }
334
+
335
+ if (document.activeElement == document.body)
336
+ {
337
+ particleSystem.pos = mouseIsDown(0) ? mousePos : vec2();
338
+ if (mouseWheel)
339
+ {
340
+ cameraScale -= sign(mouseWheel)*cameraScale/5;
341
+ cameraScale = clamp(cameraScale, 10, 300);
342
+ }
343
+ }
344
+ }
345
+
346
+ ///////////////////////////////////////////////////////////////////////////////
347
+ function gameUpdatePost()
348
+ {
349
+
350
+ }
351
+
352
+ ///////////////////////////////////////////////////////////////////////////////
353
+ function gameRender()
354
+ {
355
+ }
356
+
357
+ ///////////////////////////////////////////////////////////////////////////////
358
+ function gameRenderPost()
359
+ {
360
+ }
361
+
362
+ ///////////////////////////////////////////////////////////////////////////////
363
+ // Startup LittleJS Engine
364
+ engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, 'tiles.png');
365
+
366
+ </script>
Binary file
@@ -73,18 +73,18 @@ function gameRender()
73
73
  function gameRenderPost()
74
74
  {
75
75
  // draw to overlay canvas for hud rendering
76
- const drawText = (text, x, y, size=70) =>
76
+ const drawText = (text, x, y, size=50) =>
77
77
  {
78
78
  overlayContext.textAlign = 'center';
79
79
  overlayContext.textBaseline = 'top';
80
80
  overlayContext.font = size + 'px arial';
81
81
  overlayContext.fillStyle = '#fff';
82
- overlayContext.lineWidth = 3;
82
+ overlayContext.lineWidth = 2;
83
83
  overlayContext.strokeText(text, x, y);
84
84
  overlayContext.fillText(text, x, y);
85
85
  }
86
- drawText('Score: ' + score, overlayCanvas.width*1/3, 20);
87
- drawText('Deaths: ' + deaths, overlayCanvas.width*2/3, 20);
86
+ drawText('Score: ' + score, overlayCanvas.width*1/4, 20);
87
+ drawText('Deaths: ' + deaths, overlayCanvas.width*3/4, 20);
88
88
  }
89
89
 
90
90
  ///////////////////////////////////////////////////////////////////////////////