diff --git a/_public/home.js b/_public/home.js deleted file mode 100644 index b8d3369..0000000 --- a/_public/home.js +++ /dev/null @@ -1,342 +0,0 @@ - -function pointInInterval(a, b, x) { - return a <= x && x <= b; -} - -function intervalIntersectsInterval(a, b, c, d) { - if (c <= a) { - return a <= d; - } - - return pointInInterval(a, b, c); -} - -function rectIntersectRect(x1, y1, x2, y2, x3, y3, x4, y4) { - return intervalIntersectsInterval(x1, x2, x3, x4) && intervalIntersectsInterval(y1, y2, y3, y4); -} - -function intersects(x1, y1, x2, y2, x3, y3, x4, y4) { - const a_minx = Math.min(x1, x2); - const a_maxx = Math.max(x1, x2); - const a_miny = Math.min(y1, y2); - const a_maxy = Math.max(y1, y2); - - const b_minx = Math.min(x3, x4); - const b_maxx = Math.max(x3, x4); - const b_miny = Math.min(y3, y4); - const b_maxy = Math.max(y3, y4); - - if (!rectIntersectRect(a_minx, a_miny, a_maxx, a_maxy, b_minx, b_miny, b_maxx, b_maxy)) - return false; - - const a_dx = x2 - x1; - const a_dy = y2 - y1; - - const b_dx = x4 - x3; - const b_dy = y4 - y3; - - const det = -b_dx * a_dy + a_dx * b_dy; - - if (Math.abs(det) === 0 && -a_dy * (x3 - x1) + a_dx * (y3 - y1) === 0) { - return y1 <= y3 <= y2 || y1 <= y4 <= y2; - } - - const s = (-a_dy * (x1 - x3) + a_dx * (y1 - y3)) / det; - const t = (+b_dx * (y1 - y3) - b_dy * (x1 - x3)) / det; - - return s >= 0 && s <= 1 && t >= 0 && t <= 1; -} - -const $canvas = document.querySelector('#circuit-pattern'); -let g = $canvas.getContext('2d'); - -let WIDTH = $canvas.offsetWidth; -let HEIGHT = $canvas.offsetHeight; - -const TS = 20; - -let ROWS = HEIGHT / TS; -let COLS = WIDTH / TS; - -function updateCanvasDimensions() { - g = $canvas.getContext('2d'); - - WIDTH = $canvas.offsetWidth; - HEIGHT = $canvas.offsetHeight; - - ROWS = HEIGHT / TS; - COLS = WIDTH / TS; - - $canvas.width = WIDTH * devicePixelRatio; - $canvas.height = HEIGHT * devicePixelRatio; - g.scale(devicePixelRatio, devicePixelRatio); -} - -window.addEventListener('resize', () => updateCanvasDimensions()); -updateCanvasDimensions(); - -const state = { - wires: [], // :: [(Int, Int)] - nextWire: null, - nextWireIndex: 0, - nextSegmentLen: 0, - t: 0, -}; - -function randomFloat(min, max) { - return Math.random() * (max - min) + min; -} - -function randomInt(min, max) { - return Math.floor(Math.random() * (max - min + 1) + min); -} - -function randomChoice(list) { - return list[randomInt(0, list.length - 1)]; -} - -const DIRS = { - left: [-1, 1], - center: [0, 1], - right: [+1, 1], -}; - -const NEXT_DIRS = { - left: ['center'], - center: ['left', 'right'], - right: ['center'], -}; - -function canPlaceSegment([[p1x, p1y], [p2x, p2y]]) { - return state.wires.every(wire => { - return everyWireSegment(wire, ([[sx, sy], [lx, ly]]) => { - return !intersects(sx, sy, lx, ly, p1x, p1y, p2x, p2y); - }); - }) -} - -function everyWireSegment(wire, segmentFn) { - let [start, ...rest] = wire; - - return rest.every((pt) => { - const r = segmentFn([start, pt]); - start = pt; - return r; - }); -} - -function generateWire() { - const pieceCount = Math.pow(randomFloat(1, 2.5), 2) | 0; - const startPoint = [ - randomInt(0, COLS), - Math.pow(randomFloat(0, ROWS / 12), 2) | 0, - ]; - const sizes = Array(pieceCount).fill(0).map(() => randomInt(2, 4) | 0); - - const dirs = [randomChoice(Object.keys(DIRS))]; - for (let i = 0; i < pieceCount - 1; i++) { - const last = dirs[dirs.length - 1]; - dirs.push(randomChoice(NEXT_DIRS[last])); - } - - const wire = [startPoint]; - for (let i = 0; i < pieceCount; i++) { - const [lpx, lpy] = wire[wire.length - 1]; - const [dx, dy] = DIRS[dirs[i]]; - const s = sizes[i]; - - const s_bonus = (dirs[i] === 'center' ? s * 2 : s) | 0; - - wire.push([lpx + dx * s_bonus, lpy + dy * s_bonus]); - } - - const ok = everyWireSegment(wire, segment => { - return canPlaceSegment(segment); - }); - - if (!ok) - return null; - - return wire; -} - -// // LinearintERPolation -function lerp(a, b, t) { - return t * (b - a) + a; -} -function lerpPoint([x1, y1], [x2, y2], t) { - return [lerp(x1, x2, t), lerp(y1, y2, t)]; -} - -const CELLS_PER_SECOND = 15; - -let lastTime = new Date().getTime(); - -function update() { - const now = new Date().getTime(); - const delta = (now - lastTime) / 1000; - lastTime = now; - - if (state.nextWire) { - state.t += CELLS_PER_SECOND * delta; - - if (state.t >= 1.0) { - const [[x1, y1], [x2, y2]] = state.nextWire.slice(state.nextWireIndex - 2, state.nextWireIndex); - const dx = Math.abs(x2 - x1); - const dy = Math.abs(y2 - y1); - state.t = 0; - state.nextSegmentLen = Math.sqrt(dx * dx + dy * dy); - - state.nextWireIndex++; - } - - if (state.nextWireIndex > state.nextWire.length) { - state.wires.push(state.nextWire); - state.nextWire = null; - } - } else { - const wire = generateWire(); - if (wire) { - state.nextWire = wire; - state.nextWireIndex = 2; - - const [[x1, y1], [x2, y2]] = state.nextWire.slice(state.nextWireIndex - 2, state.nextWireIndex); - const dx = Math.abs(x2 - x1); - const dy = Math.abs(y2 - y1); - state.t = 0; - state.nextSegmentLen = Math.sqrt(dx * dx + dy * dy); - } - } -} - -function getColors() { - if (document.body.classList.contains('dark-mode')) { - return { - BACKGROUND: '#282828', - CIRCUIT: '#38302e', - } - } else { - return { - BACKGROUND: '#eaeaea', - CIRCUIT: '#d4d4d4', - }; - } -} - -function render() { - const { BACKGROUND, CIRCUIT } = getColors(); - - g.clearRect(0, 0, WIDTH, HEIGHT); - - g.strokeStyle = CIRCUIT; - g.lineWidth = 3; - - state.wires.forEach(wire => { - const [[sx, sy], ...rest] = wire; - - function renderDot(x, y) { - if (y === 0) { - return; - } - - g.beginPath(); - g.ellipse(x * TS, y * TS, TS / 5, TS / 5, 0, 0, Math.PI * 2); - g.stroke(); - } - - renderDot(sx, sy); - - g.beginPath(); - g.moveTo(sx * TS, sy * TS); - rest.forEach(([x, y]) => { - g.lineTo(x * TS, y * TS); - }); - g.stroke(); - - const [lx, ly] = wire[wire.length - 1]; - - renderDot(lx, ly); - - [wire[0], wire[wire.length - 1]].forEach(([x, y]) => { - if (y === 0) { - return; - } - - g.fillStyle = BACKGROUND; - g.beginPath(); - g.ellipse(x * TS, y * TS, TS / 5 - 1, TS / 5 - 1, 0, 0, Math.PI * 2); - g.fill(); - }); - }); - - if (state.nextWire) { - const wirePart = state.nextWire.slice(0, state.nextWireIndex); - const wire = [ - ...wirePart.slice(0, wirePart.length - 1), - lerpPoint( - wirePart[wirePart.length - 2], - wirePart[wirePart.length - 1], - state.t - ) - ]; - const [[sx, sy], ...rest] = wire; - - function renderDot(x, y) { - if (y === 0) { - return; - } - - g.beginPath(); - g.ellipse(x * TS, y * TS, TS / 5, TS / 5, 0, 0, Math.PI * 2); - g.stroke(); - } - - renderDot(sx, sy); - - g.beginPath(); - g.moveTo(sx * TS, sy * TS); - rest.forEach(([x, y]) => { - g.lineTo(x * TS, y * TS); - }); - g.stroke(); - - const [lx, ly] = wire[wire.length - 1]; - - renderDot(lx, ly); - - [wire[0], wire[wire.length - 1]].forEach(([x, y]) => { - if (y === 0) { - return; - } - - g.fillStyle = BACKGROUND; - g.beginPath(); - g.ellipse(x * TS, y * TS, TS / 5 - 1, TS / 5 - 1, 0, 0, Math.PI * 2); - g.fill(); - }); - } - - requestAnimationFrame(render); -} - -// g.translate(0.5, 0.5); - -window.addEventListener('DOMContentLoaded', () => { - // $canvas.classList.remove('hide'); - - render(); - - let i = 20; - while (i > 0) { - const wire = generateWire(); - - if (wire) { - state.wires.push(wire); - i--; - } - } - - setInterval(() => { - update(); - }, 1000 / 30); -})