Web Dev Solutions

Catalin Mititiuc

aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCatalin Mititiuc <webdevcat@proton.me>2024-04-30 10:17:45 -0700
committerCatalin Mititiuc <webdevcat@proton.me>2024-04-30 10:17:45 -0700
commit82d3a4b415ba920176058d615b697e84a49adabc (patch)
tree7bc250d9f332689e3dc0c4e7aec5949175a0f9fa /src
parenta4888a3e0905f3561781cb0ef4686befc0dff122 (diff)
Create record sheet dynamically when map is loaded
Diffstat (limited to 'src')
-rw-r--r--src/index.js41
-rw-r--r--src/map.js13
-rw-r--r--src/modules/game/firing_arc.js4
-rw-r--r--src/modules/game/soldier.js4
-rw-r--r--src/modules/gameboard.js36
-rw-r--r--src/modules/record_sheet.js67
6 files changed, 129 insertions, 36 deletions
diff --git a/src/index.js b/src/index.js
index a6bd5d0..b6315f5 100644
--- a/src/index.js
+++ b/src/index.js
@@ -16,6 +16,35 @@ object.addEventListener('load', function (e) {
const svg = this.contentDocument.querySelector('svg');
panzoom.start(svg);
gameboard.start(svg);
+
+ recordSheet.clear();
+
+ const recordTemplate = document.querySelector('template#soldier-record-block');
+ const startLoc = svg.querySelector('.start-locations');
+ const forces = recordSheet.createRecords(gameboard.getUnits(), recordTemplate);
+
+ for (const affiliation in forces) {
+ const container = document.querySelector(`#${affiliation}-record`);
+ const name = startLoc.dataset[`${affiliation}Name`];
+ if (name) {
+ container.querySelector('.name').textContent = name;
+ }
+ forces[affiliation].forEach(r => container.appendChild(r));
+ }
+
+ 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);
+ }
+ })
+ );
+
+ window.game = gameboard;
});
gameboard.setDistanceCallback((count = '-') => {
@@ -26,18 +55,6 @@ gameboard.setDistanceCallback((count = '-') => {
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();
diff --git a/src/map.js b/src/map.js
index 06b6ce6..e5c9cd4 100644
--- a/src/map.js
+++ b/src/map.js
@@ -4,16 +4,23 @@ const svg = document.querySelector('svg');
const gb = svg.querySelector('.gameboard');
const bg = svg.querySelector('#background');
const imageMaps = svg.querySelector('#image-maps');
-
+const grid = gb.querySelector('.grid');
if ('cols' in dataset && 'rows' in dataset) {
const cellTemplate = svg.querySelector('#hex');
- const grid = gb.querySelector('.grid');
createCells(grid, dataset, cellTemplate.id);
}
-setElAttrs(bg, calcComputedBboxFor(imageMaps));
+const sequence = getComputedStyle(gb).transform.match(/-?\d+\.?\d*/g);
+const mtx = new DOMMatrix(sequence || '');
+bg.style.transform = mtx;
+
+const bbox = grid.getBBox();
+
+bbox.height += 5;
+
+setElAttrs(bg, bbox);
svg.setAttribute('viewBox', formatForViewBox(calcComputedBboxFor(gb)));
function setElAttrs(el, attrs) {
diff --git a/src/modules/game/firing_arc.js b/src/modules/game/firing_arc.js
index 817bc44..cea8bd0 100644
--- a/src/modules/game/firing_arc.js
+++ b/src/modules/game/firing_arc.js
@@ -13,8 +13,8 @@ const horzToVertDistRatio = 2 * Math.sqrt(3) / 3,
},
firingArcVisibility = {
- davion: false,
- liao: false
+ defender: false,
+ attacker: false
},
clippedFiringArcRadius = 25;
diff --git a/src/modules/game/soldier.js b/src/modules/game/soldier.js
index 922faca..b01ed15 100644
--- a/src/modules/game/soldier.js
+++ b/src/modules/game/soldier.js
@@ -29,6 +29,10 @@ function getCounterAndClones(svg, counter) {
return svg.querySelectorAll(`.counter${dataSelector(counter)}`);
}
+export function getAllCounters(container) {
+ return container.querySelectorAll('g.counter[data-allegiance][data-number]');
+}
+
export function getCounter(svg, selected) {
return svg.querySelector(`.counter${dataSelector(selected)}:not(.clone)`);
}
diff --git a/src/modules/gameboard.js b/src/modules/gameboard.js
index 5a804a3..47533dd 100644
--- a/src/modules/gameboard.js
+++ b/src/modules/gameboard.js
@@ -2,6 +2,10 @@ import * as firingArc from './game/firing_arc.js';
import * as sightLine from './game/sight_line.js';
import * as soldier from './game/soldier.js';
+let svg, distanceCallback, proneFlagCallback, selectCallback,
+ selected,
+ placing = [];
+
function getCellContents(cell) {
return cell.querySelectorAll('*:not(use[href="#hex"])');
}
@@ -26,8 +30,8 @@ function getLockedSightLine(svg) {
return svg.querySelector('line.sight-line:not(.active)');
}
-export function getSightLine(svg) {
- return svg.querySelector('line.sight-line');
+function getSightLine() {
+ return sightLine.getSightLine();
}
function getActiveSightLine(svg) {
@@ -109,8 +113,9 @@ function drawSightLine(sourceCell, targetCell) {
distanceCallback && distanceCallback(hexes.length - 1);
}
-let svg, distanceCallback, proneFlagCallback, selectCallback,
- placing = [];
+export function getUnits() {
+ return soldier.getAllCounters(svg);
+}
export function setDistanceCallback(callback) {
distanceCallback = callback;
@@ -143,13 +148,7 @@ export function start(el) {
} else if (toPlace && !state.occupant) {
soldier.place(svg, toPlace, cell);
placing.push(toPlace);
- const lockedSl = getLockedSightLine(svg);
-
- if (!lockedSl) {
- clearSightLine();
- } else {
- updateSightLine(cell);
- }
+ getLockedSightLine(svg) ? updateSightLine(cell) : clearSightLine();
} else if (toPlace && state.occupant) {
if (toPlace === state.occupant) {
if ('previous' in toPlace.dataset) {
@@ -187,13 +186,7 @@ export function start(el) {
toPlace = state.occupant;
soldier.removeClones(svg, toPlace);
soldier.getTrace(svg, toPlace).remove();
- const lockedSl = getLockedSightLine(svg);
-
- if (!lockedSl) {
- clearSightLine();
- } else {
- updateSightLine(cell);
- }
+ getLockedSightLine(svg) ? updateSightLine(cell) : clearSightLine();
} else {
const index = getGridIndex(state.occupant),
trace = soldier.getTrace(svg, toPlace),
@@ -242,10 +235,15 @@ export function start(el) {
});
cell.addEventListener('pointerover', () => {
+ // should we draw a sight line?
+ // conditions:
+ // we have a soldier selected
+ // that soldier's counter is on the board
+ // the sight line is not locked
let selected = getSelected();
if (selected) {
- let sl = getSightLine(svg),
+ let sl = getSightLine(),
isOnBoard = selected.parentElement.hasAttribute('data-x'),
sourceCell = selected.parentElement;
diff --git a/src/modules/record_sheet.js b/src/modules/record_sheet.js
index e5e8de6..88c8e15 100644
--- a/src/modules/record_sheet.js
+++ b/src/modules/record_sheet.js
@@ -1,3 +1,51 @@
+function createIcon(number) {
+ const svgns = 'http://www.w3.org/2000/svg';
+ const [icon, circle, text] = ['svg', 'circle', 'text'].map(t => document.createElementNS(svgns, t));
+
+ icon.setAttributeNS(null, 'viewBox', '-5 -5 10 10')
+ icon.setAttribute('xmlns', svgns);
+
+ circle.setAttributeNS(null, 'cx', 0);
+ circle.setAttributeNS(null, 'cy', 0);
+ circle.setAttributeNS(null, 'r', 5);
+
+ text.textContent = number;
+
+ icon.appendChild(circle);
+ icon.appendChild(text);
+
+ return icon;
+}
+
+function createRecord({ dataset: { allegiance, number }}) {
+ const div = document.createElement('div', { is: 'soldier-record-block' }),
+ spans = Array(5).fill('span').map(t => document.createElement(t)),
+ [tn, pwt, pwd, pwrs, pwrl] = spans;
+
+ div.setAttribute('class', 'soldier-record');
+ div.dataset.number = number;
+ div.dataset.allegiance = allegiance;
+
+ tn.setAttribute('slot', 'troop-number');
+ tn.appendChild(createIcon(number));
+
+ pwt.setAttribute('slot', 'primary-weapon-type');
+ pwt.textContent = 'Rifle';
+
+ pwd.setAttribute('slot', 'primary-weapon-damage');
+ pwd.textContent = '4L';
+
+ pwrs.setAttribute('slot', 'primary-weapon-range-short');
+ pwrs.textContent = '1-27';
+
+ pwrl.setAttribute('slot', 'primary-weapon-range-long');
+ pwrl.textContent = '28-75';
+
+ spans.forEach(el => div.appendChild(el));
+
+ return div;
+}
+
export function unSelect() {
const selected = getSelected();
@@ -30,3 +78,22 @@ export function endMove() {
unSelect();
}
+
+export function createRecords(units, { content }) {
+ const grouped = Array.from(units).reduce((acc, unit) => {
+ acc[unit.dataset.allegiance]?.push(unit) || (acc[unit.dataset.allegiance] = [unit]);
+ return acc;
+ }, {});
+
+ for (const al in grouped) {
+ grouped[al] = grouped[al].map(createRecord);
+ }
+
+ return grouped;
+}
+
+export function clear() {
+ document.querySelectorAll('#attacker-record > div, #defender-record > div').forEach(el => el.remove());
+ document.querySelector('#attacker-record .name').textContent = 'attacker';
+ document.querySelector('#defender-record .name').textContent = 'defender';
+}