litecanvas 0.400.0 → 0.402.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dist.dev.js +85 -87
- package/dist/dist.js +68 -70
- package/dist/dist.min.js +1 -1
- package/package.json +3 -3
- package/src/index.js +93 -155
- package/src/mulberry32.js +21 -0
- package/src/version.js +1 -1
- package/types/global.d.ts +4 -5
- package/types/types.d.ts +7 -6
package/dist/dist.dev.js
CHANGED
|
@@ -115,7 +115,15 @@
|
|
|
115
115
|
var assert = (condition, message = "Assertion failed") => {
|
|
116
116
|
if (!condition) throw new Error("[Litecanvas] " + message);
|
|
117
117
|
};
|
|
118
|
-
var version = "0.
|
|
118
|
+
var version = "0.402.0";
|
|
119
|
+
var mulberry32 = (seed) => {
|
|
120
|
+
return () => {
|
|
121
|
+
let t = (seed += 1831565813);
|
|
122
|
+
t = Math.imul(t ^ (t >>> 15), t | 1);
|
|
123
|
+
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
124
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
125
|
+
};
|
|
126
|
+
};
|
|
119
127
|
function litecanvas(settings = {}) {
|
|
120
128
|
const root = window,
|
|
121
129
|
math = Math,
|
|
@@ -166,6 +174,7 @@
|
|
|
166
174
|
_fontSize = 20,
|
|
167
175
|
_fontLineHeight = 1.2,
|
|
168
176
|
_rngSeed = Date.now(),
|
|
177
|
+
_rngNext = mulberry32(_rngSeed >>> 0),
|
|
169
178
|
_currentPalette = defaultPalette,
|
|
170
179
|
_lastPalette = defaultPalette,
|
|
171
180
|
_colorPaletteState = [],
|
|
@@ -177,6 +186,32 @@
|
|
|
177
186
|
T: 0,
|
|
178
187
|
MX: -1,
|
|
179
188
|
MY: -1,
|
|
189
|
+
rand: (min = 0, max = 1) => {
|
|
190
|
+
DEV: assert(isNumber(min), "rand() 1st argument must be a number");
|
|
191
|
+
DEV: assert(isNumber(max), "rand() 2nd argument must be a number");
|
|
192
|
+
DEV: assert(
|
|
193
|
+
max >= min,
|
|
194
|
+
"rand() the 1st argument must be less than the 2nd argument",
|
|
195
|
+
);
|
|
196
|
+
return min + _rngNext() * (max - min);
|
|
197
|
+
},
|
|
198
|
+
randi: (min = 0, max = 1) => {
|
|
199
|
+
DEV: assert(isNumber(min), "randi() 1st argument must be a number");
|
|
200
|
+
DEV: assert(isNumber(max), "randi() 2nd argument must be a number");
|
|
201
|
+
DEV: assert(
|
|
202
|
+
max >= min,
|
|
203
|
+
"randi() the 1st argument must be less than the 2nd argument",
|
|
204
|
+
);
|
|
205
|
+
return ~~instance.rand(min, max + 1);
|
|
206
|
+
},
|
|
207
|
+
rseed(value) {
|
|
208
|
+
DEV: assert(
|
|
209
|
+
isNumber(value) && value >= 0,
|
|
210
|
+
"rseed() 1st argument must be a non-negative integer",
|
|
211
|
+
);
|
|
212
|
+
_rngSeed = value;
|
|
213
|
+
_rngNext = mulberry32(_rngSeed >>> 0);
|
|
214
|
+
},
|
|
180
215
|
TAU,
|
|
181
216
|
lerp: (start, end, t) => {
|
|
182
217
|
DEV: assert(isNumber(start), "lerp() 1st argument must be a number");
|
|
@@ -265,35 +300,6 @@
|
|
|
265
300
|
);
|
|
266
301
|
return instance.map(value, start, stop, 0, 1);
|
|
267
302
|
},
|
|
268
|
-
rand: (min = 0, max = 1) => {
|
|
269
|
-
DEV: assert(isNumber(min), "rand() 1st argument must be a number");
|
|
270
|
-
DEV: assert(isNumber(max), "rand() 2nd argument must be a number");
|
|
271
|
-
DEV: assert(
|
|
272
|
-
max >= min,
|
|
273
|
-
"rand() the 1st argument must be less than the 2nd argument",
|
|
274
|
-
);
|
|
275
|
-
const a = 1664525;
|
|
276
|
-
const c = 1013904223;
|
|
277
|
-
const m = 4294967296;
|
|
278
|
-
_rngSeed = (a * _rngSeed + c) % m;
|
|
279
|
-
return (_rngSeed / m) * (max - min) + min;
|
|
280
|
-
},
|
|
281
|
-
randi: (min = 0, max = 1) => {
|
|
282
|
-
DEV: assert(isNumber(min), "randi() 1st argument must be a number");
|
|
283
|
-
DEV: assert(isNumber(max), "randi() 2nd argument must be a number");
|
|
284
|
-
DEV: assert(
|
|
285
|
-
max >= min,
|
|
286
|
-
"randi() the 1st argument must be less than the 2nd argument",
|
|
287
|
-
);
|
|
288
|
-
return ~~instance.rand(min, max + 1);
|
|
289
|
-
},
|
|
290
|
-
rseed(value) {
|
|
291
|
-
DEV: assert(
|
|
292
|
-
isNumber(value) && value >= 0,
|
|
293
|
-
"rseed() 1st argument must be a non-negative integer",
|
|
294
|
-
);
|
|
295
|
-
_rngSeed = ~~value;
|
|
296
|
-
},
|
|
297
303
|
cls(color) {
|
|
298
304
|
DEV: assert(
|
|
299
305
|
null == color ||
|
|
@@ -990,77 +996,56 @@
|
|
|
990
996
|
},
|
|
991
997
|
_checkTapped = (tap) => tap && perf.now() - tap.t <= 300;
|
|
992
998
|
let _pressingMouse = false;
|
|
993
|
-
on(_canvas, "
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
instance.emit("tap", x, y, 0);
|
|
998
|
-
_registerTap(0, x, y);
|
|
999
|
+
on(_canvas, "pointerdown", (ev) => {
|
|
1000
|
+
const [x, y] = _getXY(ev);
|
|
1001
|
+
if ("mouse" === ev.pointerType) {
|
|
1002
|
+
if (ev.button) return;
|
|
999
1003
|
_pressingMouse = true;
|
|
1000
1004
|
}
|
|
1005
|
+
const id = ev.pointerId;
|
|
1006
|
+
_registerTap(id, x, y);
|
|
1007
|
+
instance.emit("tap", x, y, id);
|
|
1008
|
+
_canvas.setPointerCapture(id);
|
|
1001
1009
|
});
|
|
1002
|
-
on(_canvas, "
|
|
1003
|
-
if (!ev.button) {
|
|
1004
|
-
preventDefault(ev);
|
|
1005
|
-
const tap = _taps.get(0);
|
|
1006
|
-
const [x, y] = _getXY(ev);
|
|
1007
|
-
if (_checkTapped(tap)) {
|
|
1008
|
-
instance.emit("tapped", tap.xi, tap.yi, 0);
|
|
1009
|
-
}
|
|
1010
|
-
instance.emit("untap", x, y, 0);
|
|
1011
|
-
_taps.delete(0);
|
|
1012
|
-
_pressingMouse = false;
|
|
1013
|
-
}
|
|
1014
|
-
});
|
|
1015
|
-
on(root, "mousemove", (ev) => {
|
|
1016
|
-
preventDefault(ev);
|
|
1010
|
+
on(_canvas, "pointermove", (ev) => {
|
|
1017
1011
|
const [x, y] = _getXY(ev);
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
_updateTap(0, x, y);
|
|
1023
|
-
});
|
|
1024
|
-
on(_canvas, "touchstart", (ev) => {
|
|
1025
|
-
preventDefault(ev);
|
|
1026
|
-
const touches = ev.changedTouches;
|
|
1027
|
-
for (const touch of touches) {
|
|
1028
|
-
const [x, y] = _getXY(touch);
|
|
1029
|
-
instance.emit("tap", x, y, touch.identifier + 1);
|
|
1030
|
-
_registerTap(touch.identifier + 1, x, y);
|
|
1012
|
+
if ("mouse" === ev.pointerType) {
|
|
1013
|
+
instance.def("MX", x);
|
|
1014
|
+
instance.def("MY", y);
|
|
1015
|
+
if (!_pressingMouse) return;
|
|
1031
1016
|
}
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
for (const touch of touches) {
|
|
1037
|
-
const [x, y] = _getXY(touch);
|
|
1038
|
-
instance.emit("tapping", x, y, touch.identifier + 1);
|
|
1039
|
-
_updateTap(touch.identifier + 1, x, y);
|
|
1017
|
+
const id = ev.pointerId;
|
|
1018
|
+
if (_taps.get(id)) {
|
|
1019
|
+
instance.emit("tapping", x, y, id);
|
|
1020
|
+
_updateTap(id, x, y);
|
|
1040
1021
|
}
|
|
1041
1022
|
});
|
|
1042
|
-
const
|
|
1043
|
-
|
|
1044
|
-
const
|
|
1045
|
-
|
|
1046
|
-
|
|
1023
|
+
const _pointerUpHandler = (ev) => {
|
|
1024
|
+
const id = ev.pointerId;
|
|
1025
|
+
const tap = _taps.get(id);
|
|
1026
|
+
const [x, y] = _getXY(ev);
|
|
1027
|
+
if (!tap) return;
|
|
1028
|
+
if ("mouse" === ev.pointerType) {
|
|
1029
|
+
if (ev.button) return;
|
|
1030
|
+
_pressingMouse = false;
|
|
1047
1031
|
}
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
if (_checkTapped(tap)) {
|
|
1051
|
-
instance.emit("tapped", tap.xi, tap.yi, id);
|
|
1052
|
-
}
|
|
1053
|
-
instance.emit("untap", tap.x, tap.y, id);
|
|
1054
|
-
_taps.delete(id);
|
|
1032
|
+
if (_checkTapped(tap)) {
|
|
1033
|
+
instance.emit("tapped", tap.xi, tap.yi, id);
|
|
1055
1034
|
}
|
|
1035
|
+
instance.emit("untap", x, y, id);
|
|
1036
|
+
_taps.delete(id);
|
|
1037
|
+
_canvas.releasePointerCapture(id);
|
|
1056
1038
|
};
|
|
1057
|
-
on(_canvas, "
|
|
1058
|
-
on(_canvas, "
|
|
1039
|
+
on(_canvas, "pointerup", _pointerUpHandler);
|
|
1040
|
+
on(_canvas, "pointercancel", _pointerUpHandler);
|
|
1059
1041
|
on(root, "blur", () => {
|
|
1060
1042
|
_pressingMouse = false;
|
|
1061
1043
|
for (const [id, tap] of _taps) {
|
|
1062
1044
|
instance.emit("untap", tap.x, tap.y, id);
|
|
1063
1045
|
_taps.delete(id);
|
|
1046
|
+
try {
|
|
1047
|
+
_canvas.releasePointerCapture(id);
|
|
1048
|
+
} catch (_) {}
|
|
1064
1049
|
}
|
|
1065
1050
|
});
|
|
1066
1051
|
}
|
|
@@ -1180,7 +1165,7 @@
|
|
|
1180
1165
|
instance.def("H", height);
|
|
1181
1166
|
_canvas.width = width;
|
|
1182
1167
|
_canvas.height = height;
|
|
1183
|
-
_canvas.style = "image-rendering:pixelated";
|
|
1168
|
+
_canvas.style = "image-rendering:pixelated;touch-action:none";
|
|
1184
1169
|
if (settings.autoscale) {
|
|
1185
1170
|
let maxScale = +settings.autoscale;
|
|
1186
1171
|
if (!_canvas.style.display) {
|
|
@@ -1242,3 +1227,16 @@
|
|
|
1242
1227
|
}
|
|
1243
1228
|
window.litecanvas = litecanvas;
|
|
1244
1229
|
})();
|
|
1230
|
+
/**
|
|
1231
|
+
* Mulberry32 is a 32-bit pseudo-random number generator (PRNG).
|
|
1232
|
+
* You provide a 32-bit seed, and it produces a deterministic sequence of values.
|
|
1233
|
+
* The same seed always gives the same sequence.
|
|
1234
|
+
*
|
|
1235
|
+
* @copyright https://gist.github.com/tommyettinger/46a874533244883189143505d203312c
|
|
1236
|
+
* @license CC0-1.0 (Public Domain)
|
|
1237
|
+
*
|
|
1238
|
+
* @param {number} seed an unsigned 32-bit integer
|
|
1239
|
+
* @param {number} t
|
|
1240
|
+
* @param {typeof Math.imul} i
|
|
1241
|
+
* @returns {() => number}
|
|
1242
|
+
*/
|
package/dist/dist.js
CHANGED
|
@@ -112,6 +112,14 @@
|
|
|
112
112
|
};
|
|
113
113
|
};
|
|
114
114
|
var defaultPalette = ["#211e20", "#555568", "#a0a08b", "#e9efec"];
|
|
115
|
+
var mulberry32 = (seed) => {
|
|
116
|
+
return () => {
|
|
117
|
+
let t = (seed += 1831565813);
|
|
118
|
+
t = Math.imul(t ^ (t >>> 15), t | 1);
|
|
119
|
+
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
120
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
121
|
+
};
|
|
122
|
+
};
|
|
115
123
|
function litecanvas(settings = {}) {
|
|
116
124
|
const root = window,
|
|
117
125
|
math = Math,
|
|
@@ -158,6 +166,7 @@
|
|
|
158
166
|
_fontSize = 20,
|
|
159
167
|
_fontLineHeight = 1.2,
|
|
160
168
|
_rngSeed = Date.now(),
|
|
169
|
+
_rngNext = mulberry32(_rngSeed >>> 0),
|
|
161
170
|
_currentPalette = defaultPalette,
|
|
162
171
|
_lastPalette = defaultPalette,
|
|
163
172
|
_colorPaletteState = [],
|
|
@@ -169,6 +178,16 @@
|
|
|
169
178
|
T: 0,
|
|
170
179
|
MX: -1,
|
|
171
180
|
MY: -1,
|
|
181
|
+
rand: (min = 0, max = 1) => {
|
|
182
|
+
return min + _rngNext() * (max - min);
|
|
183
|
+
},
|
|
184
|
+
randi: (min = 0, max = 1) => {
|
|
185
|
+
return ~~instance.rand(min, max + 1);
|
|
186
|
+
},
|
|
187
|
+
rseed(value) {
|
|
188
|
+
_rngSeed = value;
|
|
189
|
+
_rngNext = mulberry32(_rngSeed >>> 0);
|
|
190
|
+
},
|
|
172
191
|
TAU,
|
|
173
192
|
lerp: (start, end, t) => {
|
|
174
193
|
return start + t * (end - start);
|
|
@@ -208,19 +227,6 @@
|
|
|
208
227
|
norm: (value, start, stop) => {
|
|
209
228
|
return instance.map(value, start, stop, 0, 1);
|
|
210
229
|
},
|
|
211
|
-
rand: (min = 0, max = 1) => {
|
|
212
|
-
const a = 1664525;
|
|
213
|
-
const c = 1013904223;
|
|
214
|
-
const m = 4294967296;
|
|
215
|
-
_rngSeed = (a * _rngSeed + c) % m;
|
|
216
|
-
return (_rngSeed / m) * (max - min) + min;
|
|
217
|
-
},
|
|
218
|
-
randi: (min = 0, max = 1) => {
|
|
219
|
-
return ~~instance.rand(min, max + 1);
|
|
220
|
-
},
|
|
221
|
-
rseed(value) {
|
|
222
|
-
_rngSeed = ~~value;
|
|
223
|
-
},
|
|
224
230
|
cls(color) {
|
|
225
231
|
if (null == color) {
|
|
226
232
|
_ctx.clearRect(0, 0, instance.W, instance.H);
|
|
@@ -564,77 +570,56 @@
|
|
|
564
570
|
},
|
|
565
571
|
_checkTapped = (tap) => tap && perf.now() - tap.t <= 300;
|
|
566
572
|
let _pressingMouse = false;
|
|
567
|
-
on(_canvas, "
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
instance.emit("tap", x, y, 0);
|
|
572
|
-
_registerTap(0, x, y);
|
|
573
|
+
on(_canvas, "pointerdown", (ev) => {
|
|
574
|
+
const [x, y] = _getXY(ev);
|
|
575
|
+
if ("mouse" === ev.pointerType) {
|
|
576
|
+
if (ev.button) return;
|
|
573
577
|
_pressingMouse = true;
|
|
574
578
|
}
|
|
579
|
+
const id = ev.pointerId;
|
|
580
|
+
_registerTap(id, x, y);
|
|
581
|
+
instance.emit("tap", x, y, id);
|
|
582
|
+
_canvas.setPointerCapture(id);
|
|
575
583
|
});
|
|
576
|
-
on(_canvas, "
|
|
577
|
-
if (!ev.button) {
|
|
578
|
-
preventDefault(ev);
|
|
579
|
-
const tap = _taps.get(0);
|
|
580
|
-
const [x, y] = _getXY(ev);
|
|
581
|
-
if (_checkTapped(tap)) {
|
|
582
|
-
instance.emit("tapped", tap.xi, tap.yi, 0);
|
|
583
|
-
}
|
|
584
|
-
instance.emit("untap", x, y, 0);
|
|
585
|
-
_taps.delete(0);
|
|
586
|
-
_pressingMouse = false;
|
|
587
|
-
}
|
|
588
|
-
});
|
|
589
|
-
on(root, "mousemove", (ev) => {
|
|
590
|
-
preventDefault(ev);
|
|
584
|
+
on(_canvas, "pointermove", (ev) => {
|
|
591
585
|
const [x, y] = _getXY(ev);
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
_updateTap(0, x, y);
|
|
597
|
-
});
|
|
598
|
-
on(_canvas, "touchstart", (ev) => {
|
|
599
|
-
preventDefault(ev);
|
|
600
|
-
const touches = ev.changedTouches;
|
|
601
|
-
for (const touch of touches) {
|
|
602
|
-
const [x, y] = _getXY(touch);
|
|
603
|
-
instance.emit("tap", x, y, touch.identifier + 1);
|
|
604
|
-
_registerTap(touch.identifier + 1, x, y);
|
|
586
|
+
if ("mouse" === ev.pointerType) {
|
|
587
|
+
instance.def("MX", x);
|
|
588
|
+
instance.def("MY", y);
|
|
589
|
+
if (!_pressingMouse) return;
|
|
605
590
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
for (const touch of touches) {
|
|
611
|
-
const [x, y] = _getXY(touch);
|
|
612
|
-
instance.emit("tapping", x, y, touch.identifier + 1);
|
|
613
|
-
_updateTap(touch.identifier + 1, x, y);
|
|
591
|
+
const id = ev.pointerId;
|
|
592
|
+
if (_taps.get(id)) {
|
|
593
|
+
instance.emit("tapping", x, y, id);
|
|
594
|
+
_updateTap(id, x, y);
|
|
614
595
|
}
|
|
615
596
|
});
|
|
616
|
-
const
|
|
617
|
-
|
|
618
|
-
const
|
|
619
|
-
|
|
620
|
-
|
|
597
|
+
const _pointerUpHandler = (ev) => {
|
|
598
|
+
const id = ev.pointerId;
|
|
599
|
+
const tap = _taps.get(id);
|
|
600
|
+
const [x, y] = _getXY(ev);
|
|
601
|
+
if (!tap) return;
|
|
602
|
+
if ("mouse" === ev.pointerType) {
|
|
603
|
+
if (ev.button) return;
|
|
604
|
+
_pressingMouse = false;
|
|
621
605
|
}
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
if (_checkTapped(tap)) {
|
|
625
|
-
instance.emit("tapped", tap.xi, tap.yi, id);
|
|
626
|
-
}
|
|
627
|
-
instance.emit("untap", tap.x, tap.y, id);
|
|
628
|
-
_taps.delete(id);
|
|
606
|
+
if (_checkTapped(tap)) {
|
|
607
|
+
instance.emit("tapped", tap.xi, tap.yi, id);
|
|
629
608
|
}
|
|
609
|
+
instance.emit("untap", x, y, id);
|
|
610
|
+
_taps.delete(id);
|
|
611
|
+
_canvas.releasePointerCapture(id);
|
|
630
612
|
};
|
|
631
|
-
on(_canvas, "
|
|
632
|
-
on(_canvas, "
|
|
613
|
+
on(_canvas, "pointerup", _pointerUpHandler);
|
|
614
|
+
on(_canvas, "pointercancel", _pointerUpHandler);
|
|
633
615
|
on(root, "blur", () => {
|
|
634
616
|
_pressingMouse = false;
|
|
635
617
|
for (const [id, tap] of _taps) {
|
|
636
618
|
instance.emit("untap", tap.x, tap.y, id);
|
|
637
619
|
_taps.delete(id);
|
|
620
|
+
try {
|
|
621
|
+
_canvas.releasePointerCapture(id);
|
|
622
|
+
} catch (_) {}
|
|
638
623
|
}
|
|
639
624
|
});
|
|
640
625
|
}
|
|
@@ -719,7 +704,7 @@
|
|
|
719
704
|
instance.def("H", height);
|
|
720
705
|
_canvas.width = width;
|
|
721
706
|
_canvas.height = height;
|
|
722
|
-
_canvas.style = "image-rendering:pixelated";
|
|
707
|
+
_canvas.style = "image-rendering:pixelated;touch-action:none";
|
|
723
708
|
if (settings.autoscale) {
|
|
724
709
|
let maxScale = +settings.autoscale;
|
|
725
710
|
if (!_canvas.style.display) {
|
|
@@ -775,3 +760,16 @@
|
|
|
775
760
|
}
|
|
776
761
|
window.litecanvas = litecanvas;
|
|
777
762
|
})();
|
|
763
|
+
/**
|
|
764
|
+
* Mulberry32 is a 32-bit pseudo-random number generator (PRNG).
|
|
765
|
+
* You provide a 32-bit seed, and it produces a deterministic sequence of values.
|
|
766
|
+
* The same seed always gives the same sequence.
|
|
767
|
+
*
|
|
768
|
+
* @copyright https://gist.github.com/tommyettinger/46a874533244883189143505d203312c
|
|
769
|
+
* @license CC0-1.0 (Public Domain)
|
|
770
|
+
*
|
|
771
|
+
* @param {number} seed an unsigned 32-bit integer
|
|
772
|
+
* @param {number} t
|
|
773
|
+
* @param {typeof Math.imul} i
|
|
774
|
+
* @returns {() => number}
|
|
775
|
+
*/
|
package/dist/dist.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{var e=["#211e20","#555568","#a0a08b","#e9efec"];window.litecanvas=function(
|
|
1
|
+
(()=>{var e=["#211e20","#555568","#a0a08b","#e9efec"],t=e=>()=>{let t=e+=0x6d2b79f5;return t=Math.imul(t^t>>>15,1|t),(((t^=t+Math.imul(t^t>>>7,61|t))^t>>>14)>>>0)/0x100000000};window.litecanvas=function(a={}){let n,l=window,i=Math,o=performance,r=2*i.PI,s=requestAnimationFrame,f=[],d=(e,t,a)=>{e.addEventListener(t,a,!1),f.push(()=>e.removeEventListener(t,a,!1))},c=(l.zzfxX=new AudioContext,l.zzfxV=1,(e=1,t=.05,a=220,n=0,l=0,i=.1,o=0,r=1,s=0,f=0,d=0,c=0,p=0,u=0,h=0,m=0,g=0,w=1,x=0,y=0,v=0)=>{let b=Math,z=2*b.PI,k=s*=500*z/44100/44100,C=a*=(1-t+2*t*b.random(t=[]))*z/44100,E=0,P=0,I=0,T=1,L=0,M=0,S=0,A=v<0?-1:1,N=z*A*v*2/44100,W=b.cos(N),X=b.sin,H=X(N)/4,q=1+H,B=-2*W/q,V=(1-H)/q,D=(1+A*W)/2/q,O=-(A+W)/q,G=0,R=0,Y=0,$=0;for(n=44100*n+9,x*=44100,l*=44100,i*=44100,g*=44100,f*=500*z/85766121e6,h*=z/44100,d*=z/44100,c*=44100,p=44100*p|0,e*=.3*zzfxV,A=n+x+l+i+g|0;I<A;t[I++]=S*e)++M%(100*m|0)||(S=o?1<o?2<o?3<o?X(E*E):b.max(b.min(b.tan(E),1),-1):1-(2*E/z%2+2)%2:1-4*b.abs(b.round(E/z)-E/z):X(E),S=(p?1-y+y*X(z*I/p):1)*(S<0?-1:1)*b.abs(S)**r*(I<n?I/n:I<n+x?1-(I-n)/x*(1-w):I<n+x+l?w:I<A-g?(A-I-g)/i*w:0),S=g?S/2+(g>I?0:(I<A-g?1:(A-I)/g)*t[I-g|0]/2/e):S,v&&(S=$=D*G+O*(G=R)+D*(R=S)-V*Y-B*(Y=$))),E+=(N=(a+=s+=f)*b.cos(h*P++))+N*u*X(I**5),T&&++T>c&&(a+=d,C+=d,T=0),!p||++L%p||(a=C,s=k,T=T||1);(e=zzfxX.createBuffer(1,A,44100)).getChannelData(0).set(t),(a=zzfxX.createBufferSource()).buffer=e,a.connect(zzfxX.destination),a.start()}),p=(a=Object.assign({width:null,height:null,autoscale:!0,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0},a)).loop,u,h,m,g=1,w,x=.5,y=1,v,b=1e3/60,z,k=0,C=3,E="sans-serif",P=20,I=1.2,T=Date.now(),L=t(T>>>0),M=e,S=e,A=[],N=[.5,0,1750,,,.3,1,,,,600,.1],W={},X={W:0,H:0,T:0,MX:-1,MY:-1,rand:(e=0,t=1)=>e+L()*(t-e),randi:(e=0,t=1)=>~~X.rand(e,t+1),rseed(e){L=t((T=e)>>>0)},TAU:r,lerp:(e,t,a)=>e+a*(t-e),deg2rad:e=>i.PI/180*e,rad2deg:e=>180/i.PI*e,mod:(e,t)=>(e%t+t)%t||0,round:(e,t=0)=>{if(!t)return i.round(e);let a=10**t;return i.round(e*a)/a},clamp:(e,t,a)=>e<t?t:e>a?a:e,dist:(e,t,a,n)=>i.hypot(a-e,n-t),wrap:(e,t,a)=>e-(a-t)*i.floor((e-t)/(a-t)),map(e,t,a,n,l,i){let o=(e-t)/(a-t)*(l-n)+n;return i?X.clamp(o,n,l):o},norm:(e,t,a)=>X.map(e,t,a,0,1),cls(e){null==e?w.clearRect(0,0,X.W,X.H):X.rectfill(0,0,X.W,X.H,e)},rect(e,t,a,n,l,i){w.beginPath(),w[i?"roundRect":"rect"](~~e-x,~~t-x,~~a+2*x,~~n+2*x,i),X.stroke(l)},rectfill(e,t,a,n,l,i){w.beginPath(),w[i?"roundRect":"rect"](~~e,~~t,~~a,~~n,i),X.fill(l)},oval(e,t,a,n,l){w.beginPath(),w.ellipse(~~e,~~t,~~a,~~n,0,0,r),X.stroke(l)},ovalfill(e,t,a,n,l){w.beginPath(),w.ellipse(~~e,~~t,~~a,~~n,0,0,r),X.fill(l)},circ(e,t,a,n){X.oval(e,t,a,a,n)},circfill(e,t,a,n){X.ovalfill(e,t,a,a,n)},shape(e){w.beginPath();for(let t=0;t<e.length;t+=2)t?w.lineTo(~~e[t],~~e[t+1]):w.moveTo(~~e[t],~~e[t+1]);w.lineTo(~~e[0],~~e[1])},line(e,t,a,n,l){w.beginPath();let i=x&&~~e==~~a?.5:0,o=x&&~~t==~~n?.5:0;w.moveTo(~~e+i,~~t+o),w.lineTo(~~a+i,~~n+o),X.stroke(l)},linewidth(e){w.lineWidth=~~e,x=~~e%2?.5:0},linedash(e,t=0){w.setLineDash(e),w.lineDashOffset=t},text(e,t,a,n=C,l="normal"){w.font=`${l} ${P}px ${E}`,w.fillStyle=D(n);let i=(""+a).split("\n");for(let a=0;a<i.length;a++)w.fillText(i[a],~~e,~~t+P*I*a)},textgap(e){I=e},textfont(e){E=e},textsize(e){P=e},textalign(e,t){e&&(w.textAlign=e),t&&(w.textBaseline=t)},image(e,t,a){w.drawImage(a,~~e,~~t)},spr(e,t,a){let n=a.replace(/[^\w.\n]/g,"").split("\n").filter(e=>e);for(let a=0;a<n.length;a++)for(let l=0;l<n[a].length;l++)"."!==n[a][l]&&X.rectfill(e+l,t+a,1,1,parseInt(n[a][l],36)||0)},paint(e,t,a,n={}){let l=n.canvas||new OffscreenCanvas(1,1),i=n.scale||1,o=w;return l.width=e*i,l.height=t*i,(w=l.getContext("2d")).scale(i,i),a(w),w=o,l.transferToImageBitmap()},ctx:e=>(e&&(w=e),w),push(e=0,t=e,a=0,n=1,l=n){w.save(),X.translate(e,t),X.rotate(a),X.scale(n,l)},pop(){w.restore()},translate(e,t){w.translate(~~e,~~t)},scale(e,t=e){w.scale(e,t)},rotate(e){w.rotate(e)},alpha(e){w.globalAlpha=X.clamp(e,0,1)},fill(e){w.fillStyle=D(e),w.fill()},stroke(e){w.strokeStyle=D(e),w.stroke()},clip(e){w.beginPath(),e(w),w.clip()},sfx:(e,t,a)=>!!l.zzfxV&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e||=N,(t||a>=0)&&((e=e.slice())[0]=a*(e[0]||1),e[10]=~~e[10]+t),c.apply(0,e),e),volume(e){l.zzfxV=e},canvas:()=>m,use(e,t={}){var a=e,n=t;let l=a(X,n);for(let e in l)X.def(e,l[e])},resize(e,t=e,n){a.width=e,a.height=t,a.autoscale=null==n?a.autoscale:n,B()},listen:(e,t)=>{W[e=e.toLowerCase()]=W[e]||new Set,W[e].add(t)},unlisten:(e,t)=>{W[e=e.toLowerCase()]&&W[e].delete(t)},emit:(e,t,a,n,i)=>(u&&(V("before:"+(e=e.toLowerCase()),t,a,n,i),p||l[e]===X[e]||"function"!=typeof l[e]||l[e](t,a,n,i),V(e,t,a,n,i),V("after:"+e,t,a,n,i)),t),pal(e,t=3){null==e?M=S:(S=M,M=e),A=[],C=t,X.emit("pal",M,C)},palc(e,t){null==e?A=[]:A[e]=t},def(e,t){X[e]=t,a.global&&(l[e]=t)},timescale(e){y=e},framerate(e){b=1e3/~~e},stat:e=>[a,u,b/1e3,g,W,M,N,y,l.zzfxV,T,P,E,A,I][e],ispaused:()=>h,pause(){h||(h=!0,k=~~cancelAnimationFrame(k),X.emit("paused"))},resume(){u&&h&&(H(),h=!1,X.emit("resumed"))},quit(){for(let e of(X.emit("quit"),X.pause(),u=!1,W={},f))e();if(a.global){for(let e in X)delete l[e];delete l.ENGINE}}};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,min,max,pow,sqrt,sign".split(","))X[e]=i[e];function H(){k||(z=0,v=o.now(),k=s(q))}function q(){k=s(q);let e=o.now(),t=0,a=e-v;for(v=e,z+=a<100?a:b;z>=b;){t++,z-=b;let e=b/1e3*y;X.emit("update",e,t),X.def("T",X.T+e)}t&&(X.emit("draw",w),t>1&&(z=0))}function B(){let e=a.width>0?a.width:innerWidth,t=a.width>0?a.height||a.width:innerHeight;if(X.def("W",e),X.def("H",t),m.width=e,m.height=t,m.style="image-rendering:pixelated;touch-action:none",a.autoscale){let n=+a.autoscale;m.style.display||(m.style.display="block",m.style.margin="auto"),g=i.min(innerWidth/e,innerHeight/t),g=n>1&&g>n?n:g,m.style.width=e*g+"px",m.style.height=t*g+"px"}w.imageSmoothingEnabled=!1,X.textalign("start","top"),X.emit("resized",g)}function V(e,t,a,n,l){if(W[e])for(let i of W[e])i(t,a,n,l)}function D(e){return e>=0?M[~~(A[e]??e)%M.length]:e}if(a.global){if(l.ENGINE)throw Error("only one global litecanvas is allowed");Object.assign(l,X),l.ENGINE=X}if(n=document,w=(m=(m="string"==typeof a.canvas?n.querySelector(a.canvas):a.canvas)||n.createElement("canvas")).getContext("2d"),d(m,"click",()=>focus()),m.parentNode||n.body.appendChild(m),m.oncontextmenu=()=>!1,B(),p)for(let e in p)p[e]&&X.listen(e,p[e]);return s(function(){if(a.autoscale&&d(l,"resize",B),a.tapEvents){let e=e=>[(e.pageX-m.offsetLeft)/g,(e.pageY-m.offsetTop)/g],t=new Map,a=(e,a,n)=>{let l={x:a,y:n,xi:a,yi:n,t:o.now()};return t.set(e,l),l},n=!1;d(m,"pointerdown",t=>{let[l,i]=e(t);if("mouse"===t.pointerType){if(t.button)return;n=!0}let o=t.pointerId;a(o,l,i),X.emit("tap",l,i,o),m.setPointerCapture(o)}),d(m,"pointermove",l=>{let[i,o]=e(l);if("mouse"===l.pointerType&&(X.def("MX",i),X.def("MY",o),!n))return;let r=l.pointerId;if(t.get(r)){let e;X.emit("tapping",i,o,r),(e=t.get(r)||a(r)).x=i,e.y=o}});let i=a=>{let l=a.pointerId,i=t.get(l),[r,s]=e(a);if(i){if("mouse"===a.pointerType){if(a.button)return;n=!1}i&&o.now()-i.t<=300&&X.emit("tapped",i.xi,i.yi,l),X.emit("untap",r,s,l),t.delete(l),m.releasePointerCapture(l)}};d(m,"pointerup",i),d(m,"pointercancel",i),d(l,"blur",()=>{for(let[e,a]of(n=!1,t)){X.emit("untap",a.x,a.y,e),t.delete(e);try{m.releasePointerCapture(e)}catch(e){}}})}if(a.keyboardEvents){let e=new Set,t=new Set,a=(e,t="")=>(t=t.toLowerCase())?e.has("space"===t?" ":t):e.size>0,n="";d(l,"keydown",a=>{let l=a.key.toLowerCase();e.has(l)||(e.add(l),t.add(l),n=" "===l?"space":l)}),d(l,"keyup",t=>{e.delete(t.key.toLowerCase())}),d(l,"blur",()=>e.clear()),X.listen("after:update",()=>t.clear()),X.def("iskeydown",t=>a(e,t)),X.def("iskeypressed",e=>a(t,e)),X.def("lastkey",()=>n)}u=!0,X.emit("init",X),h||H()}),X}})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "litecanvas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.402.0",
|
|
4
4
|
"description": "Lightweight HTML5 canvas 2D game engine suitable for small projects and creative coding. Inspired by PICO-8 and p5.js/Processing.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Luiz Bills <luizbills@pm.me>",
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"creative coding"
|
|
33
33
|
],
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@happy-dom/global-registrator": "^21.0.
|
|
35
|
+
"@happy-dom/global-registrator": "^21.0.3",
|
|
36
36
|
"@size-limit/preset-small-lib": "^14.2.0",
|
|
37
37
|
"@swc/core": "^1.16.18",
|
|
38
|
-
"ava": "^8.0
|
|
38
|
+
"ava": "^8.1.0",
|
|
39
39
|
"esbuild": "^0.28.2",
|
|
40
40
|
"genversion": "^3.2.0",
|
|
41
41
|
"gzip-size": "^7.0.0",
|
package/src/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { setupZzFX } from './zzfx.js'
|
|
|
3
3
|
import { defaultPalette } from './palette.js'
|
|
4
4
|
import { assert } from './dev.js'
|
|
5
5
|
import { version } from './version.js'
|
|
6
|
+
import { mulberry32 } from './mulberry32.js'
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* The litecanvas constructor
|
|
@@ -84,13 +85,15 @@ export default function litecanvas(settings = {}) {
|
|
|
84
85
|
_fontLineHeight = 1.2,
|
|
85
86
|
/** @type {number} */
|
|
86
87
|
_rngSeed = Date.now(),
|
|
88
|
+
/** @type {() => number} */
|
|
89
|
+
_rngNext = mulberry32(_rngSeed >>> 0),
|
|
87
90
|
/** @type {string[]} */
|
|
88
91
|
_currentPalette = defaultPalette,
|
|
89
92
|
/** @type {string[]} */
|
|
90
93
|
_lastPalette = defaultPalette,
|
|
91
94
|
/** @type {number[]} */
|
|
92
95
|
_colorPaletteState = [],
|
|
93
|
-
/** @type {number[]} */
|
|
96
|
+
/** @type {(number|undefined)[]} */
|
|
94
97
|
_defaultSound = [0.5, 0, 1750, , , 0.3, 1, , , , 600, 0.1],
|
|
95
98
|
/**
|
|
96
99
|
* @type {Object<string,Set<Function>>} game event listeners
|
|
@@ -114,6 +117,54 @@ export default function litecanvas(settings = {}) {
|
|
|
114
117
|
/** @type {number} */
|
|
115
118
|
MY: -1,
|
|
116
119
|
|
|
120
|
+
/** RNG API */
|
|
121
|
+
/**
|
|
122
|
+
* Generates a pseudo random float between min (inclusive) and max (exclusive)
|
|
123
|
+
* using the Mulberry32 algorithm.
|
|
124
|
+
*
|
|
125
|
+
* @param {number} [min=0.0]
|
|
126
|
+
* @param {number} [max=1.0]
|
|
127
|
+
* @returns {number} the random number
|
|
128
|
+
*/
|
|
129
|
+
rand: (min = 0.0, max = 1.0) => {
|
|
130
|
+
DEV: assert(isNumber(min), 'rand() 1st argument must be a number')
|
|
131
|
+
DEV: assert(isNumber(max), 'rand() 2nd argument must be a number')
|
|
132
|
+
DEV: assert(max >= min, 'rand() the 1st argument must be less than the 2nd argument')
|
|
133
|
+
|
|
134
|
+
return min + _rngNext() * (max - min)
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Generates a pseudo random integer between min (inclusive) and max (inclusive).
|
|
139
|
+
*
|
|
140
|
+
* @param {number} [min=0]
|
|
141
|
+
* @param {number} [max=1]
|
|
142
|
+
* @returns {number} the random number
|
|
143
|
+
*/
|
|
144
|
+
randi: (min = 0, max = 1) => {
|
|
145
|
+
DEV: assert(isNumber(min), 'randi() 1st argument must be a number')
|
|
146
|
+
DEV: assert(isNumber(max), 'randi() 2nd argument must be a number')
|
|
147
|
+
DEV: assert(max >= min, 'randi() the 1st argument must be less than the 2nd argument')
|
|
148
|
+
|
|
149
|
+
return ~~instance.rand(min, max + 1)
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Initializes the random number generator with an explicit seed value.
|
|
154
|
+
*
|
|
155
|
+
* Note: The seed should be a integer number greater than or equal to zero.
|
|
156
|
+
*
|
|
157
|
+
* @param {number} value
|
|
158
|
+
*/
|
|
159
|
+
rseed(value) {
|
|
160
|
+
DEV: assert(
|
|
161
|
+
isNumber(value) && value >= 0,
|
|
162
|
+
'rseed() 1st argument must be a non-negative integer'
|
|
163
|
+
)
|
|
164
|
+
_rngSeed = value
|
|
165
|
+
_rngNext = mulberry32(_rngSeed >>> 0)
|
|
166
|
+
},
|
|
167
|
+
|
|
117
168
|
/** MATH API */
|
|
118
169
|
/**
|
|
119
170
|
* Twice the value of the mathematical constant PI (π).
|
|
@@ -306,60 +357,6 @@ export default function litecanvas(settings = {}) {
|
|
|
306
357
|
return instance.map(value, start, stop, 0, 1)
|
|
307
358
|
},
|
|
308
359
|
|
|
309
|
-
/** RNG API */
|
|
310
|
-
/**
|
|
311
|
-
* Generates a pseudorandom float between min (inclusive) and max (exclusive)
|
|
312
|
-
* using the Linear Congruential Generator (LCG) algorithm.
|
|
313
|
-
*
|
|
314
|
-
* @param {number} [min=0.0]
|
|
315
|
-
* @param {number} [max=1.0]
|
|
316
|
-
* @returns {number} the random number
|
|
317
|
-
*/
|
|
318
|
-
rand: (min = 0.0, max = 1.0) => {
|
|
319
|
-
DEV: assert(isNumber(min), 'rand() 1st argument must be a number')
|
|
320
|
-
DEV: assert(isNumber(max), 'rand() 2nd argument must be a number')
|
|
321
|
-
DEV: assert(max >= min, 'rand() the 1st argument must be less than the 2nd argument')
|
|
322
|
-
|
|
323
|
-
const a = 1664525
|
|
324
|
-
const c = 1013904223
|
|
325
|
-
const m = 4294967296
|
|
326
|
-
|
|
327
|
-
_rngSeed = (a * _rngSeed + c) % m
|
|
328
|
-
|
|
329
|
-
return (_rngSeed / m) * (max - min) + min
|
|
330
|
-
},
|
|
331
|
-
|
|
332
|
-
/**
|
|
333
|
-
* Generates a pseudorandom integer between min (inclusive) and max (inclusive)
|
|
334
|
-
*
|
|
335
|
-
* @param {number} [min=0]
|
|
336
|
-
* @param {number} [max=1]
|
|
337
|
-
* @returns {number} the random number
|
|
338
|
-
*/
|
|
339
|
-
randi: (min = 0, max = 1) => {
|
|
340
|
-
DEV: assert(isNumber(min), 'randi() 1st argument must be a number')
|
|
341
|
-
DEV: assert(isNumber(max), 'randi() 2nd argument must be a number')
|
|
342
|
-
DEV: assert(max >= min, 'randi() the 1st argument must be less than the 2nd argument')
|
|
343
|
-
|
|
344
|
-
return ~~instance.rand(min, max + 1)
|
|
345
|
-
},
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* Initializes the random number generator with an explicit seed value.
|
|
349
|
-
*
|
|
350
|
-
* Note: The seed should be a integer number greater than or equal to zero.
|
|
351
|
-
*
|
|
352
|
-
* @param {number} value
|
|
353
|
-
*/
|
|
354
|
-
rseed(value) {
|
|
355
|
-
DEV: assert(
|
|
356
|
-
isNumber(value) && value >= 0,
|
|
357
|
-
'rseed() 1st argument must be a non-negative integer'
|
|
358
|
-
)
|
|
359
|
-
|
|
360
|
-
_rngSeed = ~~value
|
|
361
|
-
},
|
|
362
|
-
|
|
363
360
|
/** BASIC GRAPHICS API */
|
|
364
361
|
/**
|
|
365
362
|
* Clear the game screen with an optional color.
|
|
@@ -1502,128 +1499,70 @@ export default function litecanvas(settings = {}) {
|
|
|
1502
1499
|
|
|
1503
1500
|
let _pressingMouse = false
|
|
1504
1501
|
|
|
1505
|
-
on(
|
|
1506
|
-
|
|
1507
|
-
'mousedown',
|
|
1508
|
-
/**
|
|
1509
|
-
* @param {MouseEvent} ev
|
|
1510
|
-
*/
|
|
1511
|
-
(ev) => {
|
|
1512
|
-
if (!ev.button) {
|
|
1513
|
-
preventDefault(ev)
|
|
1514
|
-
const [x, y] = _getXY(ev)
|
|
1515
|
-
instance.emit('tap', x, y, 0)
|
|
1516
|
-
_registerTap(0, x, y)
|
|
1517
|
-
_pressingMouse = true
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
|
-
)
|
|
1502
|
+
on(_canvas, 'pointerdown', (ev) => {
|
|
1503
|
+
const [x, y] = _getXY(ev)
|
|
1521
1504
|
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
/**
|
|
1526
|
-
* @param {MouseEvent} ev
|
|
1527
|
-
*/
|
|
1528
|
-
(ev) => {
|
|
1529
|
-
if (!ev.button) {
|
|
1530
|
-
preventDefault(ev)
|
|
1531
|
-
const tap = _taps.get(0)
|
|
1532
|
-
const [x, y] = _getXY(ev)
|
|
1533
|
-
if (_checkTapped(tap)) {
|
|
1534
|
-
instance.emit('tapped', tap.xi, tap.yi, 0)
|
|
1535
|
-
}
|
|
1536
|
-
instance.emit('untap', x, y, 0)
|
|
1537
|
-
_taps.delete(0)
|
|
1538
|
-
_pressingMouse = false
|
|
1539
|
-
}
|
|
1505
|
+
if ('mouse' === ev.pointerType) {
|
|
1506
|
+
if (ev.button) return
|
|
1507
|
+
_pressingMouse = true
|
|
1540
1508
|
}
|
|
1541
|
-
)
|
|
1542
1509
|
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
'
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1510
|
+
const id = ev.pointerId
|
|
1511
|
+
_registerTap(id, x, y)
|
|
1512
|
+
instance.emit('tap', x, y, id)
|
|
1513
|
+
|
|
1514
|
+
_canvas.setPointerCapture(id)
|
|
1515
|
+
})
|
|
1516
|
+
|
|
1517
|
+
on(_canvas, 'pointermove', (ev) => {
|
|
1518
|
+
const [x, y] = _getXY(ev)
|
|
1551
1519
|
|
|
1552
|
-
|
|
1520
|
+
if ('mouse' === ev.pointerType) {
|
|
1553
1521
|
instance.def('MX', x)
|
|
1554
1522
|
instance.def('MY', y)
|
|
1555
|
-
|
|
1556
1523
|
if (!_pressingMouse) return
|
|
1557
|
-
|
|
1558
|
-
instance.emit('tapping', x, y, 0)
|
|
1559
|
-
_updateTap(0, x, y)
|
|
1560
1524
|
}
|
|
1561
|
-
)
|
|
1562
1525
|
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
* @param {TouchEvent} ev
|
|
1568
|
-
*/
|
|
1569
|
-
(ev) => {
|
|
1570
|
-
preventDefault(ev)
|
|
1571
|
-
/** @type {TouchList} touches */
|
|
1572
|
-
const touches = ev.changedTouches
|
|
1573
|
-
for (const touch of touches) {
|
|
1574
|
-
const [x, y] = _getXY(touch)
|
|
1575
|
-
instance.emit('tap', x, y, touch.identifier + 1)
|
|
1576
|
-
_registerTap(touch.identifier + 1, x, y)
|
|
1577
|
-
}
|
|
1526
|
+
const id = ev.pointerId
|
|
1527
|
+
if (_taps.get(id)) {
|
|
1528
|
+
instance.emit('tapping', x, y, id)
|
|
1529
|
+
_updateTap(id, x, y)
|
|
1578
1530
|
}
|
|
1579
|
-
)
|
|
1531
|
+
})
|
|
1580
1532
|
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
* @param {TouchEvent} ev
|
|
1586
|
-
*/
|
|
1587
|
-
(ev) => {
|
|
1588
|
-
preventDefault(ev)
|
|
1589
|
-
const touches = ev.changedTouches
|
|
1590
|
-
for (const touch of touches) {
|
|
1591
|
-
const [x, y] = _getXY(touch)
|
|
1592
|
-
instance.emit('tapping', x, y, touch.identifier + 1)
|
|
1593
|
-
_updateTap(touch.identifier + 1, x, y)
|
|
1594
|
-
}
|
|
1595
|
-
}
|
|
1596
|
-
)
|
|
1533
|
+
const _pointerUpHandler = (ev) => {
|
|
1534
|
+
const id = ev.pointerId
|
|
1535
|
+
const tap = _taps.get(id)
|
|
1536
|
+
const [x, y] = _getXY(ev)
|
|
1597
1537
|
|
|
1598
|
-
|
|
1599
|
-
* @param {TouchEvent} ev
|
|
1600
|
-
*/
|
|
1601
|
-
const _touchEndHandler = (ev) => {
|
|
1602
|
-
preventDefault(ev)
|
|
1603
|
-
const existing = []
|
|
1538
|
+
if (!tap) return
|
|
1604
1539
|
|
|
1605
|
-
|
|
1606
|
-
|
|
1540
|
+
if ('mouse' === ev.pointerType) {
|
|
1541
|
+
if (ev.button) return
|
|
1542
|
+
_pressingMouse = false
|
|
1607
1543
|
}
|
|
1608
1544
|
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
if (_checkTapped(tap)) {
|
|
1612
|
-
instance.emit('tapped', tap.xi, tap.yi, id)
|
|
1613
|
-
}
|
|
1614
|
-
instance.emit('untap', tap.x, tap.y, id)
|
|
1615
|
-
_taps.delete(id)
|
|
1545
|
+
if (_checkTapped(tap)) {
|
|
1546
|
+
instance.emit('tapped', tap.xi, tap.yi, id)
|
|
1616
1547
|
}
|
|
1548
|
+
|
|
1549
|
+
instance.emit('untap', x, y, id)
|
|
1550
|
+
|
|
1551
|
+
_taps.delete(id)
|
|
1552
|
+
_canvas.releasePointerCapture(id)
|
|
1617
1553
|
}
|
|
1618
1554
|
|
|
1619
|
-
on(_canvas, '
|
|
1620
|
-
on(_canvas, '
|
|
1555
|
+
on(_canvas, 'pointerup', _pointerUpHandler)
|
|
1556
|
+
on(_canvas, 'pointercancel', _pointerUpHandler)
|
|
1621
1557
|
|
|
1622
1558
|
on(root, 'blur', () => {
|
|
1623
1559
|
_pressingMouse = false
|
|
1624
1560
|
for (const [id, tap] of _taps) {
|
|
1625
1561
|
instance.emit('untap', tap.x, tap.y, id)
|
|
1626
1562
|
_taps.delete(id)
|
|
1563
|
+
try {
|
|
1564
|
+
_canvas.releasePointerCapture(id)
|
|
1565
|
+
} catch (_) {}
|
|
1627
1566
|
}
|
|
1628
1567
|
})
|
|
1629
1568
|
}
|
|
@@ -1806,8 +1745,7 @@ export default function litecanvas(settings = {}) {
|
|
|
1806
1745
|
_canvas.width = width
|
|
1807
1746
|
_canvas.height = height
|
|
1808
1747
|
|
|
1809
|
-
|
|
1810
|
-
_canvas.style = 'image-rendering:pixelated'
|
|
1748
|
+
_canvas.style = 'image-rendering:pixelated;touch-action:none'
|
|
1811
1749
|
|
|
1812
1750
|
if (settings.autoscale) {
|
|
1813
1751
|
let maxScale = +settings.autoscale
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mulberry32 is a 32-bit pseudo-random number generator (PRNG).
|
|
3
|
+
* You provide a 32-bit seed, and it produces a deterministic sequence of values.
|
|
4
|
+
* The same seed always gives the same sequence.
|
|
5
|
+
*
|
|
6
|
+
* @copyright https://gist.github.com/tommyettinger/46a874533244883189143505d203312c
|
|
7
|
+
* @license CC0-1.0 (Public Domain)
|
|
8
|
+
*
|
|
9
|
+
* @param {number} seed an unsigned 32-bit integer
|
|
10
|
+
* @param {number} t
|
|
11
|
+
* @param {typeof Math.imul} i
|
|
12
|
+
* @returns {() => number}
|
|
13
|
+
*/
|
|
14
|
+
export const mulberry32 = (seed) => {
|
|
15
|
+
return () => {
|
|
16
|
+
let t = (seed += 0x6d2b79f5)
|
|
17
|
+
t = Math.imul(t ^ (t >>> 15), t | 1)
|
|
18
|
+
t ^= t + Math.imul(t ^ (t >>> 7), t | 61)
|
|
19
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296
|
|
20
|
+
}
|
|
21
|
+
}
|
package/src/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '0.
|
|
2
|
+
export const version = '0.402.0'
|
package/types/global.d.ts
CHANGED
|
@@ -186,7 +186,8 @@ declare global {
|
|
|
186
186
|
|
|
187
187
|
/** RNG API */
|
|
188
188
|
/**
|
|
189
|
-
* Generates a
|
|
189
|
+
* Generates a pseudo random float between min (inclusive) and max (exclusive)
|
|
190
|
+
* using the Mulberry32 algorithm.
|
|
190
191
|
*
|
|
191
192
|
* @param [min=0.0]
|
|
192
193
|
* @param [max=1.0]
|
|
@@ -194,7 +195,7 @@ declare global {
|
|
|
194
195
|
*/
|
|
195
196
|
function rand(min?: number, max?: number): number
|
|
196
197
|
/**
|
|
197
|
-
* Generates a
|
|
198
|
+
* Generates a pseudo random integer between min (inclusive) and max (inclusive).
|
|
198
199
|
*
|
|
199
200
|
* @param [min=0]
|
|
200
201
|
* @param [max=1]
|
|
@@ -204,9 +205,7 @@ declare global {
|
|
|
204
205
|
/**
|
|
205
206
|
* Initializes the random number generator with an explicit seed value.
|
|
206
207
|
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
* @param value
|
|
208
|
+
* @param value the PRNG seed. Must be an non-negative number.
|
|
210
209
|
*/
|
|
211
210
|
function rseed(value: number): void
|
|
212
211
|
|
package/types/types.d.ts
CHANGED
|
@@ -180,7 +180,8 @@ type LitecanvasInstance = {
|
|
|
180
180
|
|
|
181
181
|
/** RNG API */
|
|
182
182
|
/**
|
|
183
|
-
* Generates a
|
|
183
|
+
* Generates a pseudo random float between min (inclusive) and max (exclusive)
|
|
184
|
+
* using the Mulberry32 algorithm.
|
|
184
185
|
*
|
|
185
186
|
* @param [min=0.0]
|
|
186
187
|
* @param [max=1.0]
|
|
@@ -188,7 +189,7 @@ type LitecanvasInstance = {
|
|
|
188
189
|
*/
|
|
189
190
|
rand(min?: number, max?: number): number
|
|
190
191
|
/**
|
|
191
|
-
* Generates a
|
|
192
|
+
* Generates a pseudo random integer between min (inclusive) and max (inclusive)
|
|
192
193
|
*
|
|
193
194
|
* @param [min=0]
|
|
194
195
|
* @param [max=1]
|
|
@@ -196,11 +197,11 @@ type LitecanvasInstance = {
|
|
|
196
197
|
*/
|
|
197
198
|
randi(min?: number, max?: number): number
|
|
198
199
|
/**
|
|
199
|
-
*
|
|
200
|
+
* Generates a pseudo random integer between min (inclusive) and max (inclusive).
|
|
200
201
|
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
* @
|
|
202
|
+
* @param [min=0]
|
|
203
|
+
* @param [max=1]
|
|
204
|
+
* @returns the random number
|
|
204
205
|
*/
|
|
205
206
|
rseed(value: number): void
|
|
206
207
|
|