Add ability to change maps
This commit is contained in:
parent
3e513c5684
commit
b980544203
@ -104,7 +104,7 @@
|
|||||||
Loading...
|
Loading...
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<object type="image/svg+xml" data="map.svg"></object>
|
<object type="image/svg+xml" data="map1.svg"></object>
|
||||||
|
|
||||||
<div id="status">
|
<div id="status">
|
||||||
<span id="hex-counter">Distance: <span id="hex-count">-</span></span>
|
<span id="hex-counter">Distance: <span id="hex-count">-</span></span>
|
||||||
@ -134,6 +134,25 @@
|
|||||||
<span class="inning-top">◓</span>
|
<span class="inning-top">◓</span>
|
||||||
<span class="inning-bottom">◒</span>
|
<span class="inning-bottom">◒</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
<dialog id="map-dialog">
|
||||||
|
<form>
|
||||||
|
<p>
|
||||||
|
<label>
|
||||||
|
Map:
|
||||||
|
<select>
|
||||||
|
<option value="map1">Map1</option>
|
||||||
|
<option value="map2">Map2</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<button value="cancel" formmethod="dialog">Cancel</button>
|
||||||
|
<button id="confirm-btn" value="default">Confirm</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</dialog>
|
||||||
|
<button id="show-dialog">Change map</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="record-sheet">
|
<div id="record-sheet">
|
||||||
|
@ -203,11 +203,11 @@ g.selected use {
|
|||||||
transform: translate(19px, 31px) scale(4);
|
transform: translate(19px, 31px) scale(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
g.start-locations > g:first-child {
|
g.start-locations > g:first-child:not([data-y]) {
|
||||||
--i: -2;
|
--i: -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
g.start-locations > g:last-child {
|
g.start-locations > g:last-child:not([data-y]) {
|
||||||
--i: 52;
|
--i: 52;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,6 +249,7 @@ g[data-y]:nth-child(odd) {
|
|||||||
transform: translateX(calc(var(--x-step) * var(--i))) scale(var(--scale));
|
transform: translateX(calc(var(--x-step) * var(--i))) scale(var(--scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g[data-y="-2"] { --i: -2; }
|
||||||
g[data-y="0"] { --i: 0; }
|
g[data-y="0"] { --i: 0; }
|
||||||
g[data-y="1"] { --i: 1; }
|
g[data-y="1"] { --i: 1; }
|
||||||
g[data-y="2"] { --i: 2; }
|
g[data-y="2"] { --i: 2; }
|
||||||
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 81 KiB |
84
public/map2.svg
Normal file
84
public/map2.svg
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||||
|
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg viewBox="-25 -150 400 570" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="map.css" type="text/css"/>
|
||||||
|
<defs>
|
||||||
|
<polygon id="hex" points="0,10 8.66,5 8.66,-5 0,-10 -8.66,-5 -8.66,5"/>
|
||||||
|
|
||||||
|
<circle id="counter-base" cx="0" cy="0" r="5"/>
|
||||||
|
|
||||||
|
<g id="t-1" class="troop-counter-template"><use href="#counter-base"/><text>1</text></g>
|
||||||
|
<g id="t-2" class="troop-counter-template"><use href="#counter-base"/><text>2</text></g>
|
||||||
|
<g id="t-3" class="troop-counter-template"><use href="#counter-base"/><text>3</text></g>
|
||||||
|
<g id="t-4" class="troop-counter-template"><use href="#counter-base"/><text>4</text></g>
|
||||||
|
<g id="t-5" class="troop-counter-template"><use href="#counter-base"/><text>5</text></g>
|
||||||
|
<g id="t-6" class="troop-counter-template"><use href="#counter-base"/><text>6</text></g>
|
||||||
|
<g id="t-7" class="troop-counter-template"><use href="#counter-base"/><text>7</text></g>
|
||||||
|
|
||||||
|
<image id="counter-prone" href="counter_prone.jpg" width="10"/>
|
||||||
|
<image id="counter-grenade" href="counter_grenade.jpg" width="10"/>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<rect id="background" x="-18" y="-10" width="386" height="322"/>
|
||||||
|
|
||||||
|
<g class="board">
|
||||||
|
<g id="firing-arcs">
|
||||||
|
<g id="shapes"/>
|
||||||
|
<g id="lines"/>
|
||||||
|
</g>
|
||||||
|
<g class="start-locations">
|
||||||
|
<g data-y="-2">
|
||||||
|
<g data-x="4" class="counter" data-allegiance="liao" data-number="1"><use href="#t-1"/></g>
|
||||||
|
<g data-x="3" class="counter" data-allegiance="liao" data-number="2"><use href="#t-2"/></g>
|
||||||
|
<g data-x="2" class="counter" data-allegiance="liao" data-number="3"><use href="#t-3"/></g>
|
||||||
|
<g data-x="1" class="counter" data-allegiance="liao" data-number="4"><use href="#t-4"/></g>
|
||||||
|
<g data-x="0" class="counter" data-allegiance="liao" data-number="5"><use href="#t-5"/></g>
|
||||||
|
</g>
|
||||||
|
<g data-y="6">
|
||||||
|
<g data-x="0" class="counter" data-allegiance="davion" data-number="1"><use href="#t-1"/></g>
|
||||||
|
<g data-x="1" class="counter" data-allegiance="davion" data-number="2"><use href="#t-2"/></g>
|
||||||
|
<g data-x="2" class="counter" data-allegiance="davion" data-number="3"><use href="#t-3"/></g>
|
||||||
|
<g data-x="3" class="counter" data-allegiance="davion" data-number="4"><use href="#t-4"/></g>
|
||||||
|
<g data-x="4" class="counter" data-allegiance="davion" data-number="5"><use href="#t-5"/></g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g class="grid">
|
||||||
|
<g data-y="0">
|
||||||
|
<g data-x="0"><use href="#hex"/></g>
|
||||||
|
<g data-x="1"><use href="#hex"/></g>
|
||||||
|
<g data-x="2"><use href="#hex"/></g>
|
||||||
|
<g data-x="3"><use href="#hex"/></g>
|
||||||
|
<g data-x="4"><use href="#hex"/></g>
|
||||||
|
</g>
|
||||||
|
<g data-y="1">
|
||||||
|
<g data-x="0"><use href="#hex"/></g>
|
||||||
|
<g data-x="1"><use href="#hex"/></g>
|
||||||
|
<g data-x="2"><use href="#hex"/></g>
|
||||||
|
<g data-x="3"><use href="#hex"/></g>
|
||||||
|
<g data-x="4"><use href="#hex"/></g>
|
||||||
|
</g>
|
||||||
|
<g data-y="2">
|
||||||
|
<g data-x="0"><use href="#hex"/></g>
|
||||||
|
<g data-x="1"><use href="#hex"/></g>
|
||||||
|
<g data-x="2"><use href="#hex"/></g>
|
||||||
|
<g data-x="3"><use href="#hex"/></g>
|
||||||
|
<g data-x="4"><use href="#hex"/></g>
|
||||||
|
</g>
|
||||||
|
<g data-y="3">
|
||||||
|
<g data-x="0"><use href="#hex"/></g>
|
||||||
|
<g data-x="1"><use href="#hex"/></g>
|
||||||
|
<g data-x="2"><use href="#hex"/></g>
|
||||||
|
<g data-x="3"><use href="#hex"/></g>
|
||||||
|
<g data-x="4"><use href="#hex"/></g>
|
||||||
|
</g>
|
||||||
|
<g data-y="4">
|
||||||
|
<g data-x="0"><use href="#hex"/></g>
|
||||||
|
<g data-x="1"><use href="#hex"/></g>
|
||||||
|
<g data-x="2"><use href="#hex"/></g>
|
||||||
|
<g data-x="3"><use href="#hex"/></g>
|
||||||
|
<g data-x="4"><use href="#hex"/></g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.8 KiB |
173
src/index.js
173
src/index.js
@ -6,13 +6,89 @@ globalThis.svgns = "http://www.w3.org/2000/svg";
|
|||||||
|
|
||||||
const mapPlaceholder = document.querySelector('.map-placeholder'),
|
const mapPlaceholder = document.querySelector('.map-placeholder'),
|
||||||
distanceOutput = document.getElementById('status'),
|
distanceOutput = document.getElementById('status'),
|
||||||
proneToggle = document.getElementById('toggle-prone-counter');
|
proneToggle = document.getElementById('toggle-prone-counter'),
|
||||||
|
object = document.querySelector('object');
|
||||||
|
|
||||||
document.querySelector('object').addEventListener('load', function () {
|
object.addEventListener('load', function () {
|
||||||
mapPlaceholder.remove();
|
mapPlaceholder.remove();
|
||||||
this.style.opacity = 1;
|
this.style.opacity = 1;
|
||||||
|
|
||||||
|
const svg = this.contentDocument.querySelector('svg');
|
||||||
|
panzoom.start(svg);
|
||||||
|
gameboard.start(svg);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
gameboard.setDistanceCallback((count = '-') => {
|
||||||
|
distanceOutput.querySelector('#hex-count').textContent = count;
|
||||||
|
distanceOutput.style.display = count === '-' ? 'none' : 'block';
|
||||||
|
});
|
||||||
|
|
||||||
|
gameboard.setProneFlagCallback(checked => proneToggle.checked = checked);
|
||||||
|
gameboard.setSelectCallback(data => recordSheet.select(data));
|
||||||
|
|
||||||
|
document.querySelectorAll('.soldier-record').forEach(el =>
|
||||||
|
el.addEventListener('click', () => {
|
||||||
|
if (el.classList.contains('selected')) {
|
||||||
|
el.classList.remove('selected');
|
||||||
|
gameboard.unSelect();
|
||||||
|
recordSheet.unSelect();
|
||||||
|
} else {
|
||||||
|
gameboard.select(el);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
document.querySelectorAll('.end-move').forEach(el => el.addEventListener('click', () => {
|
||||||
|
recordSheet.endMove();
|
||||||
|
gameboard.endMove();
|
||||||
|
}));
|
||||||
|
|
||||||
|
document.querySelectorAll('.end-turn').forEach(el =>
|
||||||
|
el.addEventListener('click', ({ target: { dataset: { allegiance }}}) => {
|
||||||
|
const dataSelector = `[data-allegiance="${allegiance}"]`,
|
||||||
|
records = Array.from(document.querySelectorAll(`.soldier-record${dataSelector}`)),
|
||||||
|
turnCounter = document.getElementById('turn-count'),
|
||||||
|
{ dataset: { update }} = turnCounter;
|
||||||
|
|
||||||
|
el.setAttribute('disabled', '');
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelector(`button.end-turn:not([data-allegiance="${allegiance}"])`)
|
||||||
|
.removeAttribute('disabled');
|
||||||
|
|
||||||
|
if (update === '1') {
|
||||||
|
turnCounter.children.namedItem('count').textContent++
|
||||||
|
turnCounter.dataset.update = '0';
|
||||||
|
} else {
|
||||||
|
turnCounter.dataset.update = '1';
|
||||||
|
}
|
||||||
|
|
||||||
|
records
|
||||||
|
.sort((el1, el2) => el1.dataset.number > el2.dataset.number)
|
||||||
|
.forEach(el => el.classList.remove('movement-ended'));
|
||||||
|
|
||||||
|
gameboard.endTurn(allegiance);
|
||||||
|
gameboard.select(records.at(0));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
document.querySelectorAll('.set-firing-arc').forEach(el =>
|
||||||
|
el.addEventListener('click', gameboard.setFiringArc)
|
||||||
|
);
|
||||||
|
|
||||||
|
document.querySelector('.set-grenade').addEventListener('click', gameboard.setGrenade);
|
||||||
|
|
||||||
|
document.querySelectorAll('#toggle-firing-arc-vis input').forEach(el =>
|
||||||
|
el.addEventListener('input', gameboard.toggleFiringArcVisibility)
|
||||||
|
);
|
||||||
|
|
||||||
|
document.getElementById('toggle-prone-counter').addEventListener('input', function () {
|
||||||
|
const selected = recordSheet.getSelected();
|
||||||
|
selected && gameboard.toggleProne();
|
||||||
|
});
|
||||||
|
|
||||||
|
object.data = `${localStorage.getItem('map') || 'map1'}.svg`;
|
||||||
|
|
||||||
document
|
document
|
||||||
.querySelector('#content input[type="checkbox"].visible')
|
.querySelector('#content input[type="checkbox"].visible')
|
||||||
.addEventListener('input', function () {
|
.addEventListener('input', function () {
|
||||||
@ -27,78 +103,27 @@ document
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener('load', () => {
|
const showButton = document.getElementById('show-dialog'),
|
||||||
const svg = document.querySelector('object').contentDocument.querySelector('svg');
|
mapDialog = document.getElementById('map-dialog'),
|
||||||
|
selectEl = mapDialog.querySelector('select'),
|
||||||
|
confirmBtn = mapDialog.querySelector('#confirm-btn');
|
||||||
|
|
||||||
gameboard.start(svg);
|
mapDialog.querySelectorAll('option').forEach(option =>
|
||||||
panzoom.start(svg);
|
option.value === localStorage.getItem('map') && (option.selected = true)
|
||||||
|
);
|
||||||
|
|
||||||
gameboard.setDistanceCallback((count = '-') => {
|
showButton.addEventListener('click', () => {
|
||||||
distanceOutput.querySelector('#hex-count').textContent = count;
|
mapDialog.showModal();
|
||||||
distanceOutput.style.display = count === '-' ? 'none' : 'block';
|
});
|
||||||
});
|
|
||||||
|
selectEl.addEventListener('change', () => {
|
||||||
gameboard.setProneFlagCallback(checked => proneToggle.checked = checked);
|
confirmBtn.value = selectEl.value;
|
||||||
gameboard.setSelectCallback(data => recordSheet.select(data));
|
});
|
||||||
|
|
||||||
document.querySelectorAll('.soldier-record').forEach(el =>
|
confirmBtn.addEventListener('click', e => {
|
||||||
el.addEventListener('click', () => {
|
e.preventDefault();
|
||||||
if (el.classList.contains('selected')) {
|
localStorage.removeItem('pan-zoom');
|
||||||
el.classList.remove('selected');
|
localStorage.setItem('map', selectEl.value);
|
||||||
gameboard.unSelect();
|
document.querySelector('object').data = `${selectEl.value}.svg`;
|
||||||
recordSheet.unSelect();
|
mapDialog.close();
|
||||||
} else {
|
|
||||||
gameboard.select(el);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
document.querySelectorAll('.end-move').forEach(el => el.addEventListener('click', () => {
|
|
||||||
recordSheet.endMove();
|
|
||||||
gameboard.endMove();
|
|
||||||
}));
|
|
||||||
|
|
||||||
document.querySelectorAll('.end-turn').forEach(el =>
|
|
||||||
el.addEventListener('click', ({ target: { dataset: { allegiance }}}) => {
|
|
||||||
const dataSelector = `[data-allegiance="${allegiance}"]`,
|
|
||||||
records = Array.from(document.querySelectorAll(`.soldier-record${dataSelector}`)),
|
|
||||||
turnCounter = document.getElementById('turn-count'),
|
|
||||||
{ dataset: { update }} = turnCounter;
|
|
||||||
|
|
||||||
el.setAttribute('disabled', '');
|
|
||||||
|
|
||||||
document
|
|
||||||
.querySelector(`button.end-turn:not([data-allegiance="${allegiance}"])`)
|
|
||||||
.removeAttribute('disabled');
|
|
||||||
|
|
||||||
if (update === '1') {
|
|
||||||
turnCounter.children.namedItem('count').textContent++
|
|
||||||
turnCounter.dataset.update = '0';
|
|
||||||
} else {
|
|
||||||
turnCounter.dataset.update = '1';
|
|
||||||
}
|
|
||||||
|
|
||||||
records
|
|
||||||
.sort((el1, el2) => el1.dataset.number > el2.dataset.number)
|
|
||||||
.forEach(el => el.classList.remove('movement-ended'));
|
|
||||||
|
|
||||||
gameboard.endTurn(allegiance);
|
|
||||||
gameboard.select(records.at(0));
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
document.querySelectorAll('.set-firing-arc').forEach(el =>
|
|
||||||
el.addEventListener('click', gameboard.setFiringArc)
|
|
||||||
);
|
|
||||||
|
|
||||||
document.querySelector('.set-grenade').addEventListener('click', gameboard.setGrenade);
|
|
||||||
|
|
||||||
document.querySelectorAll('#toggle-firing-arc-vis input').forEach(el =>
|
|
||||||
el.addEventListener('input', gameboard.toggleFiringArcVisibility)
|
|
||||||
);
|
|
||||||
|
|
||||||
document.getElementById('toggle-prone-counter').addEventListener('input', function () {
|
|
||||||
const selected = recordSheet.getSelected();
|
|
||||||
selected && gameboard.toggleProne();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@ -19,14 +19,14 @@ function getCellOccupant(cell) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getCells(svg) {
|
function getCells(svg) {
|
||||||
return svg.querySelectorAll('g[data-y] > g[data-x]');
|
return svg.querySelectorAll('g.grid > g[data-y] > g[data-x]');
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLockedSightLine(svg) {
|
function getLockedSightLine(svg) {
|
||||||
return svg.querySelector('line.sight-line:not(.active)');
|
return svg.querySelector('line.sight-line:not(.active)');
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSightLine(svg) {
|
export function getSightLine(svg) {
|
||||||
return svg.querySelector('line.sight-line');
|
return svg.querySelector('line.sight-line');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ function getCellPosition(cell) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getCell(x, y) {
|
function getCell(x, y) {
|
||||||
return svg.querySelector(`g[data-y="${y}"] > g[data-x="${x}"]`);
|
return svg.querySelector(`g.grid > g[data-y="${y}"] > g[data-x="${x}"]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCounterAtGridIndex(x, y) {
|
function getCounterAtGridIndex(x, y) {
|
||||||
@ -85,7 +85,7 @@ function updateSightLine(cell) {
|
|||||||
{ dataset: { x: tX }, parentElement: { dataset: { y: tY }}} = sightLine.getLockTarget();
|
{ dataset: { x: tX }, parentElement: { dataset: { y: tY }}} = sightLine.getLockTarget();
|
||||||
|
|
||||||
const selector = sightLine.calcIndexes(+sX, +sY, +tX, +tY)
|
const selector = sightLine.calcIndexes(+sX, +sY, +tX, +tY)
|
||||||
.map(([x, y]) => `g[data-y="${y}"] g[data-x="${x}"] use[href="#hex"]`)
|
.map(([x, y]) => `g.grid g[data-y="${y}"] g[data-x="${x}"] use[href="#hex"]`)
|
||||||
.join(', ');
|
.join(', ');
|
||||||
|
|
||||||
const hexes = svg.querySelectorAll(selector);
|
const hexes = svg.querySelectorAll(selector);
|
||||||
@ -99,7 +99,7 @@ function drawSightLine(sourceCell, targetCell) {
|
|||||||
{ dataset: { x: tX }, parentElement: { dataset: { y: tY }}} = targetCell;
|
{ dataset: { x: tX }, parentElement: { dataset: { y: tY }}} = targetCell;
|
||||||
|
|
||||||
const selector = sightLine.calcIndexes(+sX, +sY, +tX, +tY)
|
const selector = sightLine.calcIndexes(+sX, +sY, +tX, +tY)
|
||||||
.map(([x, y]) => `g[data-y="${y}"] g[data-x="${x}"] use[href="#hex"]`)
|
.map(([x, y]) => `g.grid g[data-y="${y}"] g[data-x="${x}"] use[href="#hex"]`)
|
||||||
.join(', ');
|
.join(', ');
|
||||||
|
|
||||||
const hexes = svg.querySelectorAll(selector);
|
const hexes = svg.querySelectorAll(selector);
|
||||||
@ -277,9 +277,9 @@ export function start(el) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// debug
|
// debug
|
||||||
const c = soldier.getCounter(svg, { dataset: { allegiance: 'davion', number: '1' }});
|
// const c = soldier.getCounter(svg, { dataset: { allegiance: 'davion', number: '1' }});
|
||||||
soldier.place(svg, c, getCell(17, 25));
|
// soldier.place(svg, c, getCell(17, 25));
|
||||||
select(c);
|
// select(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function select(selected) {
|
export function select(selected) {
|
||||||
|
@ -14,9 +14,9 @@ export function getSelected() {
|
|||||||
|
|
||||||
export function select(data) {
|
export function select(data) {
|
||||||
const selector =
|
const selector =
|
||||||
`#record-sheet .soldier-record[data-number="${data.number}"][data-allegiance="${data.allegiance}"]`
|
`#record-sheet .soldier-record[data-number="${data.number}"][data-allegiance="${data.allegiance}"]`
|
||||||
|
|
||||||
unSelect();
|
unSelect();
|
||||||
document.querySelector(selector).classList.add('selected');
|
document.querySelector(selector).classList.add('selected');
|
||||||
document.getElementById('toggle-prone-counter').checked = data.prone;
|
document.getElementById('toggle-prone-counter').checked = data.prone;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user