|
2 | 2 | // public/litecanvas.js
|
3 | 3 | (() => {
|
4 | 4 | var zzfxX = /* @__PURE__ */ new AudioContext();
|
5 |
| - var zzfx = (p = 1, k = 0.05, b = 220, e = 0, r = 0, t = 0.1, q = 0, D = 1, u = 0, y = 0, v = 0, z = 0, l = 0, E = 0, A = 0, F = 0, c = 0, w = 1, m = 0, B = 0, N = 0) => { |
6 |
| - let M = Math, d = 2 * M.PI, R = 44100, G = u *= 500 * d / R / R, C = b *= (1 - k + 2 * k * M.random(k = [])) * d / R, g = 0, H = 0, a = 0, n = 1, I = 0, J = 0, f = 0, h = N < 0 ? -1 : 1, x = d * h * N * 2 / R, L = M.cos(x), Z = M.sin, K = Z(x) / 4, O = 1 + K, X = -2 * L / O, Y = (1 - K) / O, P = (1 + h * L) / 2 / O, Q = -(h + L) / O, S = P, T = 0, U = 0, V = 0, W = 0; |
7 |
| - e = R * e + 9; |
8 |
| - m *= R; |
9 |
| - r *= R; |
10 |
| - t *= R; |
11 |
| - c *= R; |
12 |
| - y *= 500 * d / R ** 3; |
13 |
| - A *= d / R; |
14 |
| - v *= d / R; |
15 |
| - z *= R; |
16 |
| - l = R * l | 0; |
17 |
| - p *= 0.3 * (globalThis.zzfxV || 1); |
18 |
| - for (h = e + m + r + t + c | 0; a < h; k[a++] = f * p) |
19 |
| - ++J % (100 * F | 0) || (f = q ? 1 < q ? 2 < q ? 3 < q ? Z(g * g) : M.max(M.min(M.tan(g), 1), -1) : 1 - (2 * g / d % 2 + 2) % 2 : 1 - 4 * M.abs(M.round(g / d) - g / d) : Z(g), f = (l ? 1 - B + B * Z(d * a / l) : 1) * (f < 0 ? -1 : 1) * M.abs(f) ** D * (a < e ? a / e : a < e + m ? 1 - (a - e) / m * (1 - w) : a < e + m + r ? w : a < h - c ? (h - a - c) / t * w : 0), f = c ? f / 2 + (c > a ? 0 : (a < h - c ? 1 : (h - a) / c) * k[a - c | 0] / 2 / p) : f, N ? f = W = S * T + Q * (T = U) + P * (U = f) - Y * V - X * (V = W) : 0), x = (b += u += y) * M.cos(A * H++), g += x + x * E * Z(a ** 5), n && ++n > z && (b += v, C += v, n = 0), !l || ++I % l || (b = C, u = G, n = n || 1); |
20 |
| - p = zzfxX.createBuffer(1, h, R); |
21 |
| - p.getChannelData(0).set(k); |
22 |
| - b = zzfxX.createBufferSource(); |
23 |
| - b.buffer = p; |
24 |
| - b.connect(zzfxX.destination); |
25 |
| - b.start(); |
| 5 | + var zzfx = (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) => { |
| 6 | + 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; |
| 7 | + 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 * (globalThis.zzfxV || 1), 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); |
| 8 | + i = zzfxX.createBuffer(1, s, a), i.getChannelData(0).set(d), z = zzfxX.createBufferSource(), z.buffer = i, z.connect(zzfxX.destination), z.start(); |
26 | 9 | };
|
27 | 10 | var colors = [
|
28 | 11 | "#111",
|
|
96 | 79 | /** @type {number[]} */
|
97 | 80 | DEFAULT_SFX: [0.5, , 1675, , 0.06, 0.2, 1, 1.8, , , 637, 0.06],
|
98 | 81 | /** MATH API */
|
99 |
| - /** |
100 |
| - * The value of the mathematical constant PI (π). |
101 |
| - * Approximately 3.14159 |
102 |
| - * |
103 |
| - * @type {number} |
104 |
| - */ |
105 |
| - PI, |
106 | 82 | /**
|
107 | 83 | * Twice the value of the mathematical constant PI (π).
|
108 | 84 | * Approximately 6.28318
|
|
119 | 95 | *
|
120 | 96 | * @type {number}
|
121 | 97 | */
|
122 |
| - HALF_PI: PI * 0.5, |
| 98 | + HALF_PI: PI / 2, |
123 | 99 | /**
|
124 | 100 | * Calculates a linear (interpolation) value over t%.
|
125 | 101 | *
|
|
135 | 111 | assert(isFinite(end), "lerp: 2nd param must be a number");
|
136 | 112 | assert(isFinite(t), "lerp: 3rd param must be a number");
|
137 | 113 | }
|
138 |
| - return start + t * (end - start); |
| 114 | + return t * (end - start) + start; |
139 | 115 | },
|
140 | 116 | /**
|
141 | 117 | * Convert degrees to radians
|
|
1091 | 1067 | }
|
1092 | 1068 | }
|
1093 | 1069 | };
|
1094 |
| - for (const k of [ |
1095 |
| - "sin", |
1096 |
| - "cos", |
1097 |
| - "atan2", |
1098 |
| - "hypot", |
1099 |
| - "tan", |
1100 |
| - "abs", |
1101 |
| - "ceil", |
1102 |
| - "round", |
1103 |
| - "floor", |
1104 |
| - "trunc", |
1105 |
| - "min", |
1106 |
| - "max", |
1107 |
| - "pow", |
1108 |
| - "sqrt", |
1109 |
| - "sign", |
1110 |
| - "exp" |
1111 |
| - ]) { |
| 1070 | + for (const k of "PI,sin,cos,atan2,hypot,tan,abs,ceil,round,floor,trunc,min,max,pow,sqrt,sign,exp".split(",")) { |
1112 | 1071 | instance[k] = Math[k];
|
1113 | 1072 | }
|
1114 | 1073 | function init() {
|
|
1143 | 1102 | const tap = _taps.get(id) || _registerTap(id);
|
1144 | 1103 | tap.x = x;
|
1145 | 1104 | tap.y = y;
|
1146 |
| - }, _checkTapped = (tap) => tap && performance.now() - tap.ts <= 200; |
| 1105 | + }, _checkTapped = (tap) => tap && performance.now() - tap.ts <= 200, preventDefault = (ev) => ev.preventDefault(); |
1147 | 1106 | let _pressingMouse = false;
|
1148 | 1107 | on(_canvas, "mousedown", (ev) => {
|
1149 |
| - ev.preventDefault(); |
1150 |
| - const [x, y] = _getXY(ev.pageX, ev.pageY); |
1151 |
| - instance.emit("tap", x, y, 0); |
1152 |
| - _registerTap(0, x, y); |
1153 |
| - _pressingMouse = true; |
| 1108 | + if (ev.button === 0) { |
| 1109 | + preventDefault(ev); |
| 1110 | + const [x, y] = _getXY(ev.pageX, ev.pageY); |
| 1111 | + instance.emit("tap", x, y, 0); |
| 1112 | + _registerTap(0, x, y); |
| 1113 | + _pressingMouse = true; |
| 1114 | + } |
| 1115 | + }); |
| 1116 | + on(_canvas, "mouseup", (ev) => { |
| 1117 | + if (ev.button === 0) { |
| 1118 | + preventDefault(ev); |
| 1119 | + const tap = _taps.get(0); |
| 1120 | + const [x, y] = _getXY(ev.pageX, ev.pageY); |
| 1121 | + if (_checkTapped(tap)) { |
| 1122 | + instance.emit("tapped", tap.startX, tap.startY, 0); |
| 1123 | + } |
| 1124 | + instance.emit("untap", x, y, 0); |
| 1125 | + _taps.delete(0); |
| 1126 | + _pressingMouse = false; |
| 1127 | + } |
1154 | 1128 | });
|
1155 | 1129 | on(_canvas, "mousemove", (ev) => {
|
1156 |
| - ev.preventDefault(); |
| 1130 | + preventDefault(ev); |
1157 | 1131 | const [x, y] = _getXY(ev.pageX, ev.pageY);
|
1158 | 1132 | instance.setvar("MOUSEX", x);
|
1159 | 1133 | instance.setvar("MOUSEY", y);
|
1160 | 1134 | if (!_pressingMouse) return;
|
1161 | 1135 | instance.emit("tapping", x, y, 0);
|
1162 | 1136 | _updateTap(0, x, y);
|
1163 | 1137 | });
|
1164 |
| - on(_canvas, "mouseup", (ev) => { |
1165 |
| - ev.preventDefault(); |
1166 |
| - const tap = _taps.get(0); |
1167 |
| - const [x, y] = _getXY(ev.pageX, ev.pageY); |
1168 |
| - if (_checkTapped(tap)) { |
1169 |
| - instance.emit("tapped", tap.startX, tap.startY, 0); |
1170 |
| - } |
1171 |
| - instance.emit("untap", x, y, 0); |
1172 |
| - _taps.delete(0); |
1173 |
| - _pressingMouse = false; |
1174 |
| - }); |
1175 | 1138 | on(_canvas, "touchstart", (ev) => {
|
1176 |
| - ev.preventDefault(); |
| 1139 | + preventDefault(ev); |
1177 | 1140 | const touches = ev.changedTouches;
|
1178 | 1141 | for (const touch of touches) {
|
1179 | 1142 | const [x, y] = _getXY(touch.pageX, touch.pageY);
|
|
1182 | 1145 | }
|
1183 | 1146 | });
|
1184 | 1147 | on(_canvas, "touchmove", (ev) => {
|
1185 |
| - ev.preventDefault(); |
| 1148 | + preventDefault(ev); |
1186 | 1149 | const touches = ev.changedTouches;
|
1187 | 1150 | for (const touch of touches) {
|
1188 | 1151 | const [x, y] = _getXY(touch.pageX, touch.pageY);
|
|
1191 | 1154 | }
|
1192 | 1155 | });
|
1193 | 1156 | const _touchEndHandler = (ev) => {
|
1194 |
| - ev.preventDefault(); |
| 1157 | + preventDefault(ev); |
1195 | 1158 | const existing = [];
|
1196 | 1159 | if (ev.targetTouches.length > 0) {
|
1197 | 1160 | for (const touch of ev.targetTouches) {
|
|
1258 | 1221 | }
|
1259 | 1222 | let updated = 0, frameTime = (now - _lastFrameTime) / 1e3;
|
1260 | 1223 | _lastFrameTime = now;
|
1261 |
| - if (frameTime > 1) return; |
| 1224 | + if (frameTime > _deltaTime * 30) |
| 1225 | + return void 0; |
1262 | 1226 | _accumulated += frameTime;
|
1263 | 1227 | if (!_animated) {
|
1264 | 1228 | _accumulated = _deltaTime;
|
|
1278 | 1242 | }
|
1279 | 1243 | function setupCanvas() {
|
1280 | 1244 | _canvas = "string" === typeof _canvas ? document.querySelector(_canvas) : _canvas;
|
| 1245 | + if (true) { |
| 1246 | + assert( |
| 1247 | + _canvas && _canvas.tagName === "CANVAS", |
| 1248 | + "Invalid canvas element" |
| 1249 | + ); |
| 1250 | + assert( |
| 1251 | + null === instance.WIDTH || instance.WIDTH > 0, |
| 1252 | + `Litecanvas' "width" option should be null or a positive number` |
| 1253 | + ); |
| 1254 | + assert( |
| 1255 | + null === instance.HEIGHT || instance.HEIGHT > 0, |
| 1256 | + `Litecanvas' "width" option should be null or a positive number` |
| 1257 | + ); |
| 1258 | + } |
1281 | 1259 | instance.setvar("CANVAS", _canvas);
|
1282 | 1260 | _ctx = _canvas.getContext("2d");
|
1283 | 1261 | on(_canvas, "click", () => root.focus());
|
|
1311 | 1289 | instance.setvar("CENTERY", instance.HEIGHT / 2);
|
1312 | 1290 | if (!settings.antialias || settings.pixelart) {
|
1313 | 1291 | _ctx.imageSmoothingEnabled = false;
|
1314 |
| - _canvas.style.imageRendering = "pixelated"; |
| 1292 | + styles.imageRendering = "pixelated"; |
1315 | 1293 | }
|
1316 | 1294 | instance.emit("resized", _scale);
|
1317 | 1295 | if (!_animated) {
|
|
1326 | 1304 | }
|
1327 | 1305 | function loadPlugin(callback, config) {
|
1328 | 1306 | const pluginData = callback(instance, _helpers, config);
|
1329 |
| - if ("object" === typeof pluginData) { |
1330 |
| - for (const key of Object.keys(pluginData)) { |
1331 |
| - instance.setvar(key, pluginData[key]); |
1332 |
| - } |
| 1307 | + if (true) { |
| 1308 | + assert( |
| 1309 | + null == pluginData || "object" === typeof pluginData, |
| 1310 | + "Litecanvas plugins should return an object or nothing" |
| 1311 | + ); |
| 1312 | + } |
| 1313 | + for (const key in pluginData) { |
| 1314 | + instance.setvar(key, pluginData[key]); |
1333 | 1315 | }
|
1334 | 1316 | }
|
1335 | 1317 | if (_global) {
|
|
0 commit comments