WIP: add multiple counters to troopers and cells
This commit is contained in:
parent
afd0ff2f6a
commit
edb5af99c7
@ -516,30 +516,39 @@ use[class^="counter-"] {
|
|||||||
--translateX: -5px;
|
--translateX: -5px;
|
||||||
--translateY: -5px;
|
--translateY: -5px;
|
||||||
transform: scale(var(--scale)) translate(var(--translateX), var(--translateY));
|
transform: scale(var(--scale)) translate(var(--translateX), var(--translateY));
|
||||||
/*transform: translate(var(--translateX), var(--translateY)) scale(var(--scale));*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
use[class^="counter-"] {
|
use[class^="counter-"] {
|
||||||
transition: x 0.25s, y 0.25s;
|
transition: x 0.25s, y 0.25s;
|
||||||
--scale: 0.5;
|
--scale: 0.5;
|
||||||
/*--translateY: 0px;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
.counter use[href^="#counter"] {
|
|
||||||
/*transform: scale(0.5);*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g.counter use[class^="counter-"] {
|
g.counter use[class^="counter-"] {
|
||||||
x: calc(var(--x) * 1.25);
|
x: calc(var(--x) * 1.25);
|
||||||
y: calc(var(--y) * 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) * 1.5);
|
x: calc(var(--x) / 6);
|
||||||
y: calc(var(--y) * 1.5);
|
y: calc(var(--y) / 6);
|
||||||
/*--scale: 1;*/
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
--translateY: -5px;
|
--translateY: -5px;
|
||||||
}
|
}
|
||||||
|
31
public/assets/images/counter-prone.svg
Normal file
31
public/assets/images/counter-prone.svg
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="71"
|
||||||
|
height="71"
|
||||||
|
viewBox="0 0 71 71"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xml:space="preserve"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs1" /><g
|
||||||
|
id="layer1"><circle
|
||||||
|
style="fill:#000000;stroke:none;stroke-width:0.32991;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
id="path2"
|
||||||
|
cx="29.117487"
|
||||||
|
cy="32.638958"
|
||||||
|
r="3.7584312" /><path
|
||||||
|
style="color:#000000;fill:#000000;-inkscape-stroke:none"
|
||||||
|
d="m 31.271484,34.935547 -6.664062,4.232422 -5.97461,-3.947266 -2.089843,4.261719 8.039062,4.958984 7.128906,-4.455078 7.513672,2.103516 1.279297,-4.570313 z"
|
||||||
|
id="path7" /><path
|
||||||
|
style="color:#000000;fill:#000000;-inkscape-stroke:none"
|
||||||
|
d="m 37.242187,37.804687 0.521485,7.400391 1.986328,1.75 h 13.289062 v -4 H 42.800781 l -0.314453,-1.150391 h 8.075195 8.075196 v -4 H 47.939453 Z"
|
||||||
|
id="path3" /><path
|
||||||
|
style="color:#000000;fill:#000000;-inkscape-stroke:none"
|
||||||
|
d="M 12.447266,34.826172 V 37.96875 H 29.117187 V 34.826172 Z"
|
||||||
|
id="path5" /><path
|
||||||
|
style="color:#000000;fill:#000000;-inkscape-stroke:none"
|
||||||
|
d="m 31.765625,36.871094 -2.080078,3.416015 8.078125,4.917969 2.082031,-3.416016 z"
|
||||||
|
id="path8" /></g></svg>
|
After Width: | Height: | Size: 1.4 KiB |
70
public/assets/images/counter_grenade2.svg
Normal file
70
public/assets/images/counter_grenade2.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 43 KiB |
14
public/assets/images/counter_prone.svg
Normal file
14
public/assets/images/counter_prone.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 6.8 KiB |
70
public/assets/images/counter_prone2.svg
Normal file
70
public/assets/images/counter_prone2.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 43 KiB |
@ -28,11 +28,11 @@
|
|||||||
|
|
||||||
<g id="counter-grenade">
|
<g id="counter-grenade">
|
||||||
<rect x="0" y="0" width="10" height="10" fill="beige" stroke="black" stroke-width="0.5"/>
|
<rect x="0" y="0" width="10" height="10" fill="beige" stroke="black" stroke-width="0.5"/>
|
||||||
<image href="counter_grenade.png" width="10"/>
|
<image href="counter_grenade2.svg" width="10"/>
|
||||||
</g>
|
</g>
|
||||||
<g id="counter-prone">
|
<g id="counter-prone">
|
||||||
<rect x="0" y="0" width="10" height="10" fill="beige" stroke="black" stroke-width="0.5"/>
|
<rect x="0" y="0" width="10" height="10" fill="beige" stroke="black" stroke-width="0.5"/>
|
||||||
<image href="counter_prone.png" width="10"/>
|
<image href="counter_prone2.svg" width="10"/>
|
||||||
</g>
|
</g>
|
||||||
<g id="counter-basement">
|
<g id="counter-basement">
|
||||||
<rect x="0" y="0" width="10" height="10" fill="beige" stroke="black" stroke-width="0.5"/>
|
<rect x="0" y="0" width="10" height="10" fill="beige" stroke="black" stroke-width="0.5"/>
|
||||||
@ -63,6 +63,6 @@
|
|||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g class="grid"/>
|
<g class="grid"/>
|
||||||
<g class="pieces"/>
|
<g class="grid-top"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
@ -234,12 +234,6 @@
|
|||||||
<button type="button" class="set-mech-template">Mech</button>
|
<button type="button" class="set-mech-template">Mech</button>
|
||||||
</span>
|
</span>
|
||||||
<div class="counters-list">
|
<div class="counters-list">
|
||||||
<!--<img src="assets/images/counter_grenade.png" />-->
|
|
||||||
<!--<img src="assets/images/counter_prone.png" />-->
|
|
||||||
<!--<img src="assets/images/counter_basement.png" />-->
|
|
||||||
<!--<img src="assets/images/counter_1st_floor.png" />-->
|
|
||||||
<!--<img src="assets/images/counter_2nd_floor.png" />-->
|
|
||||||
<!--<img src="assets/images/counter_3rd_floor.png" />-->
|
|
||||||
<button type="button" class="grenade">
|
<button type="button" class="grenade">
|
||||||
<img src="assets/images/icon_grenade.png" height="12" />
|
<img src="assets/images/icon_grenade.png" height="12" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -84,6 +84,11 @@ async function buildScenario(req) {
|
|||||||
|
|
||||||
// recordSheet.start(svg.querySelector('.start-locations'), gameboard.getUnits());
|
// recordSheet.start(svg.querySelector('.start-locations'), gameboard.getUnits());
|
||||||
recordSheet.start(null, scenarioUnits);
|
recordSheet.start(null, scenarioUnits);
|
||||||
|
|
||||||
|
const [trooper] = gameboard.getUnits();
|
||||||
|
Observable.notify('select', trooper);
|
||||||
|
gameboard.setCounter('prone');
|
||||||
|
gameboard.setCounter('1st-floor');
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTurnCounter() {
|
function updateTurnCounter() {
|
||||||
|
@ -34,7 +34,7 @@ function updatePlacement(cell, selected, clone) {
|
|||||||
const { q, r, s, t } = clone.parentElement.dataset;
|
const { q, r, s, t } = clone.parentElement.dataset;
|
||||||
|
|
||||||
selected.dataset.previous = [q, r, s, t];
|
selected.dataset.previous = [q, r, s, t];
|
||||||
cell.appendChild(selected);
|
placeIn(cell, selected);
|
||||||
|
|
||||||
Array.from(selected.children).forEach(n => {
|
Array.from(selected.children).forEach(n => {
|
||||||
if (n.classList.contains('removed')) {
|
if (n.classList.contains('removed')) {
|
||||||
@ -56,6 +56,10 @@ function createTrace(previous, current, selected) {
|
|||||||
return trace;
|
return trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function placeIn(location, target) {
|
||||||
|
location.querySelector('use[href="#hex"]').after(target);
|
||||||
|
}
|
||||||
|
|
||||||
export function createCounter(selected, weapon = 'rifle') {
|
export function createCounter(selected, weapon = 'rifle') {
|
||||||
const g = document.createElementNS(svgns, 'g');
|
const g = document.createElementNS(svgns, 'g');
|
||||||
const weaponCounter = document.createElementNS(svgns, 'use');
|
const weaponCounter = document.createElementNS(svgns, 'use');
|
||||||
@ -126,7 +130,7 @@ export function place(svg, selected, cell) {
|
|||||||
handleTrace(svg, selected, clone, getCellPosition(cell));
|
handleTrace(svg, selected, clone, getCellPosition(cell));
|
||||||
} else {
|
} else {
|
||||||
selected.removeAttribute('data-x');
|
selected.removeAttribute('data-x');
|
||||||
cell.appendChild(selected);
|
placeIn(cell, selected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,8 +34,9 @@ function getActiveSightLine(svg) {
|
|||||||
return svg.querySelector('line.sight-line.active');
|
return svg.querySelector('line.sight-line.active');
|
||||||
}
|
}
|
||||||
|
|
||||||
function isGrenade(el) {
|
function isCounter(el) {
|
||||||
return el && el.getAttribute('href') === '#counter-grenade';
|
const regex = new RegExp('^#counter-')
|
||||||
|
return el && regex.test(el.getAttribute('href'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMechTemplate(el) {
|
function isMechTemplate(el) {
|
||||||
@ -196,10 +197,10 @@ function endMove() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function returnPieces(collection) {
|
function returnPieces(top) {
|
||||||
[...svg.querySelector('.pieces').children].forEach(piece => {
|
[...top.container.children].forEach(piece => {
|
||||||
collection.get(piece).parent.append(piece);
|
top.collection.get(piece).parent.append(piece);
|
||||||
collection.delete(piece);
|
top.collection.delete(piece);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,19 +210,19 @@ export function start(el) {
|
|||||||
const startingLocations = svg.querySelector('.start-locations');
|
const startingLocations = svg.querySelector('.start-locations');
|
||||||
startingLocations && getUnits(startingLocations).forEach(unit => unit.addEventListener('click', selectOffBoard));
|
startingLocations && getUnits(startingLocations).forEach(unit => unit.addEventListener('click', selectOffBoard));
|
||||||
|
|
||||||
|
const top = {
|
||||||
const pieces = svg.querySelector('.pieces');
|
container: svg.querySelector('.grid-top'),
|
||||||
const inFront = new Map();
|
collection: new Map()
|
||||||
let inFrontParent;
|
};
|
||||||
//addEventListener('pointerout', e => { returnPieces(inFront) });
|
|
||||||
|
|
||||||
getCells(svg).forEach(cell => {
|
getCells(svg).forEach(cell => {
|
||||||
cell.addEventListener('click', e => {
|
cell.addEventListener('click', e => {
|
||||||
const occupant = getCellOccupant(cell);
|
const occupant = getCellOccupant(cell);
|
||||||
let toPlace = placing.pop();
|
let toPlace = placing.pop();
|
||||||
|
|
||||||
if (isGrenade(toPlace) || isMechTemplate(toPlace)) {
|
if (isCounter(toPlace) || isMechTemplate(toPlace)) {
|
||||||
getHex(cell).after(toPlace);
|
getHex(cell).after(toPlace);
|
||||||
|
if (isCounter(toPlace)) arrangeCounters(cell);
|
||||||
removeEventListener("keydown", handleMechTemplateRotation);
|
removeEventListener("keydown", handleMechTemplateRotation);
|
||||||
} else if (toPlace && !occupant) {
|
} else if (toPlace && !occupant) {
|
||||||
soldier.place(svg, toPlace, cell);
|
soldier.place(svg, toPlace, cell);
|
||||||
@ -282,12 +283,12 @@ export function start(el) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
cell.addEventListener('pointerover', () => {
|
cell.addEventListener('pointerover', () => {
|
||||||
if (!pieces.contains(cell)) {
|
if (!top.container.contains(cell)) {
|
||||||
returnPieces(inFront);
|
returnPieces(top);
|
||||||
inFront.set(cell, { parent: cell.parentElement });
|
top.collection.set(cell, { parent: cell.parentElement });
|
||||||
pieces.append(cell);
|
top.container.append(cell);
|
||||||
}
|
}
|
||||||
|
console.log(top.container.children[0].children);
|
||||||
const selected = getSelected();
|
const selected = getSelected();
|
||||||
|
|
||||||
if (placing[0]?.getAttributeNS(null, 'class') == 'mech-template') {
|
if (placing[0]?.getAttributeNS(null, 'class') == 'mech-template') {
|
||||||
@ -307,22 +308,6 @@ export function start(el) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
cell.addEventListener('pointerout', () => {
|
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();
|
getActiveSightLine(svg) && clearSightLine();
|
||||||
|
|
||||||
const occupant = getCellOccupant(cell);
|
const occupant = getCellOccupant(cell);
|
||||||
@ -334,27 +319,27 @@ export function start(el) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// debug //
|
// debug //
|
||||||
|
// Add a trooper counter
|
||||||
const attacker = { dataset: { allegiance: 'attacker', number: 1, squad: 1 }};
|
const attacker = { dataset: { allegiance: 'attacker', number: 1, squad: 1 }};
|
||||||
// const defender = { dataset: { allegiance: 'defender', number: 1, squad: 2 }};
|
// const defender = { dataset: { allegiance: 'defender', number: 1, squad: 2 }};
|
||||||
|
const cell = getCell(0, 0, 0, 0);
|
||||||
const cell = getCell(2, 0, -2, 0);
|
|
||||||
const trooper = soldier.createCounter(attacker, 'blazer');
|
const trooper = soldier.createCounter(attacker, 'blazer');
|
||||||
soldier.place(svg, trooper, cell);
|
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('select', select);
|
||||||
Observable.subscribe('endmove', endMove);
|
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');
|
console.log('gameboard.js loaded');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,6 +412,30 @@ export function setCounter(name) {
|
|||||||
placing.push(counter);
|
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) {
|
function handleMechTemplateRotation(event) {
|
||||||
const counter = placing[0];
|
const counter = placing[0];
|
||||||
const upper = placing[0].querySelector('use[href="#mech-template-upper"]');
|
const upper = placing[0].querySelector('use[href="#mech-template-upper"]');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user