Web Dev Solutions

Catalin Mititiuc

const svgns = "http://www.w3.org/2000/svg", targetClassName = 'sight-line-target', activeClassName = 'active'; function evenr_to_axial(x, y) { return { q: x - (y + (y & 1)) / 2, r: y }; } function axial_to_evenr(q, r) { return { x: q + (r + (r & 1)) / 2, y: r }; } function axial_distance(q1, r1, q2, r2) { return (Math.abs(q1 - q2) + Math.abs(q1 + r1 - q2 - r2) + Math.abs(r1 - r2)) / 2; } function offset_distance(x1, y1, x2, y2) { const { q: q1, r: r1 } = evenr_to_axial(x1, y1), { q: q2, r: r2 } = evenr_to_axial(x2, y2); return axial_distance(q1, r1, q2, r2); } function cube_to_axial(q, r, _) { return { q, r }; } function axial_to_cube(q, r) { return { q, r, s: -q - r }; } function cube_round(q, r, s) { let rQ = Math.round(q), rR = Math.round(r), rS = Math.round(s); const q_diff = Math.abs(rQ - q), r_diff = Math.abs(rR - r), s_diff = Math.abs(rS - s); if (q_diff > r_diff && q_diff > s_diff) { rQ = -rR - rS; } else if (r_diff > s_diff) { rR = -rQ - rS; } else { rS = -rQ - rR; } return { q: rQ, r: rR, s: rS }; } function axial_round(q, r) { const cube = axial_to_cube(q, r), round = cube_round(cube.q, cube.r, cube.s), axial = cube_to_axial(round.q, round.r, round.s); return { q: axial.q, r: axial.r }; } function lerp(a, b, t) { return a + (b - a) * t; } function axial_lerp(q1, r1, q2, r2, t) { return { q: lerp(q1, q2, t), r: lerp(r1, r2, t) }; } function calcIndexes(x1, y1, x2, y2) { const axial1 = evenr_to_axial(x1, y1), axial2 = evenr_to_axial(x2, y2), n = offset_distance(x1, y1, x2, y2), results = []; for (let i = 0; i <= n; i++) { const lerp = axial_lerp(axial1.q, axial1.r, axial2.q, axial2.r, 1.0 / n * i), round = axial_round(lerp.q, lerp.r), { x, y } = axial_to_evenr(round.q, round.r); results.push([x, y]); } return results; } function create({ x: x1, y: y1 }, { x: x2, y: y2 }) { const sightLine = document.createElementNS(svgns, 'line'); sightLine.classList.add('sight-line'); sightLine.classList.add(activeClassName); sightLine.setAttributeNS(null, 'x1', x1); sightLine.setAttributeNS(null, 'y1', y1); sightLine.setAttributeNS(null, 'x2', x2); sightLine.setAttributeNS(null, 'y2', y2); return sightLine; } function lock(sightLine, cell) { sightLine.classList.remove(activeClassName); cell.classList.add(targetClassName); return cell; } function unlock(sightLine, lockTarget) { sightLine.classList.add(activeClassName); lockTarget.classList.remove(targetClassName); return null; } export default function (board) { let sightLine, lockTarget, activeHexes = []; return { calcIndexes, drawLine: function (...positions) { this.clear(); sightLine = create(...positions); board.appendChild(sightLine); }, clear: function () { sightLine && sightLine.remove(); sightLine = null; lockTarget && lockTarget.classList.remove(targetClassName); lockTarget = null; }, update: function ({ x, y }) { sightLine.setAttributeNS(null, 'x1', x); sightLine.setAttributeNS(null, 'y1', y); }, toggleLock: function (cell) { lockTarget = lockTarget ? unlock(sightLine, lockTarget) : lock(sightLine, cell); }, get sightLine() { return sightLine; }, get lockTarget() { return lockTarget; }, set hexes(hexes) { activeHexes.forEach(h => h.classList.remove(activeClassName)); hexes.forEach(h => h.classList.add(activeClassName)); activeHexes = hexes; } }; }