index : btroops | |
Virtual board game-aid for BattleTroops, an infantry combat simulator wargame published by FASA in 1989. |
aboutsummaryrefslogtreecommitdiff |
diff options
Diffstat (limited to 'index.js')
-rw-r--r-- | index.js | 158 |
1 files changed, 83 insertions, 75 deletions
@@ -1,6 +1,6 @@ -var isEven = n => n % 2 === 0; -var toFixed = n => Number.parseFloat(n).toFixed(2); -var radToDeg = radians => radians * 180 / Math.PI; +let isEven = n => n % 2 === 0; +let toFixed = n => Number.parseFloat(n).toFixed(2); +let radToDeg = radians => radians * 180 / Math.PI; let getPointCoords = (x, y) => { let point = document.querySelector(`[data-x="${x}"][data-y="${y}"]`); @@ -8,23 +8,77 @@ let getPointCoords = (x, y) => { return [point.x.baseVal.value, point.y.baseVal.value] }; -var svgns = "http://www.w3.org/2000/svg", +let svgns = "http://www.w3.org/2000/svg", svg = document.querySelector('svg'), rect = document.querySelector('rect#map'); -var columnCount = 33, +let columnCount = 33, rowCount = 25, pointDistanceInInches = 1.005; -var columns = [...Array(columnCount).keys()], +let columns = [...Array(columnCount).keys()], rows = [...Array(rowCount).keys()], points = rows.map(y => columns.map(x => [x, y])); -var xOffset = 0.25, +let xOffset = 0.25, yOffset = 0.45; calcY = Math.sqrt(3) * pointDistanceInInches / 2, alternatingOffset = pointDistanceInInches / 2; +let firingArcSize = { + 'small': Math.atan(pointDistanceInInches / (6 * calcY)), + 'medium': Math.atan((pointDistanceInInches / 2) / calcY), + 'large': Math.atan((21 * pointDistanceInInches) / (6 * calcY)) +} + +function edgePoint(x1, y1, x2, y2, maxX, maxY) { + let pointCoords, + xDiff = x2 - x1, + yDiff = y2 - y1, + xIntercept = y => (y - y1) * (xDiff) / (yDiff) + x1, + yIntercept = x => (x - x1) * (yDiff) / (xDiff) + y1; + + if (xDiff > 0 && yDiff > 0) { + let yWhenXisMax = yIntercept(maxX); + let xWhenYisMax = xIntercept(maxY); + + if (xWhenYisMax <= maxX) { + pointCoords = [xWhenYisMax, maxY]; + } else { + pointCoords = [maxX, yWhenXisMax]; + } + } else if (xDiff > 0 && yDiff < 0) { + let yWhenXisMax = yIntercept(maxX); + let xWhenYisZero = xIntercept(0); + + if (xWhenYisZero <= maxX) { + pointCoords = [xWhenYisZero, 0]; + } else { + pointCoords = [maxX, yWhenXisMax]; + } + } else if (xDiff < 0 && yDiff < 0) { + let yWhenXisZero = yIntercept(0); + let xWhenYisZero = xIntercept(0); + + if (yWhenXisZero >= 0) { + pointCoords = [0, yWhenXisZero]; + } else { + pointCoords = [xWhenYisZero, 0]; + } + } else { + let yWhenXisZero = yIntercept(0); + let xWhenYisMax = xIntercept(maxY); + + if (yWhenXisZero <= maxY) { + pointCoords = [0, yWhenXisZero]; + } else { + pointCoords = [xWhenYisMax, maxY]; + } + } + + return pointCoords; +} + rect.addEventListener('mousemove', e => { var rect = e.target.getBoundingClientRect(); var x = e.clientX - rect.left; @@ -34,16 +88,14 @@ rect.addEventListener('mousemove', e => { // console.log('x', `${toFixed(x / rect.width * maxX)}"`, 'y', `${toFixed(y / rect.height * maxY)}"`); - let aim = document.querySelector('.firing-arc.active'); + let aim = document.querySelector('line.firing-arc.active'); let p = document.querySelector('polyline.firing-arc.active'); // TODO: handle horizontal and vertical lines - if (aim || p) { + if (aim && p) { let xIntercept = y => (y - y1) * (x2 - x1) / (y2 - y1) + x1; let yIntercept = x => (x - x1) * (y2 - y1) / (x2 - x1) + y1; - let xInterceptPx = y => (y - y1px) * (x2px - x1px) / (y2px - y1px) + x1px; - let yInterceptPx = x => (x - x1px) * (y2px - y1px) / (x2px - x1px) + y1px; let newX, newY; let [x1, y1] = [aim.x1, aim.y1].map(v => v.baseVal.valueInSpecifiedUnits); @@ -52,52 +104,6 @@ rect.addEventListener('mousemove', e => { let {x: x1px, y: y1px} = p.points[1]; let [x2px, y2px] = [x / rect.width * maxXpx, y / rect.height * maxYpx]; - if (x2px - x1px > 0 && y2px - y1px > 0) { - let yWhenXisMax = yInterceptPx(maxXpx); - let xWhenYisMax = xInterceptPx(maxYpx); - - if (xWhenYisMax <= maxXpx) { - newX = xWhenYisMax; - newY = maxYpx; - } else { - newX = maxXpx; - newY = yWhenXisMax; - } - } else if (x2px - x1px > 0 && y2px - y1px < 0) { - let yWhenXisMax = yInterceptPx(maxXpx); - let xWhenYisZero = xInterceptPx(0); - - if (xWhenYisZero <= maxXpx) { - newX = xWhenYisZero; - newY = 0; - } else { - newX = maxXpx; - newY = yWhenXisMax; - } - } else if (x2px - x1px < 0 && y2px - y1px < 0) { - let yWhenXisZero = yInterceptPx(0); - let xWhenYisZero = xInterceptPx(0); - - if (yWhenXisZero >= 0) { - newX = 0; - newY = yWhenXisZero; - } else { - newX = xWhenYisZero; - newY = 0; - } - } else { - let yWhenXisZero = yInterceptPx(0); - let xWhenYisMax = xInterceptPx(maxYpx); - - if (yWhenXisZero <= maxYpx) { - newX = 0; - newY = yWhenXisZero; - } else { - newX = xWhenYisMax; - newY = maxYpx; - } - } - let width = x2px - x1px; let height = -(y2px - y1px); let angle = Math.abs(Math.atan(height / width)); @@ -113,28 +119,26 @@ rect.addEventListener('mousemove', e => { angle = 2 * Math.PI - angle; } - console.log('angle', angle, 'degrees', radToDeg(angle)); - - let smlArcAngle = Math.atan(pointDistanceInInches / (6 * calcY)); - let medArcAngle = Math.atan((pointDistanceInInches / 2) / calcY); - let lrgArcAngle = Math.atan((21 * pointDistanceInInches) / (6 * calcY)); - - let arcAngle = lrgArcAngle; + console.log('angle:', `${toFixed(radToDeg(angle))}\u00B0`, `${angle}rad`); + let arcAngle = firingArcSize[p.dataset.size]; let distance = Math.sqrt((x2px - x1px)**2 + (y2px - y1px)**2); + let yDelta = distance * Math.cos(angle) * Math.tan(arcAngle); + let xDelta = distance * Math.sin(angle) * Math.tan(arcAngle); + + let newY1 = y2px + yDelta; + let newX1 = x2px + xDelta; - let newY1 = y2px + (distance * Math.cos(angle)) * Math.tan(arcAngle); - let newY2 = y2px - (distance * Math.cos(angle)) * Math.tan(arcAngle); + let newY2 = y2px - yDelta; + let newX2 = x2px - xDelta; - let newX1 = x2px + (distance * Math.sin(angle)) * Math.tan(arcAngle); - let newX2 = x2px - (distance * Math.sin(angle)) * Math.tan(arcAngle); + [newX1, newY1] = edgePoint(x1px, y1px, newX1, newY1, maxXpx, maxYpx); + [newX2, newY2] = edgePoint(x1px, y1px, newX2, newY2, maxXpx, maxYpx); // p.setAttributeNS(null, 'points', `${newX},${newY} ${x1px},${y1px} ${newX},${newY}`); // p.setAttributeNS(null, 'points', `${x2px},${y2px} ${x1px},${y1px} ${x2px},${y2px}`); p.setAttributeNS(null, 'points', `${newX1},${newY1} ${x1px},${y1px} ${newX2},${newY2}`); - // console.log(p); - if (x2 - x1 > 0 && y2 - y1 > 0) { let yWhenXisMax = yIntercept(maxX); let xWhenYisMax = xIntercept(maxY); @@ -217,17 +221,19 @@ document.querySelectorAll('.soldier-record').forEach(el => }) ); -document.querySelector('#set-firing-arc').addEventListener('click', e => { +document.querySelectorAll('.set-firing-arc').forEach(el => el.addEventListener('click', e => { let selectedSoldier = document.querySelector('.soldier-record.selected'); if (selectedSoldier) { let {troopNumber, troopAllegiance} = selectedSoldier.dataset; - let existingArc = document.querySelector( + let existingArcs = document.querySelectorAll( `.firing-arc[data-troop-number="${troopNumber}"][data-troop-allegiance="${troopAllegiance}"]` ); - if (existingArc) { existingArc.remove() } + if (existingArcs.length > 0) { + existingArcs.forEach(el => el.remove()); + } let counter = document.querySelector( `circle.counter[data-troop-number="${troopNumber}"][data-troop-allegiance="${troopAllegiance}"]` @@ -238,6 +244,7 @@ document.querySelector('#set-firing-arc').addEventListener('click', e => { aim.classList.add('firing-arc', 'active'); aim.dataset.troopNumber = troopNumber; aim.dataset.troopAllegiance = troopAllegiance; + aim.dataset.size = e.target.dataset.size; aim.setAttributeNS(null, 'x1', counter.cx.baseVal.valueAsString); aim.setAttributeNS(null, 'y1', counter.cy.baseVal.valueAsString); aim.setAttributeNS(null, 'x2', counter.cx.baseVal.valueAsString); @@ -256,13 +263,14 @@ document.querySelector('#set-firing-arc').addEventListener('click', e => { firingArc.classList.add('firing-arc', 'active'); firingArc.dataset.troopNumber = troopNumber; firingArc.dataset.troopAllegiance = troopAllegiance; + firingArc.dataset.size = e.target.dataset.size; firingArc.setAttributeNS(null, 'points', `${pivotPoint} ${pivotPoint} ${pivotPoint}`); svg.appendChild(firingArc); document.querySelector('circle#point').style.display = 'none'; } -}); +})); points.forEach((row, index) => row.forEach(([x, y]) => { var cx = x * pointDistanceInInches + xOffset + (isEven(index) ? alternatingOffset : 0), @@ -310,7 +318,7 @@ points.forEach((row, index) => row.forEach(([x, y]) => { })); let smlArc = document.createElementNS(svgns, 'polygon'); -smlArc.setAttributeNS(null, 'id', 'small-arc'); +smlArc.setAttributeNS(null, 'id', 'sml-arc'); let smlArcPoints = `${getPointCoords(1, 24)} ${getPointCoords(1, 21)} ${getPointCoords(2, 21)}`; smlArc.setAttributeNS(null, 'points', smlArcPoints); |