litecanvas 0.103.4 → 0.103.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dist.js CHANGED
@@ -1,103 +1,187 @@
1
1
  (() => {
2
- // src/zzfx.js
3
2
  var setupZzFX = (global) => {
4
3
  const zzfxX = new AudioContext();
5
4
  global.zzfxV = 1;
6
- return (i = 1, d = 0.05, z = 220, e = 0, P = 0, S = 0.1, I = 0, c = 1, T = 0, H = 0, V = 0, J = 0, h = 0, j = 0, K = 0, E = 0, r = 0, B = 1, X = 0, L = 0, D = 0) => {
7
- let n = Math, t = 2 * n.PI, a = 44100, F = T *= 500 * t / a / a, O = z *= (1 - d + 2 * d * n.random(d = [])) * t / a, x = 0, _ = 0, f = 0, g = 1, $ = 0, l = 0, o = 0, s = D < 0 ? -1 : 1, u = t * s * D * 2 / a, G = n.cos(u), C = n.sin, Q = C(u) / 4, M = 1 + Q, m = -2 * G / M, y = (1 - Q) / M, R = (1 + s * G) / 2 / M, A = -(s + G) / M, v = R, U = 0, W = 0, Y = 0, Z = 0;
8
- for (e = a * e + 9, X *= a, P *= a, S *= a, r *= a, H *= 500 * t / a ** 3, K *= t / a, V *= t / a, J *= a, h = a * h | 0, i *= 0.3 * global.zzfxV, s = e + X + P + S + r | 0; f < s; d[f++] = o * i) ++l % (100 * E | 0) || (o = I ? 1 < I ? 2 < I ? 3 < I ? C(x * x) : n.max(n.min(n.tan(x), 1), -1) : 1 - (2 * x / t % 2 + 2) % 2 : 1 - 4 * n.abs(n.round(x / t) - x / t) : C(x), o = (h ? 1 - L + L * C(t * f / h) : 1) * (o < 0 ? -1 : 1) * n.abs(o) ** c * (f < e ? f / e : f < e + X ? 1 - (f - e) / X * (1 - B) : f < e + X + P ? B : f < s - r ? (s - f - r) / S * B : 0), o = r ? o / 2 + (r > f ? 0 : (f < s - r ? 1 : (s - f) / r) * d[f - r | 0] / 2 / i) : o, D && (o = Z = v * U + A * (U = W) + R * (W = o) - y * Y - m * (Y = Z))), u = (z += T += H) * n.cos(K * _++), x += u + u * j * C(f ** 5), g && ++g > J && (z += V, O += V, g = 0), !h || ++$ % h || (z = O, T = F, g = g || 1);
9
- i = zzfxX.createBuffer(1, s, a), i.getChannelData(0).set(d), z = zzfxX.createBufferSource(), z.buffer = i, z.connect(zzfxX.destination), z.start();
5
+ return (
6
+ i = 1,
7
+ d = 0.05,
8
+ z = 220,
9
+ e = 0,
10
+ P = 0,
11
+ S = 0.1,
12
+ I = 0,
13
+ c = 1,
14
+ T = 0,
15
+ H = 0,
16
+ V = 0,
17
+ J = 0,
18
+ h = 0,
19
+ j = 0,
20
+ K = 0,
21
+ E = 0,
22
+ r = 0,
23
+ B = 1,
24
+ X = 0,
25
+ L = 0,
26
+ D = 0,
27
+ ) => {
28
+ let n = Math,
29
+ t = 2 * n.PI,
30
+ a = 44100,
31
+ F = (T *= (500 * t) / a / a),
32
+ O = (z *= ((1 - d + 2 * d * n.random((d = []))) * t) / a),
33
+ x = 0,
34
+ _ = 0,
35
+ f = 0,
36
+ g = 1,
37
+ $ = 0,
38
+ l = 0,
39
+ o = 0,
40
+ s = D < 0 ? -1 : 1,
41
+ u = (t * s * D * 2) / a,
42
+ G = n.cos(u),
43
+ C = n.sin,
44
+ Q = C(u) / 4,
45
+ M = 1 + Q,
46
+ m = (-2 * G) / M,
47
+ y = (1 - Q) / M,
48
+ R = (1 + s * G) / 2 / M,
49
+ A = -(s + G) / M,
50
+ v = R,
51
+ U = 0,
52
+ W = 0,
53
+ Y = 0,
54
+ Z = 0;
55
+ for (
56
+ e = a * e + 9,
57
+ X *= a,
58
+ P *= a,
59
+ S *= a,
60
+ r *= a,
61
+ H *= (500 * t) / a ** 3,
62
+ K *= t / a,
63
+ V *= t / a,
64
+ J *= a,
65
+ h = (a * h) | 0,
66
+ i *= 0.3 * global.zzfxV,
67
+ s = (e + X + P + S + r) | 0;
68
+ f < s;
69
+ d[f++] = o * i
70
+ )
71
+ (++l % ((100 * E) | 0) ||
72
+ ((o = I
73
+ ? 1 < I
74
+ ? 2 < I
75
+ ? 3 < I
76
+ ? C(x * x)
77
+ : n.max(n.min(n.tan(x), 1), -1)
78
+ : 1 - (((((2 * x) / t) % 2) + 2) % 2)
79
+ : 1 - 4 * n.abs(n.round(x / t) - x / t)
80
+ : C(x)),
81
+ (o =
82
+ (h ? 1 - L + L * C((t * f) / h) : 1) *
83
+ (o < 0 ? -1 : 1) *
84
+ n.abs(o) ** c *
85
+ (f < e
86
+ ? f / e
87
+ : f < e + X
88
+ ? 1 - ((f - e) / X) * (1 - B)
89
+ : f < e + X + P
90
+ ? B
91
+ : f < s - r
92
+ ? ((s - f - r) / S) * B
93
+ : 0)),
94
+ (o = r
95
+ ? o / 2 +
96
+ (r > f
97
+ ? 0
98
+ : ((f < s - r ? 1 : (s - f) / r) * d[(f - r) | 0]) / 2 / i)
99
+ : o),
100
+ D &&
101
+ (o = Z = v * U + A * (U = W) + R * (W = o) - y * Y - m * (Y = Z))),
102
+ (u = (z += T += H) * n.cos(K * _++)),
103
+ (x += u + u * j * C(f ** 5)),
104
+ g && ++g > J && ((z += V), (O += V), (g = 0)),
105
+ !h || ++$ % h || ((z = O), (T = F), (g = g || 1)));
106
+ ((i = zzfxX.createBuffer(1, s, a)),
107
+ i.getChannelData(0).set(d),
108
+ (z = zzfxX.createBufferSource()),
109
+ (z.buffer = i),
110
+ z.connect(zzfxX.destination),
111
+ z.start());
10
112
  };
11
113
  };
12
-
13
- // src/palette.js
14
114
  var defaultPalette = ["#211e20", "#555568", "#a0a08b", "#e9efec"];
15
-
16
- // src/index.js
17
115
  function litecanvas(settings = {}) {
18
- const root = window, math = Math, TWO_PI = math.PI * 2, raf = requestAnimationFrame, _browserEventListeners = [], on = (elem, evt, callback) => {
19
- elem.addEventListener(evt, callback, false);
20
- _browserEventListeners.push(() => elem.removeEventListener(evt, callback, false));
21
- }, lowerCase = (str) => str.toLowerCase(), preventDefault = (ev) => ev.preventDefault(), beginPath = (c) => c.beginPath(), isNumber = Number.isFinite, zzfx = setupZzFX(root), defaults = {
22
- width: null,
23
- height: null,
24
- autoscale: true,
25
- canvas: null,
26
- global: true,
27
- loop: null,
28
- tapEvents: true,
29
- keyboardEvents: true
30
- };
116
+ const root = window,
117
+ math = Math,
118
+ perf = performance,
119
+ TWO_PI = math.PI * 2,
120
+ loggerPrefix = "[Litecanvas] ",
121
+ raf = requestAnimationFrame,
122
+ _browserEventListeners = [],
123
+ on = (elem, evt, callback) => {
124
+ elem.addEventListener(evt, callback, false);
125
+ _browserEventListeners.push(() =>
126
+ elem.removeEventListener(evt, callback, false),
127
+ );
128
+ },
129
+ lowerCase = (str) => str.toLowerCase(),
130
+ preventDefault = (ev) => ev.preventDefault(),
131
+ beginPath = (c) => c.beginPath(),
132
+ isNumber = Number.isFinite,
133
+ zzfx = setupZzFX(root),
134
+ defaults = {
135
+ width: null,
136
+ height: null,
137
+ autoscale: true,
138
+ canvas: null,
139
+ global: true,
140
+ loop: null,
141
+ tapEvents: true,
142
+ keyboardEvents: true,
143
+ };
31
144
  settings = Object.assign(defaults, settings);
32
- let _initialized = false, _paused = true, _canvas, _canvasScale = 1, _ctx, _outline_fix = 0.5, _timeScale = 1, _lastFrameTime, _fpsInterval = 1e3 / 60, _accumulated, _rafid, _defaultTextColor = 3, _fontFamily = "sans-serif", _fontSize = 20, _fontLineHeight = 1.2, _rngSeed = Date.now(), _colorPalette = defaultPalette, _colorPaletteState = [], _defaultSound = [0.5, 0, 1750, , , 0.3, 1, , , , 600, 0.1], _coreEvents = "init,update,draw,tap,untap,tapping,tapped,resized", _mathFunctions = "PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp", _eventListeners = {};
145
+ let _initialized = false,
146
+ _paused = true,
147
+ _canvas,
148
+ _canvasScale = 1,
149
+ _ctx,
150
+ _outline_fix = 0.5,
151
+ _timeScale = 1,
152
+ _lastFrameTime,
153
+ _fpsInterval = 1e3 / 60,
154
+ _accumulated,
155
+ _rafid,
156
+ _defaultTextColor = 3,
157
+ _fontFamily = "sans-serif",
158
+ _fontSize = 20,
159
+ _fontLineHeight = 1.2,
160
+ _rngSeed = Date.now(),
161
+ _colorPalette = defaultPalette,
162
+ _colorPaletteState = [],
163
+ _defaultSound = [0.5, 0, 1750, , , 0.3, 1, , , , 600, 0.1],
164
+ _coreEvents = "init,update,draw,tap,untap,tapping,tapped,resized",
165
+ _mathFunctions =
166
+ "PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp",
167
+ _eventListeners = {};
33
168
  const instance = {
34
- /** @type {number} */
35
169
  W: 0,
36
- /** @type {number} */
37
170
  H: 0,
38
- /** @type {number} */
39
171
  T: 0,
40
- /** @type {number} */
41
172
  MX: -1,
42
- /** @type {number} */
43
173
  MY: -1,
44
- /** MATH API */
45
- /**
46
- * Twice the value of the mathematical constant PI (π).
47
- * Approximately 6.28318
48
- *
49
- * Note: TWO_PI radians equals 360°, PI radians equals 180°,
50
- * HALF_PI radians equals 90°, and HALF_PI/2 radians equals 45°.
51
- *
52
- * @type {number}
53
- */
54
174
  TWO_PI,
55
- /**
56
- * Half the value of the mathematical constant PI (π).
57
- * Approximately 1.57079
58
- *
59
- * @type {number}
60
- */
61
175
  HALF_PI: TWO_PI / 4,
62
- /**
63
- * Calculates a linear (interpolation) value over t%.
64
- *
65
- * @param {number} start
66
- * @param {number} end
67
- * @param {number} t The progress in percentage, where 0 = 0% and 1 = 100%.
68
- * @returns {number} The unterpolated value
69
- * @tutorial https://gamedev.net/tutorials/programming/general-and-gameplay-programming/a-brief-introduction-to-lerp-r4954/
70
- */
71
176
  lerp: (start, end, t) => {
72
177
  return start + t * (end - start);
73
178
  },
74
- /**
75
- * Convert degrees to radians
76
- *
77
- * @param {number} degs
78
- * @returns {number} the value in radians
79
- */
80
179
  deg2rad: (degs) => {
81
- return math.PI / 180 * degs;
180
+ return (math.PI / 180) * degs;
82
181
  },
83
- /**
84
- * Convert radians to degrees
85
- *
86
- * @param {number} rads
87
- * @returns {number} the value in degrees
88
- */
89
182
  rad2deg: (rads) => {
90
- return 180 / math.PI * rads;
183
+ return (180 / math.PI) * rads;
91
184
  },
92
- /**
93
- * Returns the rounded value of an number to optional precision (number of digits after the decimal point).
94
- *
95
- * Note: precision is optional but must be >= 0
96
- *
97
- * @param {number} n number to round.
98
- * @param {number} [precision] number of decimal digits to round to, default is 0.
99
- * @returns {number} rounded number.
100
- */
101
185
  round: (n, precision = 0) => {
102
186
  if (!precision) {
103
187
  return math.round(n);
@@ -105,131 +189,45 @@
105
189
  const multiplier = 10 ** precision;
106
190
  return math.round(n * multiplier) / multiplier;
107
191
  },
108
- /**
109
- * Constrains a number between `min` and `max`.
110
- *
111
- * @param {number} value
112
- * @param {number} min
113
- * @param {number} max
114
- * @returns {number}
115
- */
116
192
  clamp: (value, min, max) => {
117
193
  if (value < min) return min;
118
194
  if (value > max) return max;
119
195
  return value;
120
196
  },
121
- /**
122
- * Calculates the distance between a point (x1, y1) to another (x2, y2).
123
- *
124
- * @param {number} x1
125
- * @param {number} y1
126
- * @param {number} x2
127
- * @param {number} y2
128
- * @returns {number}
129
- */
130
197
  dist: (x1, y1, x2, y2) => {
131
198
  return math.hypot(x2 - x1, y2 - y1);
132
199
  },
133
- /**
134
- * Wraps a number between `min` (inclusive) and `max` (exclusive).
135
- *
136
- * @param {number} value
137
- * @param {number} min
138
- * @param {number} max
139
- * @returns {number}
140
- */
141
200
  wrap: (value, min, max) => {
142
201
  return value - (max - min) * math.floor((value - min) / (max - min));
143
202
  },
144
- /**
145
- * Re-maps a number from one range to another.
146
- *
147
- * @param {number} value the value to be remapped.
148
- * @param {number} start1 lower bound of the value's current range.
149
- * @param {number} stop1 upper bound of the value's current range.
150
- * @param {number} start2 lower bound of the value's target range.
151
- * @param {number} stop2 upper bound of the value's target range.
152
- * @param {boolean} [withinBounds=false] constrain the value to the newly mapped range
153
- * @returns {number} the remapped number
154
- */
155
203
  map(value, start1, stop1, start2, stop2, withinBounds) {
156
- const result = (value - start1) / (stop1 - start1) * (stop2 - start2) + start2;
204
+ const result =
205
+ ((value - start1) / (stop1 - start1)) * (stop2 - start2) + start2;
157
206
  return withinBounds ? instance.clamp(result, start2, stop2) : result;
158
207
  },
159
- /**
160
- * Maps a number from one range to a value between 0 and 1.
161
- * Identical to `map(value, min, max, 0, 1)`.
162
- * Note: Numbers outside the range are not clamped to 0 and 1.
163
- *
164
- * @param {number} value
165
- * @param {number} start
166
- * @param {number} stop
167
- * @returns {number} the normalized number.
168
- */
169
208
  norm: (value, start, stop) => {
170
209
  return instance.map(value, start, stop, 0, 1);
171
210
  },
172
- /** RNG API */
173
- /**
174
- * Generates a pseudorandom float between min (inclusive) and max (exclusive)
175
- * using the Linear Congruential Generator (LCG) algorithm.
176
- *
177
- * @param {number} [min=0.0]
178
- * @param {number} [max=1.0]
179
- * @returns {number} the random number
180
- */
181
211
  rand: (min = 0, max = 1) => {
182
212
  const a = 1664525;
183
213
  const c = 1013904223;
184
214
  const m = 4294967296;
185
215
  _rngSeed = (a * _rngSeed + c) % m;
186
- return _rngSeed / m * (max - min) + min;
216
+ return (_rngSeed / m) * (max - min) + min;
187
217
  },
188
- /**
189
- * Generates a pseudorandom integer between min (inclusive) and max (inclusive)
190
- *
191
- * @param {number} [min=0]
192
- * @param {number} [max=1]
193
- * @returns {number} the random number
194
- */
195
218
  randi: (min = 0, max = 1) => {
196
- return math.floor(instance.rand(min, max + 1));
219
+ return ~~instance.rand(min, max + 1);
197
220
  },
198
- /**
199
- * Initializes the random number generator with an explicit seed value.
200
- *
201
- * Note: The seed should be a integer number greater than or equal to zero.
202
- *
203
- * @param {number} value
204
- */
205
221
  rseed(value) {
206
222
  _rngSeed = ~~value;
207
223
  },
208
- /** BASIC GRAPHICS API */
209
- /**
210
- * Clear the game screen with an optional color
211
- *
212
- * @param {number} [color] The background color (index) or null/undefined (for transparent)
213
- */
214
224
  cls(color) {
215
225
  if (null == color) {
216
- _ctx.clearRect(0, 0, _ctx.canvas.width, _ctx.canvas.height);
226
+ _ctx.clearRect(0, 0, instance.W, instance.H);
217
227
  } else {
218
- instance.rectfill(0, 0, _ctx.canvas.width, _ctx.canvas.height, color);
228
+ instance.rectfill(0, 0, instance.W, instance.H, color);
219
229
  }
220
230
  },
221
- /**
222
- * Draw a rectangle outline
223
- *
224
- * @param {number} x
225
- * @param {number} y
226
- * @param {number} width
227
- * @param {number} height
228
- * @param {number} [color=0] the color index
229
- * @param {number|number[]} [radii] A number or list specifying the radii used to draw a rounded-borders rectangle
230
- *
231
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/roundRect
232
- */
233
231
  rect(x, y, width, height, color, radii) {
234
232
  beginPath(_ctx);
235
233
  _ctx[radii ? "roundRect" : "rect"](
@@ -237,85 +235,35 @@
237
235
  ~~y - _outline_fix,
238
236
  ~~width + _outline_fix * 2,
239
237
  ~~height + _outline_fix * 2,
240
- radii
238
+ radii,
241
239
  );
242
240
  instance.stroke(color);
243
241
  },
244
- /**
245
- * Draw a color-filled rectangle
246
- *
247
- * @param {number} x
248
- * @param {number} y
249
- * @param {number} width
250
- * @param {number} height
251
- * @param {number} [color=0] the color index
252
- * @param {number|number[]} [radii] A number or list specifying the radii used to draw a rounded-borders rectangle
253
- */
254
242
  rectfill(x, y, width, height, color, radii) {
255
243
  beginPath(_ctx);
256
244
  _ctx[radii ? "roundRect" : "rect"](~~x, ~~y, ~~width, ~~height, radii);
257
245
  instance.fill(color);
258
246
  },
259
- /**
260
- * Draw a circle outline
261
- *
262
- * @param {number} x
263
- * @param {number} y
264
- * @param {number} radius
265
- * @param {number} [color=0] the color index
266
- */
267
247
  circ(x, y, radius, color) {
268
248
  beginPath(_ctx);
269
249
  _ctx.arc(~~x, ~~y, ~~radius, 0, TWO_PI);
270
250
  instance.stroke(color);
271
251
  },
272
- /**
273
- * Draw a color-filled circle
274
- *
275
- * @param {number} x
276
- * @param {number} y
277
- * @param {number} radius
278
- * @param {number} [color=0] the color index
279
- */
280
252
  circfill(x, y, radius, color) {
281
253
  beginPath(_ctx);
282
254
  _ctx.arc(~~x, ~~y, ~~radius, 0, TWO_PI);
283
255
  instance.fill(color);
284
256
  },
285
- /**
286
- * Draw a ellipse outline
287
- *
288
- * @param {number} x
289
- * @param {number} y
290
- * @param {number} radiusX
291
- * @param {number} radiusY
292
- * @param {number} [color=0] the color index
293
- */
294
257
  oval(x, y, radiusX, radiusY, color) {
295
258
  beginPath(_ctx);
296
259
  _ctx.ellipse(~~x, ~~y, ~~radiusX, ~~radiusY, 0, 0, TWO_PI);
297
260
  instance.stroke(color);
298
261
  },
299
- /**
300
- * Draw a color-filled ellipse
301
- *
302
- * @param {number} x
303
- * @param {number} y
304
- * @param {number} radiusX
305
- * @param {number} radiusY
306
- * @param {number} [color=0] the color index
307
- */
308
262
  ovalfill(x, y, radiusX, radiusY, color) {
309
263
  beginPath(_ctx);
310
264
  _ctx.ellipse(~~x, ~~y, ~~radiusX, ~~radiusY, 0, 0, TWO_PI);
311
265
  instance.fill(color);
312
266
  },
313
- /**
314
- * Make a custom shape in the canvas context.
315
- * Then, just use `fill` or `stroke` to draw the shape.
316
- *
317
- * @param {number[]} points an array of Xs and Ys coordinates
318
- */
319
267
  shape(points) {
320
268
  beginPath(_ctx);
321
269
  for (let i = 0; i < points.length; i += 2) {
@@ -327,15 +275,6 @@
327
275
  }
328
276
  _ctx.lineTo(~~points[0], ~~points[1]);
329
277
  },
330
- /**
331
- * Draw a line
332
- *
333
- * @param {number} x1
334
- * @param {number} y1
335
- * @param {number} x2
336
- * @param {number} y2
337
- * @param {number} [color=0] the color index
338
- */
339
278
  line(x1, y1, x2, y2, color) {
340
279
  beginPath(_ctx);
341
280
  let xfix = _outline_fix !== 0 && ~~x1 === ~~x2 ? 0.5 : 0;
@@ -344,102 +283,42 @@
344
283
  _ctx.lineTo(~~x2 + xfix, ~~y2 + yfix);
345
284
  instance.stroke(color);
346
285
  },
347
- /**
348
- * Sets the thickness of the lines
349
- *
350
- * @param {number} value
351
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineWidth
352
- */
353
286
  linewidth(value) {
354
287
  _ctx.lineWidth = ~~value;
355
288
  _outline_fix = 0 === ~~value % 2 ? 0 : 0.5;
356
289
  },
357
- /**
358
- * Sets the line dash pattern used when drawing lines
359
- *
360
- * @param {number[]} segments the line dash pattern
361
- * @param {number} [offset=0] the line dash offset, or "phase".
362
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash
363
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset
364
- */
365
290
  linedash(segments, offset = 0) {
366
291
  _ctx.setLineDash(segments);
367
292
  _ctx.lineDashOffset = offset;
368
293
  },
369
- /** TEXT RENDERING API */
370
- /**
371
- * Draw text. You can use `\n` to break lines.
372
- *
373
- * @param {number} x
374
- * @param {number} y
375
- * @param {string} message the text message
376
- * @param {number} [color] the color index
377
- * @param {string} [fontStyle] can be "normal" (default), "italic" and/or "bold".
378
- */
379
294
  text(x, y, message, color = _defaultTextColor, fontStyle = "normal") {
380
295
  _ctx.font = `${fontStyle} ${_fontSize}px ${_fontFamily}`;
381
296
  _ctx.fillStyle = getColor(color);
382
297
  const messages = ("" + message).split("\n");
383
298
  for (let i = 0; i < messages.length; i++) {
384
- _ctx.fillText(messages[i], ~~x, ~~y + _fontSize * _fontLineHeight * i);
299
+ _ctx.fillText(
300
+ messages[i],
301
+ ~~x,
302
+ ~~y + _fontSize * _fontLineHeight * i,
303
+ );
385
304
  }
386
305
  },
387
- /**
388
- * Sets the height ratio of the text lines based on current text size.
389
- *
390
- * Default = `1.2`
391
- *
392
- * @param value
393
- */
394
306
  textgap(value) {
395
307
  _fontLineHeight = value;
396
308
  },
397
- /**
398
- * Set the font family
399
- *
400
- * @param {string} family
401
- */
402
309
  textfont(family) {
403
310
  _fontFamily = family;
404
311
  },
405
- /**
406
- * Set the font size
407
- *
408
- * @param {number} size
409
- */
410
312
  textsize(size) {
411
313
  _fontSize = size;
412
314
  },
413
- /**
414
- * Sets the alignment used when drawing texts
415
- *
416
- * @param {CanvasTextAlign} align the horizontal alignment. Possible values: "left", "right", "center", "start" or "end"
417
- * @param {CanvasTextBaseline} baseline the vertical alignment. Possible values: "top", "bottom", "middle", "hanging" or "ideographic"
418
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textBaseline
419
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign
420
- */
421
315
  textalign(align, baseline) {
422
316
  if (align) _ctx.textAlign = align;
423
317
  if (baseline) _ctx.textBaseline = baseline;
424
318
  },
425
- /** IMAGE GRAPHICS API */
426
- /**
427
- * Draw an image
428
- *
429
- * @param {number} x
430
- * @param {number} y
431
- * @param {CanvasImageSource} source
432
- */
433
319
  image(x, y, source2) {
434
320
  _ctx.drawImage(source2, ~~x, ~~y);
435
321
  },
436
- /**
437
- * Draw a sprite pixel by pixel represented by a string. Each pixel must be a base 36 number (0-9 or a-z) or a dot.
438
- *
439
- * @param {number} x
440
- * @param {number} y
441
- * @param {string} pixels
442
- */
443
322
  spr(x, y, pixels) {
444
323
  const rows = pixels.trim().split("\n");
445
324
  for (let row = 0; row < rows.length; row++) {
@@ -447,25 +326,21 @@
447
326
  for (let col = 0; col < chars.length; col++) {
448
327
  const char = chars[col];
449
328
  if (char !== "." && char !== " ") {
450
- instance.rectfill(x + col, y + row, 1, 1, parseInt(char, 36) || 0);
329
+ instance.rectfill(
330
+ x + col,
331
+ y + row,
332
+ 1,
333
+ 1,
334
+ parseInt(char, 36) || 0,
335
+ );
451
336
  }
452
337
  }
453
338
  }
454
339
  },
455
- /**
456
- * Draw in an OffscreenCanvas and returns its image.
457
- *
458
- * @param {number} width
459
- * @param {number} height
460
- * @param {drawCallback} callback
461
- * @param {object} [options]
462
- * @param {number} [options.scale=1]
463
- * @param {OffscreenCanvas} [options.canvas]
464
- * @returns {ImageBitmap}
465
- * @see https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas
466
- */
467
340
  paint(width, height, callback, options = {}) {
468
- const canvas = options.canvas || new OffscreenCanvas(1, 1), scale = options.scale || 1, currentContext = _ctx;
341
+ const canvas = options.canvas || new OffscreenCanvas(1, 1),
342
+ scale = options.scale || 1,
343
+ currentContext = _ctx;
469
344
  canvas.width = width * scale;
470
345
  canvas.height = height * scale;
471
346
  _ctx = canvas.getContext("2d");
@@ -474,114 +349,48 @@
474
349
  _ctx = currentContext;
475
350
  return canvas.transferToImageBitmap();
476
351
  },
477
- /** ADVANCED GRAPHICS API */
478
- /**
479
- * Get or set the canvas context 2D
480
- *
481
- * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
482
- * @returns {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D}
483
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
484
- */
485
352
  ctx(context) {
486
353
  if (context) {
487
354
  _ctx = context;
488
355
  }
489
356
  return _ctx;
490
357
  },
491
- /**
492
- * saves the current drawing style settings and transformations
493
- *
494
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/save
495
- */
496
358
  push() {
497
359
  _ctx.save();
498
360
  },
499
- /**
500
- * restores the drawing style settings and transformations
501
- *
502
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/restore
503
- */
504
361
  pop() {
505
362
  _ctx.restore();
506
363
  },
507
- /**
508
- * Adds a translation to the transformation matrix.
509
- *
510
- * @param {number} x
511
- * @param {number} y
512
- */
513
364
  translate(x, y) {
514
365
  _ctx.translate(~~x, ~~y);
515
366
  },
516
- /**
517
- * Adds a scaling transformation to the canvas units horizontally and/or vertically.
518
- *
519
- * @param {number} x
520
- * @param {number} [y]
521
- */
522
367
  scale(x, y) {
523
368
  _ctx.scale(x, y || x);
524
369
  },
525
- /**
526
- * Adds a rotation to the transformation matrix.
527
- *
528
- * @param {number} radians
529
- */
530
370
  rotate(radians) {
531
371
  _ctx.rotate(radians);
532
372
  },
533
- /**
534
- * Sets the alpha (opacity) value to apply when drawing new shapes and images
535
- *
536
- * @param {number} value float from 0 to 1 (e.g: 0.5 = 50% transparent)
537
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalAlpha
538
- */
539
373
  alpha(value) {
540
374
  _ctx.globalAlpha = instance.clamp(value, 0, 1);
541
375
  },
542
- /**
543
- * Fills the current path with a given color.
544
- *
545
- * @param {number} [color=0]
546
- */
547
376
  fill(color) {
548
377
  _ctx.fillStyle = getColor(color);
549
378
  _ctx.fill();
550
379
  },
551
- /**
552
- * Outlines the current path with a given color.
553
- *
554
- * @param {number} [color=0]
555
- */
556
380
  stroke(color) {
557
381
  _ctx.strokeStyle = getColor(color);
558
382
  _ctx.stroke();
559
383
  },
560
- /**
561
- * Turns a path (in the callback) into the current clipping region.
562
- *
563
- * @param {clipCallback} callback
564
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip
565
- */
566
384
  clip(callback) {
567
385
  beginPath(_ctx);
568
386
  callback(_ctx);
569
387
  _ctx.clip();
570
388
  },
571
- /** SOUND API */
572
- /**
573
- * Play a sound effects using ZzFX library.
574
- * If the first argument is omitted, plays an default sound.
575
- *
576
- * @param {number[]} [zzfxParams] a ZzFX array of params
577
- * @param {number} [pitchSlide] a value to increment/decrement the pitch
578
- * @param {number} [volumeFactor] the volume factor
579
- * @returns {number[] | boolean} The sound that was played or `false`
580
- *
581
- * @see https://github.com/KilledByAPixel/ZzFX
582
- */
583
389
  sfx(zzfxParams, pitchSlide = 0, volumeFactor = 1) {
584
- if (!root.zzfxV || navigator.userActivation && !navigator.userActivation.hasBeenActive) {
390
+ if (
391
+ !root.zzfxV ||
392
+ (navigator.userActivation && !navigator.userActivation.hasBeenActive)
393
+ ) {
585
394
  return false;
586
395
  }
587
396
  zzfxParams = zzfxParams || _defaultSound;
@@ -593,52 +402,19 @@
593
402
  zzfx.apply(0, zzfxParams);
594
403
  return zzfxParams;
595
404
  },
596
- /**
597
- * Set the ZzFX's global volume factor.
598
- * Note: use 0 to mute all sound effects.
599
- *
600
- * @param {number} value
601
- */
602
405
  volume(value) {
603
406
  root.zzfxV = value;
604
407
  },
605
- /** PLUGINS API */
606
- /**
607
- * Returns the canvas
608
- *
609
- * @returns {HTMLCanvasElement}
610
- */
611
408
  canvas: () => _canvas,
612
- /**
613
- * Prepares a plugin to be loaded
614
- *
615
- * @param {pluginCallback} callback
616
- */
617
409
  use(callback, config = {}) {
618
410
  loadPlugin(callback, config);
619
411
  },
620
- /**
621
- * Add a game event listener
622
- *
623
- * @param {string} eventName the event type name
624
- * @param {Function} callback the function that is called when the event occurs
625
- * @returns {Function} a function to remove the listener
626
- */
627
412
  listen(eventName, callback) {
628
413
  eventName = lowerCase(eventName);
629
- _eventListeners[eventName] = _eventListeners[eventName] || /* @__PURE__ */ new Set();
414
+ _eventListeners[eventName] = _eventListeners[eventName] || new Set();
630
415
  _eventListeners[eventName].add(callback);
631
416
  return () => _eventListeners[eventName]?.delete(callback);
632
417
  },
633
- /**
634
- * Call all listeners attached to a game event
635
- *
636
- * @param {string} eventName The event type name
637
- * @param {*} [arg1] any data to be passed over the listeners
638
- * @param {*} [arg2] any data to be passed over the listeners
639
- * @param {*} [arg3] any data to be passed over the listeners
640
- * @param {*} [arg4] any data to be passed over the listeners
641
- */
642
418
  emit(eventName, arg1, arg2, arg3, arg4) {
643
419
  if (_initialized) {
644
420
  eventName = lowerCase(eventName);
@@ -647,27 +423,11 @@
647
423
  triggerEvent("after:" + eventName, arg1, arg2, arg3, arg4);
648
424
  }
649
425
  },
650
- /**
651
- * Set new palette colors or restore the default palette.
652
- *
653
- * @param {string[]} [colors] an array of colors
654
- * @param {number} [textColor] the default text color this palette
655
- */
656
426
  pal(colors, textColor = 3) {
657
427
  _colorPalette = colors || defaultPalette;
658
428
  _colorPaletteState = [];
659
429
  _defaultTextColor = textColor;
660
430
  },
661
- /**
662
- * Replace the color "a" with color "b".
663
- *
664
- * If called without arguments, reset the current palette.
665
- *
666
- * Note: `palc()` don't affect drawings made with `image()`.
667
- *
668
- * @param {number?} a
669
- * @param {number?} b
670
- */
671
431
  palc(a, b) {
672
432
  if (a == null) {
673
433
  _colorPaletteState = [];
@@ -675,106 +435,54 @@
675
435
  _colorPaletteState[a] = b;
676
436
  }
677
437
  },
678
- /**
679
- * Define or update a instance property.
680
- *
681
- * @param {string} key
682
- * @param {*} value
683
- */
684
438
  def(key, value) {
685
439
  instance[key] = value;
686
440
  if (settings.global) {
687
441
  root[key] = value;
688
442
  }
689
443
  },
690
- /**
691
- * The scale of the game's delta time (dt).
692
- * Values higher than 1 increase the speed of time, while values smaller than 1 decrease it.
693
- * A value of 0 freezes time and is effectively equivalent to pausing.
694
- *
695
- * @param {number} value
696
- */
697
444
  timescale(value) {
698
445
  _timeScale = value;
699
446
  },
700
- /**
701
- * Set the target FPS (frames per second).
702
- *
703
- * @param {number} value
704
- */
705
447
  framerate(value) {
706
448
  _fpsInterval = 1e3 / ~~value;
707
449
  },
708
- /**
709
- * Returns information about the engine instance.
710
- *
711
- * @param {number|string} index
712
- * @returns {any}
713
- */
714
450
  stat(index) {
715
451
  const internals = [
716
- // 0
717
452
  settings,
718
- // 1
719
453
  _initialized,
720
- // 2
721
454
  _fpsInterval / 1e3,
722
- // 3
723
455
  _canvasScale,
724
- // 4
725
456
  _eventListeners,
726
- // 5
727
457
  _colorPalette,
728
- // 6
729
458
  _defaultSound,
730
- // 7
731
459
  _timeScale,
732
- // 8
733
460
  root.zzfxV,
734
- // 9
735
461
  _rngSeed,
736
- // 10
737
462
  _fontSize,
738
- // 11
739
463
  _fontFamily,
740
- // 12
741
464
  _colorPaletteState,
742
- // 13
743
- _fontLineHeight
465
+ _fontLineHeight,
744
466
  ];
745
467
  const data = { index, value: internals[index] };
746
468
  instance.emit("stat", data);
747
469
  return data.value;
748
470
  },
749
- /**
750
- * Pauses the engine loop (update & draw).
751
- */
752
471
  pause() {
753
472
  _paused = true;
754
473
  cancelAnimationFrame(_rafid);
755
474
  },
756
- /**
757
- * Resumes (if paused) the engine loop.
758
- */
759
475
  resume() {
760
476
  if (_initialized && _paused) {
761
477
  _paused = false;
762
478
  _accumulated = _fpsInterval;
763
- _lastFrameTime = Date.now();
479
+ _lastFrameTime = perf.now();
764
480
  _rafid = raf(drawFrame);
765
481
  }
766
482
  },
767
- /**
768
- * Returns `true` if the engine loop is paused.
769
- *
770
- * @returns {boolean}
771
- */
772
483
  paused() {
773
484
  return _paused;
774
485
  },
775
- /**
776
- * Shutdown the litecanvas instance and remove all event listeners.
777
- */
778
486
  quit() {
779
487
  instance.emit("quit");
780
488
  instance.pause();
@@ -789,7 +497,7 @@
789
497
  }
790
498
  delete root.ENGINE;
791
499
  }
792
- }
500
+ },
793
501
  };
794
502
  for (const k of _mathFunctions.split(",")) {
795
503
  instance[k] = math[k];
@@ -799,138 +507,72 @@
799
507
  on(root, "resize", resizeCanvas);
800
508
  }
801
509
  if (settings.tapEvents) {
802
- const _getXY = (
803
- /**
804
- * @param {MouseEvent | Touch} ev
805
- */
806
- (ev) => [
510
+ const _getXY = (ev) => [
807
511
  (ev.pageX - _canvas.offsetLeft) / _canvasScale,
808
- (ev.pageY - _canvas.offsetTop) / _canvasScale
809
- ]
810
- ), _taps = /* @__PURE__ */ new Map(), _registerTap = (
811
- /**
812
- * @param {number} id
813
- * @param {number} [x]
814
- * @param {number} [y]
815
- */
816
- (id, x, y) => {
817
- const tap = {
818
- // current x
819
- x,
820
- // current y
821
- y,
822
- // initial x
823
- xi: x,
824
- // initial y
825
- yi: y,
826
- // timestamp
827
- t: Date.now()
828
- };
512
+ (ev.pageY - _canvas.offsetTop) / _canvasScale,
513
+ ],
514
+ _taps = new Map(),
515
+ _registerTap = (id, x, y) => {
516
+ const tap = { x, y, xi: x, yi: y, t: perf.now() };
829
517
  _taps.set(id, tap);
830
518
  return tap;
831
- }
832
- ), _updateTap = (
833
- /**
834
- * @param {number} id
835
- * @param {number} x
836
- * @param {number} y
837
- */
838
- (id, x, y) => {
519
+ },
520
+ _updateTap = (id, x, y) => {
839
521
  const tap = _taps.get(id) || _registerTap(id);
840
522
  tap.x = x;
841
523
  tap.y = y;
842
- }
843
- ), _checkTapped = (
844
- /**
845
- * @param {{t: number}} tap
846
- */
847
- (tap) => tap && Date.now() - tap.t <= 300
848
- );
524
+ },
525
+ _checkTapped = (tap) => tap && perf.now() - tap.t <= 300;
849
526
  let _pressingMouse = false;
850
- on(
851
- _canvas,
852
- "mousedown",
853
- /**
854
- * @param {MouseEvent} ev
855
- */
856
- (ev) => {
857
- if (ev.button === 0) {
858
- preventDefault(ev);
859
- const [x, y] = _getXY(ev);
860
- instance.emit("tap", x, y, 0);
861
- _registerTap(0, x, y);
862
- _pressingMouse = true;
863
- }
864
- }
865
- );
866
- on(
867
- _canvas,
868
- "mouseup",
869
- /**
870
- * @param {MouseEvent} ev
871
- */
872
- (ev) => {
873
- if (ev.button === 0) {
874
- preventDefault(ev);
875
- const tap = _taps.get(0);
876
- const [x, y] = _getXY(ev);
877
- if (_checkTapped(tap)) {
878
- instance.emit("tapped", tap.xi, tap.yi, 0);
879
- }
880
- instance.emit("untap", x, y, 0);
881
- _taps.delete(0);
882
- _pressingMouse = false;
883
- }
884
- }
885
- );
886
- on(
887
- root,
888
- "mousemove",
889
- /**
890
- * @param {MouseEvent} ev
891
- */
892
- (ev) => {
527
+ on(_canvas, "mousedown", (ev) => {
528
+ if (ev.button === 0) {
893
529
  preventDefault(ev);
894
530
  const [x, y] = _getXY(ev);
895
- instance.def("MX", x);
896
- instance.def("MY", y);
897
- if (!_pressingMouse) return;
898
- instance.emit("tapping", x, y, 0);
899
- _updateTap(0, x, y);
531
+ instance.emit("tap", x, y, 0);
532
+ _registerTap(0, x, y);
533
+ _pressingMouse = true;
900
534
  }
901
- );
902
- on(
903
- _canvas,
904
- "touchstart",
905
- /**
906
- * @param {TouchEvent} ev
907
- */
908
- (ev) => {
535
+ });
536
+ on(_canvas, "mouseup", (ev) => {
537
+ if (ev.button === 0) {
909
538
  preventDefault(ev);
910
- const touches = ev.changedTouches;
911
- for (const touch of touches) {
912
- const [x, y] = _getXY(touch);
913
- instance.emit("tap", x, y, touch.identifier + 1);
914
- _registerTap(touch.identifier + 1, x, y);
539
+ const tap = _taps.get(0);
540
+ const [x, y] = _getXY(ev);
541
+ if (_checkTapped(tap)) {
542
+ instance.emit("tapped", tap.xi, tap.yi, 0);
915
543
  }
544
+ instance.emit("untap", x, y, 0);
545
+ _taps.delete(0);
546
+ _pressingMouse = false;
916
547
  }
917
- );
918
- on(
919
- _canvas,
920
- "touchmove",
921
- /**
922
- * @param {TouchEvent} ev
923
- */
924
- (ev) => {
925
- preventDefault(ev);
926
- const touches = ev.changedTouches;
927
- for (const touch of touches) {
928
- const [x, y] = _getXY(touch);
929
- instance.emit("tapping", x, y, touch.identifier + 1);
930
- _updateTap(touch.identifier + 1, x, y);
931
- }
548
+ });
549
+ on(root, "mousemove", (ev) => {
550
+ preventDefault(ev);
551
+ const [x, y] = _getXY(ev);
552
+ instance.def("MX", x);
553
+ instance.def("MY", y);
554
+ if (!_pressingMouse) return;
555
+ instance.emit("tapping", x, y, 0);
556
+ _updateTap(0, x, y);
557
+ });
558
+ on(_canvas, "touchstart", (ev) => {
559
+ preventDefault(ev);
560
+ const touches = ev.changedTouches;
561
+ for (const touch of touches) {
562
+ const [x, y] = _getXY(touch);
563
+ instance.emit("tap", x, y, touch.identifier + 1);
564
+ _registerTap(touch.identifier + 1, x, y);
932
565
  }
933
- );
566
+ });
567
+ on(_canvas, "touchmove", (ev) => {
568
+ preventDefault(ev);
569
+ const touches = ev.changedTouches;
570
+ for (const touch of touches) {
571
+ const [x, y] = _getXY(touch);
572
+ instance.emit("tapping", x, y, touch.identifier + 1);
573
+ _updateTap(touch.identifier + 1, x, y);
574
+ }
575
+ });
934
576
  const _touchEndHandler = (ev) => {
935
577
  preventDefault(ev);
936
578
  const existing = [];
@@ -959,11 +601,13 @@
959
601
  });
960
602
  }
961
603
  if (settings.keyboardEvents) {
962
- const _keysDown = /* @__PURE__ */ new Set();
963
- const _keysPress = /* @__PURE__ */ new Set();
604
+ const _keysDown = new Set();
605
+ const _keysPress = new Set();
964
606
  const keyCheck = (keySet, key = "") => {
965
607
  key = lowerCase(key);
966
- return !key ? keySet.size > 0 : keySet.has("space" === key ? " " : key);
608
+ return !key
609
+ ? keySet.size > 0
610
+ : keySet.has("space" === key ? " " : key);
967
611
  };
968
612
  let _lastKey = "";
969
613
  on(root, "keydown", (event) => {
@@ -979,33 +623,13 @@
979
623
  });
980
624
  on(root, "blur", () => _keysDown.clear());
981
625
  instance.listen("after:update", () => _keysPress.clear());
982
- instance.def(
983
- "iskeydown",
984
- /**
985
- * @param {string} [key]
986
- * @returns {boolean}
987
- */
988
- (key) => {
989
- return keyCheck(_keysDown, key);
990
- }
991
- );
992
- instance.def(
993
- "iskeypressed",
994
- /**
995
- * @param {string} [key]
996
- * @returns {boolean}
997
- */
998
- (key) => {
999
- return keyCheck(_keysPress, key);
1000
- }
1001
- );
1002
- instance.def(
1003
- "lastkey",
1004
- /**
1005
- * @returns {string}
1006
- */
1007
- () => _lastKey
1008
- );
626
+ instance.def("iskeydown", (key) => {
627
+ return keyCheck(_keysDown, key);
628
+ });
629
+ instance.def("iskeypressed", (key) => {
630
+ return keyCheck(_keysPress, key);
631
+ });
632
+ instance.def("lastkey", () => _lastKey);
1009
633
  }
1010
634
  _initialized = true;
1011
635
  instance.resume();
@@ -1013,7 +637,7 @@
1013
637
  }
1014
638
  function drawFrame() {
1015
639
  _rafid = raf(drawFrame);
1016
- let now = Date.now();
640
+ let now = perf.now();
1017
641
  let updated = 0;
1018
642
  let frameTime = now - _lastFrameTime;
1019
643
  _lastFrameTime = now;
@@ -1021,7 +645,7 @@
1021
645
  while (_accumulated >= _fpsInterval) {
1022
646
  updated++;
1023
647
  _accumulated -= _fpsInterval;
1024
- let dt = _fpsInterval / 1e3 * _timeScale;
648
+ let dt = (_fpsInterval / 1e3) * _timeScale;
1025
649
  instance.emit("update", dt, updated);
1026
650
  instance.def("T", instance.T + dt);
1027
651
  }
@@ -1049,7 +673,9 @@
1049
673
  _canvas.oncontextmenu = () => false;
1050
674
  }
1051
675
  function resizeCanvas() {
1052
- const width = settings.width > 0 ? settings.width : innerWidth, height = settings.width > 0 ? settings.height || settings.width : innerHeight;
676
+ const width = settings.width > 0 ? settings.width : innerWidth,
677
+ height =
678
+ settings.width > 0 ? settings.height || settings.width : innerHeight;
1053
679
  instance.def("W", width);
1054
680
  instance.def("H", height);
1055
681
  _canvas.width = width;
@@ -1061,7 +687,8 @@
1061
687
  _canvas.style.margin = "auto";
1062
688
  }
1063
689
  _canvasScale = math.min(innerWidth / width, innerHeight / height);
1064
- _canvasScale = maxScale > 1 && _canvasScale > maxScale ? maxScale : _canvasScale;
690
+ _canvasScale =
691
+ maxScale > 1 && _canvasScale > maxScale ? maxScale : _canvasScale;
1065
692
  _canvas.style.width = width * _canvasScale + "px";
1066
693
  _canvas.style.height = height * _canvasScale + "px";
1067
694
  }
@@ -1104,7 +731,5 @@
1104
731
  }
1105
732
  return instance;
1106
733
  }
1107
-
1108
- // src/web.js
1109
734
  window.litecanvas = litecanvas;
1110
735
  })();