Web Dev Solutions

Catalin Mititiuc

From f1d67663dab2fd084c7e3996a83d17e9a6c5e037 Mon Sep 17 00:00:00 2001 From: Catalin Mititiuc Date: Thu, 25 Jul 2024 12:25:44 -0700 Subject: WIP: add multiple counters to troopers and cells --- public/assets/css/map.css | 31 +++++---- public/assets/images/counter-prone.svg | 31 +++++++++ public/assets/images/counter_grenade2.svg | 70 ++++++++++++++++++++ public/assets/images/counter_prone.svg | 14 ++++ public/assets/images/counter_prone2.svg | 70 ++++++++++++++++++++ public/assets/images/scenario_template.svg | 6 +- public/index.html | 6 -- src/index.js | 5 ++ src/modules/game/soldier.js | 8 ++- src/modules/gameboard.js | 101 ++++++++++++++++------------- 10 files changed, 274 insertions(+), 68 deletions(-) create mode 100644 public/assets/images/counter-prone.svg create mode 100644 public/assets/images/counter_grenade2.svg create mode 100644 public/assets/images/counter_prone.svg create mode 100644 public/assets/images/counter_prone2.svg diff --git a/public/assets/css/map.css b/public/assets/css/map.css index e6a25aa..06fe169 100644 --- a/public/assets/css/map.css +++ b/public/assets/css/map.css @@ -516,30 +516,39 @@ use[class^="counter-"] { --translateX: -5px; --translateY: -5px; transform: scale(var(--scale)) translate(var(--translateX), var(--translateY)); - /*transform: translate(var(--translateX), var(--translateY)) scale(var(--scale));*/ } use[class^="counter-"] { transition: x 0.25s, y 0.25s; --scale: 0.5; - /*--translateY: 0px;*/ -} - -.counter use[href^="#counter"] { - /*transform: scale(0.5);*/ } g.counter use[class^="counter-"] { x: calc(var(--x) * 1.25); y: calc(var(--y) * 1.25); - /*y: 10px;*/ - /*x: var(--x);*/ - /*y: var(--y);*/ } -[data-q][data-r][data-s][data-t]:hover use[class^="counter-"], +[data-q][data-r][data-s][data-t] > use[class^="counter-"] { + x: calc(var(--x) / 6); + y: calc(var(--y) / 6); +} + +/* Counters carried by a trooper */ +[data-q][data-r][data-s][data-t]:hover g.counter use[class^="counter-"] { + /*x: calc(var(--x) * 1.5);*/ + /*y: calc(var(--y) * 1.5);*/ + /*--translateY: -5px;*/ +} + +/* Counters placed on a hex */ +[data-q][data-r][data-s][data-t]:hover > g.counter ~ use[class^="counter-"] { + x: calc(var(--x) * 2); + y: calc(var(--y) * 2); + --translateY: -5px; +} + +[data-q][data-r][data-s][data-t]:hover > use[class^="counter-"] { x: calc(var(--x) * 1.5); y: calc(var(--y) * 1.5); - /*--scale: 1;*/ --translateY: -5px; } diff --git a/public/assets/images/counter-prone.svg b/public/assets/images/counter-prone.svg new file mode 100644 index 0000000..d93bb31 --- /dev/null +++ b/public/assets/images/counter-prone.svg @@ -0,0 +1,31 @@ + + + + diff --git a/public/assets/images/counter_grenade2.svg b/public/assets/images/counter_grenade2.svg new file mode 100644 index 0000000..21e6804 --- /dev/null +++ b/public/assets/images/counter_grenade2.svg @@ -0,0 +1,70 @@ + + + + diff --git a/public/assets/images/counter_prone.svg b/public/assets/images/counter_prone.svg new file mode 100644 index 0000000..ee224b3 --- /dev/null +++ b/public/assets/images/counter_prone.svg @@ -0,0 +1,14 @@ + + + + diff --git a/public/assets/images/counter_prone2.svg b/public/assets/images/counter_prone2.svg new file mode 100644 index 0000000..b59bba2 --- /dev/null +++ b/public/assets/images/counter_prone2.svg @@ -0,0 +1,70 @@ + + + + diff --git a/public/assets/images/scenario_template.svg b/public/assets/images/scenario_template.svg index efd6c8e..ad7cba3 100644 --- a/public/assets/images/scenario_template.svg +++ b/public/assets/images/scenario_template.svg @@ -28,11 +28,11 @@ - + - + @@ -63,6 +63,6 @@ - + diff --git a/public/index.html b/public/index.html index 562c3a2..c565a71 100644 --- a/public/index.html +++ b/public/index.html @@ -234,12 +234,6 @@
- - - - - - diff --git a/src/index.js b/src/index.js index d2c1b01..df48274 100644 --- a/src/index.js +++ b/src/index.js @@ -84,6 +84,11 @@ async function buildScenario(req) { // recordSheet.start(svg.querySelector('.start-locations'), gameboard.getUnits()); recordSheet.start(null, scenarioUnits); + + const [trooper] = gameboard.getUnits(); + Observable.notify('select', trooper); + gameboard.setCounter('prone'); + gameboard.setCounter('1st-floor'); } function updateTurnCounter() { diff --git a/src/modules/game/soldier.js b/src/modules/game/soldier.js index a024f9f..81dce74 100644 --- a/src/modules/game/soldier.js +++ b/src/modules/game/soldier.js @@ -34,7 +34,7 @@ function updatePlacement(cell, selected, clone) { const { q, r, s, t } = clone.parentElement.dataset; selected.dataset.previous = [q, r, s, t]; - cell.appendChild(selected); + placeIn(cell, selected); Array.from(selected.children).forEach(n => { if (n.classList.contains('removed')) { @@ -56,6 +56,10 @@ function createTrace(previous, current, selected) { return trace; } +function placeIn(location, target) { + location.querySelector('use[href="#hex"]').after(target); +} + export function createCounter(selected, weapon = 'rifle') { const g = document.createElementNS(svgns, 'g'); const weaponCounter = document.createElementNS(svgns, 'use'); @@ -126,7 +130,7 @@ export function place(svg, selected, cell) { handleTrace(svg, selected, clone, getCellPosition(cell)); } else { selected.removeAttribute('data-x'); - cell.appendChild(selected); + placeIn(cell, selected); } } diff --git a/src/modules/gameboard.js b/src/modules/gameboard.js index 0c33f05..530a7f5 100644 --- a/src/modules/gameboard.js +++ b/src/modules/gameboard.js @@ -34,8 +34,9 @@ function getActiveSightLine(svg) { return svg.querySelector('line.sight-line.active'); } -function isGrenade(el) { - return el && el.getAttribute('href') === '#counter-grenade'; +function isCounter(el) { + const regex = new RegExp('^#counter-') + return el && regex.test(el.getAttribute('href')); } function isMechTemplate(el) { @@ -196,10 +197,10 @@ function endMove() { } } -function returnPieces(collection) { - [...svg.querySelector('.pieces').children].forEach(piece => { - collection.get(piece).parent.append(piece); - collection.delete(piece); +function returnPieces(top) { + [...top.container.children].forEach(piece => { + top.collection.get(piece).parent.append(piece); + top.collection.delete(piece); }); } @@ -209,19 +210,19 @@ export function start(el) { const startingLocations = svg.querySelector('.start-locations'); startingLocations && getUnits(startingLocations).forEach(unit => unit.addEventListener('click', selectOffBoard)); - - const pieces = svg.querySelector('.pieces'); - const inFront = new Map(); - let inFrontParent; - //addEventListener('pointerout', e => { returnPieces(inFront) }); + const top = { + container: svg.querySelector('.grid-top'), + collection: new Map() + }; getCells(svg).forEach(cell => { cell.addEventListener('click', e => { const occupant = getCellOccupant(cell); let toPlace = placing.pop(); - if (isGrenade(toPlace) || isMechTemplate(toPlace)) { + if (isCounter(toPlace) || isMechTemplate(toPlace)) { getHex(cell).after(toPlace); + if (isCounter(toPlace)) arrangeCounters(cell); removeEventListener("keydown", handleMechTemplateRotation); } else if (toPlace && !occupant) { soldier.place(svg, toPlace, cell); @@ -282,12 +283,12 @@ export function start(el) { }); cell.addEventListener('pointerover', () => { - if (!pieces.contains(cell)) { - returnPieces(inFront); - inFront.set(cell, { parent: cell.parentElement }); - pieces.append(cell); + if (!top.container.contains(cell)) { + returnPieces(top); + top.collection.set(cell, { parent: cell.parentElement }); + top.container.append(cell); } - + console.log(top.container.children[0].children); const selected = getSelected(); if (placing[0]?.getAttributeNS(null, 'class') == 'mech-template') { @@ -307,22 +308,6 @@ export function start(el) { }); cell.addEventListener('pointerout', () => { - //if (inFront && inFrontParent) { - // inFrontParent.append(inFront); - // inFront = null; - // inFrontParent = null; - //} - - //for (const [el, parent] of inFront) { - // parent.append(el); - // inFront.delete(el); - //} - //[...pieces.children].forEach(piece => { - // inFront.get(piece).parent.append(piece); - // inFront.delete(piece); - //}); - //returnPieces(inFront); - getActiveSightLine(svg) && clearSightLine(); const occupant = getCellOccupant(cell); @@ -334,27 +319,27 @@ export function start(el) { }); // debug // - const attacker = { dataset: { allegiance: 'attacker', number: 1, squad: 1 }}; + // Add a trooper counter + const attacker = { dataset: { allegiance: 'attacker', number: 1, squad: 1 }}; // const defender = { dataset: { allegiance: 'defender', number: 1, squad: 2 }}; - - const cell = getCell(2, 0, -2, 0); + const cell = getCell(0, 0, 0, 0); const trooper = soldier.createCounter(attacker, 'blazer'); soldier.place(svg, trooper, cell); + + // Add some counters in an unoccupied cell + const countersCell = getCell(-1, 1, 0, 0); + setCounter('grenade'); + setCounter('prone'); + setCounter('1st-floor'); + const e = new PointerEvent('click'); + countersCell.dispatchEvent(e); + countersCell.dispatchEvent(e); + countersCell.dispatchEvent(e); /////////// Observable.subscribe('select', select); Observable.subscribe('endmove', endMove); - Observable.notify('select', trooper); - - //Array(1).fill(null).forEach(() => { - // const counter = document.createElementNS(svgns, 'use'); - // counter.setAttributeNS(null, 'href', '#counter-grenade'); - // counter.classList.add('counter-grenade'); - // trooper.appendChild(counter); - //}); - // - //setGrenade(); console.log('gameboard.js loaded'); } @@ -427,6 +412,30 @@ export function setCounter(name) { placing.push(counter); } +function arrangeCounters(cell) { + const counters = cell.querySelectorAll('[class^="counter-"]'); + const length = 12; + const gravity = 1; + const lateralForce = gravity; + const rads = Math.atan(lateralForce / gravity); + const bestFitCount = 8; + const deflection = counters.length > bestFitCount ? 2 * Math.PI / counters.length : Math.atan(lateralForce / gravity); + + counters.forEach((counter, index, arr) => { + const mult = index - arr.length / 2 + 0.5; + const theta = deflection * mult; + const x = length * Math.sin(theta); + const y = length * Math.cos(theta); + //counter.setAttributeNS(null, 'x', 0); + //counter.setAttributeNS(null, 'y', 10); + //counter.setAttributeNS(null, 'transform', `rotate(${theta * 180 / Math.PI})`); + //counter.setAttributeNS(null, 'style', `y: 10px; transform-origin: 5px 0; transform: translateX(-5px) rotate(${theta * 180 / Math.PI}deg)`); + counter.setAttributeNS(null, 'style', `--x: ${-x}px; --y: ${y}px`); + //counter.setAttributeNS(null, 'style', `x: 0; y: 10px;`); + }); + console.log(counters); +} + function handleMechTemplateRotation(event) { const counter = placing[0]; const upper = placing[0].querySelector('use[href="#mech-template-upper"]'); -- cgit v1.2.3