index : btroops | |
Virtual board game-aid for BattleTroops, an infantry combat simulator wargame published by FASA in 1989. |
aboutsummaryrefslogtreecommitdiff |
diff options
author | Catalin Mititiuc <Catalin.Mititiuc@gmail.com> | 2024-04-01 12:20:04 -0700 |
---|---|---|
committer | Catalin Mititiuc <Catalin.Mititiuc@gmail.com> | 2024-04-01 12:20:04 -0700 |
commit | 5c1dfbca50d6809e4a9546472b1a4ec092f35358 (patch) | |
tree | 48bf7178b8bcae1e20f5f077f4d91a63d8d73315 /index.js | |
parent | 64aeda4b5591d7801948406f9ace46121c037e8b (diff) |
WIP: end movement, turn buttons
Diffstat (limited to 'index.js')
-rw-r--r-- | index.js | 230 |
1 files changed, 142 insertions, 88 deletions
@@ -64,9 +64,13 @@ const svgns = "http://www.w3.org/2000/svg", map = document.querySelector('rect#map'), hex = document.getElementById('point'), ptGrp = document.getElementById('points'), + cntrGrp = document.getElementById('counters'), settingsPanel = document.getElementById('panel'), recordSheetVisibility = document.querySelector('#content input[type="checkbox"].visible'); +const q = s => document.querySelector(s), + qA = s => document.querySelectorAll(s); + const { x: VIEWBOX_X, y: VIEWBOX_Y, width: VIEWBOX_WIDTH, height: VIEWBOX_HEIGHT } = svg.viewBox.baseVal; @@ -135,7 +139,7 @@ let info = document.getElementById('status'); return acc; }, {}); - let transform = `translate(${translateX}px, ${translateY}px) rotate(${rotate}deg) scale(${scale}) ` + let transform = `translate(${translateX}px, ${translateY}px) rotate(${rotate}deg) scale(${scale})`; target.style.transform = transform; }); @@ -177,27 +181,22 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => { {troopNumber, troopAllegiance} = selectedSoldier.dataset, selector = troopSelector(troopNumber, troopAllegiance); - let transProp = getComputedStyle(ptGrp).transform.match(/-?\d+\.?\d*/g), - mtx = new DOMMatrix(transProp || ''), - pt = new DOMPoint(point.x.baseVal.value, point.y.baseVal.value), - svgP = pt.matrixTransform(mtx); - info.querySelector('#hex-count').textContent = '-'; info.style.display = 'none'; ptGrp.querySelectorAll('.active').forEach(el => el.removeAttribute('class')); svg.querySelectorAll('.sight-line').forEach(el => el.remove()); - counter.setAttributeNS(null, 'cx', svgP.x); - counter.setAttributeNS(null, 'cy', svgP.y); - counter.setAttributeNS(null, 'r', '0.25in'); + counter.setAttributeNS(null, 'cx', cx); + counter.setAttributeNS(null, 'cy', cy); + counter.setAttributeNS(null, 'r', '5'); counter.dataset.troopNumber = troopNumber; counter.dataset.troopAllegiance = troopAllegiance; counter.dataset.x = point.dataset.x; counter.dataset.y = point.dataset.y; counter.classList.add('counter'); - text.setAttributeNS(null, 'x', svgP.x); - text.setAttributeNS(null, 'y', svgP.y); + text.setAttributeNS(null, 'x', cx); + text.setAttributeNS(null, 'y', cy); text.dataset.troopNumber = troopNumber; text.dataset.troopAllegiance = troopAllegiance; text.textContent = troopNumber; @@ -205,7 +204,7 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => { document.querySelectorAll(`.counter${selector}`).forEach(el => el.remove()); - counter.addEventListener('click', e => { + counter.addEventListener('dblclick', e => { let selectedSoldier = document.querySelector('.soldier-record.selected'); if (selectedSoldier) { @@ -223,40 +222,50 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => { } }); - counter.addEventListener('mouseenter', e => { - let selectedSoldier = document.querySelector('.soldier-record.selected'); + // counter.addEventListener('mouseenter', e => { + // let selectedSoldier = document.querySelector('.soldier-record.selected'); - if (selectedSoldier) { - let {troopNumber, troopAllegiance} = selectedSoldier.dataset, - selector = troopSelector(troopNumber, troopAllegiance), - source = document.querySelector(`circle.counter${selector}`), + // if (selectedSoldier) { + // let {troopNumber, troopAllegiance} = selectedSoldier.dataset, + // selector = troopSelector(troopNumber, troopAllegiance), + // source = document.querySelector(`circle.counter${selector}`), - // TODO: use isEqualNode() method instead - sourceAndTargetAreNotTheSame = [ - troopNumber != e.target.dataset.troopNumber, - troopAllegiance != e.target.dataset.troopAllegiance - ].some(el => el); + // // TODO: use isEqualNode() method instead + // sourceAndTargetAreNotTheSame = [ + // troopNumber != e.target.dataset.troopNumber, + // troopAllegiance != e.target.dataset.troopAllegiance + // ].some(el => el); - if (source && sourceAndTargetAreNotTheSame) { - let sightLine = document.createElementNS(svgns, 'line'); + // if (source && sourceAndTargetAreNotTheSame) { + // let sightLine = document.createElementNS(svgns, 'line'); - sightLine.classList.add('sight-line'); - sightLine.setAttributeNS(null, 'x1', source.getAttribute('cx')); - sightLine.setAttributeNS(null, 'y1', source.getAttribute('cy')); - sightLine.setAttributeNS(null, 'x2', e.target.getAttribute('cx')); - sightLine.setAttributeNS(null, 'y2', e.target.getAttribute('cy')); + // sightLine.classList.add('sight-line'); + // sightLine.setAttributeNS(null, 'x1', source.getAttribute('cx')); + // sightLine.setAttributeNS(null, 'y1', source.getAttribute('cy')); + // sightLine.setAttributeNS(null, 'x2', e.target.getAttribute('cx')); + // sightLine.setAttributeNS(null, 'y2', e.target.getAttribute('cy')); - svg.appendChild(sightLine); - } - } - }); + // svg.appendChild(sightLine); + // } + // } + // }); - counter.addEventListener('mouseleave', e => { - document.querySelectorAll('.sight-line').forEach(el => el.remove()); - }); + // counter.addEventListener('mouseleave', e => { + // document.querySelectorAll('.sight-line').forEach(el => el.remove()); + // }); + + // svg.insertBefore(counter, ptGrp); + + // let symbCtr = document.createElementNS(svgns, 'use'); + + // symbCtr.setAttributeNS(null, 'href', '#troop-counter'); + // symbCtr.setAttributeNS(null, 'x', cx); + // symbCtr.setAttributeNS(null, 'y', cy); - svg.insertBefore(counter, ptGrp); - svg.insertBefore(text, ptGrp); + // cntrGrp.appendChild(symbCtr); + + cntrGrp.appendChild(counter); + cntrGrp.appendChild(text); } }); @@ -271,6 +280,13 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => { let sl = svg.querySelector('.sight-line'); if (counter && (!sl || sl.classList.contains('active'))) { + if (sl) { + info.querySelector('#hex-count').textContent = '-'; + info.style.display = 'none'; + ptGrp.querySelectorAll('.active').forEach(el => el.removeAttribute('class')); + svg.querySelectorAll('.sight-line').forEach(el => el.remove()); + } + let source = ptGrp.querySelector(`use[data-x="${counter.dataset.x}"][data-y="${counter.dataset.y}"]`); let [x1, y1] = [source.x.baseVal.value, source.y.baseVal.value]; let [x2, y2] = [e.target.x.baseVal.value, e.target.y.baseVal.value]; @@ -288,7 +304,8 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => { sightLine.setAttributeNS(null, 'x2', svgX2); sightLine.setAttributeNS(null, 'y2', svgY2); - svg.insertBefore(sightLine, ptGrp); + // svg.insertBefore(sightLine, ptGrp); + document.getElementById('grid').appendChild(sightLine); let coords = [ counter.dataset.x, @@ -309,16 +326,16 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => { } }); - point.addEventListener('mouseout', e => { - let sl = svg.querySelector('.sight-line.active'); + // point.addEventListener('mouseout', e => { + // let sl = svg.querySelector('.sight-line.active'); - if (sl) { - info.querySelector('#hex-count').textContent = '-'; - info.style.display = 'none'; - ptGrp.querySelectorAll('.active').forEach(el => el.removeAttribute('class')); - svg.querySelectorAll('.sight-line').forEach(el => el.remove()); - } - }); + // if (sl) { + // info.querySelector('#hex-count').textContent = '-'; + // info.style.display = 'none'; + // ptGrp.querySelectorAll('.active').forEach(el => el.removeAttribute('class')); + // svg.querySelectorAll('.sight-line').forEach(el => el.remove()); + // } + // }); point.addEventListener('click', e => { let sl = svg.querySelector('.sight-line'); @@ -477,7 +494,7 @@ function linedraw(x1, y1, x2, y2) { for (let i = 0; i <= n; i++) { let 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) + { x, y } = axial_to_evenr(round.q, round.r); results.push([x, y]); } @@ -485,22 +502,22 @@ function linedraw(x1, y1, x2, y2) { return results; } -map.addEventListener('mousemove', e => { - let boundingRect = e.target.getBoundingClientRect(); - let pointerX = e.clientX - boundingRect.left; - let pointerY = e.clientY - boundingRect.top; - let [maxXpx, maxYpx] = [e.target.width, e.target.height].map(v => v.baseVal.value); - - let activeFiringArc = document.querySelector('polygon.firing-arc.active'); +function positionFiringArc(e) { + activeFiringArc = document.querySelector('polygon.firing-arc.active'); // TODO: handle exactly horizontal and vertical lines if (activeFiringArc) { - let {x: x1px, y: y1px} = activeFiringArc.points[0]; + let board = document.getElementById('image-maps'), + { width, height } = board.getBBox(), + pt = new DOMPoint(e.clientX, e.clientY), + { x: pointerX, y: pointerY } = pt.matrixTransform(board.getScreenCTM().inverse()), + [maxXpx, maxYpx] = [width, height], + {x: x1px, y: y1px} = activeFiringArc.points[0]; let [x2px, y2px] = [ - pointerX / boundingRect.width * maxXpx, - pointerY / boundingRect.height * maxYpx + pointerX / width * maxXpx, + pointerY / height * maxYpx ]; let xDiff = x2px - x1px; @@ -595,7 +612,7 @@ map.addEventListener('mousemove', e => { activeFiringArc.setAttributeNS(null, 'points', points); } -}); +} document.querySelectorAll('.soldier-record').forEach(el => el.addEventListener('click', e => { @@ -639,15 +656,13 @@ document.querySelectorAll('.set-firing-arc').forEach(el => el.addEventListener(' if (counter) { let arcLayer = document.getElementById('firing-arcs'); - let firingArcPlacementListener = e => { - document.querySelectorAll('.firing-arc.active').forEach(el => el.classList.remove('active')); - document.querySelector('#point').style.display = ''; - map.removeEventListener('click', firingArcPlacementListener); - }; - - map.addEventListener('click', firingArcPlacementListener); + let grid = document.getElementById('grid'); + const transform = getComputedStyle(grid).transform.match(/-?\d+\.?\d*/g); + const pt = new DOMPoint(counter.cx.baseVal.value, counter.cy.baseVal.value); + const mtx = new DOMMatrix(transform); + let tPt = pt.matrixTransform(mtx); - let pivotPoint = [counter.cx.baseVal.value, counter.cy.baseVal.value]; + let pivotPoint = [tPt.x, tPt.y]; let firingArc = document.createElementNS(svgns, 'polygon'); firingArc.classList.add('firing-arc', 'active'); @@ -656,8 +671,17 @@ document.querySelectorAll('.set-firing-arc').forEach(el => el.addEventListener(' firingArc.dataset.size = e.target.dataset.size; firingArc.setAttributeNS(null, 'points', `${pivotPoint} ${pivotPoint} ${pivotPoint}`); - arcLayer.prepend(firingArc); + arcLayer.appendChild(firingArc); + let firingArcPlacementListener = e => { + document.querySelectorAll('.firing-arc.active').forEach(el => el.classList.remove('active')); + document.querySelector('#point').style.display = ''; + firingArc.removeEventListener('click', firingArcPlacementListener); + svg.removeEventListener('mousemove', positionFiringArc); + }; + + svg.addEventListener('mousemove', positionFiringArc); + firingArc.addEventListener('click', firingArcPlacementListener); document.querySelector('#point').style.display = 'none'; } } @@ -674,30 +698,25 @@ document.querySelectorAll('.clear-firing-arcs').forEach(el => svg.addEventListener('wheel', e => { e.preventDefault(); - // const pt = svg.createSVGPoint(); - const pt = new DOMPoint(e.clientX, e.clientY); - - // pt.x = e.clientX; - // pt.y = e.clientY; - - const svgP = pt.matrixTransform(svg.getScreenCTM().inverse()); + const pt = new DOMPoint(e.clientX, e.clientY), + svgP = pt.matrixTransform(svg.getScreenCTM().inverse()); - let { x, y, width, height } = svg.viewBox.baseVal; + let { x, y, width, height } = svg.viewBox.baseVal, - let widthDelta = width * 0.25; - let heightDelta = height * 0.25; + widthDelta = width * 0.25, + heightDelta = height * 0.25, - let xChange = (svgP.x - x) / width * widthDelta; - let yChange = (svgP.y - y) / height * heightDelta; + xChange = (svgP.x - x) / width * widthDelta, + yChange = (svgP.y - y) / height * heightDelta, - let widthChange = (1 - ((svgP.x - x) / width)) * widthDelta; - let heightChange = (1 - ((svgP.y - y) / height)) * heightDelta; + widthChange = (1 - ((svgP.x - x) / width)) * widthDelta, + heightChange = (1 - ((svgP.y - y) / height)) * heightDelta, - let newX = parseInt(e.deltaY < 0 ? x + xChange : x - xChange); - let newWidth = parseInt(e.deltaY < 0 ? width - xChange - widthChange : width + xChange + widthChange); + newX = parseInt(e.deltaY < 0 ? x + xChange : x - xChange), + newWidth = parseInt(e.deltaY < 0 ? width - xChange - widthChange : width + xChange + widthChange), - let newY = parseInt(e.deltaY < 0 ? y + yChange : y - yChange); - let newHeight = parseInt(e.deltaY < 0 ? height - yChange - heightChange : height + yChange + heightChange); + newY = parseInt(e.deltaY < 0 ? y + yChange : y - yChange), + newHeight = parseInt(e.deltaY < 0 ? height - yChange - heightChange : height + yChange + heightChange); // console.log('VIEWBOX_X', 'VIEWBOX_Y', VIEWBOX_X, VIEWBOX_Y); // console.log('VIEWBOX_WIDTH', 'VIEWBOX_HEIGHT', VIEWBOX_WIDTH, VIEWBOX_HEIGHT); @@ -727,6 +746,17 @@ svg.addEventListener('wheel', e => { svg.setAttributeNS(null, 'viewBox', vb); }); +ptGrp.addEventListener('mouseout', e => { + let sl = svg.querySelector('.sight-line'); + + if (sl && sl.classList.contains('active')) { + info.querySelector('#hex-count').textContent = '-'; + info.style.display = 'none'; + ptGrp.querySelectorAll('.active').forEach(el => el.removeAttribute('class')); + svg.querySelectorAll('.sight-line').forEach(el => el.remove()); + } +}); + svg.addEventListener('pointerdown', e => { const minPanDistanceThreshold = 5; @@ -772,6 +802,30 @@ svg.addEventListener('pointerdown', e => { svg.addEventListener('pointerup', pointerUp); }); +// svg.addEventListener('pointermove', e => { +// if (e.target.classList.contains('counter')) { +// let p = svg.querySelector(`use[data-x="${e.target.dataset.x}"][data-y="${e.target.dataset.y}"]`); +// p.classList.add('hover'); +// p.dispatchEvent(new MouseEvent('mouseover')); + +// let removeHover = e => { +// p.classList.remove('hover'); +// e.target.removeEventListener('pointerout', removeHover); +// }; + +// e.target.addEventListener('pointerout', removeHover); +// } +// }); + recordSheetVisibility.addEventListener('input', e => { localStorage.setItem('recordsVisibility', recordSheetVisibility.checked); +}); + +document.querySelector('.end-move').addEventListener('click', e => { + let selectedSoldier = document.querySelector('.soldier-record.selected'); + + if (selectedSoldier) { + selectedSoldier.classList.toggle('selected'); + selectedSoldier.classList.toggle('movement-ended'); + } });
\ No newline at end of file |