canvas实现自定义ai数量俄罗斯方块对战游戏代码
代码语言:html
所属分类:游戏
代码描述:canvas实现自定义ai数量俄罗斯方块对战游戏代码,可设置ai的速度和数量,还可以设置自己的方块速速,还有排行榜,看看你能战胜ai吗?
代码标签: canvas 自定义 ai 数量 俄罗斯 方块 对战 游戏 代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> /* latin-ext */ @font-face { font-family: 'Courier Prime'; font-style: normal; font-weight: 400; font-display: swap; src: url(https://fonts.gstatic.com/s/courierprime/v9/u-450q2lgwslOqpF_6gQ8kELaw9pWt_-.woff2) format('woff2'); unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { font-family: 'Courier Prime'; font-style: normal; font-weight: 400; font-display: swap; src: url(https://fonts.gstatic.com/s/courierprime/v9/u-450q2lgwslOqpF_6gQ8kELawFpWg.woff2) format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } body,html{ background: #000; margin: 0; height: 100vh; overflow: hidden; font-family: Courier Prime; } #c:focus{ outline: none; } #c{ background:#000; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); } </style> </head> <body translate="no"> <canvas id="c" tabindex=0></canvas> <script > c = document.querySelector('#c'); c.width = 1920; c.height = 1080; x = c.getContext('2d'); C = Math.cos; S = Math.sin; t = 0; T = Math.tan; rsz = window.onresize = () => { setTimeout(() => { if (document.body.clientWidth > document.body.clientHeight * 1.77777778) { c.style.height = '100vh'; setTimeout(() => c.style.width = c.clientHeight * 1.77777778 + 'px', 0); } else { c.style.width = '100vw'; setTimeout(() => c.style.height = c.clientWidth / 1.77777778 + 'px', 0); } }, 0); }; rsz(); async function Draw() { oX = oY = oZ = 0; if (!t) { reflect = (a, n) => { let d1 = Math.hypot(...a) + .0001; let d2 = Math.hypot(...n) + .0001; a[0] /= d1; a[1] /= d1; a[2] /= d1; n[0] /= d2; n[1] /= d2; n[2] /= d2; let dot = -a[0] * n[0] + -a[1] * n[1] + -a[2] * n[2]; let rx = -a[0] - 2 * n[0] * dot; let ry = -a[1] - 2 * n[1] * dot; let rz = -a[2] - 2 * n[2] * dot; return [-rx * d1, -ry * d1, -rz * d1]; }; spawnTunnel = ( tx, ty, tz, rw, cl, sp = 1, rad = .5, theta1 = 0, theta2 = 0, theta1ModFreq = 0, theta1ModMag = 0, theta2ModFreq = 0, theta2ModMag = 0, theta1Offset = 0, theta2Offset = 0, radModFreq = 0, radModMag = 0, radModOffset = 0, showLine = false) => { let X_ = X = tx; let Y_ = Y = ty; let Z_ = Z = tz; let ret = []; let p2a, p2, p2a1, ls; if (showLine) x.beginPath(); for (let i = cl + 1; i--;) { let p1 = theta1 + C(Math.PI * 2 / cl * i * theta1ModFreq + theta1Offset) * theta1ModMag; let p2 = theta2 + C(Math.PI * 2 / cl * i * theta2ModFreq + theta2Offset) * theta2ModMag; let p2a1 = theta2 + C(Math.PI * 2 / cl * (i + 1) * theta2ModFreq + theta2Offset) * theta2ModMag; let lsa = rad + C(Math.PI * 2 / cl * i * radModFreq + radModOffset) * rad / 2 * radModMag; let lsb = rad + C(Math.PI * 2 / cl * (i + 1) * radModFreq + radModOffset) * rad / 2 * radModMag; if (i == cl) { p2a = p2; ls = lsa; } else if (i == 0) { p2a = p2a1; ls = lsb; } else { p2a = (p2 + p2a1) / 2; ls = (lsa + lsb) / 2; } let a = []; for (let j = rw + 1; j--;) { p = Math.PI * 2 / rw * j + Math.PI / rw; X = S(p) * ls; Y = 0; Z = C(p) * ls; R(-p2a + Math.PI / 2, 0, 0); R(0, 0, -p1); a = [...a, [X + X_, Y + Y_, Z + Z_]]; } ret = [...ret, a]; if (showLine) { X = X_; Y = Y_; Z = Z_; R(Rl, Pt, Yw, 1); if (Z > 0) x.lineTo(...Q()); } vx = C(p1) * C(p2) * sp; vy = S(p2) * sp; vz = S(p1) * C(p2) * sp; X_ += vx; Y_ += vy; Z_ += vz; } if (showLine) stroke('#f00', '', 2, false); a = []; ret.map((v, i) => { if (i) { let s1 = ret[i]; let s2 = ret[i - 1]; for (let j = rw; j--;) { b = []; let l1_ = (j + 0) % rw; let l2_ = (j + 1) % rw; X = s1[l1_][0]; Y = s1[l1_][1]; Z = s1[l1_][2]; b = [...b, [X, Y, Z]]; X = s1[l2_][0]; Y = s1[l2_][1]; Z = s1[l2_][2]; b = [...b, [X, Y, Z]]; X = s2[l2_][0]; Y = s2[l2_][1]; Z = s2[l2_][2]; b = [...b, [X, Y, Z]]; X = s2[l1_][0]; Y = s2[l1_][1]; Z = s2[l1_][2]; b = [...b, [X, Y, Z]]; a = [...a, b]; } } }); return a; }; HSVFromRGB = (R, G, B) => { let R_ = R / 256; let G_ = G / 256; let B_ = B / 256; let Cmin = Math.min(R_, G_, B_); let Cmax = Math.max(R_, G_, B_); let val = Cmax; //(Cmax+Cmin) / 2 let delta = Cmax - Cmin; let sat = Cmax ? delta / Cmax : 0; let min = Math.min(R, G, B); let max = Math.max(R, G, B); let hue = 0; if (delta) { if (R >= G && R >= B) hue = (G - B) / (max - min); if (G >= R && G >= B) hue = 2 + (B - R) / (max - min); if (B >= G && B >= R) hue = 4 + (R - G) / (max - min); } hue *= 60; while (hue < 0) hue += 360; while (hue >= 360) hue -= 360; return [hue, sat, val]; }; RGBFromHSV = (H, S, V) => { while (H < 0) H += 360; while (H >= 360) H -= 360; let C = V * S; let X = C * (1 - Math.abs(H / 60 % 2 - 1)); let m = V - C; let R_, G_, B_; if (H >= 0 && H < 60) R_ = C, G_ = X, B_ = 0; if (H >= 60 && H < 120) R_ = X, G_ = C, B_ = 0; if (H >= 120 && H < 180) R_ = 0, G_ = C, B_ = X; if (H >= 180 && H < 240) R_ = 0, G_ = X, B_ = C; if (H >= 240 && H < 300) R_ = X, G_ = 0, B_ = C; if (H >= 300 && H < 360) R_ = C, G_ = 0, B_ = X; let R = (R_ + m) * 256; let G = (G_ + m) * 256; let B = (B_ + m) * 256; return [R, G, B]; }; R = R2 = (Rl, Pt, Yw, m) => { M = Math; A = M.atan2; H = M.hypot; X = S(p = A(X, Z) + Yw) * (d = H(X, Z)); Z = C(p) * d; Y = S(p = A(Y, Z) + Pt) * (d = H(Y, Z)); Z = C(p) * d; X = S(p = A(X, Y) + Rl) * (d = H(X, Y)); Y = C(p) * d; if (m) { X += oX; Y += oY; Z += oZ; } }; Q = () => [c.width / 2 + X / Z * 700, c.height / 2 + Y / Z * 700]; I = (A, B, M, D, E, F, G, H) => (K = ((G - E) * (B - F) - (H - F) * (A - E)) / (J = (H - F) * (M - A) - (G - E) * (D - B))) >= 0 && K <= 1 && (L = ((M - A) * (B - F) - (D - B) * (A - E)) / J) >= 0 && L <= 1 ? [A + K * (M - A), B + K * (D - B)] : 0; Rn = Math.random; async function loadOBJ(url, scale, tx, ty, tz, rl, pt, yw, recenter = true) { let res; await fetch(url, res => res).then(data => data.text()).then(data => { a = []; data.split("\nv ").map(v => { a = [...a, v.split("\n")[0]]; }); a = a.filter((v, i) => i).map(v => [...v.split(' ').map(n => +n.replace("\n", ''))]); ax = ay = az = 0; a.map(v => { v[1] *= -1; if (recenter) { ax += v[0]; ay += v[1]; az += v[2]; } }); ax /= a.length; ay /= a.length; az /= a.length; a.map(v => { X = (v[0] - ax) * scale; Y = (v[1] - ay) * scale; Z = (v[2] - az) * scale; R2(rl, pt, yw, 0); v[0] = X; v[1] = Y; v[2] = Z; }); maxY = -6e6; a.map(v => { if (v[1] > maxY) maxY = v[1]; }); a.map(v => { v[1] -= maxY - oY; v[0] += tx; v[1] += ty; v[2] += tz; }); b = []; data.split("\nf ").map(v => { b = [...b, v.split("\n")[0]]; }); b.shift(); b = b.map(v => v.split(' ')); b = b.map(v => { v = v.map(q => { return +q.split('/')[0]; }); v = v.filter(q => q); return v; }); res = []; b.map(v => { e = []; v.map(q => { e = [...e, a[q - 1]]; }); e = e.filter(q => q); res = [...res, e]; }); }); return res; } function loadAnimation(name, size, X, Y, Z, rl, pt, yw, speed = 1) { let rootURL = 'https://srmcgann.github.io/animations'; if (typeof animations == 'undefined') animations = []; let animation = { name, speed, frameCt: 0, fileList: '', curFrame: 0, loopRangeStart: 0, loopRangeEnd: 0, hasLoop: false, looping: false, frameData: [], loaded: false, active: true }; fetch(`${rootURL}/${name}/fileList.json`).then(v => v.json()).then(data => { animation.fileList = data.fileList; if (animation.fileList.hasLoop) { animation.hasLoop = true; animation.looping = true; animation.loopRangeStart = animation.fileList.loopRangeStart; animation.loopRangeEnd = animation.fileList.loopRangeEnd; } for (let i = 0; i < +animation.fileList.fileCount; i++) { let file = `${rootURL}/${name}/${animation.fileList.fileName}${i}.${animation.fileList.suffix}`; loadOBJ(file, size, X, Y, Z, rl, pt, yw, false).then(el => { animation.frameData[i] = el; animation.frameCt++; if (animation.frameCt == +animation.fileList.fileCount) { console.log(`loaded animation: ${name}`); animation.loaded = true; animations = [...animations, animation]; } }); } }); return name; } drawAnimation = (animation_name, scol = '#8888', fcol = '', lineWidth = 2, glowing = true, overrideGlobalAlpha = 1) => { let animation = animations.filter(el => animation_name == el.name); if (animation.length) { animation = animation[0]; animation.curFrame += animation.speed; if (animation.hasLoop && animation.looping) { animation.curFrame %= Math.min(animation.loopRangeEnd, animation.frameCt); if (animation.curFrame < 1) animation.curFrame = Math.max(0, animation.loopRangeStart); } else { animation.curFrame %= animation.frameCt; } animation.frameData[animation.curFrame | 0].map((v, i) => { x.beginPath(); v.map(q => { X = q[0]; Y = q[1]; Z = q[2]; R(Rl, Pt, Yw, 1); if (Z > 0) x.lineTo(...Q()); }); stroke(scol, fcol, lineWidth, glowing, overrideGlobalAlpha); }); } }; geoSphere = (mx, my, mz, iBc, size) => { let collapse = 0; let B = Array(iBc).fill().map(v => { X = Rn() - .5; Y = Rn() - .5; Z = Rn() - .5; return [X, Y, Z]; }); for (let m = 200; m--;) { B.map((v, i) => { X = v[0]; Y = v[1]; Z = v[2]; B.map((q, j) => { if (j != i) { X2 = q[0]; Y2 = q[1]; Z2 = q[2]; d = 1 + (Math.hypot(X - X2, Y - Y2, Z - Z2) * (3 + iBc / 40) * 3) ** 4; X += (X - X2) * 99 / d; Y += (Y - Y2) * 99 / d; Z += (Z - Z2) * 99 / d; } }); d = Math.hypot(X, Y, Z); v[0] = X / d; v[1] = Y / d; v[2] = Z / d; if (collapse) { d = 25 + Math.hypot(X, Y, Z); v[0] = (X - X / d) / 1.1; v[1] = (Y - Y / d) / 1.1; v[2] = (Z - Z / d) / 1.1; } }); } mind = 6e6; B.map((v, i) => { X1 = v[0]; Y1 = v[1]; Z1 = v[2]; B.map((q, j) => { X2 = q[0]; Y2 = q[1]; Z2 = q[2]; if (i != j) { d = Math.hypot(a = X1 - X2, b = Y1 - Y2, e = Z1 - Z2); if (d < mind) mind = d; } }); }); a = []; B.map((v, i) => { X1 = v[0]; Y1 = v[1]; Z1 = v[2]; B.map((q, j) => { X2 = q[0]; Y2 = q[1]; Z2 = q[2]; if (i != j) { d = Math.hypot(X1 - X2, Y1 - Y2, Z1 - Z2); if (d < mind * 2) { if (!a.filter(q => q[0] == X2 && q[1] == Y2 && q[2] == Z2 && q[3] == X1 && q[4] == Y1 && q[5] == Z1).length) a = [...a, [X1 * size, Y1 * size, Z1 * size, X2 * size, Y2 * size, Z2 * size]]; } } }); }); B.map(v => { v[0] *= size; v[1] *= size; v[2] *= size; v[0] += mx; v[1] += my; v[2] += mz; }); return [mx, my, mz, size, B, a]; }; lineFaceI = (X1, Y1, Z1, X2, Y2, Z2, facet, autoFlipNormals = false, showNormals = false) => { let X_, Y_, Z_, d, m, l_, K, J, L, p; let I_ = (A, B, M, D, E, F, G, H) => (K = ((G - E) * (B - F) - (H - F) * (A - E)) / (J = (H - F) * (M - A) - (G - E) * (D - B))) >= 0 && K <= 1 && (L = ((M - A) * (B - F) - (D - B) * (A - E)) / J) >= 0 && L <= 1 ? [A + K * (M - A), B + K * (D - B)] : 0; let Q_ = () => [c.width / 2 + X_ / Z_ * 600, c.height / 2 + Y_ / Z_ * 600]; let R_ = (Rl, Pt, Yw, m) => { let M = Math,A = M.atan2,H = M.hypot; X_ = S(p = A(X_, Y_) + Rl) * (d = H(X_, Y_)), Y_ = C(p) * d, X_ = S(p = A(X_, Z_) + Yw) * (d = H(X_, Z_)), Z_ = C(p) * d, Y_ = S(p = A(Y_, Z_) + Pt) * (d = H(Y_, Z_)), Z_ = C(p) * d; if (m) {X_ += oX, Y_ += oY, Z_ += oZ;} }; let rotSwitch = m => { switch (m) { case 0:R_(0, 0, Math.PI / 2);break; case 1:R_(0, Math.PI / 2, 0);break; case 2:R_(Math.PI / 2, 0, Math.PI / 2);break;} }; let ax = 0,ay = 0,az = 0; facet.map(q_ => {ax += q_[0], ay += q_[1], az += q_[2];}); ax /= facet.length, ay /= facet.length, az /= facet.length; let b1 = facet[2][0] - facet[1][0],b2 = facet[2][1] - facet[1][1],b3 = facet[2][2] - facet[1][2]; let c1 = facet[1][0] - facet[0][0],c2 = facet[1][1] - facet[0][1],c3 = facet[1][2] - facet[0][2]; let crs = [b2 * c3 - b3 * c2, b3 * c1 - b1 * c3, b1 * c2 - b2 * c1]; d = Math.hypot(...crs) + .001; let nls = 1; //normal line length crs = crs.map(q => q / d * nls); let X1_ = ax,Y1_ = ay,Z1_ = az; let flip = 1; if (autoFlipNormals) { let d1_ = Math.hypot(X1_ - X1, Y1_ - Y1, Z1_ - Z1); let d2_ = Math.hypot(X1 - (ax + crs[0] / 99), Y1 - (ay + crs[1] / 99), Z1 - (az + crs[2] / 99)); flip = d2_ > d1_ ? -1 : 1; } let X2_ = ax + (crs[0] *= flip),Y2_ = ay + (crs[1] *= flip),Z2_ = az + (crs[2] *= flip); if (showNormals) { x.beginPath(); X_ = X1_, Y_ = Y1_, Z_ = Z1_; R_(Rl, Pt, Yw, 1); if (Z_ > 0) x.lineTo(...Q_()); X_ = X2_, Y_ = Y2_, Z_ = Z2_; R_(Rl, Pt, Yw, 1); if (Z_ > 0) x.lineTo(...Q_()); x.lineWidth = 5; x.strokeStyle = '#f004'; x.stroke(); } let p1_ = Math.atan2(X2_ - X1_, Z2_ - Z1_); let p2_ = -(Math.acos((Y2_ - Y1_) / (Math.hypot(X2_ - X1_, Y2_ - Y1_, Z2_ - Z1_) + .001)) + Math.PI / 2); let isc = false,iscs = [false, false, false]; X_ = X1, Y_ = Y1, Z_ = Z1; R_(0, -p2_, -p1_); let rx_ = X_,ry_ = Y_,rz_ = Z_; for (let m = 3; m--;) { if (isc === false) { X_ = rx_, Y_ = ry_, Z_ = rz_; rotSwitch(m); X1_ = X_, Y1_ = Y_, Z1_ = Z_ = 5, X_ = X2, Y_ = Y2, Z_ = Z2; R_(0, -p2_, -p1_); rotSwitch(m); X2_ = X_, Y2_ = Y_, Z2_ = Z_; facet.map((q_, j_) => { if (isc === false) { let l = j_; X_ = facet[l][0], Y_ = facet[l][1], Z_ = facet[l][2]; R_(0, -p2_, -p1_); rotSwitch(m); let X3_ = X_,Y3_ = Y_,Z3_ = Z_; l = (j_ + 1) % facet.length; X_ = facet[l][0], Y_ = facet[l][1], Z_ = facet[l][2]; R_(0, -p2_, -p1_); rotSwitch(m); let X4_ = X_,Y4_ = Y_,Z4_ = Z_; if (l_ = I_(X1_, Y1_, X2_, Y2_, X3_, Y3_, X4_, Y4_)) iscs[m] = l_; } }); } } if (iscs.filter(v => v !== false).length == 3) { let iscx = iscs[1][0],iscy = iscs[0][1],iscz = iscs[0][0]; let pointInPoly = true; ax = 0, ay = 0, az = 0; facet.map((q_, j_) => {ax += q_[0], ay += q_[1], az += q_[2];}); ax /= facet.length, ay /= facet.length, az /= facet.length; X_ = ax, Y_ = ay, Z_ = az; R_(0, -p2_, -p1_); X1_ = X_, Y1_ = Y_, Z1_ = Z_; X2_ = iscx, Y2_ = iscy, Z2_ = iscz; facet.map((q_, j_) => { if (pointInPoly) { let l = j_; X_ = facet[l][0], Y_ = facet[l][1], Z_ = facet[l][2]; R_(0, -p2_, -p1_); let X3_ = X_,Y3_ = Y_,Z3_ = Z_; l = (j_ + 1) % facet.length; X_ = facet[l][0], Y_ = facet[l][1], Z_ = facet[l][2]; R_(0, -p2_, -p1_); let X4_ = X_,Y4_ = Y_,Z4_ = Z_; if (I_(X1_, Y1_, X2_, Y2_, X3_, Y3_, X4_, Y4_)) pointInPoly = false; } }); if (pointInPoly) { X_ = iscx, Y_ = iscy, Z_ = iscz; R_(0, p2_, 0); R_(0, 0, p1_); isc = [[X_, Y_, Z_], [crs[0], crs[1], crs[2]]]; } } return isc; }; TruncatedOctahedron = ls => { let shp = [],a = []; mind = 6e6; for (let i = 6; i--;) { X = S(p = Math.PI * 2 / 6 * i + Math.PI / 6) * ls; Y = C(p) * ls; Z = 0; if (Y < mind) mind = Y; a = [...a, [X, Y, Z]]; } let theta = .6154797086703867; a.map(v => { X = v[0]; Y = v[1] - mind; Z = v[2]; R(0, theta, 0); v[0] = X; v[1] = Y; v[2] = Z + 1.5; }); b = JSON.parse(JSON.stringify(a)).map(v => { v[1] *= -1; return v; }); shp = [...shp, a, b]; e = JSON.parse(JSON.stringify(shp)).map(v => { v.map(q => { X = q[0]; Y = q[1]; Z = q[2]; R(0, 0, Math.PI); q[0] = X; q[1] = Y; q[2] = Z; }); return v; }); shp = [...shp, ...e]; e = JSON.parse(JSON.stringify(shp)).map(v => { v.map(q => { X = q[0]; Y = q[1]; Z = q[2]; R(0, 0, Math.PI / 2); q[0] = X; q[1] = Y; q[2] = Z; }); return v; }); shp = [...shp, ...e]; coords = [ [[3, 1], [4, 3], [4, 4], [3, 2]], [[3, 4], [3, 3], [2, 4], [6, 2]], [[1, 4], [0, 3], [0, 4], [4, 2]], [[1, 1], [1, 2], [6, 4], [7, 3]], [[3, 5], [7, 5], [1, 5], [3, 0]], [[2, 5], [6, 5], [0, 5], [4, 5]]]; a = []; coords.map(v => { b = []; v.map(q => { X = shp[q[0]][q[1]][0]; Y = shp[q[0]][q[1]][1]; Z = shp[q[0]][q[1]][2]; b = [...b, [X, Y, Z]]; }); a = [...a, b]; }); shp = [...shp, ...a]; return shp.map(v => { v.map(q => { q[0] /= 3; q[1] /= 3; q[2] /= 3; q[0] *= ls; q[1] *= ls; q[2] *= ls; }); return v; }); }; Cylinder = (rw, cl, ls1, ls2) => { let a = []; for (let i = rw; i--;) { let b = []; for (let j = cl; j--;) { X = S(p = Math.PI * 2 / cl * j) * ls1; Y = (1 / rw * i - .5) * ls2; Z = C(p) * ls1; b = [...b, [X, Y, Z]]; } //a = [...a, b] for (let j = cl; j--;) { b = []; X = S(p = Math.PI * 2 / cl * j) * ls1; Y = (1 / rw * i - .5) * ls2; Z = C(p) * ls1; b = [...b, [X, Y, Z]]; X = S(p = Math.PI * 2 / cl * (j + 1)) * ls1; Y = (1 / rw * i - .5) * ls2; Z = C(p) * ls1; b = [...b, [X, Y, Z]]; X = S(p = Math.PI * 2 / cl * (j + 1)) * ls1; Y = (1 / rw * (i + 1) - .5) * ls2; Z = C(p) * ls1; b = [...b, [X, Y, Z]]; X = S(p = Math.PI * 2 / cl * j) * ls1; Y = (1 / rw * (i + 1) - .5) * ls2; Z = C(p) * ls1; b = [...b, [X, Y, Z]]; a = [...a, b]; } } b = []; for (let j = cl; j--;) { X = S(p = Math.PI * 2 / cl * j) * ls1; Y = ls2 / 2; Z = C(p) * ls1; b = [...b, [X, Y, Z]]; } //a = [...a, b] return a; }; Tetrahedron = size => { ret = []; a = []; let h = size / 1.4142 / 1.25; for (i = 3; i--;) { X = S(p = Math.PI * 2 / 3 * i) * size / 1.25; Y = C(p) * size / 1.25; Z = h; a = [...a, [X, Y, Z]]; } ret = [...ret, a]; for (j = 3; j--;) { a = []; X = 0; Y = 0; Z = -h; a = [...a, [X, Y, Z]]; X = S(p = Math.PI * 2 / 3 * j) * size / 1.25; Y = C(p) * size / 1.25; Z = h; a = [...a, [X, Y, Z]]; X = S(p = Math.PI * 2 / 3 * (j + 1)) * size / 1.25; Y = C(p) * size / 1.25; Z = h; a = [...a, [X, Y, Z]]; ret = [...ret, a]; } ax = ay = az = ct = 0; ret.map(v => { v.map(q => { ax += q[0]; ay += q[1]; az += q[2]; ct++; }); }); ax /= ct; ay /= ct; az /= ct; ret.map(v => { v.map(q => { q[0] -= ax; q[1] -= ay; q[2] -= az; }); }); return ret; }; Cube = size => { for (CB = [], j = 6; j--; CB = [...CB, b]) for (b = [], i = 4; i--;) b = [...b, [(a = [S(p = Math.PI * 2 / 4 * i + Math.PI / 4), C(p), 2 ** .5 / 2])[j % 3] * (l = j < 3 ? size / 1.5 : -size / 1.5), a[(j + 1) % 3] * l, a[(j + 2) % 3] * l]]; return CB; }; Octahedron = size => { ret = []; let h = size / 1.25; for (j = 8; j--;) { a = []; X = 0; Y = 0; Z = h * (j < 4 ? -1 : 1); a = [...a, [X, Y, Z]]; X = S(p = Math.PI * 2 / 4 * j) * size / 1.25; Y = C(p) * size / 1.25; Z = 0; a = [...a, [X, Y, Z]]; X = S(p = Math.PI * 2 / 4 * (j + 1)) * size / 1.25; Y = C(p) * size / 1.25; Z = 0; a = [...a, [X, Y, Z]]; ret = [...ret, a]; } return ret; }; Dodecahedron = size => { ret = []; a = []; mind = -6e6; for (i = 5; i--;) { X = S(p = Math.PI * 2 / 5 * i + Math.PI / 5); Y = C(p); Z = 0; if (Y > mind) mind = Y; a = [...a, [X, Y, Z]]; } a.map(v => { X = v[0]; Y = v[1] -= mind; Z = v[2]; R(0, .553573, 0); v[0] = X; v[1] = Y; v[2] = Z; }); b = JSON.parse(JSON.stringify(a)); b.map(v => { v[1] *= -1; }); ret = [...ret, a, b]; mind = -6e6; ret.map(v => { v.map(q => { X = q[0]; Y = q[1]; Z = q[2]; if (Z > mind) mind = Z; }); }); d1 = Math.hypot(ret[0][0][0] - ret[0][1][0], ret[0][0][1] - ret[0][1][1], ret[0][0][2] - ret[0][1][2]); ret.map(v => { v.map(q => { q[2] -= mind + d1 / 2; }); }); b = JSON.parse(JSON.stringify(ret)); b.map(v => { v.map(q => { q[2] *= -1; }); }); ret = [...ret, ...b]; b = JSON.parse(JSON.stringify(ret)); b.map(v => { v.map(q => { X = q[0]; Y = q[1]; Z = q[2]; R(0, 0, Math.PI / 2); R(0, Math.PI / 2, 0); q[0] = X; q[1] = Y; q[2] = Z; }); }); e = JSON.parse(JSON.stringify(ret)); e.map(v => { v.map(q => { X = q[0]; Y = q[1]; Z = q[2]; R(0, 0, Math.PI / 2); R(Math.PI / 2, 0, 0); q[0] = X; q[1] = Y; q[2] = Z; }); }); ret = [...ret, ...b, ...e]; ret.map(v => { v.map(q => { q[0] *= size / 2; q[1] *= size / 2; q[2] *= size / 2; }); }); return ret; }; Icosahedron = size => { ret = []; let B = [ [[0, 3], [1, 0], [2, 2]], [[0, 3], [1, 0], [1, 3]], [[0, 3], [2, 3], [1, 3]], [[0, 2], [2, 1], [1, 0]], [[0, 2], [1, 3], [1, 0]], [[0, 2], [1, 3], [2, 0]], [[0, 3], [2, 2], [0, 0]], [[1, 0], [2, 2], [2, 1]], [[1, 1], [2, 2], [2, 1]], [[1, 1], [2, 2], [0, 0]], [[1, 1], [2, 1], [0, 1]], [[0, 2], [2, 1], [0, 1]], [[2, 0], [1, 2], [2, 3]], [[0, 0], [0, 3], [2, 3]], [[1, 3], [2, 0], [2, 3]], [[2, 3], [0, 0], [1, 2]], [[1, 2], [2, 0], [0, 1]], [[0, 0], [1, 2], [1, 1]], [[0, 1], [1, 2], [1, 1]], [[0, 2], [2, 0], [0, 1]]]; for (p = [1, 1], i = 38; i--;) p = [...p, p[l = p.length - 1] + p[l - 1]]; phi = p[l] / p[l - 1]; a = [ [-phi, -1, 0], [phi, -1, 0], [phi, 1, 0], [-phi, 1, 0]]; for (j = 3; j--; ret = [...ret, b]) for (b = [], i = 4; i--;) b = [...b, [a[i][j], a[i][(j + 1) % 3], a[i][(j + 2) % 3]]]; ret.map(v => { v.map(q => { q[0] *= size / 2.25; q[1] *= size / 2.25; q[2] *= size / 2.25; }); }); cp = JSON.parse(JSON.stringify(ret)); out = []; a = []; B.map(v => { idx1a = v[0][0]; idx2a = v[1][0]; idx3a = v[2][0]; idx1b = v[0][1]; idx2b = v[1][1]; idx3b = v[2][1]; a = [...a, [cp[idx1a][idx1b], cp[idx2a][idx2b], cp[idx3a][idx3b]]]; }); out = [...out, ...a]; return out; }; stroke = (scol, fcol, lwo = 1, od = true, oga = 1, overrideClosePath = false) => { if (scol) { if (!overrideClosePath) x.closePath(); if (od) x.globalAlpha = .2 * oga; x.strokeStyle = scol; x.lineWidth = Math.min(1000, 100 * lwo / Z); if (od) x.stroke(); x.lineWidth /= 4; x.globalAlpha = 1 * oga; x.stroke(); } if (fcol) { x.globalAlpha = 1 * oga; x.fillStyle = fcol; x.fill(); } x.globalAlpha = 1; }; bezTo = (X1, Y1, X2, Y2, col1, col2, lw = 1, dual = true, oga = 1, horizontal = true) => { let Xa, Ya, Xb, Yb, X, Y, l1, l2, l3; if (horizontal) { Xa = X1 + (X2 - X1) / 3 * 2; Ya = Y1; Xb = X1 + (X2 - X1) / 3 * 1; Yb = Y2; } else { Xa = X1; Ya = Y1 + (Y2 - Y1) / 3 * 2; Xb = X2; Yb = Y1 + (Y2 - Y1) / 3 * 1; } x.beginPath(); X = X1; Y = Y1; x.moveTo(X, Y); x.bezierCurveTo(Xa, Ya, Xb, Yb, X2, Y2); Z = 5; stroke(col1, col2, lw, dual, oga, true); }; subbed = (subs, size, sphereize, shape) => { for (let m = subs; m--;) { base = shape; shape = []; base.map(v => { l = 0; X1 = v[l][0]; Y1 = v[l][1]; Z1 = v[l][2]; l = 1; X2 = v[l][0]; Y2 = v[l][1]; Z2 = v[l][2]; l = 2; X3 = v[l][0]; Y3 = v[l][1]; Z3 = v[l][2]; if (v.length > 3) { l = 3; X4 = v[l][0]; Y4 = v[l][1]; Z4 = v[l][2]; if (v.length > 4) { l = 4; X5 = v[l][0]; Y5 = v[l][1]; Z5 = v[l][2]; } } mx1 = (X1 + X2) / 2; my1 = (Y1 + Y2) / 2; mz1 = (Z1 + Z2) / 2; mx2 = (X2 + X3) / 2; my2 = (Y2 + Y3) / 2; mz2 = (Z2 + Z3) / 2; a = []; switch (v.length) { case 3: mx3 = (X3 + X1) / 2; my3 = (Y3 + Y1) / 2; mz3 = (Z3 + Z1) / 2; X = X1, Y = Y1, Z = Z1, a = [...a, [X, Y, Z]]; X = mx1, Y = my1, Z = mz1, a = [...a, [X, Y, Z]]; X = mx3, Y = my3, Z = mz3, a = [...a, [X, Y, Z]]; shape = [...shape, a]; a = []; X = mx1, Y = my1, Z = mz1, a = [...a, [X, Y, Z]]; X = X2, Y = Y2, Z = Z2, a = [...a, [X, Y, Z]]; X = mx2, Y = my2, Z = mz2, a = [...a, [X, Y, Z]]; shape = [...shape, a]; a = []; X = mx3, Y = my3, Z = mz3, a = [...a, [X, Y, Z]]; X = mx2, Y = my2, Z = mz2, a = [...a, [X, Y, Z]]; X = X3, Y = Y3, Z = Z3, a = [...a, [X, Y, Z]]; shape = [...shape, a]; a = []; X = mx1, Y = my1, Z = mz1, a = [...a, [X, Y, Z]]; X = mx2, Y = my2, Z = mz2, a = [...a, [X, Y, Z]]; X = mx3, Y = my3, Z = mz3, a = [...a, [X, Y, Z]]; shape = [...shape, a]; break; case 4: mx3 = (X3 + X4) / 2; my3 = (Y3 + Y4) / 2; mz3 = (Z3 + Z4) / 2; mx4 = (X4 + X1) / 2; my4 = (Y4 + Y1) / 2; mz4 = (Z4 + Z1) / 2; cx = (X1 + X2 + X3 + X4) / 4; cy = (Y1 + Y2 + Y3 + Y4) / 4; cz = (Z1 + Z2 + Z3 + Z4) / 4; X = X1, Y = Y1, Z = Z1, a = [...a, [X, Y, Z]]; X = mx1, Y = my1, Z = mz1, a = [...a, [X, Y, Z]]; X = cx, Y = cy, Z = cz, a = [...a, [X, Y, Z]]; X = mx4, Y = my4, Z = mz4, a = [...a, [X, Y, Z]]; shape = [...shape, a]; a = []; X = mx1, Y = my1, Z = mz1, a = [...a, [X, Y, Z]]; X = X2, Y = Y2, Z = Z2, a = [...a, [X, Y, Z]]; X = mx2, Y = my2, Z = mz2, a = [...a, [X, Y, Z]]; X = cx, Y = cy, Z = cz, a = [...a, [X, Y, Z]]; shape = [...shape, a]; a = []; X = cx, Y = cy, Z = cz, a = [...a, [X, Y, Z]]; X = mx2, Y = my2, Z = mz2, a = [...a, [X, Y, Z]]; X = X3, Y = Y3, Z = Z3, a = [...a, [X, Y, Z]]; X = mx3, Y = my3, Z = mz3, a = [...a, [X, Y, Z]]; shape = [...shape, a]; a = []; X = mx4, Y = my4, Z = mz4, a = [...a, [X, Y, Z]]; X = cx, Y = cy, Z = cz, a = [...a, [X, Y, Z]]; X = mx3, Y = my3, Z = mz3, a = [...a, [X, Y, Z]]; X = X4, Y = Y4, Z = Z4, a = [...a, [X, Y, Z]]; shape = [...shape, a]; break; case 5: cx = (X1 + X2 + X3 + X4 + X5) / 5; cy = (Y1 + Y2 + Y3 + Y4 + Y5) / 5; cz = (Z1 + Z2 + Z3 + Z4 + Z5) / 5; mx3 = (X3 + X4) / 2; my3 = (Y3 + Y4) / 2; mz3 = (Z3 + Z4) / 2; mx4 = (X4 + X5) / 2; my4 = (Y4 + Y5) / 2; mz4 = (Z4 + Z5) / 2; mx5 = (X5 + X1) / 2; my5 = (Y5 + Y1) / 2; mz5 = (Z5 + Z1) / 2; X = X1, Y = Y1, Z = Z1, a = [...a, [X, Y, Z]]; X = X2, Y = Y2, Z = Z2, a = [...a, [X, Y, Z]]; X = cx, Y = cy, Z = cz, a = [...a, [X, Y, Z]]; shape = [...shape, a]; a = []; X = X2, Y = Y2, Z = Z2, a = [...a, [X, Y, Z]]; X = X3, Y = Y3, Z = Z3, a = [...a, [X, Y, Z]]; X = cx, Y = cy, Z = cz, a = [...a, [X, Y, Z]]; shape = [...shape, a]; a = []; X = X3, Y = Y3, Z = Z3, a = [...a, [X, Y, Z]]; X = X4, Y = Y4, Z = Z4, a = [...a, [X, Y, Z]]; X = cx, Y = cy, Z = cz, a = [...a, [X, Y, Z]]; shape = [...shape, a]; a = []; X = X4, Y = Y4, Z = Z4, a = [...a, [X, Y, Z]]; X = X5, Y = Y5, Z = Z5, a = [...a, [X, Y, Z]]; X = cx, Y = cy, Z = cz, a = [...a, [X, Y, Z]]; shape = [...shape, a]; a = []; X = X5, Y = Y5, Z = Z5, a = [...a, [X, Y, Z]]; X = X1, Y = Y1, Z = Z1, a = [...a, [X, Y, Z]]; X = cx, Y = cy, Z = cz, a = [...a, [X, Y, Z]]; shape = [...shape, a]; a = []; break;} }); } if (sphereize) { ip1 = sphereize; ip2 = 1 - sphereize; shape = shape.map(v => { v = v.map(q => { X = q[0]; Y = q[1]; Z = q[2]; d = Math.hypot(X, Y, Z); X /= d; Y /= d; Z /= d; X *= size * .75 * ip1 + d * ip2; Y *= size * .75 * ip1 + d * ip2; Z *= size * .75 * ip1 + d * ip2; return [X, Y, Z]; }); return v; }); } return shape; }; subDividedIcosahedron = (size, subs, sphereize = 0) => subbed(subs, size, sphereize, Icosahedron(size)); subDividedTetrahedron = (size, subs, sphereize = 0) => subbed(subs, size, sphereize, Tetrahedron(size)); subDividedOctahedron = (size, subs, sphereize = 0) => subbed(subs, size, sphereize, Octahedron(size)); subDividedCube = (size, subs, sphereize = 0) => subbed(subs, size, sphereize, Cube(size)); subDividedDodecahedron = (size, subs, sphereize = 0) => subbed(subs, size, sphereize, Dodecahedron(size)); Rn = Math.random; LsystemRecurse = (size, splits, p1, p2, stem, theta, LsystemReduction, twistFactor) => { if (size < .25) return; let X1 = stem[0]; let Y1 = stem[1]; let Z1 = stem[2]; let X2 = stem[3]; let Y2 = stem[4]; let Z2 = stem[5]; let p1a = Math.atan2(X2 - X1, Z2 - Z1); let p2a = -Math.acos((Y2 - Y1) / (Math.hypot(X2 - X1, Y2 - Y1, Z2 - Z1) + .0001)) + Math.PI; size /= LsystemReduction; for (let i = splits; i--;) { X = 0; Y = -size; Z = 0; R(0, theta, 0); R(0, 0, Math.PI * 2 / splits * i + twistFactor); R(0, p2a, 0); R(0, 0, p1a + twistFactor); X += X2; Y += Y2; Z += Z2; let newStem = [X2, Y2, Z2, X, Y, Z]; Lshp = [...Lshp, newStem]; LsystemRecurse(size, splits, p1 + Math.PI * 2 / splits * i + twistFactor, p2 + theta, newStem, theta, LsystemReduction, twistFactor); } }; DrawLsystem = shp => { shp.map(v => { x.beginPath(); X = v[0]; Y = v[1]; Z = v[2]; R(Rl, Pt, Yw, 1); if (Z > 0) x.lineTo(...Q()); X = v[3]; Y = v[4]; Z = v[5]; R(Rl, Pt, Yw, 1); if (Z > 0) x.lineTo(...Q()); lwo = Math.hypot(v[0] - v[3], v[1] - v[4], v[2] - v[5]) * 4; stroke('#0f82', '', lwo); }); }; Lsystem = (size, splits, theta, LsystemReduction, twistFactor) => { Lshp = []; stem = [0, 0, 0, 0, -size, 0]; Lshp = [...Lshp, stem]; LsystemRecurse(size, splits, 0, 0, stem, theta, LsystemReduction, twistFactor); Lshp.map(v => { v[1] += size * 1.5; v[4] += size * 1.5; }); return Lshp; }; Sphere = (ls, rw, cl) => { a = []; ls /= 1.25; for (j = rw; j--;) { for (i = cl; i--;) { b = []; X = S(p = Math.PI * 2 / cl * i) * S(q = Math.PI / rw * j) * ls; Y = C(q) * ls; Z = C(p) * S(q) * ls; b = [...b, [X, Y, Z]]; X = S(p = Math.PI * 2 / cl * (i + 1)) * S(q = Math.PI / rw * j) * ls; Y = C(q) * ls; Z = C(p) * S(q) * ls; b = [...b, [X, Y, Z]]; X = S(p = Math.PI * 2 / cl * (i + 1)) * S(q = Math.PI / rw * (j + 1)) * ls; Y = C(q) * ls; Z = C(p) * S(q) * ls; b = [...b, [X, Y, Z]]; X = S(p = Math.PI * 2 / cl * i) * S(q = Math.PI / rw * (j + 1)) * ls; Y = C(q) * ls; Z = C(p) * S(q) * ls; b = [...b, [X, Y, Z]]; a = [...a, b]; } } return a; }; Torus = (rw, cl, ls1, ls2, parts = 1, twists = 0, part_spacing = 1.5) => { let ret = [],tx = 0,ty = 0,tz = 0,prl1 = 0,p2a = 0; let tx1 = 0,ty1 = 0,tz1 = 0,prl2 = 0,p2b = 0,tx2 = 0,ty2 = 0,tz2 = 0; for (let m = parts; m--;) { avgs = Array(rw).fill().map(v => [0, 0, 0]); for (j = rw; j--;) for (let i = cl; i--;) { if (parts > 1) { ls3 = ls1 * part_spacing; X = S(p = Math.PI * 2 / parts * m) * ls3; Y = C(p) * ls3; Z = 0; R(prl1 = Math.PI * 2 / rw * (j - 1) * twists, 0, 0); tx1 = X; ty1 = Y; tz1 = Z; R(0, 0, Math.PI * 2 / rw * (j - 1)); ax1 = X; ay1 = Y; az1 = Z; X = S(p = Math.PI * 2 / parts * m) * ls3; Y = C(p) * ls3; Z = 0; R(prl2 = Math.PI * 2 / rw * j * twists, 0, 0); tx2 = X; ty2 = Y; tz2 = Z; R(0, 0, Math.PI * 2 / rw * j); ax2 = X; ay2 = Y; az2 = Z; p1a = Math.atan2(ax2 - ax1, az2 - az1); p2a = Math.PI / 2 + Math.acos((ay2 - ay1) / (Math.hypot(ax2 - ax1, ay2 - ay1, az2 - az1) + .001)); X = S(p = Math.PI * 2 / parts * m) * ls3; Y = C(p) * ls3; Z = 0; R(Math.PI * 2 / rw * j * twists, 0, 0); tx1b = X; ty1b = Y; tz1b = Z; R(0, 0, Math.PI * 2 / rw * j); ax1b = X; ay1b = Y; az1b = Z; X = S(p = Math.PI * 2 / parts * m) * ls3; Y = C(p) * ls3; Z = 0; R(Math.PI * 2 / rw * (j + 1) * twists, 0, 0); tx2b = X; ty2b = Y; tz2b = Z; R(0, 0, Math.PI * 2 / rw * (j + 1)); ax2b = X; ay2b = Y; az2b = Z; p1b = Math.atan2(ax2b - ax1b, az2b - az1b); p2b = Math.PI / 2 + Math.acos((ay2b - ay1b) / (Math.hypot(ax2b - ax1b, ay2b - ay1b, az2b - az1b) + .001)); } a = []; X = S(p = Math.PI * 2 / cl * i) * ls1; Y = C(p) * ls1; Z = 0; //R(0,0,-p1a) R(prl1, p2a, 0); X += ls2 + tx1, Y += ty1, Z += tz1; R(0, 0, Math.PI * 2 / rw * j); a = [...a, [X, Y, Z]]; X = S(p = Math.PI * 2 / cl * (i + 1)) * ls1; Y = C(p) * ls1; Z = 0; //R(0,0,-p1a) R(prl1, p2a, 0); X += ls2 + tx1, Y += ty1, Z += tz1; R(0, 0, Math.PI * 2 / rw * j); a = [...a, [X, Y, Z]]; X = S(p = Math.PI * 2 / cl * (i + 1)) * ls1; Y = C(p) * ls1; Z = 0; //R(0,0,-p1b) R(prl2, p2b, 0); X += ls2 + tx2, Y += ty2, Z += tz2; R(0, 0, Math.PI * 2 / rw * (j + 1)); a = [...a, [X, Y, Z]]; X = S(p = Math.PI * 2 / cl * i) * ls1; Y = C(p) * ls1; Z = 0; //R(0,0,-p1b) R(prl2, p2b, 0); X += ls2 + tx2, Y += ty2, Z += tz2; R(0, 0, Math.PI * 2 / rw * (j + 1)); a = [...a, [X, Y, Z]]; ret = [...ret, a]; } } return ret; }; G_ = 100000, iSTc = 1e4; ST = Array(iSTc).fill().map(v => { X = (Rn() - .5) * G_; Y = (Rn() - .5) * G_; Z = (Rn() - .5) * G_; return [X, Y, Z]; }); burst = new Image(); burst.src = "https://srmcgann.github.io/temp/burst.png"; document.body.onload = () => { c.focus(); }; starsLoaded = false, starImgs = [{ loaded: false }]; starImgs = Array(9).fill().map((v, i) => { let a = { img: new Image(), loaded: false }; a.img.onload = () => { a.loaded = true; setTimeout(() => { if (starImgs.filter(v => v.loaded).length == 9) starsLoaded = true; }, 0); }; a.img.src = `//repo.bfw.wiki/bfwrepo/images/game/fangkuai/star${i + 1}.png`; return a; }); showstars = true; tboard = new Image(); //tboard.src = 'tboard.png' tboard.src = '//repo.bfw.wiki/bfwrepo/images/game/fangkuai/tXnnqzu.png'; tboard_inactive = new Image(); //tboard_inactive.src = 'tboard_inactive.jpg' tboard_inactive.src = '//repo.bfw.wiki/bfwrepo/images/game/fangkuai/FhBEuaY.jpeg'; gridoverlay = new Image(); //gridoverlay.src = 'gridoverlay.png' gridoverlay.src = '//repo.bfw.wiki/bfwrepo/images/game/fangkuai/QzF5K9b.png'; border = new Image(); //border.src = 'border.png' border.src = '//repo.bfw.wiki/bfwrepo/images/game/fangkuai/yzLTMwN.png'; manualBoards = false; spawnPiece = (uid, rndPc = true, pc = 0) => { let ret = []; if (rndPc && uid != -1 && typeof players != 'undefined' && players.length) { let player = players.filter(player => player.id == uid); let np; if (player.length && typeof player[0]?.nextPieces != 'undefined' && player[0]?.nextPieces.length) { np = player[0]?.nextPieces[player[0]?.nextPieces.length - 1][1]; //force non-duplicate next-piece do { pieceSel = Rn() * 7 | 0; } while (np == pieceSel); // use NES Tetris® rule: re-draw only once on duplicate //pieceSel = Rn()*7|0 } else { pieceSel = Rn() * 7 | 0; } } else { pieceSel = rndPc ? Rn() * 7 | 0 : pc; } switch (pieceSel) { case 0: // longboi ret = [ [0, 0, 0], [0, 1, 0], [0, -2, 0], [0, -1, 0]]; break; case 1: // square ret = [ [0, 0, 0], [-1, -1, 0], [0, -1, 0], [-1, 0, 0]]; break; case 2: // zig ret = [ [0, -1, 0], [-1, -2, 0], [-1, -1, 0], [0, 0, 0]]; break; case 3: // zag ret = [ [0, -1, 0], [0, -2, 0], [-1, -1, 0], [-1, 0, 0]]; break; case 4: // L ret = [ [-1, -1, 0], [-1, 0, 0], [0, 0, 0], [-1, -2, 0]]; break; case 5: // 7 ret = [ [0, -1, 0], [0, 0, 0], [0, -2, 0], [-1, 0, 0]]; break; case 6: // T ret = [ [0, 0, 0], [-1, 0, 0], [1, 0, 0], [0, -1, 0]]; break;} ret = ret.map(v => { v[1] -= 3; X = v[6] = v[3] = v[0]; Y = v[7] = v[4] = v[1]; Z = v[8] = v[5] = v[2]; if (typeof players != 'undefined' && players.length && players.length - 1 > uid) { let idx = Y * 10 + X + 95; l = players.filter(player => player.id == uid)[0]; if (l.alive && l.box[idx] != -1) { l.alive = false; l.respawns++; } } return v; }); return [ret, pieceSel]; }; spawnPlayer = (uid, max = 0, speed = 10, tetrises = 0, respawns = 0) => { let ret = { keys: Array(128).fill().map(v => false), keyTimers: Array(128).fill(0), box: Array(10 * 30).fill(-1), alive: true, name: uid ? 'AI p. ' + uid : 'human', deathGrow: 0, pieceSwapped: false, moveDecided: false, speed: speed, respawns: respawns, tetrises: tetrises, rowsCompleted: 0, maxRowsCompleted: max, swapPiece: [], keyQueue: [0, 0], curPiece: spawnPiece(uid), id: uid, settledTimer: -1, nextPieces: Array(10).fill().map(piece => spawnPiece(uid)) }; return ret; }; masterInit = (setAI = false) => { if (1 || !setAI) { rw = 20; cl = 10; localsp = sp = 2.125; spawnBoard = (tx, ty, tz, sp, active = false, name = 'unknown player') => { let board = {}; if (name.length > 7) { name = name.substring(0, 7) + '…'; } board.grid = Array(rw * cl).fill().map((v, i) => { X = (i % cl - cl / 2 + .5) * sp + tx; Y = ((i / cl | 0) - rw / 2 + .5) * sp + ty; Z = tz; return [X, Y, Z]; }); board.sp = sp; board.active = active; return board; }; boards = []; boards = [...boards, spawnBoard(-sp * 12.5, 3, 0, sp)]; cbcl = 5; cbrw = 3; remotesp = sp = .5; for (let i = 0; i < cbcl * cbrw; i++) { let X = (i % cbcl - cbcl / 2 + .5) * sp * 12 + sp * 40 + 4; let Y = ((i / cbcl | 0) - cbrw / 2 + .5) * sp * 27 - 4.5; let Z = 0; boards = [...boards, spawnBoard(X, Y, Z, sp, !i)]; } } players = []; iPlayerc = 4; if (setAI) { do { iPlayerc = +prompt('how many AI players? [0-14]'); } while (!(iPlayerc !== null && iPlayerc >= 0 && iPlayerc <= 14)); } showSideBars = true; sidebarPieces = setAI ? sidebarPieces : Array(7).fill().map((v, i) => spawnPiece(-1, false, i)); settleInterval = .15; showInfo = false; mousedown = false; instadropAI = false; buttons = setAI ? buttons : []; buttonsLoaded = setAI ? buttonsLoaded : false; dropTimer = 50; flashes = []; lerpFactor = 5; sortCriteria = 'maxRowsCompleted'; paused = false; sliders = setAI ? sliders : []; grav = .005; showLeaderBoard = true; AISpeed = setAI ? AISpeed : 25; gameInPlay = true; keyTimerInterval = .14; tplayer = spawnPlayer(0); players = [tplayer, tplayer]; Array(iPlayerc).fill().map((player, idx) => { players = [...players, spawnPlayer(idx + 1, 0, AISpeed)]; }); players.map((player, idx) => { boards[idx].active = true; }); }; masterInit(); togglePause = () => { paused = !paused; }; c.onkeydown = e => { e.preventDefault(); e.stopPropagation(); let player = players[0]; player.keys[e.keyCode] = true; if (e.keyCode == 32 && player.deathGrow > 200) resetGame(player, 0); }; c.onkeyup = e => { e.preventDefault(); e.stopPropagation(); let player = players[0]; player.keys[e.keyCode] = false; player.keyTimers[e.keyCode] = 0; }; c.onmousedown = e => { let rect = c.getBoundingClientRect(); mx = (e.pageX - rect.left) / c.clientWidth * c.width; my = (e.pageY - rect.top) / c.clientHeight * c.height; if (sliders.length) { sliders.map(slider => { X = slider.posX - slider.width / 2 + slider.width / (slider.max - slider.min) * eval(slider.valVariable); .........完整代码请登录后点击上方下载按钮下载查看
网友评论0