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/modules/game/counter.js')
-rw-r--r-- | src/modules/game/counter.js | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/src/modules/game/counter.js b/src/modules/game/counter.js new file mode 100644 index 0000000..69552d8 --- /dev/null +++ b/src/modules/game/counter.js @@ -0,0 +1,148 @@ +const svgns = "http://www.w3.org/2000/svg"; + +export default class Counter { + constructor(svg) { + this.svg = svg; + this.selectedClass = 'selected'; + } + + dataSelector({ dataset: { allegiance, number }}) { + return `[data-number="${number}"][data-allegiance="${allegiance}"]`; + } + + position(x, y) { + return `g[data-x="${x}"][data-y="${y}"]`; + } + + counterPosition(x, y) { + return `.counter[data-x="${x}"][data-x="${y}"]`; + } + + traceSelector(counter) { + return `polyline.move-trace${this.dataSelector(counter)}`; + } + + getClones(counter) { + return this.svg.querySelectorAll(`.counter.clone${this.dataSelector(counter)}`); + } + + getCounter(selected) { + return this.svg.querySelector(`.counter${this.dataSelector(selected)}:not(.clone)`); + } + + getCounterAndClones(counter) { + return this.svg.querySelectorAll(`.counter${this.dataSelector(counter)}`); + } + + getTrace(counter) { + return this.svg.querySelector(this.traceSelector(counter)); + } + + getCellPosition(cell) { + let pt = new DOMPoint(0, 0), + transform = getComputedStyle(cell).transform.match(/-?\d+\.?\d*/g), + mtx = new DOMMatrix(transform); + pt = pt.matrixTransform(mtx); + + transform = getComputedStyle(cell.parentElement).transform.match(/-?\d+\.?\d*/g); + mtx = new DOMMatrix(transform); + pt = pt.matrixTransform(mtx); + + return pt; + } + + getBoard() { + return this.svg.querySelector('.board'); + } + + place(selected, cell) { + let points, + counterNodeList = this.getCounterAndClones(selected); + + if (counterNodeList.length > 0 && selected.parentElement.hasAttribute('data-x')) { + let trace = this.svg.querySelector(this.traceSelector(selected)); + + let prevCoords = [ + selected.parentElement.dataset.x, + selected.parentElement.parentElement.dataset.y + ] + + let clone = selected.cloneNode(true); + clone.classList.remove(this.selectedClass); + clone.classList.add('clone'); + + selected.dataset.previous = prevCoords; + selected.parentElement.appendChild(clone); + cell.appendChild(selected); + + selected.childNodes.forEach(n => { + if (n.classList.contains('removed')) { + n.remove(); + } else if ('preexisting' in n.dataset) { + delete n.dataset.preexisting; + } + }); + + let previous = this.getCellPosition(clone.parentElement), + current = this.getCellPosition(selected.parentElement); + + if (!trace) { + trace = document.createElementNS(svgns, 'polyline'); + + points = `${previous.x},${previous.y} ${current.x},${current.y}`; + + trace.dataset.number = selected.dataset.number; + trace.dataset.allegiance = selected.dataset.allegiance; + trace.classList.add('move-trace'); + + this.getBoard().prepend(trace); + } else { + points = `${trace.getAttribute('points')} ${current.x},${current.y}`; + } + + trace.setAttributeNS(null, 'points', points); + } else { + selected.removeAttribute('data-x'); + cell.appendChild(selected); + } + } + + removeClones(counter) { + this.getClones(counter).forEach(c => c.remove()); + } + + endMove(counter) { + const trace = this.svg.querySelector(this.traceSelector(counter)), + proneCounter = counter.querySelector('[href="#counter-prone"]'); + + if (trace) { + trace.remove(); + } + + delete counter.dataset.previous; + + if (proneCounter) { + proneCounter.dataset.preexisting = ''; + } + + this.removeClones(counter); + } + + hasProne(counter) { + return !!counter.querySelector('[href="#counter-prone"]'); + } + + toggleProne(counter) { + let proneCounter = counter.querySelector('[href="#counter-prone"]'); + + if (!proneCounter) { + proneCounter = document.createElementNS(svgns, 'use'); + proneCounter.setAttributeNS(null, 'href', '#counter-prone'); + counter.appendChild(proneCounter); + } else if ('preexisting' in proneCounter.dataset) { + proneCounter.classList.toggle('removed'); + } else { + proneCounter.remove(); + } + } +} |