|
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