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.dev.js CHANGED
@@ -1,121 +1,213 @@
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/dev.js
17
115
  var assert = (condition, message = "Assertion failed") => {
18
- if (!condition) throw new Error(message);
116
+ if (!condition) throw new Error("[litecanvas] " + message);
19
117
  };
20
-
21
- // src/version.js
22
- var version = "0.103.4";
23
-
24
- // src/index.js
118
+ var version = "0.103.6";
25
119
  function litecanvas(settings = {}) {
26
- const root = window, math = Math, TWO_PI = math.PI * 2, raf = requestAnimationFrame, _browserEventListeners = [], on = (elem, evt, callback) => {
27
- elem.addEventListener(evt, callback, false);
28
- _browserEventListeners.push(() => elem.removeEventListener(evt, callback, false));
29
- }, lowerCase = (str) => str.toLowerCase(), preventDefault = (ev) => ev.preventDefault(), beginPath = (c) => c.beginPath(), isNumber = Number.isFinite, zzfx = setupZzFX(root), defaults = {
30
- width: null,
31
- height: null,
32
- autoscale: true,
33
- canvas: null,
34
- global: true,
35
- loop: null,
36
- tapEvents: true,
37
- keyboardEvents: true
38
- };
120
+ const root = window,
121
+ math = Math,
122
+ perf = performance,
123
+ TWO_PI = math.PI * 2,
124
+ loggerPrefix = "[Litecanvas] ",
125
+ raf = requestAnimationFrame,
126
+ _browserEventListeners = [],
127
+ on = (elem, evt, callback) => {
128
+ elem.addEventListener(evt, callback, false);
129
+ _browserEventListeners.push(() =>
130
+ elem.removeEventListener(evt, callback, false),
131
+ );
132
+ },
133
+ lowerCase = (str) => str.toLowerCase(),
134
+ preventDefault = (ev) => ev.preventDefault(),
135
+ beginPath = (c) => c.beginPath(),
136
+ isNumber = Number.isFinite,
137
+ zzfx = setupZzFX(root),
138
+ defaults = {
139
+ width: null,
140
+ height: null,
141
+ autoscale: true,
142
+ canvas: null,
143
+ global: true,
144
+ loop: null,
145
+ tapEvents: true,
146
+ keyboardEvents: true,
147
+ };
39
148
  settings = Object.assign(defaults, settings);
40
- 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 = {};
149
+ let _initialized = false,
150
+ _paused = true,
151
+ _canvas,
152
+ _canvasScale = 1,
153
+ _ctx,
154
+ _outline_fix = 0.5,
155
+ _timeScale = 1,
156
+ _lastFrameTime,
157
+ _fpsInterval = 1e3 / 60,
158
+ _accumulated,
159
+ _rafid,
160
+ _defaultTextColor = 3,
161
+ _fontFamily = "sans-serif",
162
+ _fontSize = 20,
163
+ _fontLineHeight = 1.2,
164
+ _rngSeed = Date.now(),
165
+ _colorPalette = defaultPalette,
166
+ _colorPaletteState = [],
167
+ _defaultSound = [0.5, 0, 1750, , , 0.3, 1, , , , 600, 0.1],
168
+ _coreEvents = "init,update,draw,tap,untap,tapping,tapped,resized",
169
+ _mathFunctions =
170
+ "PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp",
171
+ _eventListeners = {};
41
172
  const instance = {
42
- /** @type {number} */
43
173
  W: 0,
44
- /** @type {number} */
45
174
  H: 0,
46
- /** @type {number} */
47
175
  T: 0,
48
- /** @type {number} */
49
176
  MX: -1,
50
- /** @type {number} */
51
177
  MY: -1,
52
- /** MATH API */
53
- /**
54
- * Twice the value of the mathematical constant PI (π).
55
- * Approximately 6.28318
56
- *
57
- * Note: TWO_PI radians equals 360°, PI radians equals 180°,
58
- * HALF_PI radians equals 90°, and HALF_PI/2 radians equals 45°.
59
- *
60
- * @type {number}
61
- */
62
178
  TWO_PI,
63
- /**
64
- * Half the value of the mathematical constant PI (π).
65
- * Approximately 1.57079
66
- *
67
- * @type {number}
68
- */
69
179
  HALF_PI: TWO_PI / 4,
70
- /**
71
- * Calculates a linear (interpolation) value over t%.
72
- *
73
- * @param {number} start
74
- * @param {number} end
75
- * @param {number} t The progress in percentage, where 0 = 0% and 1 = 100%.
76
- * @returns {number} The unterpolated value
77
- * @tutorial https://gamedev.net/tutorials/programming/general-and-gameplay-programming/a-brief-introduction-to-lerp-r4954/
78
- */
79
180
  lerp: (start, end, t) => {
80
- DEV: assert(isNumber(start), "[litecanvas] lerp() 1st param must be a number");
81
- DEV: assert(isNumber(end), "[litecanvas] lerp() 2nd param must be a number");
82
- DEV: assert(isNumber(t), "[litecanvas] lerp() 3rd param must be a number");
181
+ DEV: assert(
182
+ isNumber(start),
183
+ loggerPrefix + "lerp() 1st param must be a number",
184
+ );
185
+ DEV: assert(
186
+ isNumber(end),
187
+ loggerPrefix + "lerp() 2nd param must be a number",
188
+ );
189
+ DEV: assert(
190
+ isNumber(t),
191
+ loggerPrefix + "lerp() 3rd param must be a number",
192
+ );
83
193
  return start + t * (end - start);
84
194
  },
85
- /**
86
- * Convert degrees to radians
87
- *
88
- * @param {number} degs
89
- * @returns {number} the value in radians
90
- */
91
195
  deg2rad: (degs) => {
92
196
  DEV: assert(isNumber(degs), "deg2rad: 1st param must be a number");
93
- return math.PI / 180 * degs;
197
+ return (math.PI / 180) * degs;
94
198
  },
95
- /**
96
- * Convert radians to degrees
97
- *
98
- * @param {number} rads
99
- * @returns {number} the value in degrees
100
- */
101
199
  rad2deg: (rads) => {
102
200
  DEV: assert(isNumber(rads), "rad2deg: 1st param must be a number");
103
- return 180 / math.PI * rads;
201
+ return (180 / math.PI) * rads;
104
202
  },
105
- /**
106
- * Returns the rounded value of an number to optional precision (number of digits after the decimal point).
107
- *
108
- * Note: precision is optional but must be >= 0
109
- *
110
- * @param {number} n number to round.
111
- * @param {number} [precision] number of decimal digits to round to, default is 0.
112
- * @returns {number} rounded number.
113
- */
114
203
  round: (n, precision = 0) => {
115
- DEV: assert(isNumber(n), "[litecanvas] round() 1st param must be a number");
204
+ DEV: assert(
205
+ isNumber(n),
206
+ loggerPrefix + "round() 1st param must be a number",
207
+ );
116
208
  DEV: assert(
117
209
  isNumber(precision) && precision >= 0,
118
- "[litecanvas] round() 2nd param must be a positive number or zero"
210
+ loggerPrefix + "round() 2nd param must be a positive number or zero",
119
211
  );
120
212
  if (!precision) {
121
213
  return math.round(n);
@@ -123,203 +215,197 @@
123
215
  const multiplier = 10 ** precision;
124
216
  return math.round(n * multiplier) / multiplier;
125
217
  },
126
- /**
127
- * Constrains a number between `min` and `max`.
128
- *
129
- * @param {number} value
130
- * @param {number} min
131
- * @param {number} max
132
- * @returns {number}
133
- */
134
218
  clamp: (value, min, max) => {
135
- DEV: assert(isNumber(value), "[litecanvas] clamp() 1st param must be a number");
136
- DEV: assert(isNumber(min), "[litecanvas] clamp() 2nd param must be a number");
137
- DEV: assert(isNumber(max), "[litecanvas] clamp() 3rd param must be a number");
219
+ DEV: assert(
220
+ isNumber(value),
221
+ loggerPrefix + "clamp() 1st param must be a number",
222
+ );
223
+ DEV: assert(
224
+ isNumber(min),
225
+ loggerPrefix + "clamp() 2nd param must be a number",
226
+ );
227
+ DEV: assert(
228
+ isNumber(max),
229
+ loggerPrefix + "clamp() 3rd param must be a number",
230
+ );
138
231
  DEV: assert(
139
232
  max > min,
140
- "[litecanvas] clamp() the 2nd param must be less than the 3rd param"
233
+ loggerPrefix +
234
+ "clamp() the 2nd param must be less than the 3rd param",
141
235
  );
142
236
  if (value < min) return min;
143
237
  if (value > max) return max;
144
238
  return value;
145
239
  },
146
- /**
147
- * Calculates the distance between a point (x1, y1) to another (x2, y2).
148
- *
149
- * @param {number} x1
150
- * @param {number} y1
151
- * @param {number} x2
152
- * @param {number} y2
153
- * @returns {number}
154
- */
155
240
  dist: (x1, y1, x2, y2) => {
156
- DEV: assert(isNumber(x1), "[litecanvas] dist() 1st param must be a number");
157
- DEV: assert(isNumber(y1), "[litecanvas] dist() 2nd param must be a number");
158
- DEV: assert(isNumber(x2), "[litecanvas] dist() 3rd param must be a number");
159
- DEV: assert(isNumber(y2), "[litecanvas] dist() 4th param must be a number");
241
+ DEV: assert(
242
+ isNumber(x1),
243
+ loggerPrefix + "dist() 1st param must be a number",
244
+ );
245
+ DEV: assert(
246
+ isNumber(y1),
247
+ loggerPrefix + "dist() 2nd param must be a number",
248
+ );
249
+ DEV: assert(
250
+ isNumber(x2),
251
+ loggerPrefix + "dist() 3rd param must be a number",
252
+ );
253
+ DEV: assert(
254
+ isNumber(y2),
255
+ loggerPrefix + "dist() 4th param must be a number",
256
+ );
160
257
  return math.hypot(x2 - x1, y2 - y1);
161
258
  },
162
- /**
163
- * Wraps a number between `min` (inclusive) and `max` (exclusive).
164
- *
165
- * @param {number} value
166
- * @param {number} min
167
- * @param {number} max
168
- * @returns {number}
169
- */
170
259
  wrap: (value, min, max) => {
171
- DEV: assert(isNumber(value), "[litecanvas] wrap() 1st param must be a number");
172
- DEV: assert(isNumber(min), "[litecanvas] wrap() 2nd param must be a number");
173
- DEV: assert(isNumber(max), "[litecanvas] wrap() 3rd param must be a number");
260
+ DEV: assert(
261
+ isNumber(value),
262
+ loggerPrefix + "wrap() 1st param must be a number",
263
+ );
264
+ DEV: assert(
265
+ isNumber(min),
266
+ loggerPrefix + "wrap() 2nd param must be a number",
267
+ );
268
+ DEV: assert(
269
+ isNumber(max),
270
+ loggerPrefix + "wrap() 3rd param must be a number",
271
+ );
174
272
  DEV: assert(
175
273
  max > min,
176
- "[litecanvas] wrap() the 2nd param must be less than the 3rd param"
274
+ loggerPrefix + "wrap() the 2nd param must be less than the 3rd param",
177
275
  );
178
276
  return value - (max - min) * math.floor((value - min) / (max - min));
179
277
  },
180
- /**
181
- * Re-maps a number from one range to another.
182
- *
183
- * @param {number} value the value to be remapped.
184
- * @param {number} start1 lower bound of the value's current range.
185
- * @param {number} stop1 upper bound of the value's current range.
186
- * @param {number} start2 lower bound of the value's target range.
187
- * @param {number} stop2 upper bound of the value's target range.
188
- * @param {boolean} [withinBounds=false] constrain the value to the newly mapped range
189
- * @returns {number} the remapped number
190
- */
191
278
  map(value, start1, stop1, start2, stop2, withinBounds) {
192
- DEV: assert(isNumber(value), "[litecanvas] map() 1st param must be a number");
193
- DEV: assert(isNumber(start1), "[litecanvas] map() 2nd param must be a number");
194
- DEV: assert(isNumber(stop1), "[litecanvas] map() 3rd param must be a number");
195
- DEV: assert(isNumber(start2), "[litecanvas] map() 4th param must be a number");
196
- DEV: assert(isNumber(stop2), "[litecanvas] map() 5th param must be a number");
279
+ DEV: assert(
280
+ isNumber(value),
281
+ loggerPrefix + "map() 1st param must be a number",
282
+ );
283
+ DEV: assert(
284
+ isNumber(start1),
285
+ loggerPrefix + "map() 2nd param must be a number",
286
+ );
287
+ DEV: assert(
288
+ isNumber(stop1),
289
+ loggerPrefix + "map() 3rd param must be a number",
290
+ );
291
+ DEV: assert(
292
+ isNumber(start2),
293
+ loggerPrefix + "map() 4th param must be a number",
294
+ );
295
+ DEV: assert(
296
+ isNumber(stop2),
297
+ loggerPrefix + "map() 5th param must be a number",
298
+ );
197
299
  DEV: assert(
198
300
  stop1 !== start1,
199
- "[litecanvas] map() the 2nd param must be different than the 3rd param"
301
+ loggerPrefix +
302
+ "map() the 2nd param must be different than the 3rd param",
200
303
  );
201
- const result = (value - start1) / (stop1 - start1) * (stop2 - start2) + start2;
304
+ const result =
305
+ ((value - start1) / (stop1 - start1)) * (stop2 - start2) + start2;
202
306
  return withinBounds ? instance.clamp(result, start2, stop2) : result;
203
307
  },
204
- /**
205
- * Maps a number from one range to a value between 0 and 1.
206
- * Identical to `map(value, min, max, 0, 1)`.
207
- * Note: Numbers outside the range are not clamped to 0 and 1.
208
- *
209
- * @param {number} value
210
- * @param {number} start
211
- * @param {number} stop
212
- * @returns {number} the normalized number.
213
- */
214
308
  norm: (value, start, stop) => {
215
- DEV: assert(isNumber(value), "[litecanvas] norm() 1st param must be a number");
216
- DEV: assert(isNumber(start), "[litecanvas] norm() 2nd param must be a number");
217
- DEV: assert(isNumber(stop), "[litecanvas] norm() 3rd param must be a number");
309
+ DEV: assert(
310
+ isNumber(value),
311
+ loggerPrefix + "norm() 1st param must be a number",
312
+ );
313
+ DEV: assert(
314
+ isNumber(start),
315
+ loggerPrefix + "norm() 2nd param must be a number",
316
+ );
317
+ DEV: assert(
318
+ isNumber(stop),
319
+ loggerPrefix + "norm() 3rd param must be a number",
320
+ );
218
321
  DEV: assert(
219
322
  start !== stop,
220
- "[litecanvas] norm() the 2nd param must be different than the 3rd param"
323
+ loggerPrefix +
324
+ "norm() the 2nd param must be different than the 3rd param",
221
325
  );
222
326
  return instance.map(value, start, stop, 0, 1);
223
327
  },
224
- /** RNG API */
225
- /**
226
- * Generates a pseudorandom float between min (inclusive) and max (exclusive)
227
- * using the Linear Congruential Generator (LCG) algorithm.
228
- *
229
- * @param {number} [min=0.0]
230
- * @param {number} [max=1.0]
231
- * @returns {number} the random number
232
- */
233
328
  rand: (min = 0, max = 1) => {
234
- DEV: assert(isNumber(min), "[litecanvas] rand() 1st param must be a number");
235
- DEV: assert(isNumber(max), "[litecanvas] rand() 2nd param must be a number");
329
+ DEV: assert(
330
+ isNumber(min),
331
+ loggerPrefix + "rand() 1st param must be a number",
332
+ );
333
+ DEV: assert(
334
+ isNumber(max),
335
+ loggerPrefix + "rand() 2nd param must be a number",
336
+ );
236
337
  DEV: assert(
237
338
  max > min,
238
- "[litecanvas] rand() the 1st param must be less than the 2nd param"
339
+ loggerPrefix + "rand() the 1st param must be less than the 2nd param",
239
340
  );
240
341
  const a = 1664525;
241
342
  const c = 1013904223;
242
343
  const m = 4294967296;
243
344
  _rngSeed = (a * _rngSeed + c) % m;
244
- return _rngSeed / m * (max - min) + min;
345
+ return (_rngSeed / m) * (max - min) + min;
245
346
  },
246
- /**
247
- * Generates a pseudorandom integer between min (inclusive) and max (inclusive)
248
- *
249
- * @param {number} [min=0]
250
- * @param {number} [max=1]
251
- * @returns {number} the random number
252
- */
253
347
  randi: (min = 0, max = 1) => {
254
- DEV: assert(isNumber(min), "[litecanvas] randi() 1st param must be a number");
255
- DEV: assert(isNumber(max), "[litecanvas] randi() 2nd param must be a number");
348
+ DEV: assert(
349
+ isNumber(min),
350
+ loggerPrefix + "randi() 1st param must be a number",
351
+ );
352
+ DEV: assert(
353
+ isNumber(max),
354
+ loggerPrefix + "randi() 2nd param must be a number",
355
+ );
256
356
  DEV: assert(
257
357
  min <= max,
258
- "[litecanvas] randi() the 1st param must be less than the 2nd param"
358
+ loggerPrefix +
359
+ "randi() the 1st param must be less than the 2nd param",
259
360
  );
260
- return math.floor(instance.rand(min, max + 1));
361
+ return ~~instance.rand(min, max + 1);
261
362
  },
262
- /**
263
- * Initializes the random number generator with an explicit seed value.
264
- *
265
- * Note: The seed should be a integer number greater than or equal to zero.
266
- *
267
- * @param {number} value
268
- */
269
363
  rseed(value) {
270
364
  DEV: assert(
271
365
  isNumber(value) && value >= 0,
272
- "[litecanvas] rseed() 1st param must be a positive integer or zero"
366
+ loggerPrefix + "rseed() 1st param must be a positive integer or zero",
273
367
  );
274
368
  _rngSeed = ~~value;
275
369
  },
276
- /** BASIC GRAPHICS API */
277
- /**
278
- * Clear the game screen with an optional color
279
- *
280
- * @param {number} [color] The background color (index) or null/undefined (for transparent)
281
- */
282
370
  cls(color) {
283
371
  DEV: assert(
284
- null == color || isNumber(color) && color >= 0,
285
- "[litecanvas] cls() 1st param must be a positive number or zero or undefined"
372
+ null == color || (isNumber(color) && color >= 0),
373
+ loggerPrefix +
374
+ "cls() 1st param must be a positive number or zero or undefined",
286
375
  );
287
376
  if (null == color) {
288
- _ctx.clearRect(0, 0, _ctx.canvas.width, _ctx.canvas.height);
377
+ _ctx.clearRect(0, 0, instance.W, instance.H);
289
378
  } else {
290
- instance.rectfill(0, 0, _ctx.canvas.width, _ctx.canvas.height, color);
379
+ instance.rectfill(0, 0, instance.W, instance.H, color);
291
380
  }
292
381
  },
293
- /**
294
- * Draw a rectangle outline
295
- *
296
- * @param {number} x
297
- * @param {number} y
298
- * @param {number} width
299
- * @param {number} height
300
- * @param {number} [color=0] the color index
301
- * @param {number|number[]} [radii] A number or list specifying the radii used to draw a rounded-borders rectangle
302
- *
303
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/roundRect
304
- */
305
382
  rect(x, y, width, height, color, radii) {
306
- DEV: assert(isNumber(x), "[litecanvas] rect() 1st param must be a number");
307
- DEV: assert(isNumber(y), "[litecanvas] rect() 2nd param must be a number");
383
+ DEV: assert(
384
+ isNumber(x),
385
+ loggerPrefix + "rect() 1st param must be a number",
386
+ );
387
+ DEV: assert(
388
+ isNumber(y),
389
+ loggerPrefix + "rect() 2nd param must be a number",
390
+ );
308
391
  DEV: assert(
309
392
  isNumber(width) && width > 0,
310
- "[litecanvas] rect() 3rd param must be a positive number"
393
+ loggerPrefix + "rect() 3rd param must be a positive number",
311
394
  );
312
395
  DEV: assert(
313
396
  isNumber(height) && height >= 0,
314
- "[litecanvas] rect() 4th param must be a positive number or zero"
397
+ loggerPrefix + "rect() 4th param must be a positive number or zero",
315
398
  );
316
399
  DEV: assert(
317
- null == color || isNumber(color) && color >= 0,
318
- "[litecanvas] rect() 5th param must be a positive number or zero"
400
+ null == color || (isNumber(color) && color >= 0),
401
+ loggerPrefix + "rect() 5th param must be a positive number or zero",
319
402
  );
320
403
  DEV: assert(
321
- null == radii || isNumber(radii) || Array.isArray(radii) && radii.length >= 1,
322
- "[litecanvas] rect() 6th param must be a number or array of numbers"
404
+ null == radii ||
405
+ isNumber(radii) ||
406
+ (Array.isArray(radii) && radii.length >= 1),
407
+ loggerPrefix +
408
+ "rect() 6th param must be a number or array of numbers",
323
409
  );
324
410
  beginPath(_ctx);
325
411
  _ctx[radii ? "roundRect" : "rect"](
@@ -327,159 +413,151 @@
327
413
  ~~y - _outline_fix,
328
414
  ~~width + _outline_fix * 2,
329
415
  ~~height + _outline_fix * 2,
330
- radii
416
+ radii,
331
417
  );
332
418
  instance.stroke(color);
333
419
  },
334
- /**
335
- * Draw a color-filled rectangle
336
- *
337
- * @param {number} x
338
- * @param {number} y
339
- * @param {number} width
340
- * @param {number} height
341
- * @param {number} [color=0] the color index
342
- * @param {number|number[]} [radii] A number or list specifying the radii used to draw a rounded-borders rectangle
343
- */
344
420
  rectfill(x, y, width, height, color, radii) {
345
- DEV: assert(isNumber(x), "[litecanvas] rectfill() 1st param must be a number");
346
- DEV: assert(isNumber(y), "[litecanvas] rectfill() 2nd param must be a number");
421
+ DEV: assert(
422
+ isNumber(x),
423
+ loggerPrefix + "rectfill() 1st param must be a number",
424
+ );
425
+ DEV: assert(
426
+ isNumber(y),
427
+ loggerPrefix + "rectfill() 2nd param must be a number",
428
+ );
347
429
  DEV: assert(
348
430
  isNumber(width) && width >= 0,
349
- "[litecanvas] rectfill() 3rd param must be a positive number or zero"
431
+ loggerPrefix +
432
+ "rectfill() 3rd param must be a positive number or zero",
350
433
  );
351
434
  DEV: assert(
352
435
  isNumber(height) && height >= 0,
353
- "[litecanvas] rectfill() 4th param must be a positive number or zero"
436
+ loggerPrefix +
437
+ "rectfill() 4th param must be a positive number or zero",
354
438
  );
355
439
  DEV: assert(
356
- null == color || isNumber(color) && color >= 0,
357
- "[litecanvas] rectfill() 5th param must be a positive number or zero"
440
+ null == color || (isNumber(color) && color >= 0),
441
+ loggerPrefix +
442
+ "rectfill() 5th param must be a positive number or zero",
358
443
  );
359
444
  DEV: assert(
360
- null == radii || isNumber(radii) || Array.isArray(radii) && radii.length >= 1,
361
- "[litecanvas] rectfill() 6th param must be a number or array of at least 2 numbers"
445
+ null == radii ||
446
+ isNumber(radii) ||
447
+ (Array.isArray(radii) && radii.length >= 1),
448
+ loggerPrefix +
449
+ "rectfill() 6th param must be a number or array of at least 2 numbers",
362
450
  );
363
451
  beginPath(_ctx);
364
452
  _ctx[radii ? "roundRect" : "rect"](~~x, ~~y, ~~width, ~~height, radii);
365
453
  instance.fill(color);
366
454
  },
367
- /**
368
- * Draw a circle outline
369
- *
370
- * @param {number} x
371
- * @param {number} y
372
- * @param {number} radius
373
- * @param {number} [color=0] the color index
374
- */
375
455
  circ(x, y, radius, color) {
376
- DEV: assert(isNumber(x), "[litecanvas] circ() 1st param must be a number");
377
- DEV: assert(isNumber(y), "[litecanvas] circ() 2nd param must be a number");
456
+ DEV: assert(
457
+ isNumber(x),
458
+ loggerPrefix + "circ() 1st param must be a number",
459
+ );
460
+ DEV: assert(
461
+ isNumber(y),
462
+ loggerPrefix + "circ() 2nd param must be a number",
463
+ );
378
464
  DEV: assert(
379
465
  isNumber(radius) && radius >= 0,
380
- "[litecanvas] circ() 3rd param must be a positive number or zero"
466
+ loggerPrefix + "circ() 3rd param must be a positive number or zero",
381
467
  );
382
468
  DEV: assert(
383
- null == color || isNumber(color) && color >= 0,
384
- "[litecanvas] circ() 4th param must be a positive number or zero"
469
+ null == color || (isNumber(color) && color >= 0),
470
+ loggerPrefix + "circ() 4th param must be a positive number or zero",
385
471
  );
386
472
  beginPath(_ctx);
387
473
  _ctx.arc(~~x, ~~y, ~~radius, 0, TWO_PI);
388
474
  instance.stroke(color);
389
475
  },
390
- /**
391
- * Draw a color-filled circle
392
- *
393
- * @param {number} x
394
- * @param {number} y
395
- * @param {number} radius
396
- * @param {number} [color=0] the color index
397
- */
398
476
  circfill(x, y, radius, color) {
399
- DEV: assert(isNumber(x), "[litecanvas] circfill() 1st param must be a number");
400
- DEV: assert(isNumber(y), "[litecanvas] circfill() 2nd param must be a number");
477
+ DEV: assert(
478
+ isNumber(x),
479
+ loggerPrefix + "circfill() 1st param must be a number",
480
+ );
481
+ DEV: assert(
482
+ isNumber(y),
483
+ loggerPrefix + "circfill() 2nd param must be a number",
484
+ );
401
485
  DEV: assert(
402
486
  isNumber(radius) && radius >= 0,
403
- "[litecanvas] circfill() 3rd param must be a positive number or zero"
487
+ loggerPrefix +
488
+ "circfill() 3rd param must be a positive number or zero",
404
489
  );
405
490
  DEV: assert(
406
- null == color || isNumber(color) && color >= 0,
407
- "[litecanvas] circfill() 4th param must be a positive number or zero"
491
+ null == color || (isNumber(color) && color >= 0),
492
+ loggerPrefix +
493
+ "circfill() 4th param must be a positive number or zero",
408
494
  );
409
495
  beginPath(_ctx);
410
496
  _ctx.arc(~~x, ~~y, ~~radius, 0, TWO_PI);
411
497
  instance.fill(color);
412
498
  },
413
- /**
414
- * Draw a ellipse outline
415
- *
416
- * @param {number} x
417
- * @param {number} y
418
- * @param {number} radiusX
419
- * @param {number} radiusY
420
- * @param {number} [color=0] the color index
421
- */
422
499
  oval(x, y, radiusX, radiusY, color) {
423
- DEV: assert(isNumber(x), "[litecanvas] oval() 1st param must be a number");
424
- DEV: assert(isNumber(y), "[litecanvas] oval() 2nd param must be a number");
500
+ DEV: assert(
501
+ isNumber(x),
502
+ loggerPrefix + "oval() 1st param must be a number",
503
+ );
504
+ DEV: assert(
505
+ isNumber(y),
506
+ loggerPrefix + "oval() 2nd param must be a number",
507
+ );
425
508
  DEV: assert(
426
509
  isNumber(radiusX) && radiusX >= 0,
427
- "[litecanvas] oval() 3rd param must be a positive number or zero"
510
+ loggerPrefix + "oval() 3rd param must be a positive number or zero",
428
511
  );
429
512
  DEV: assert(
430
513
  isNumber(radiusY) && radiusY >= 0,
431
- "[litecanvas] oval() 4th param must be a positive number or zero"
514
+ loggerPrefix + "oval() 4th param must be a positive number or zero",
432
515
  );
433
516
  DEV: assert(
434
- null == color || isNumber(color) && color >= 0,
435
- "[litecanvas] oval() 5th param must be a positive number or zero"
517
+ null == color || (isNumber(color) && color >= 0),
518
+ loggerPrefix + "oval() 5th param must be a positive number or zero",
436
519
  );
437
520
  beginPath(_ctx);
438
521
  _ctx.ellipse(~~x, ~~y, ~~radiusX, ~~radiusY, 0, 0, TWO_PI);
439
522
  instance.stroke(color);
440
523
  },
441
- /**
442
- * Draw a color-filled ellipse
443
- *
444
- * @param {number} x
445
- * @param {number} y
446
- * @param {number} radiusX
447
- * @param {number} radiusY
448
- * @param {number} [color=0] the color index
449
- */
450
524
  ovalfill(x, y, radiusX, radiusY, color) {
451
- DEV: assert(isNumber(x), "[litecanvas] ovalfill() 1st param must be a number");
452
- DEV: assert(isNumber(y), "[litecanvas] ovalfill() 2nd param must be a number");
525
+ DEV: assert(
526
+ isNumber(x),
527
+ loggerPrefix + "ovalfill() 1st param must be a number",
528
+ );
529
+ DEV: assert(
530
+ isNumber(y),
531
+ loggerPrefix + "ovalfill() 2nd param must be a number",
532
+ );
453
533
  DEV: assert(
454
534
  isNumber(radiusX) && radiusX >= 0,
455
- "[litecanvas] ovalfill() 3rd param must be a positive number or zero"
535
+ loggerPrefix +
536
+ "ovalfill() 3rd param must be a positive number or zero",
456
537
  );
457
538
  DEV: assert(
458
539
  isNumber(radiusY) && radiusY >= 0,
459
- "[litecanvas] ovalfill() 4th param must be a positive number or zero"
540
+ loggerPrefix +
541
+ "ovalfill() 4th param must be a positive number or zero",
460
542
  );
461
543
  DEV: assert(
462
- null == color || isNumber(color) && color >= 0,
463
- "[litecanvas] ovalfill() 5th param must be a positive number or zero"
544
+ null == color || (isNumber(color) && color >= 0),
545
+ loggerPrefix +
546
+ "ovalfill() 5th param must be a positive number or zero",
464
547
  );
465
548
  beginPath(_ctx);
466
549
  _ctx.ellipse(~~x, ~~y, ~~radiusX, ~~radiusY, 0, 0, TWO_PI);
467
550
  instance.fill(color);
468
551
  },
469
- /**
470
- * Make a custom shape in the canvas context.
471
- * Then, just use `fill` or `stroke` to draw the shape.
472
- *
473
- * @param {number[]} points an array of Xs and Ys coordinates
474
- */
475
552
  shape(points) {
476
553
  DEV: assert(
477
554
  Array.isArray(points),
478
- "[litecanvas] shape() 1st param must be an array of numbers"
555
+ loggerPrefix + "shape() 1st param must be an array of numbers",
479
556
  );
480
557
  DEV: assert(
481
558
  points.length >= 6,
482
- "[litecanvas] shape() 1st param must be an array with at least 6 numbers (3 points)"
559
+ loggerPrefix +
560
+ "shape() 1st param must be an array with at least 6 numbers (3 points)",
483
561
  );
484
562
  beginPath(_ctx);
485
563
  for (let i = 0; i < points.length; i += 2) {
@@ -491,29 +569,26 @@
491
569
  }
492
570
  _ctx.lineTo(~~points[0], ~~points[1]);
493
571
  },
494
- /**
495
- * Draw a line
496
- *
497
- * @param {number} x1
498
- * @param {number} y1
499
- * @param {number} x2
500
- * @param {number} y2
501
- * @param {number} [color=0] the color index
502
- */
503
572
  line(x1, y1, x2, y2, color) {
504
- DEV: assert(isNumber(x1), "[litecanvas] line() 1st param must be a number");
505
- DEV: assert(isNumber(y1), "[litecanvas] line() 2nd param must be a number");
573
+ DEV: assert(
574
+ isNumber(x1),
575
+ loggerPrefix + "line() 1st param must be a number",
576
+ );
577
+ DEV: assert(
578
+ isNumber(y1),
579
+ loggerPrefix + "line() 2nd param must be a number",
580
+ );
506
581
  DEV: assert(
507
582
  isNumber(x2),
508
- "[litecanvas] line() 3rd param must be a positive number or zero"
583
+ loggerPrefix + "line() 3rd param must be a positive number or zero",
509
584
  );
510
585
  DEV: assert(
511
586
  isNumber(y2),
512
- "[litecanvas] line() 4th param must be a positive number or zero"
587
+ loggerPrefix + "line() 4th param must be a positive number or zero",
513
588
  );
514
589
  DEV: assert(
515
- null == color || isNumber(color) && color >= 0,
516
- "[litecanvas] line() 5th param must be a positive number or zero"
590
+ null == color || (isNumber(color) && color >= 0),
591
+ loggerPrefix + "line() 5th param must be a positive number or zero",
517
592
  );
518
593
  beginPath(_ctx);
519
594
  let xfix = _outline_fix !== 0 && ~~x1 === ~~x2 ? 0.5 : 0;
@@ -522,187 +597,162 @@
522
597
  _ctx.lineTo(~~x2 + xfix, ~~y2 + yfix);
523
598
  instance.stroke(color);
524
599
  },
525
- /**
526
- * Sets the thickness of the lines
527
- *
528
- * @param {number} value
529
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineWidth
530
- */
531
600
  linewidth(value) {
532
601
  DEV: assert(
533
602
  isNumber(value) && value >= 0,
534
- "[litecanvas] linewidth() 1st param must be a positive number or zero"
603
+ loggerPrefix +
604
+ "linewidth() 1st param must be a positive number or zero",
535
605
  );
536
606
  _ctx.lineWidth = ~~value;
537
607
  _outline_fix = 0 === ~~value % 2 ? 0 : 0.5;
538
608
  },
539
- /**
540
- * Sets the line dash pattern used when drawing lines
541
- *
542
- * @param {number[]} segments the line dash pattern
543
- * @param {number} [offset=0] the line dash offset, or "phase".
544
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash
545
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset
546
- */
547
609
  linedash(segments, offset = 0) {
548
610
  DEV: assert(
549
611
  Array.isArray(segments) && segments.length > 0,
550
- "[litecanvas] linedash() 1st param must be an array of numbers"
612
+ loggerPrefix + "linedash() 1st param must be an array of numbers",
613
+ );
614
+ DEV: assert(
615
+ isNumber(offset),
616
+ loggerPrefix + "linedash() 2nd param must be a number",
551
617
  );
552
- DEV: assert(isNumber(offset), "[litecanvas] linedash() 2nd param must be a number");
553
618
  _ctx.setLineDash(segments);
554
619
  _ctx.lineDashOffset = offset;
555
620
  },
556
- /** TEXT RENDERING API */
557
- /**
558
- * Draw text. You can use `\n` to break lines.
559
- *
560
- * @param {number} x
561
- * @param {number} y
562
- * @param {string} message the text message
563
- * @param {number} [color] the color index
564
- * @param {string} [fontStyle] can be "normal" (default), "italic" and/or "bold".
565
- */
566
621
  text(x, y, message, color = _defaultTextColor, fontStyle = "normal") {
567
- DEV: assert(isNumber(x), "[litecanvas] text() 1st param must be a number");
568
- DEV: assert(isNumber(y), "[litecanvas] text() 2nd param must be a number");
569
622
  DEV: assert(
570
- null == color || isNumber(color) && color >= 0,
571
- "[litecanvas] text() 4th param must be a positive number or zero"
623
+ isNumber(x),
624
+ loggerPrefix + "text() 1st param must be a number",
625
+ );
626
+ DEV: assert(
627
+ isNumber(y),
628
+ loggerPrefix + "text() 2nd param must be a number",
629
+ );
630
+ DEV: assert(
631
+ null == color || (isNumber(color) && color >= 0),
632
+ loggerPrefix + "text() 4th param must be a positive number or zero",
572
633
  );
573
634
  DEV: assert(
574
635
  "string" === typeof fontStyle,
575
- "[litecanvas] text() 5th param must be a string"
636
+ loggerPrefix + "text() 5th param must be a string",
576
637
  );
577
638
  _ctx.font = `${fontStyle} ${_fontSize}px ${_fontFamily}`;
578
639
  _ctx.fillStyle = getColor(color);
579
640
  const messages = ("" + message).split("\n");
580
641
  for (let i = 0; i < messages.length; i++) {
581
- _ctx.fillText(messages[i], ~~x, ~~y + _fontSize * _fontLineHeight * i);
642
+ _ctx.fillText(
643
+ messages[i],
644
+ ~~x,
645
+ ~~y + _fontSize * _fontLineHeight * i,
646
+ );
582
647
  }
583
648
  },
584
- /**
585
- * Sets the height ratio of the text lines based on current text size.
586
- *
587
- * Default = `1.2`
588
- *
589
- * @param value
590
- */
591
649
  textgap(value) {
592
650
  _fontLineHeight = value;
593
651
  },
594
- /**
595
- * Set the font family
596
- *
597
- * @param {string} family
598
- */
599
652
  textfont(family) {
600
653
  DEV: assert(
601
654
  "string" === typeof family,
602
- "[litecanvas] textfont() 1st param must be a string"
655
+ loggerPrefix + "textfont() 1st param must be a string",
603
656
  );
604
657
  _fontFamily = family;
605
658
  },
606
- /**
607
- * Set the font size
608
- *
609
- * @param {number} size
610
- */
611
659
  textsize(size) {
612
- DEV: assert(isNumber(size), "[litecanvas] textsize() 1st param must be a number");
660
+ DEV: assert(
661
+ isNumber(size),
662
+ loggerPrefix + "textsize() 1st param must be a number",
663
+ );
613
664
  _fontSize = size;
614
665
  },
615
- /**
616
- * Sets the alignment used when drawing texts
617
- *
618
- * @param {CanvasTextAlign} align the horizontal alignment. Possible values: "left", "right", "center", "start" or "end"
619
- * @param {CanvasTextBaseline} baseline the vertical alignment. Possible values: "top", "bottom", "middle", "hanging" or "ideographic"
620
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textBaseline
621
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign
622
- */
623
666
  textalign(align, baseline) {
624
667
  DEV: assert(
625
- null == align || ["left", "right", "center", "start", "end"].includes(align),
626
- "[litecanvas] textalign() 1st param must be null or one of the following strings: center, left, right, start or end."
668
+ null == align ||
669
+ ["left", "right", "center", "start", "end"].includes(align),
670
+ loggerPrefix +
671
+ "textalign() 1st param must be null or one of the following strings: center, left, right, start or end.",
627
672
  );
628
673
  DEV: assert(
629
- null == baseline || ["top", "bottom", "middle", "hanging", "alphabetic", "ideographic"].includes(
630
- baseline
631
- ),
632
- "[litecanvas] textalign() 2nd param must be null or one of the following strings: middle, top, bottom, hanging, alphabetic or ideographic."
674
+ null == baseline ||
675
+ [
676
+ "top",
677
+ "bottom",
678
+ "middle",
679
+ "hanging",
680
+ "alphabetic",
681
+ "ideographic",
682
+ ].includes(baseline),
683
+ loggerPrefix +
684
+ "textalign() 2nd param must be null or one of the following strings: middle, top, bottom, hanging, alphabetic or ideographic.",
633
685
  );
634
686
  if (align) _ctx.textAlign = align;
635
687
  if (baseline) _ctx.textBaseline = baseline;
636
688
  },
637
- /** IMAGE GRAPHICS API */
638
- /**
639
- * Draw an image
640
- *
641
- * @param {number} x
642
- * @param {number} y
643
- * @param {CanvasImageSource} source
644
- */
645
689
  image(x, y, source2) {
646
- DEV: assert(isNumber(x), "[litecanvas] image() 1st param must be a number");
647
- DEV: assert(isNumber(y), "[litecanvas] image() 2nd param must be a number");
690
+ DEV: assert(
691
+ isNumber(x),
692
+ loggerPrefix + "image() 1st param must be a number",
693
+ );
694
+ DEV: assert(
695
+ isNumber(y),
696
+ loggerPrefix + "image() 2nd param must be a number",
697
+ );
648
698
  _ctx.drawImage(source2, ~~x, ~~y);
649
699
  },
650
- /**
651
- * 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.
652
- *
653
- * @param {number} x
654
- * @param {number} y
655
- * @param {string} pixels
656
- */
657
700
  spr(x, y, pixels) {
658
- DEV: assert(isNumber(x), "[litecanvas] spr() 1st param must be a number");
659
- DEV: assert(isNumber(y), "[litecanvas] spr() 2nd param must be a number");
660
- DEV: assert("string" === typeof pixels, "[litecanvas] spr() 3rd param must be a string");
701
+ DEV: assert(
702
+ isNumber(x),
703
+ loggerPrefix + "spr() 1st param must be a number",
704
+ );
705
+ DEV: assert(
706
+ isNumber(y),
707
+ loggerPrefix + "spr() 2nd param must be a number",
708
+ );
709
+ DEV: assert(
710
+ "string" === typeof pixels,
711
+ loggerPrefix + "spr() 3rd param must be a string",
712
+ );
661
713
  const rows = pixels.trim().split("\n");
662
714
  for (let row = 0; row < rows.length; row++) {
663
715
  const chars = rows[row].trim();
664
716
  for (let col = 0; col < chars.length; col++) {
665
717
  const char = chars[col];
666
718
  if (char !== "." && char !== " ") {
667
- instance.rectfill(x + col, y + row, 1, 1, parseInt(char, 36) || 0);
719
+ instance.rectfill(
720
+ x + col,
721
+ y + row,
722
+ 1,
723
+ 1,
724
+ parseInt(char, 36) || 0,
725
+ );
668
726
  }
669
727
  }
670
728
  }
671
729
  },
672
- /**
673
- * Draw in an OffscreenCanvas and returns its image.
674
- *
675
- * @param {number} width
676
- * @param {number} height
677
- * @param {drawCallback} callback
678
- * @param {object} [options]
679
- * @param {number} [options.scale=1]
680
- * @param {OffscreenCanvas} [options.canvas]
681
- * @returns {ImageBitmap}
682
- * @see https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas
683
- */
684
730
  paint(width, height, callback, options = {}) {
685
731
  DEV: assert(
686
732
  isNumber(width) && width >= 1,
687
- "[litecanvas] paint() 1st param must be a positive number"
733
+ loggerPrefix + "paint() 1st param must be a positive number",
688
734
  );
689
735
  DEV: assert(
690
736
  isNumber(height) && height >= 1,
691
- "[litecanvas] paint() 2nd param must be a positive number"
737
+ loggerPrefix + "paint() 2nd param must be a positive number",
692
738
  );
693
739
  DEV: assert(
694
740
  "function" === typeof callback,
695
- "[litecanvas] paint() 3rd param must be a function"
741
+ loggerPrefix + "paint() 3rd param must be a function",
696
742
  );
697
743
  DEV: assert(
698
- options && null == options.scale || isNumber(options.scale),
699
- "[litecanvas] paint() 4th param (options.scale) must be a number"
744
+ (options && null == options.scale) || isNumber(options.scale),
745
+ loggerPrefix + "paint() 4th param (options.scale) must be a number",
700
746
  );
701
747
  DEV: assert(
702
- options && null == options.canvas || options.canvas instanceof OffscreenCanvas,
703
- "[litecanvas] paint() 4th param (options.canvas) must be an OffscreenCanvas"
704
- );
705
- const canvas = options.canvas || new OffscreenCanvas(1, 1), scale = options.scale || 1, currentContext = _ctx;
748
+ (options && null == options.canvas) ||
749
+ options.canvas instanceof OffscreenCanvas,
750
+ loggerPrefix +
751
+ "paint() 4th param (options.canvas) must be an OffscreenCanvas",
752
+ );
753
+ const canvas = options.canvas || new OffscreenCanvas(1, 1),
754
+ scale = options.scale || 1,
755
+ currentContext = _ctx;
706
756
  canvas.width = width * scale;
707
757
  canvas.height = height * scale;
708
758
  _ctx = canvas.getContext("2d");
@@ -711,138 +761,96 @@
711
761
  _ctx = currentContext;
712
762
  return canvas.transferToImageBitmap();
713
763
  },
714
- /** ADVANCED GRAPHICS API */
715
- /**
716
- * Get or set the canvas context 2D
717
- *
718
- * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context]
719
- * @returns {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D}
720
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
721
- */
722
764
  ctx(context) {
723
765
  if (context) {
724
766
  _ctx = context;
725
767
  }
726
768
  return _ctx;
727
769
  },
728
- /**
729
- * saves the current drawing style settings and transformations
730
- *
731
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/save
732
- */
733
770
  push() {
734
771
  _ctx.save();
735
772
  },
736
- /**
737
- * restores the drawing style settings and transformations
738
- *
739
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/restore
740
- */
741
773
  pop() {
742
774
  _ctx.restore();
743
775
  },
744
- /**
745
- * Adds a translation to the transformation matrix.
746
- *
747
- * @param {number} x
748
- * @param {number} y
749
- */
750
776
  translate(x, y) {
751
- DEV: assert(isNumber(x), "[litecanvas] translate() 1st param must be a number");
752
- DEV: assert(isNumber(y), "[litecanvas] translate() 2nd param must be a number");
777
+ DEV: assert(
778
+ isNumber(x),
779
+ loggerPrefix + "translate() 1st param must be a number",
780
+ );
781
+ DEV: assert(
782
+ isNumber(y),
783
+ loggerPrefix + "translate() 2nd param must be a number",
784
+ );
753
785
  _ctx.translate(~~x, ~~y);
754
786
  },
755
- /**
756
- * Adds a scaling transformation to the canvas units horizontally and/or vertically.
757
- *
758
- * @param {number} x
759
- * @param {number} [y]
760
- */
761
787
  scale(x, y) {
762
- DEV: assert(isNumber(x), "[litecanvas] scale() 1st param must be a number");
763
- DEV: assert(null == y || isNumber(y), "[litecanvas] scale() 2nd param must be a number");
788
+ DEV: assert(
789
+ isNumber(x),
790
+ loggerPrefix + "scale() 1st param must be a number",
791
+ );
792
+ DEV: assert(
793
+ null == y || isNumber(y),
794
+ loggerPrefix + "scale() 2nd param must be a number",
795
+ );
764
796
  _ctx.scale(x, y || x);
765
797
  },
766
- /**
767
- * Adds a rotation to the transformation matrix.
768
- *
769
- * @param {number} radians
770
- */
771
798
  rotate(radians) {
772
- DEV: assert(isNumber(radians), "[litecanvas] rotate() 1st param must be a number");
799
+ DEV: assert(
800
+ isNumber(radians),
801
+ loggerPrefix + "rotate() 1st param must be a number",
802
+ );
773
803
  _ctx.rotate(radians);
774
804
  },
775
- /**
776
- * Sets the alpha (opacity) value to apply when drawing new shapes and images
777
- *
778
- * @param {number} value float from 0 to 1 (e.g: 0.5 = 50% transparent)
779
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalAlpha
780
- */
781
805
  alpha(value) {
782
- DEV: assert(isNumber(value), "[litecanvas] alpha() 1st param must be a number");
806
+ DEV: assert(
807
+ isNumber(value),
808
+ loggerPrefix + "alpha() 1st param must be a number",
809
+ );
783
810
  _ctx.globalAlpha = instance.clamp(value, 0, 1);
784
811
  },
785
- /**
786
- * Fills the current path with a given color.
787
- *
788
- * @param {number} [color=0]
789
- */
790
812
  fill(color) {
791
813
  DEV: assert(
792
- null == color || isNumber(color) && color >= 0,
793
- "[litecanvas] fill() 1st param must be a positive number or zero"
814
+ null == color || (isNumber(color) && color >= 0),
815
+ loggerPrefix + "fill() 1st param must be a positive number or zero",
794
816
  );
795
817
  _ctx.fillStyle = getColor(color);
796
818
  _ctx.fill();
797
819
  },
798
- /**
799
- * Outlines the current path with a given color.
800
- *
801
- * @param {number} [color=0]
802
- */
803
820
  stroke(color) {
804
821
  DEV: assert(
805
- null == color || isNumber(color) && color >= 0,
806
- "[litecanvas] stroke() 1st param must be a positive number or zero"
822
+ null == color || (isNumber(color) && color >= 0),
823
+ loggerPrefix + "stroke() 1st param must be a positive number or zero",
807
824
  );
808
825
  _ctx.strokeStyle = getColor(color);
809
826
  _ctx.stroke();
810
827
  },
811
- /**
812
- * Turns a path (in the callback) into the current clipping region.
813
- *
814
- * @param {clipCallback} callback
815
- * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip
816
- */
817
828
  clip(callback) {
818
829
  DEV: assert(
819
830
  "function" === typeof callback,
820
- "[litecanvas] clip() 1st param must be a function"
831
+ loggerPrefix + "clip() 1st param must be a function",
821
832
  );
822
833
  beginPath(_ctx);
823
834
  callback(_ctx);
824
835
  _ctx.clip();
825
836
  },
826
- /** SOUND API */
827
- /**
828
- * Play a sound effects using ZzFX library.
829
- * If the first argument is omitted, plays an default sound.
830
- *
831
- * @param {number[]} [zzfxParams] a ZzFX array of params
832
- * @param {number} [pitchSlide] a value to increment/decrement the pitch
833
- * @param {number} [volumeFactor] the volume factor
834
- * @returns {number[] | boolean} The sound that was played or `false`
835
- *
836
- * @see https://github.com/KilledByAPixel/ZzFX
837
- */
838
837
  sfx(zzfxParams, pitchSlide = 0, volumeFactor = 1) {
839
838
  DEV: assert(
840
839
  null == zzfxParams || Array.isArray(zzfxParams),
841
- "[litecanvas] sfx() 1st param must be an array"
840
+ loggerPrefix + "sfx() 1st param must be an array",
841
+ );
842
+ DEV: assert(
843
+ isNumber(pitchSlide),
844
+ loggerPrefix + "sfx() 2nd param must be a number",
845
+ );
846
+ DEV: assert(
847
+ isNumber(volumeFactor),
848
+ loggerPrefix + "sfx() 3rd param must be a number",
842
849
  );
843
- DEV: assert(isNumber(pitchSlide), "[litecanvas] sfx() 2nd param must be a number");
844
- DEV: assert(isNumber(volumeFactor), "[litecanvas] sfx() 3rd param must be a number");
845
- if (!root.zzfxV || navigator.userActivation && !navigator.userActivation.hasBeenActive) {
850
+ if (
851
+ !root.zzfxV ||
852
+ (navigator.userActivation && !navigator.userActivation.hasBeenActive)
853
+ ) {
846
854
  return false;
847
855
  }
848
856
  zzfxParams = zzfxParams || _defaultSound;
@@ -854,76 +862,43 @@
854
862
  zzfx.apply(0, zzfxParams);
855
863
  return zzfxParams;
856
864
  },
857
- /**
858
- * Set the ZzFX's global volume factor.
859
- * Note: use 0 to mute all sound effects.
860
- *
861
- * @param {number} value
862
- */
863
865
  volume(value) {
864
866
  DEV: assert(
865
867
  isNumber(value) && value >= 0,
866
- "[litecanvas] volume() 1st param must be a positive number or zero"
868
+ loggerPrefix + "volume() 1st param must be a positive number or zero",
867
869
  );
868
870
  root.zzfxV = value;
869
871
  },
870
- /** PLUGINS API */
871
- /**
872
- * Returns the canvas
873
- *
874
- * @returns {HTMLCanvasElement}
875
- */
876
872
  canvas: () => _canvas,
877
- /**
878
- * Prepares a plugin to be loaded
879
- *
880
- * @param {pluginCallback} callback
881
- */
882
873
  use(callback, config = {}) {
883
874
  DEV: assert(
884
875
  "function" === typeof callback,
885
- "[litecanvas] use() 1st param must be a function"
876
+ loggerPrefix + "use() 1st param must be a function",
886
877
  );
887
878
  DEV: assert(
888
879
  "object" === typeof config,
889
- "[litecanvas] use() 2nd param must be an object"
880
+ loggerPrefix + "use() 2nd param must be an object",
890
881
  );
891
882
  loadPlugin(callback, config);
892
883
  },
893
- /**
894
- * Add a game event listener
895
- *
896
- * @param {string} eventName the event type name
897
- * @param {Function} callback the function that is called when the event occurs
898
- * @returns {Function} a function to remove the listener
899
- */
900
884
  listen(eventName, callback) {
901
885
  DEV: assert(
902
886
  "string" === typeof eventName,
903
- "[litecanvas] listen() 1st param must be a string"
887
+ loggerPrefix + "listen() 1st param must be a string",
904
888
  );
905
889
  DEV: assert(
906
890
  "function" === typeof callback,
907
- "[litecanvas] listen() 2nd param must be a function"
891
+ loggerPrefix + "listen() 2nd param must be a function",
908
892
  );
909
893
  eventName = lowerCase(eventName);
910
- _eventListeners[eventName] = _eventListeners[eventName] || /* @__PURE__ */ new Set();
894
+ _eventListeners[eventName] = _eventListeners[eventName] || new Set();
911
895
  _eventListeners[eventName].add(callback);
912
896
  return () => _eventListeners[eventName]?.delete(callback);
913
897
  },
914
- /**
915
- * Call all listeners attached to a game event
916
- *
917
- * @param {string} eventName The event type name
918
- * @param {*} [arg1] any data to be passed over the listeners
919
- * @param {*} [arg2] any data to be passed over the listeners
920
- * @param {*} [arg3] any data to be passed over the listeners
921
- * @param {*} [arg4] any data to be passed over the listeners
922
- */
923
898
  emit(eventName, arg1, arg2, arg3, arg4) {
924
899
  DEV: assert(
925
900
  "string" === typeof eventName,
926
- "[litecanvas] emit() 1st param must be a string"
901
+ loggerPrefix + "emit() 1st param must be a string",
927
902
  );
928
903
  if (_initialized) {
929
904
  eventName = lowerCase(eventName);
@@ -932,43 +907,27 @@
932
907
  triggerEvent("after:" + eventName, arg1, arg2, arg3, arg4);
933
908
  }
934
909
  },
935
- /**
936
- * Set new palette colors or restore the default palette.
937
- *
938
- * @param {string[]} [colors] an array of colors
939
- * @param {number} [textColor] the default text color this palette
940
- */
941
910
  pal(colors, textColor = 3) {
942
911
  DEV: assert(
943
- null == colors || Array.isArray(colors) && colors.length > 0,
944
- "[litecanvas] pal() 1st param must be a array of color strings"
912
+ null == colors || (Array.isArray(colors) && colors.length > 0),
913
+ loggerPrefix + "pal() 1st param must be a array of color strings",
945
914
  );
946
915
  DEV: assert(
947
916
  isNumber(textColor) && textColor >= 0,
948
- "[litecanvas] pal() 2nd param must be a positive number or zero"
917
+ loggerPrefix + "pal() 2nd param must be a positive number or zero",
949
918
  );
950
919
  _colorPalette = colors || defaultPalette;
951
920
  _colorPaletteState = [];
952
921
  _defaultTextColor = textColor;
953
922
  },
954
- /**
955
- * Replace the color "a" with color "b".
956
- *
957
- * If called without arguments, reset the current palette.
958
- *
959
- * Note: `palc()` don't affect drawings made with `image()`.
960
- *
961
- * @param {number?} a
962
- * @param {number?} b
963
- */
964
923
  palc(a, b) {
965
924
  DEV: assert(
966
- null == a || isNumber(a) && a >= 0,
967
- "[litecanvas] palc() 1st param must be a positive number"
925
+ null == a || (isNumber(a) && a >= 0),
926
+ loggerPrefix + "palc() 1st param must be a positive number",
968
927
  );
969
928
  DEV: assert(
970
929
  isNumber(a) ? isNumber(b) && b >= 0 : null == b,
971
- "[litecanvas] palc() 2nd param must be a positive number"
930
+ loggerPrefix + "palc() 2nd param must be a positive number",
972
931
  );
973
932
  if (a == null) {
974
933
  _colorPaletteState = [];
@@ -976,17 +935,15 @@
976
935
  _colorPaletteState[a] = b;
977
936
  }
978
937
  },
979
- /**
980
- * Define or update a instance property.
981
- *
982
- * @param {string} key
983
- * @param {*} value
984
- */
985
938
  def(key, value) {
986
- DEV: assert("string" === typeof key, "[litecanvas] def() 1st param must be a string");
939
+ DEV: assert(
940
+ "string" === typeof key,
941
+ loggerPrefix + "def() 1st param must be a string",
942
+ );
987
943
  DEV: if (null == value) {
988
944
  console.warn(
989
- `[litecanvas] def() changed the key "${key}" to null (previous value was ${instance[key]})`
945
+ loggerPrefix +
946
+ `def() changed the key "${key}" to null (previous value was ${instance[key]})`,
990
947
  );
991
948
  }
992
949
  instance[key] = value;
@@ -994,110 +951,66 @@
994
951
  root[key] = value;
995
952
  }
996
953
  },
997
- /**
998
- * The scale of the game's delta time (dt).
999
- * Values higher than 1 increase the speed of time, while values smaller than 1 decrease it.
1000
- * A value of 0 freezes time and is effectively equivalent to pausing.
1001
- *
1002
- * @param {number} value
1003
- */
1004
954
  timescale(value) {
1005
955
  DEV: assert(
1006
956
  isNumber(value) && value >= 0,
1007
- "[litecanvas] timescale() 1st param must be a positive number or zero"
957
+ loggerPrefix +
958
+ "timescale() 1st param must be a positive number or zero",
1008
959
  );
1009
960
  _timeScale = value;
1010
961
  },
1011
- /**
1012
- * Set the target FPS (frames per second).
1013
- *
1014
- * @param {number} value
1015
- */
1016
962
  framerate(value) {
1017
963
  DEV: assert(
1018
964
  isNumber(value) && value >= 1,
1019
- "[litecanvas] framerate() 1st param must be a positive number"
965
+ loggerPrefix + "framerate() 1st param must be a positive number",
1020
966
  );
1021
967
  _fpsInterval = 1e3 / ~~value;
1022
968
  },
1023
- /**
1024
- * Returns information about the engine instance.
1025
- *
1026
- * @param {number|string} index
1027
- * @returns {any}
1028
- */
1029
969
  stat(index) {
1030
970
  DEV: assert(
1031
971
  isNumber(index) || "string" === typeof index,
1032
- "[litecanvas] stat() 1st param must be a number or string"
972
+ loggerPrefix + "stat() 1st param must be a number or string",
1033
973
  );
1034
974
  const internals = [
1035
- // 0
1036
975
  settings,
1037
- // 1
1038
976
  _initialized,
1039
- // 2
1040
977
  _fpsInterval / 1e3,
1041
- // 3
1042
978
  _canvasScale,
1043
- // 4
1044
979
  _eventListeners,
1045
- // 5
1046
980
  _colorPalette,
1047
- // 6
1048
981
  _defaultSound,
1049
- // 7
1050
982
  _timeScale,
1051
- // 8
1052
983
  root.zzfxV,
1053
- // 9
1054
984
  _rngSeed,
1055
- // 10
1056
985
  _fontSize,
1057
- // 11
1058
986
  _fontFamily,
1059
- // 12
1060
987
  _colorPaletteState,
1061
- // 13
1062
- _fontLineHeight
988
+ _fontLineHeight,
1063
989
  ];
1064
990
  const data = { index, value: internals[index] };
1065
991
  instance.emit("stat", data);
1066
992
  return data.value;
1067
993
  },
1068
- /**
1069
- * Pauses the engine loop (update & draw).
1070
- */
1071
994
  pause() {
1072
995
  _paused = true;
1073
996
  cancelAnimationFrame(_rafid);
1074
997
  },
1075
- /**
1076
- * Resumes (if paused) the engine loop.
1077
- */
1078
998
  resume() {
1079
999
  DEV: assert(
1080
1000
  _initialized,
1081
- '[litecanvas] resume() cannot be called before the "init" event and neither after the quit() function'
1001
+ loggerPrefix +
1002
+ 'resume() cannot be called before the "init" event and neither after the quit() function',
1082
1003
  );
1083
1004
  if (_initialized && _paused) {
1084
1005
  _paused = false;
1085
1006
  _accumulated = _fpsInterval;
1086
- _lastFrameTime = Date.now();
1007
+ _lastFrameTime = perf.now();
1087
1008
  _rafid = raf(drawFrame);
1088
1009
  }
1089
1010
  },
1090
- /**
1091
- * Returns `true` if the engine loop is paused.
1092
- *
1093
- * @returns {boolean}
1094
- */
1095
1011
  paused() {
1096
1012
  return _paused;
1097
1013
  },
1098
- /**
1099
- * Shutdown the litecanvas instance and remove all event listeners.
1100
- */
1101
1014
  quit() {
1102
1015
  instance.emit("quit");
1103
1016
  instance.pause();
@@ -1112,8 +1025,10 @@
1112
1025
  }
1113
1026
  delete root.ENGINE;
1114
1027
  }
1115
- DEV: console.warn("[litecanvas] quit() terminated a Litecanvas instance.");
1116
- }
1028
+ DEV: console.warn(
1029
+ loggerPrefix + "quit() terminated a Litecanvas instance.",
1030
+ );
1031
+ },
1117
1032
  };
1118
1033
  for (const k of _mathFunctions.split(",")) {
1119
1034
  instance[k] = math[k];
@@ -1123,138 +1038,72 @@
1123
1038
  on(root, "resize", resizeCanvas);
1124
1039
  }
1125
1040
  if (settings.tapEvents) {
1126
- const _getXY = (
1127
- /**
1128
- * @param {MouseEvent | Touch} ev
1129
- */
1130
- (ev) => [
1041
+ const _getXY = (ev) => [
1131
1042
  (ev.pageX - _canvas.offsetLeft) / _canvasScale,
1132
- (ev.pageY - _canvas.offsetTop) / _canvasScale
1133
- ]
1134
- ), _taps = /* @__PURE__ */ new Map(), _registerTap = (
1135
- /**
1136
- * @param {number} id
1137
- * @param {number} [x]
1138
- * @param {number} [y]
1139
- */
1140
- (id, x, y) => {
1141
- const tap = {
1142
- // current x
1143
- x,
1144
- // current y
1145
- y,
1146
- // initial x
1147
- xi: x,
1148
- // initial y
1149
- yi: y,
1150
- // timestamp
1151
- t: Date.now()
1152
- };
1043
+ (ev.pageY - _canvas.offsetTop) / _canvasScale,
1044
+ ],
1045
+ _taps = new Map(),
1046
+ _registerTap = (id, x, y) => {
1047
+ const tap = { x, y, xi: x, yi: y, t: perf.now() };
1153
1048
  _taps.set(id, tap);
1154
1049
  return tap;
1155
- }
1156
- ), _updateTap = (
1157
- /**
1158
- * @param {number} id
1159
- * @param {number} x
1160
- * @param {number} y
1161
- */
1162
- (id, x, y) => {
1050
+ },
1051
+ _updateTap = (id, x, y) => {
1163
1052
  const tap = _taps.get(id) || _registerTap(id);
1164
1053
  tap.x = x;
1165
1054
  tap.y = y;
1166
- }
1167
- ), _checkTapped = (
1168
- /**
1169
- * @param {{t: number}} tap
1170
- */
1171
- (tap) => tap && Date.now() - tap.t <= 300
1172
- );
1055
+ },
1056
+ _checkTapped = (tap) => tap && perf.now() - tap.t <= 300;
1173
1057
  let _pressingMouse = false;
1174
- on(
1175
- _canvas,
1176
- "mousedown",
1177
- /**
1178
- * @param {MouseEvent} ev
1179
- */
1180
- (ev) => {
1181
- if (ev.button === 0) {
1182
- preventDefault(ev);
1183
- const [x, y] = _getXY(ev);
1184
- instance.emit("tap", x, y, 0);
1185
- _registerTap(0, x, y);
1186
- _pressingMouse = true;
1187
- }
1188
- }
1189
- );
1190
- on(
1191
- _canvas,
1192
- "mouseup",
1193
- /**
1194
- * @param {MouseEvent} ev
1195
- */
1196
- (ev) => {
1197
- if (ev.button === 0) {
1198
- preventDefault(ev);
1199
- const tap = _taps.get(0);
1200
- const [x, y] = _getXY(ev);
1201
- if (_checkTapped(tap)) {
1202
- instance.emit("tapped", tap.xi, tap.yi, 0);
1203
- }
1204
- instance.emit("untap", x, y, 0);
1205
- _taps.delete(0);
1206
- _pressingMouse = false;
1207
- }
1208
- }
1209
- );
1210
- on(
1211
- root,
1212
- "mousemove",
1213
- /**
1214
- * @param {MouseEvent} ev
1215
- */
1216
- (ev) => {
1058
+ on(_canvas, "mousedown", (ev) => {
1059
+ if (ev.button === 0) {
1217
1060
  preventDefault(ev);
1218
1061
  const [x, y] = _getXY(ev);
1219
- instance.def("MX", x);
1220
- instance.def("MY", y);
1221
- if (!_pressingMouse) return;
1222
- instance.emit("tapping", x, y, 0);
1223
- _updateTap(0, x, y);
1062
+ instance.emit("tap", x, y, 0);
1063
+ _registerTap(0, x, y);
1064
+ _pressingMouse = true;
1224
1065
  }
1225
- );
1226
- on(
1227
- _canvas,
1228
- "touchstart",
1229
- /**
1230
- * @param {TouchEvent} ev
1231
- */
1232
- (ev) => {
1066
+ });
1067
+ on(_canvas, "mouseup", (ev) => {
1068
+ if (ev.button === 0) {
1233
1069
  preventDefault(ev);
1234
- const touches = ev.changedTouches;
1235
- for (const touch of touches) {
1236
- const [x, y] = _getXY(touch);
1237
- instance.emit("tap", x, y, touch.identifier + 1);
1238
- _registerTap(touch.identifier + 1, x, y);
1070
+ const tap = _taps.get(0);
1071
+ const [x, y] = _getXY(ev);
1072
+ if (_checkTapped(tap)) {
1073
+ instance.emit("tapped", tap.xi, tap.yi, 0);
1239
1074
  }
1075
+ instance.emit("untap", x, y, 0);
1076
+ _taps.delete(0);
1077
+ _pressingMouse = false;
1240
1078
  }
1241
- );
1242
- on(
1243
- _canvas,
1244
- "touchmove",
1245
- /**
1246
- * @param {TouchEvent} ev
1247
- */
1248
- (ev) => {
1249
- preventDefault(ev);
1250
- const touches = ev.changedTouches;
1251
- for (const touch of touches) {
1252
- const [x, y] = _getXY(touch);
1253
- instance.emit("tapping", x, y, touch.identifier + 1);
1254
- _updateTap(touch.identifier + 1, x, y);
1255
- }
1079
+ });
1080
+ on(root, "mousemove", (ev) => {
1081
+ preventDefault(ev);
1082
+ const [x, y] = _getXY(ev);
1083
+ instance.def("MX", x);
1084
+ instance.def("MY", y);
1085
+ if (!_pressingMouse) return;
1086
+ instance.emit("tapping", x, y, 0);
1087
+ _updateTap(0, x, y);
1088
+ });
1089
+ on(_canvas, "touchstart", (ev) => {
1090
+ preventDefault(ev);
1091
+ const touches = ev.changedTouches;
1092
+ for (const touch of touches) {
1093
+ const [x, y] = _getXY(touch);
1094
+ instance.emit("tap", x, y, touch.identifier + 1);
1095
+ _registerTap(touch.identifier + 1, x, y);
1256
1096
  }
1257
- );
1097
+ });
1098
+ on(_canvas, "touchmove", (ev) => {
1099
+ preventDefault(ev);
1100
+ const touches = ev.changedTouches;
1101
+ for (const touch of touches) {
1102
+ const [x, y] = _getXY(touch);
1103
+ instance.emit("tapping", x, y, touch.identifier + 1);
1104
+ _updateTap(touch.identifier + 1, x, y);
1105
+ }
1106
+ });
1258
1107
  const _touchEndHandler = (ev) => {
1259
1108
  preventDefault(ev);
1260
1109
  const existing = [];
@@ -1283,11 +1132,13 @@
1283
1132
  });
1284
1133
  }
1285
1134
  if (settings.keyboardEvents) {
1286
- const _keysDown = /* @__PURE__ */ new Set();
1287
- const _keysPress = /* @__PURE__ */ new Set();
1135
+ const _keysDown = new Set();
1136
+ const _keysPress = new Set();
1288
1137
  const keyCheck = (keySet, key = "") => {
1289
1138
  key = lowerCase(key);
1290
- return !key ? keySet.size > 0 : keySet.has("space" === key ? " " : key);
1139
+ return !key
1140
+ ? keySet.size > 0
1141
+ : keySet.has("space" === key ? " " : key);
1291
1142
  };
1292
1143
  let _lastKey = "";
1293
1144
  on(root, "keydown", (event) => {
@@ -1303,41 +1154,23 @@
1303
1154
  });
1304
1155
  on(root, "blur", () => _keysDown.clear());
1305
1156
  instance.listen("after:update", () => _keysPress.clear());
1306
- instance.def(
1307
- "iskeydown",
1308
- /**
1309
- * @param {string} [key]
1310
- * @returns {boolean}
1311
- */
1312
- (key) => {
1313
- DEV: assert(
1314
- null == key || "string" === typeof key,
1315
- "[litecanvas] iskeydown() 1st param must be a string or undefined"
1316
- );
1317
- return keyCheck(_keysDown, key);
1318
- }
1319
- );
1320
- instance.def(
1321
- "iskeypressed",
1322
- /**
1323
- * @param {string} [key]
1324
- * @returns {boolean}
1325
- */
1326
- (key) => {
1327
- DEV: assert(
1328
- null == key || "string" === typeof key,
1329
- "[litecanvas] iskeypressed() 1st param must be a string or undefined"
1330
- );
1331
- return keyCheck(_keysPress, key);
1332
- }
1333
- );
1334
- instance.def(
1335
- "lastkey",
1336
- /**
1337
- * @returns {string}
1338
- */
1339
- () => _lastKey
1340
- );
1157
+ instance.def("iskeydown", (key) => {
1158
+ DEV: assert(
1159
+ null == key || "string" === typeof key,
1160
+ loggerPrefix +
1161
+ "iskeydown() 1st param must be a string or undefined",
1162
+ );
1163
+ return keyCheck(_keysDown, key);
1164
+ });
1165
+ instance.def("iskeypressed", (key) => {
1166
+ DEV: assert(
1167
+ null == key || "string" === typeof key,
1168
+ loggerPrefix +
1169
+ "iskeypressed() 1st param must be a string or undefined",
1170
+ );
1171
+ return keyCheck(_keysPress, key);
1172
+ });
1173
+ instance.def("lastkey", () => _lastKey);
1341
1174
  }
1342
1175
  _initialized = true;
1343
1176
  instance.resume();
@@ -1345,7 +1178,7 @@
1345
1178
  }
1346
1179
  function drawFrame() {
1347
1180
  _rafid = raf(drawFrame);
1348
- let now = Date.now();
1181
+ let now = perf.now();
1349
1182
  let updated = 0;
1350
1183
  let frameTime = now - _lastFrameTime;
1351
1184
  _lastFrameTime = now;
@@ -1353,7 +1186,7 @@
1353
1186
  while (_accumulated >= _fpsInterval) {
1354
1187
  updated++;
1355
1188
  _accumulated -= _fpsInterval;
1356
- let dt = _fpsInterval / 1e3 * _timeScale;
1189
+ let dt = (_fpsInterval / 1e3) * _timeScale;
1357
1190
  instance.emit("update", dt, updated);
1358
1191
  instance.def("T", instance.T + dt);
1359
1192
  }
@@ -1362,7 +1195,10 @@
1362
1195
  if (updated > 1) {
1363
1196
  _accumulated = 0;
1364
1197
  DEV: console.warn(
1365
- "[litecanvas] the last frame updated " + updated + " times. This can drop the FPS if it keeps happening."
1198
+ loggerPrefix +
1199
+ "the last frame updated " +
1200
+ updated +
1201
+ " times. This can drop the FPS if it keeps happening.",
1366
1202
  );
1367
1203
  }
1368
1204
  }
@@ -1372,7 +1208,8 @@
1372
1208
  _canvas = document.querySelector(settings.canvas);
1373
1209
  DEV: assert(
1374
1210
  null != _canvas,
1375
- '[litecanvas] litecanvas() option "canvas" is an invalid CSS selector'
1211
+ loggerPrefix +
1212
+ 'litecanvas() option "canvas" is an invalid CSS selector',
1376
1213
  );
1377
1214
  } else {
1378
1215
  _canvas = settings.canvas;
@@ -1380,7 +1217,8 @@
1380
1217
  _canvas = _canvas || document.createElement("canvas");
1381
1218
  DEV: assert(
1382
1219
  "CANVAS" === _canvas.tagName,
1383
- '[litecanvas] litecanvas() option "canvas" should be a canvas element or string (CSS selector)'
1220
+ loggerPrefix +
1221
+ 'litecanvas() option "canvas" should be a canvas element or string (CSS selector)',
1384
1222
  );
1385
1223
  _ctx = _canvas.getContext("2d");
1386
1224
  on(_canvas, "click", () => focus());
@@ -1393,18 +1231,25 @@
1393
1231
  }
1394
1232
  function resizeCanvas() {
1395
1233
  DEV: assert(
1396
- null == settings.width || isNumber(settings.width) && settings.width > 0,
1397
- '[litecanvas] litecanvas() option "width" should be a positive number when defined'
1234
+ null == settings.width ||
1235
+ (isNumber(settings.width) && settings.width > 0),
1236
+ loggerPrefix +
1237
+ 'litecanvas() option "width" should be a positive number when defined',
1398
1238
  );
1399
1239
  DEV: assert(
1400
- null == settings.height || isNumber(settings.height) && settings.height > 0,
1401
- '[litecanvas] litecanvas() option "height" should be a positive number when defined'
1240
+ null == settings.height ||
1241
+ (isNumber(settings.height) && settings.height > 0),
1242
+ loggerPrefix +
1243
+ 'litecanvas() option "height" should be a positive number when defined',
1402
1244
  );
1403
1245
  DEV: assert(
1404
- null == settings.height || settings.width > 0 && settings.height > 0,
1405
- '[litecanvas] litecanvas() option "width" is required when the option "height" is defined'
1246
+ null == settings.height || (settings.width > 0 && settings.height > 0),
1247
+ loggerPrefix +
1248
+ 'litecanvas() option "width" is required when the option "height" is defined',
1406
1249
  );
1407
- const width = settings.width > 0 ? settings.width : innerWidth, height = settings.width > 0 ? settings.height || settings.width : innerHeight;
1250
+ const width = settings.width > 0 ? settings.width : innerWidth,
1251
+ height =
1252
+ settings.width > 0 ? settings.height || settings.width : innerHeight;
1408
1253
  instance.def("W", width);
1409
1254
  instance.def("H", height);
1410
1255
  _canvas.width = width;
@@ -1416,7 +1261,8 @@
1416
1261
  _canvas.style.margin = "auto";
1417
1262
  }
1418
1263
  _canvasScale = math.min(innerWidth / width, innerHeight / height);
1419
- _canvasScale = maxScale > 1 && _canvasScale > maxScale ? maxScale : _canvasScale;
1264
+ _canvasScale =
1265
+ maxScale > 1 && _canvasScale > maxScale ? maxScale : _canvasScale;
1420
1266
  _canvas.style.width = width * _canvasScale + "px";
1421
1267
  _canvas.style.height = height * _canvasScale + "px";
1422
1268
  }
@@ -1434,7 +1280,8 @@
1434
1280
  const pluginData = callback(instance, config);
1435
1281
  DEV: assert(
1436
1282
  null == pluginData || "object" === typeof pluginData,
1437
- "[litecanvas] litecanvas() plugins should return an object or nothing"
1283
+ loggerPrefix +
1284
+ "litecanvas() plugins should return an object or nothing",
1438
1285
  );
1439
1286
  for (const key in pluginData) {
1440
1287
  instance.def(key, pluginData[key]);
@@ -1451,13 +1298,13 @@
1451
1298
  Object.assign(root, instance);
1452
1299
  root.ENGINE = instance;
1453
1300
  }
1454
- DEV: console.info(`[litecanvas] version ${version} started`);
1455
- DEV: console.debug(`[litecanvas] litecanvas() options =`, settings);
1301
+ DEV: console.info(loggerPrefix + `version ${version} started`);
1302
+ DEV: console.debug(loggerPrefix + `litecanvas() options =`, settings);
1456
1303
  setupCanvas();
1457
1304
  const source = settings.loop ? settings.loop : root;
1458
1305
  for (const event of _coreEvents.split(",")) {
1459
1306
  DEV: if (root === source && source[event]) {
1460
- console.info(`[litecanvas] using window.${event}()`);
1307
+ console.info(loggerPrefix + `using window.${event}()`);
1461
1308
  }
1462
1309
  if (source[event]) instance.listen(event, source[event]);
1463
1310
  }
@@ -1468,7 +1315,5 @@
1468
1315
  }
1469
1316
  return instance;
1470
1317
  }
1471
-
1472
- // src/web.js
1473
1318
  window.litecanvas = litecanvas;
1474
1319
  })();