index : btroops | |
Virtual board game-aid for BattleTroops, an infantry combat simulator wargame published by FASA in 1989. |
aboutsummaryrefslogtreecommitdiff |
diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/modules/game/firingArc.js | 113 |
1 files changed, 67 insertions, 46 deletions
diff --git a/src/modules/game/firingArc.js b/src/modules/game/firingArc.js index 6dfd8cb..cf484cd 100644 --- a/src/modules/game/firingArc.js +++ b/src/modules/game/firingArc.js @@ -49,7 +49,7 @@ function calculateAngle(xDiff, yDiff) { return angle; } -function edgePoint({ x: x1, y: y1 }, { x: x2, y: y2 }, { x: [minX, maxX], y: [minY, maxY] }) { +function calcEdgePt({ x: x1, y: y1 }, { x: x2, y: y2 }, { x: [minX, maxX], y: [minY, maxY] }) { const xDiff = x2 - x1, yDiff = y2 - y1, xIntercept = y => (y - y1) * xDiff / yDiff + x1, @@ -126,8 +126,8 @@ function findWhichTwoCorners(pt, bounds, ...pts) { return getCornerPts(bounds).filter(cp => cp[nonSharedValKey] === cornerVal); } -function chooseCornerPoints(aimPt, arcPt1, arcPt2, bounds) { - const cornerPoints = getCornerPts(bounds); +function selectCornerPoints(aimPt, arcPt1, arcPt2, bounds) { + const cornerPts = getCornerPts(bounds); let points; @@ -137,11 +137,11 @@ function chooseCornerPoints(aimPt, arcPt1, arcPt2, bounds) { } else if (touchOrthogonalEdges(arcPt1, arcPt2, bounds)) { if (touchSameEdge(aimPt, arcPt1) || touchSameEdge(aimPt, arcPt2)) { // 1-corner case - let cp = cornerPoints.find(cp => shareValue(cp, arcPt1) && shareValue(cp, arcPt2)); + let cp = cornerPts.find(cp => shareValue(cp, arcPt1) && shareValue(cp, arcPt2)); points = [cp]; } else { // 3-corner case - points = cornerPoints.filter(cp => !shareValue(cp, arcPt1) || !shareValue(cp, arcPt2)); + points = cornerPts.filter(cp => !shareValue(cp, arcPt1) || !shareValue(cp, arcPt2)); } } else { if (touchSameEdge(aimPt, arcPt1) || touchSameEdge(aimPt, arcPt2)) { @@ -149,7 +149,7 @@ function chooseCornerPoints(aimPt, arcPt1, arcPt2, bounds) { points = findWhichTwoCorners(aimPt, bounds, arcPt1, arcPt2); } else { // 2-corner case, aim and both arc points all touch different edges - points = cornerPoints.filter(cp => shareValue(cp, aimPt) || shareValue(cp, aimPt)); + points = cornerPts.filter(cp => shareValue(cp, aimPt) || shareValue(cp, aimPt)); } } @@ -162,8 +162,7 @@ function orderPoints(arcPoints, cornerPoints) { } const index = cornerPoints.findIndex(cp => shareValue(cp, arcPoints.at(0))); - cornerPoints.splice(index + 1, 0, ...arcPoints); - return cornerPoints; + return cornerPoints.slice(0, index + 1).concat(arcPoints).concat(cornerPoints.slice(index + 1)); } function calcArcLinePtDeltas(aimPt, pivotPt, { dataset: { size }}) { @@ -184,15 +183,15 @@ function position(e, firingArc, firingArcOutline, aimLine, grid) { pivotPt = new Point(aimLine.getAttribute('x1'), aimLine.getAttribute('y1')), bounds = getBounds(grid.getBBox()), - aimPt = edgePoint(pivotPt, pointerPt, bounds), + aimPt = calcEdgePt(pivotPt, pointerPt, bounds), { xDelta, yDelta } = calcArcLinePtDeltas(aimPt, pivotPt, firingArc), - arcPt1 = edgePoint(pivotPt, new Point(aimPt.x - xDelta, aimPt.y - yDelta), bounds), - arcPt2 = edgePoint(pivotPt, new Point(aimPt.x + xDelta, aimPt.y + yDelta), bounds), + arcPt1 = calcEdgePt(pivotPt, new Point(aimPt.x - xDelta, aimPt.y - yDelta), bounds), + arcPt2 = calcEdgePt(pivotPt, new Point(aimPt.x + xDelta, aimPt.y + yDelta), bounds), outlinePoints = [arcPt2, pivotPt, arcPt1], - cps = chooseCornerPoints(aimPt, arcPt1, arcPt2, bounds), - arcPoints = orderPoints(outlinePoints, cps); + cornerPoints = selectCornerPoints(aimPt, arcPt1, arcPt2, bounds), + arcPoints = orderPoints(outlinePoints, cornerPoints); aimLine.setAttributeNS(null, 'x2', aimPt.x); aimLine.setAttributeNS(null, 'y2', aimPt.y); @@ -211,61 +210,83 @@ function getClipPathId({ dataset: { allegiance, number }}) { } function getUnclipped() { - return svg.querySelectorAll('#firing-arcs :not([clip-path])'); + return svg.querySelectorAll('#firing-arcs #shapes polygon:not([clip-path]), #firing-arcs #lines polyline:not([clip-path])'); }; +function createAimLine(x, y, container) { + const aimLine = document.createElementNS(svgns, 'line'); + aimLine.setAttributeNS(null, 'x1', x); + aimLine.setAttributeNS(null, 'y1', y); + aimLine.setAttributeNS(null, 'x2', x); + aimLine.setAttributeNS(null, 'y2', y); + container.appendChild(aimLine); + + return aimLine; +} + +function createClipPath(x, y, id, container) { + const clipShape = document.createElementNS(svgns, 'circle'); + clipShape.setAttributeNS(null, 'cx', x); + clipShape.setAttributeNS(null, 'cy', y); + clipShape.setAttributeNS(null, 'r', clippedFiringArcRadius); + + const clipPath = document.createElementNS(svgns, 'clipPath'); + clipPath.setAttributeNS(null, 'id', id); + clipPath.appendChild(clipShape); + + container.appendChild(clipPath); + + return clipPath; +} + +function createFiringArc(x, y, size, container) { + const firingArc = document.createElementNS(svgns, 'polygon'); + firingArc.setAttributeNS(null, 'points', `${x},${y}`); + firingArc.dataset.size = size; + firingArc.classList.add('firing-arc', 'active'); + container.appendChild(firingArc); + + return firingArc; +} + +function createFiringArcOutline(x, y, container) { + const firingArcOutline = document.createElementNS(svgns, 'polyline'); + firingArcOutline.setAttributeNS(null, 'points', `${x},${y}`); + container.appendChild(firingArcOutline); + + return firingArcOutline; +} + export default function (el) { svg = el; this.set = function (size, counter, { x, y }) { this.get(counter).forEach(fa => fa.remove()); - let arcLayer = svg.querySelector('#shapes'); - let outlineLayer = svg.querySelector('#lines'); - let arcContainer = svg.querySelector('#firing-arcs'); - let grid = svg.querySelector('.grid'); + const grid = svg.querySelector('.grid'), + arcContainer = svg.querySelector('#firing-arcs'), + arcLayer = arcContainer.querySelector('#shapes'), + outlineLayer = arcContainer.querySelector('#lines'), - let aimLine = document.createElementNS(svgns, 'line'); - aimLine.setAttributeNS(null, 'x1', x); - aimLine.setAttributeNS(null, 'y1', y); - aimLine.setAttributeNS(null, 'x2', x); - aimLine.setAttributeNS(null, 'y2', y); - outlineLayer.appendChild(aimLine); + aimLine = createAimLine(x, y, outlineLayer), + firingArc = createFiringArc(x, y, size, arcLayer), + firingArcOutline = createFiringArcOutline(x, y, outlineLayer), + clipPath = createClipPath(x, y, getClipPathId(counter), arcContainer); - let firingArc = document.createElementNS(svgns, 'polygon'); setDataAttrs(counter, firingArc); - firingArc.setAttributeNS(null, 'points', `${x},${y}`); - firingArc.dataset.size = size; - firingArc.classList.add('firing-arc', 'active'); - - let firingArcOutline = document.createElementNS(svgns, 'polyline'); setDataAttrs(counter, firingArcOutline); - firingArcOutline.setAttributeNS(null, 'points', `${x},${y}`); - - let clipShape = document.createElementNS(svgns, 'circle'); - clipShape.setAttributeNS(null, 'cx', x); - clipShape.setAttributeNS(null, 'cy', y); - clipShape.setAttributeNS(null, 'r', clippedFiringArcRadius); - - let clipPath = document.createElementNS(svgns, 'clipPath'); setDataAttrs(counter, clipPath); - clipPath.setAttributeNS(null, 'id', getClipPathId(counter)); - clipPath.appendChild(clipShape); - - arcContainer.appendChild(clipPath); - arcLayer.appendChild(firingArc); - outlineLayer.appendChild(firingArcOutline); function positionListener(e) { position(e, firingArc, firingArcOutline, aimLine, grid); } - let placementListener = e => { + function placementListener() { grid.removeAttribute('style'); aimLine.remove(); svg.querySelectorAll('.firing-arc.active').forEach(el => el.classList.remove('active')); svg.removeEventListener('mousemove', positionListener); - }; + } let cancelPlacementListener = e => { e.preventDefault(); |