WIP: sight line

This commit is contained in:
Catalin Constantin Mititiuc 2025-06-16 22:41:28 -07:00
parent 9e7069ef13
commit 36bbe584be

199
index.js
View File

@ -375,6 +375,7 @@ const Counter = new function() {
},
clickClone = function() {
console.log('clone counter click fires');
let { troopNumber, troopAllegiance, x, y } = this.dataset,
[xAttr, yAttr] = this.parentElement.getAttribute('transform').match(/-?\d+\.?\d*/g);
@ -637,6 +638,57 @@ const RecordSheet = new function() {
};
};
const SightLine = new function() {
this.clear = function() {
let sl = grid.querySelector('line.sight-line');
if (sl) {
sl.remove();
}
this.clearHexes();
};
this.clearHexes = function() {
ptGrp.querySelectorAll('use[href="#point"].active').forEach(el => el.classList.remove('active'));
};
this.draw = function(x1, y1, x2, y2) {
let source = ptGrp.querySelector(`g[data-x="${x1}"][data-y="${y1}"]`),
target = ptGrp.querySelector(`g[data-x="${x2}"][data-y="${y2}"]`),
[slX1, slY1] = source.getAttribute('transform').match(/-?\d+\.?\d*/g),
[slX2, slY2] = target.getAttribute('transform').match(/-?\d+\.?\d*/g),
sightLine = document.createElementNS(svgns, 'line');
sightLine.classList.add('sight-line');
sightLine.classList.add('active');
sightLine.setAttributeNS(null, 'x1', slX1);
sightLine.setAttributeNS(null, 'y1', slY1);
sightLine.setAttributeNS(null, 'x2', slX2);
sightLine.setAttributeNS(null, 'y2', slY2);
grid.appendChild(sightLine);
let coords = [x1, y1, x2, y2];
this.drawHexes(...coords);
};
this.drawHexes = function(...coords) {
this.clearHexes()
info.querySelector('#hex-count').textContent = offset_distance(...coords);
info.style.display = 'block';
let lineCoords = linedraw(...coords);
lineCoords.shift();
let s = lineCoords.map(([x, y]) => `use[href="#point"][data-x="${x}"][data-y="${y}"]`).join(', ');
ptGrp.querySelectorAll(s).forEach(p => p.classList.add('active'));
};
}
POINTS.forEach((row, index) => row.forEach(([x, y]) => {
var cx = x * INRADIUS * 2 + (isEven(index) ? INRADIUS : 0),
cy = y * 3 / 2 * CIRCUMRADIUS,
@ -667,12 +719,74 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
});
group.addEventListener('click', e => {
let cl = e.target.classList;
console.log('group click fires');
let cl = e.target.classList,
sl = grid.querySelector('line.sight-line');
if (cl.contains('counter') && !cl.contains('clone')) {
RecordSheet.select(e.target);
Counter.select(e.target);
// if you click on someone else's counter (but not their clone),
// then you're selecting another soldier, so you should clear the sightline
// if it's locked, and you click on an intermediate clone, nothing should change
// if it's locked and you click on your own counter or your last clone
// it should redraw from your counter to the locked target hex because in
// both cases your counter just moved
console.log('target', e.target);
if (sl) {
let selected = RecordSheet.getSelected(),
{ troopNumber: sTn, troopAllegiance: sTa} = selected.dataset,
{ troopNumber: tTn, troopAllegiance: tTa} = e.target.dataset;
console.log('selected', selected);
console.log(cl.contains('counter'), sTn == tTn, sTa == tTa);
if (!sl.classList.contains('active') && (cl.contains('counter') && sTn == tTn && sTa == tTa)) {
let counterParent = Counter.get(tTn, tTa).parentElement,
[x, y] = counterParent.getAttribute('transform').match(/-?\d+\.?\d*/g),
target = ptGrp.querySelector(`g[transform="translate(${sl.getAttribute('x2')} ${sl.getAttribute('y2')})"]`),
{ x: x1, y: y1 } = counterParent.dataset,
{ x: x2, y: y2 } = target.dataset;
sl.setAttributeNS(null, 'x1', x);
sl.setAttributeNS(null, 'y1', y);
SightLine.drawHexes(...[x1, y1, x2, y2].map(n => parseInt(n)));
} else if ((cl.contains('counter') && sTn == tTn && sTa == tTa) || (cl.contains('counter') && !cl.contains('clone'))) {
RecordSheet.select(e.target);
Counter.select(e.target);
SightLine.clear();
}
}
// if (cl.contains('counter') && !cl.contains('clone') && !cl.contains('selected')) {
// RecordSheet.select(e.target);
// Counter.select(e.target);
// SightLine.clear();
// } else if (sl && !sl.classList.contains('active') && cl.contains('counter')) {
// let selected = RecordSheet.getSelected(),
// { troopNumber: tTn, troopAllegiance: tTa} = e.target.dataset;
// console.log('selected', selected);
// if (selected && selected.dataset.troopNumber == tTn && selected.dataset.troopAllegiance == tTa) {
// let counterParent = Counter.get(tTn, tTa).parentElement,
// [x, y] = counterParent.getAttribute('transform').match(/-?\d+\.?\d*/g),
// target = ptGrp.querySelector(`g[transform="translate(${sl.getAttribute('x2')} ${sl.getAttribute('y2')})"]`),
// { x: x1, y: y1 } = counterParent.dataset,
// { x: x2, y: y2 } = target.dataset;
// console.log('group', group);
// console.log('sl', sl);
// console.log('x1, y1, x2, y2', x1, y1, x2, y2);
// sl.setAttributeNS(null, 'x1', x);
// sl.setAttributeNS(null, 'y1', y);
// SightLine.drawHexes(...[x1, y1, x2, y2].map(n => parseInt(n)));
// }
// }
});
point.addEventListener('click', e => {
@ -681,14 +795,24 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
svg.querySelector(`.counter[data-x="${point.dataset.x}"][data-y="${point.dataset.y}"]`);
if (selectedSoldier && !existingOccupant) {
Counter.place(selectedSoldier, point);
let sl = svg.querySelector('.sight-line');
Counter.place(selectedSoldier, point);
if (sl) {
sl.classList.add('active');
point.dispatchEvent(new MouseEvent('mouseout'));
point.dispatchEvent(new MouseEvent('pointerover'));
if (sl.classList.contains('active')) {
SightLine.clear();
} else {
let [x, y] = point.parentElement.getAttribute('transform').match(/-?\d+\.?\d*/g),
target = ptGrp.querySelector(`g[transform="translate(${sl.getAttribute('x2')} ${sl.getAttribute('y2')})"]`),
{ x: x1, y: y1 } = point.dataset,
{ x: x2, y: y2 } = target.dataset;
sl.setAttributeNS(null, 'x1', x);
sl.setAttributeNS(null, 'y1', y);
SightLine.drawHexes(...[x1, y1, x2, y2].map(n => parseInt(n)));
}
}
}
});
@ -696,19 +820,16 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
group.addEventListener('contextmenu', e => {
e.preventDefault();
// if the sight line is active
// lock it
// otherwise
// try to draw sightline from active counter to click location
let sl = svg.querySelector('.sight-line');
if (sl) {
sl.classList.toggle('active');
if (sl.classList.contains('active')) {
point.dispatchEvent(new MouseEvent('mouseout'));
point.dispatchEvent(new MouseEvent('pointerover'));
SightLine.clear();
}
group.dispatchEvent(new MouseEvent('pointerover'));
}
});
@ -723,28 +844,7 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
sl = document.querySelector('line.sight-line');
if (counter && (!sl || sl.classList.contains('active'))) {
let source = ptGrp.querySelector(`g[data-x="${counter.dataset.x}"][data-y="${counter.dataset.y}"]`);
// [x1, y1] = [source.getAttribute('x'), source.getAttribute('y')],
// [x2, y2] = [e.target.getAttribute('x'), e.target.getAttribute('y')];
if (counter.dataset.x !== e.target.dataset.x || counter.dataset.y !== e.target.dataset.y) {
// let { x: svgX1, y: svgY1 } = ptGrpToSvgPt(x1, y1);
// let { x: svgX2, y: svgY2 } = ptGrpToSvgPt(x2, y2);
let sightLine = document.createElementNS(svgns, 'line');
let [x1, y1] = source.getAttribute('transform').match(/-?\d+\.?\d*/g);
let [x2, y2] = e.target.parentElement.getAttribute('transform').match(/-?\d+\.?\d*/g);
sightLine.classList.add('sight-line');
sightLine.classList.add('active');
sightLine.setAttributeNS(null, 'x1', x1);
sightLine.setAttributeNS(null, 'y1', y1);
sightLine.setAttributeNS(null, 'x2', x2);
sightLine.setAttributeNS(null, 'y2', y2);
grid.appendChild(sightLine);
let coords = [
counter.dataset.x,
counter.dataset.y,
@ -752,27 +852,17 @@ POINTS.forEach((row, index) => row.forEach(([x, y]) => {
e.target.dataset.y
].map(n => parseInt(n));
info.querySelector('#hex-count').textContent = offset_distance(...coords);
info.style.display = 'block';
let lineCoords = linedraw(...coords);
lineCoords.shift();
let s = lineCoords.map(([x, y]) => `use[href="#point"][data-x="${x}"][data-y="${y}"]`).join(', ');
ptGrp.querySelectorAll(s).forEach(p => p.classList.add('active'));
SightLine.draw(...coords);
}
}
}
});
point.addEventListener('pointerout', e => {
group.addEventListener('pointerout', e => {
let sl = svg.querySelector('.sight-line.active');
if (sl) {
// console.log('deleting sight line');
info.querySelector('#hex-count').textContent = '-';
info.style.display = 'none';
ptGrp.querySelectorAll('.active').forEach(el => el.removeAttribute('class'));
svg.querySelectorAll('.sight-line').forEach(el => el.remove());
if (sl && sl.classList.contains('active')) {
SightLine.clear();
}
});
@ -790,14 +880,7 @@ document.querySelectorAll('.soldier-record').forEach(el =>
Counter.select(el);
}
let sl = svg.querySelector('.sight-line');
if (sl) {
info.querySelector('#hex-count').textContent = '-';
info.style.display = 'none';
ptGrp.querySelectorAll('.active').forEach(el => el.removeAttribute('class'));
svg.querySelectorAll('.sight-line').forEach(el => el.remove());
}
SightLine.clear();
})
);