Web Dev Solutions

Catalin Mititiuc

aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--public/index.html108
-rw-r--r--public/map.css42
-rw-r--r--public/map1.svg95
-rw-r--r--public/map2.svg67
-rw-r--r--public/map3.svg67
-rw-r--r--public/map4.svg33
-rw-r--r--public/soldier_record_block.js1
-rw-r--r--public/style.css76
-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
14 files changed, 426 insertions, 228 deletions
diff --git a/public/index.html b/public/index.html
index 4f15e08..cdab46c 100644
--- a/public/index.html
+++ b/public/index.html
@@ -94,10 +94,10 @@
<div id="map-container">
<div id="toggle-firing-arc-vis">
- <div>Davion</div>
- <input type="checkbox" data-allegiance="davion" />
- <div>Liao</div>
- <input type="checkbox" data-allegiance="liao" />
+ <div>Defender</div>
+ <input type="checkbox" data-allegiance="defender"/>
+ <div>Attacker</div>
+ <input type="checkbox" data-allegiance="attacker"/>
</div>
<div class="map-placeholder">
@@ -114,64 +114,46 @@
<div id="content">
<input type="checkbox" class="visible"/>
<div>
- Set firing arc:
- <button type="button" class="set-firing-arc" data-size="small">
- <img src="firing_arc_small.png" height="12" /> 2 MP
- </button>
- <button type="button" class="set-firing-arc" data-size="medium">
- <img src="firing_arc_medium.png" height="12" /> 4 MP
- </button>
- <button type="button" class="set-firing-arc" data-size="large">
- <img src="firing_arc_large.png" height="12" /> 6 MP
- </button>
- Prone: <input type="checkbox" id="toggle-prone-counter" />
- <button type="button" class="set-grenade">
- <img src="icon_grenade.png" height="12" />
- </button>
Turn:
<span id="turn-count" data-update="0">
<span name="count">0</span>
<span class="inning-top">◓</span>
<span class="inning-bottom">◒</span>
</span>
-
- <dialog id="map-dialog">
- <form>
- <p>
- <label>
- Map:
- <select>
- <option value="map1">Map1</option>
- <option value="map2">Map2</option>
- <option value="map3">Map3</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>
+ <button id="show-dialog">Change scenario</button>
+ <span style="white-space: nowrap;">
+ Prone: <input type="checkbox" id="toggle-prone-counter" />
+ <button type="button" class="set-firing-arc" data-size="small">
+ <img src="firing_arc_small.png" height="12" /> 2 MP
+ </button>
+ <button type="button" class="set-firing-arc" data-size="medium">
+ <img src="firing_arc_medium.png" height="12" /> 4 MP
+ </button>
+ <button type="button" class="set-firing-arc" data-size="large">
+ <img src="firing_arc_large.png" height="12" /> 6 MP
+ </button>
+ <button type="button" class="set-grenade">
+ <img src="icon_grenade.png" height="12" />
+ </button>
+ </span>
</div>
<div id="record-sheet">
- <div>
+ <div id="attacker-record">
<!-- <img class="logo" src="logo-davion.png" /> -->
<p>
- <strong>Davion</strong>
- <button type="button" class="end-move" data-allegiance="davion">
+ <strong class="name">Attacker</strong>
+ <button type="button" class="end-move" data-allegiance="attacker">
End Movement
</button>
- <button type="button" class="end-turn" data-allegiance="liao">
+ <button type="button" class="end-turn" data-allegiance="defender">
End Turn
</button>
<br>
<!-- 1st Squad, 3rd Platoon, Bravo Company, 2nd Battalion<br>
17th Kestral Mechanized Infantry -->
</p>
- <div is="soldier-record-block" class="soldier-record" data-number="1" data-allegiance="davion">
+ <!-- <div is="soldier-record-block" class="soldier-record" data-number="1" data-allegiance="davion">
<span slot="troop-number"><svg viewBox="-5 -5 10 10" xmlns="http://www.w3.org/2000/svg"><circle cx="0" cy="0" r="5"/><text>1</text></svg></span>
<span slot="primary-weapon-type">Rifle</span>
<span slot="primary-weapon-damage">4L</span>
@@ -219,30 +201,30 @@
<span slot="primary-weapon-damage">4L</span>
<span slot="primary-weapon-range-short">1-17</span>
<span slot="primary-weapon-range-long">18-105</span>
- </div>
+ </div> -->
</div>
- <div>
+ <div id="defender-record">
<!-- <img class="logo" src="logo-liao.png" /> -->
<p>
- <strong>Liao</strong>
- <button type="button" class="end-move" data-allegiance="liao">
+ <strong class="name">Defender</strong>
+ <button type="button" class="end-move" data-allegiance="defender">
End Movement
</button>
- <button type="button" class="end-turn" data-allegiance="davion">
+ <button type="button" class="end-turn" data-allegiance="attacker">
End Turn
</button>
<br>
<!-- 2nd Squad, 1st Platoon, 3rd Company, 2nd Battalion<br>
Aldebaran Home Guard -->
</p>
- <div is="soldier-record-block" class="soldier-record" data-number="1" data-allegiance="liao">
+ <!-- <div is="soldier-record-block" class="soldier-record" data-number="1" data-allegiance="liao">
<span slot="troop-number"><svg viewBox="-5 -5 10 10" xmlns="http://www.w3.org/2000/svg"><circle cx="0" cy="0" r="5"/><text>1</text></svg></span>
<span slot="primary-weapon-type">Rifle</span>
<span slot="primary-weapon-damage">4L</span>
<span slot="primary-weapon-range-short">1-27</span>
<span slot="primary-weapon-range-long">28-75</span>
- </div>
- <div is="soldier-record-block" class="soldier-record" data-number="2" data-allegiance="liao">
+ </div> -->
+ <!-- <div is="soldier-record-block" class="soldier-record" data-number="2" data-allegiance="liao">
<span slot="troop-number"><svg viewBox="-5 -5 10 10" xmlns="http://www.w3.org/2000/svg"><circle cx="0" cy="0" r="5"/><text>2</text></svg></span>
<span slot="primary-weapon-type">Rifle</span>
<span slot="primary-weapon-damage">4L</span>
@@ -283,12 +265,32 @@
<span slot="primary-weapon-damage">4L</span>
<span slot="primary-weapon-range-short">1-17</span>
<span slot="primary-weapon-range-long">18-105</span>
- </div>
+ </div> -->
</div>
</div>
</div>
- <script src="soldier_record_block.js"></script>
+ <dialog id="map-dialog">
+ <form>
+ <p>
+ <label>
+ Scenario:
+ <select>
+ <option value="map1">Scenario 1: Side Show</option>
+ <option value="map2">Scenario 2: Dragon Hunting</option>
+ <option value="map3">Scenario 3: Race Against Time</option>
+ <option value="map4">Test</option>
+ </select>
+ </label>
+ </p>
+ <div>
+ <button value="cancel" formmethod="dialog">Cancel</button>
+ <button id="confirm-btn" value="default">Confirm</button>
+ </div>
+ </form>
+ </dialog>
+
<script src="index.js"></script>
+ <script src="soldier_record_block.js"></script>
</body>
</html>
diff --git a/public/map.css b/public/map.css
index 1a57998..0c2fed9 100644
--- a/public/map.css
+++ b/public/map.css
@@ -22,13 +22,6 @@ use[href="#hex"] {
stroke: black;
}
-/* use[href="#hex"]:hover, use[href="#hex"].hover
- {
- opacity: 1;
- fill: orange;
- stroke: orangered;
-} */
-
use[href="#hex"].active {
opacity: 0.2;
fill: teal;
@@ -41,10 +34,13 @@ use[href="#hex"].active {
fill-opacity: 0.04;
}
+polyline {
+ fill: none;
+}
+
polyline.move-trace {
stroke: white;
stroke-dasharray: 2;
- fill: none;
}
#background {
@@ -73,6 +69,11 @@ g.troop-counter-template, g.troop-counter-template use {
r: inherit;
}
+g.weapon-symbol {
+ stroke: white;
+ stroke-width: 0.5px;
+}
+
g.troop-counter-template text {
fill: white;
font-size: 12px;
@@ -108,11 +109,11 @@ g.clone [href="#counter-prone"] {
opacity: 0.5;
}
-g[data-allegiance="davion"].clone {
+g[data-allegiance="defender"].clone {
fill: rgb(255, 126, 126);
}
-g[data-allegiance="liao"].clone {
+g[data-allegiance="attacker"].clone {
fill: rgb(130, 190, 130);
}
@@ -128,11 +129,11 @@ text.counter, #troop-counter text {
user-select: none;
}
-polygon.firing-arc[data-allegiance="davion"] {
+polygon.firing-arc[data-allegiance="defender"] {
fill: red;
}
-polygon.firing-arc[data-allegiance="liao"] {
+polygon.firing-arc[data-allegiance="attacker"] {
fill: green;
}
@@ -172,7 +173,7 @@ polygon.firing-arc[data-allegiance="liao"] {
stroke-opacity: inherit;
}
-use[href*="#t-"] {
+g.counter use, use[href*="#t-"] {
r: 5px;
}
@@ -191,11 +192,11 @@ g.selected use {
}
}
-.counter[data-allegiance="liao"] {
- fill: #008000;
+.counter[data-allegiance="attacker"] {
+ fill: green;
}
-.counter[data-allegiance="davion"] {
+.counter[data-allegiance="defender"] {
fill: red;
}
@@ -203,14 +204,6 @@ g.selected use {
transform: translate(19px, 31px) scale(4);
}
-g.start-locations > g:first-child:not([data-y]) {
- --i: -2;
-}
-
-g.start-locations > g:last-child:not([data-y]) {
- --i: 52;
-}
-
/* Inradius and circumradius values come from the hexagon */
.grid, g.start-locations {
--inradius: 8.66px;
@@ -249,7 +242,6 @@ g[data-y]:nth-child(odd) {
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="1"] { --i: 1; }
g[data-y="2"] { --i: 2; }
diff --git a/public/map1.svg b/public/map1.svg
index efae907..6d767ba 100644
--- a/public/map1.svg
+++ b/public/map1.svg
@@ -3,6 +3,10 @@
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg viewBox="-18 -150 2320 3360" xmlns="http://www.w3.org/2000/svg">
<link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="map.css" type="text/css"/>
+ <style>
+ g[data-edge="north"] { --i: -2; }
+ g[data-edge="south"] { --i: 52; }
+ </style>
<defs>
<!-- <g id="hex">
<polygon points="0,10 8.66,5 8.66,-5 0,-10 -8.66,-5 -8.66,5"/>
@@ -21,6 +25,35 @@
<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>
+ <g id="semi-auto">
+ <line x1="-2" y1="1" x2="2" y2="1"/>
+ <line x1="-2" y1="2" x2="2" y2="2"/>
+ </g>
+
+ <g id="auto">
+ <line x1="-2" y1="0" x2="2" y2="0"/>
+ <line x1="-2" y1="1" x2="2" y2="1"/>
+ <line x1="-2" y1="2" x2="2" y2="2"/>
+ </g>
+
+ <g id="rifle" class="weapon-symbol">
+ <use href="#semi-auto"/>
+ <line x1="0" y1="-5" x2="0" y2="5"/>
+ <polyline points="-2,-3.5 0,-5 2,-3.5"/>
+ </g>
+
+ <g id="smg" class="weapon-symbol">
+ <use href="#auto"/>
+ <line x1="0" y1="-5" x2="0" y2="4.5"/>
+ <line x1="-2" y1="4.5" x2="2" y2="4.5"/>
+ </g>
+
+ <g id="blazer" class="weapon-symbol">
+ <use href="#auto"/>
+ <polyline points="0,-5 0,-3 -3,-2.5 3,-1.5 0,-1 0,2.5 -3,3, 3,4 0,4.5 0,5"/>
+ <polyline points="-2,-3.5 0,-5 2,-3.5"/>
+ </g>
+
<image id="counter-prone" href="counter_prone.jpg" width="10"/>
<image id="counter-grenade" href="counter_grenade.jpg" width="10"/>
<image id="numbers" href="rendered_numbers.png" width="182" height="22"/>
@@ -50,24 +83,52 @@
<g id="shapes"/>
<g id="lines"/>
</g>
- <g class="start-locations">
- <g>
- <g data-x="13" class="counter" data-allegiance="liao" data-number="1"><use href="#t-1"/></g>
- <g data-x="14" class="counter" data-allegiance="liao" data-number="2"><use href="#t-2"/></g>
- <g data-x="15" class="counter" data-allegiance="liao" data-number="3"><use href="#t-3"/></g>
- <g data-x="16" class="counter" data-allegiance="liao" data-number="4"><use href="#t-4"/></g>
- <g data-x="17" class="counter" data-allegiance="liao" data-number="5"><use href="#t-5"/></g>
- <g data-x="18" class="counter" data-allegiance="liao" data-number="6"><use href="#t-6"/></g>
- <g data-x="19" class="counter" data-allegiance="liao" data-number="7"><use href="#t-7"/></g>
+ <g class="start-locations" data-attacker-name="liao" data-defender-name="davion">
+ <g data-edge="north">
+ <g data-x="13">
+ <g class="counter" data-allegiance="attacker" data-number="1"><use href="#t-1"/></g>
+ </g>
+ <g data-x="14">
+ <g class="counter" data-allegiance="attacker" data-number="2"><use href="#t-2"/></g>
+ </g>
+ <g data-x="15">
+ <g class="counter" data-allegiance="attacker" data-number="3"><use href="#t-3"/></g>
+ </g>
+ <g data-x="16">
+ <g class="counter" data-allegiance="attacker" data-number="4"><use href="#t-4"/></g>
+ </g>
+ <g data-x="17">
+ <g class="counter" data-allegiance="attacker" data-number="5"><use href="#t-5"/></g>
+ </g>
+ <g data-x="18">
+ <g class="counter" data-allegiance="attacker" data-number="6"><use href="#t-6"/></g>
+ </g>
+ <g data-x="19">
+ <g class="counter" data-allegiance="attacker" data-number="7"><use href="#t-7"/></g>
+ </g>
</g>
- <g>
- <g data-x="13" class="counter" data-allegiance="davion" data-number="1"><use href="#t-1"/></g>
- <g data-x="14" class="counter" data-allegiance="davion" data-number="2"><use href="#t-2"/></g>
- <g data-x="15" class="counter" data-allegiance="davion" data-number="3"><use href="#t-3"/></g>
- <g data-x="16" class="counter" data-allegiance="davion" data-number="4"><use href="#t-4"/></g>
- <g data-x="17" class="counter" data-allegiance="davion" data-number="5"><use href="#t-5"/></g>
- <g data-x="18" class="counter" data-allegiance="davion" data-number="6"><use href="#t-6"/></g>
- <g data-x="19" class="counter" data-allegiance="davion" data-number="7"><use href="#t-7"/></g>
+ <g data-edge="south">
+ <g data-x="13">
+ <g class="counter" data-allegiance="defender" data-number="1"><use href="#t-1"/></g>
+ </g>
+ <g data-x="14">
+ <g class="counter" data-allegiance="defender" data-number="2"><use href="#t-2"/></g>
+ </g>
+ <g data-x="15">
+ <g class="counter" data-allegiance="defender" data-number="3"><use href="#t-3"/></g>
+ </g>
+ <g data-x="16">
+ <g class="counter" data-allegiance="defender" data-number="4"><use href="#t-4"/></g>
+ </g>
+ <g data-x="17">
+ <g class="counter" data-allegiance="defender" data-number="5"><use href="#t-5"/></g>
+ </g>
+ <g data-x="18">
+ <g class="counter" data-allegiance="defender" data-number="6"><use href="#t-6"/></g>
+ </g>
+ <g data-x="19">
+ <g class="counter" data-allegiance="defender" data-number="7"><use href="#t-7"/></g>
+ </g>
</g>
</g>
<g class="grid">
diff --git a/public/map2.svg b/public/map2.svg
index 013118d..c0ac9a4 100644
--- a/public/map2.svg
+++ b/public/map2.svg
@@ -4,13 +4,12 @@
<svg viewBox="-150 -150 600 800" xmlns="http://www.w3.org/2000/svg">
<link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="map.css" type="text/css"/>
<style>
- use[href="#hex"] {
- opacity: 0.2;
- }
-
#image-maps image {
transform: none;
}
+
+ g[data-edge="north"] { --i: -2; }
+ g[data-edge="south"] { --i: 78; }
</style>
<defs>
<polygon id="hex" points="0,10 8.66,5 8.66,-5 0,-10 -8.66,-5 -8.66,5"/>
@@ -44,22 +43,54 @@
<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 class="start-locations">
+ <g data-edge="north">
+ <g data-x="13">
+ <g class="counter" data-allegiance="attacker" data-number="1"><use href="#t-1"/></g>
+ </g>
+ <g data-x="14">
+ <g class="counter" data-allegiance="attacker" data-number="2"><use href="#t-2"/></g>
+ </g>
+ <g data-x="15">
+ <g class="counter" data-allegiance="attacker" data-number="3"><use href="#t-3"/></g>
+ </g>
+ <g data-x="16">
+ <g class="counter" data-allegiance="attacker" data-number="4"><use href="#t-4"/></g>
+ </g>
+ <g data-x="17">
+ <g class="counter" data-allegiance="attacker" data-number="5"><use href="#t-5"/></g>
+ </g>
+ <g data-x="18">
+ <g class="counter" data-allegiance="attacker" data-number="6"><use href="#t-6"/></g>
+ </g>
+ <g data-x="19">
+ <g class="counter" data-allegiance="attacker" data-number="7"><use href="#t-7"/></g>
+ </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 data-edge="south">
+ <g data-x="13">
+ <g class="counter" data-allegiance="defender" data-number="1"><use href="#t-1"/></g>
+ </g>
+ <g data-x="14">
+ <g class="counter" data-allegiance="defender" data-number="2"><use href="#t-2"/></g>
+ </g>
+ <g data-x="15">
+ <g class="counter" data-allegiance="defender" data-number="3"><use href="#t-3"/></g>
+ </g>
+ <g data-x="16">
+ <g class="counter" data-allegiance="defender" data-number="4"><use href="#t-4"/></g>
+ </g>
+ <g data-x="17">
+ <g class="counter" data-allegiance="defender" data-number="5"><use href="#t-5"/></g>
+ </g>
+ <g data-x="18">
+ <g class="counter" data-allegiance="defender" data-number="6"><use href="#t-6"/></g>
+ </g>
+ <g data-x="19">
+ <g class="counter" data-allegiance="defender" data-number="7"><use href="#t-7"/></g>
+ </g>
</g>
- </g> -->
+ </g>
<g class="grid"/>
</g>
<script href="map.js" data-cols="33" data-rows="77"></script>
diff --git a/public/map3.svg b/public/map3.svg
index 587c697..25a9518 100644
--- a/public/map3.svg
+++ b/public/map3.svg
@@ -4,13 +4,12 @@
<svg viewBox="-150 -150 600 800" xmlns="http://www.w3.org/2000/svg">
<link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="map.css" type="text/css"/>
<style>
- use[href="#hex"] {
- opacity: 0.2;
- }
-
#image-maps image {
transform: translate(-10px, 0px);
}
+
+ g[data-edge="north"] { --i: -2; }
+ g[data-edge="south"] { --i: 26; }
</style>
<defs>
<polygon id="hex" points="0,10 8.66,5 8.66,-5 0,-10 -8.66,-5 -8.66,5"/>
@@ -41,22 +40,54 @@
<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 class="start-locations">
+ <g data-edge="north">
+ <g data-x="13">
+ <g class="counter" data-allegiance="attacker" data-number="1"><use href="#t-1"/></g>
+ </g>
+ <g data-x="14">
+ <g class="counter" data-allegiance="attacker" data-number="2"><use href="#t-2"/></g>
+ </g>
+ <g data-x="15">
+ <g class="counter" data-allegiance="attacker" data-number="3"><use href="#t-3"/></g>
+ </g>
+ <g data-x="16">
+ <g class="counter" data-allegiance="attacker" data-number="4"><use href="#t-4"/></g>
+ </g>
+ <g data-x="17">
+ <g class="counter" data-allegiance="attacker" data-number="5"><use href="#t-5"/></g>
+ </g>
+ <g data-x="18">
+ <g class="counter" data-allegiance="attacker" data-number="6"><use href="#t-6"/></g>
+ </g>
+ <g data-x="19">
+ <g class="counter" data-allegiance="attacker" data-number="7"><use href="#t-7"/></g>
+ </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 data-edge="south">
+ <g data-x="13">
+ <g class="counter" data-allegiance="defender" data-number="1"><use href="#t-1"/></g>
+ </g>
+ <g data-x="14">
+ <g class="counter" data-allegiance="defender" data-number="2"><use href="#t-2"/></g>
+ </g>
+ <g data-x="15">
+ <g class="counter" data-allegiance="defender" data-number="3"><use href="#t-3"/></g>
+ </g>
+ <g data-x="16">
+ <g class="counter" data-allegiance="defender" data-number="4"><use href="#t-4"/></g>
+ </g>
+ <g data-x="17">
+ <g class="counter" data-allegiance="defender" data-number="5"><use href="#t-5"/></g>
+ </g>
+ <g data-x="18">
+ <g class="counter" data-allegiance="defender" data-number="6"><use href="#t-6"/></g>
+ </g>
+ <g data-x="19">
+ <g class="counter" data-allegiance="defender" data-number="7"><use href="#t-7"/></g>
+ </g>
</g>
- </g> -->
+ </g>
<g class="grid"/>
</g>
<script href="map.js" data-cols="33" data-rows="25"></script>
diff --git a/public/map4.svg b/public/map4.svg
new file mode 100644
index 0000000..c556811
--- /dev/null
+++ b/public/map4.svg
@@ -0,0 +1,33 @@
+<?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="-150 -150 600 800" 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"/>
+
+ <g class="gameboard">
+ <g id="firing-arcs">
+ <g id="shapes"/>
+ <g id="lines"/>
+ </g>
+ <g class="grid"/>
+ </g>
+ <script href="map.js" data-cols="33" data-rows="25"></script>
+</svg>
diff --git a/public/soldier_record_block.js b/public/soldier_record_block.js
index 0bf5a9a..3931649 100644
--- a/public/soldier_record_block.js
+++ b/public/soldier_record_block.js
@@ -49,7 +49,6 @@ customElements.define(
}
connectedCallback() {
- // this.shadowRoot.querySelectorAll('.grenades *').forEach(el => el.addEventListener('click', e => e.stopPropagation()));
this.shadowRoot.querySelector('.grenades').addEventListener('click', e => e.stopPropagation());
}
},
diff --git a/public/style.css b/public/style.css
index 22f592f..c229889 100644
--- a/public/style.css
+++ b/public/style.css
@@ -86,6 +86,10 @@ div#content {
background-color: gray;
}
+#record-sheet .name {
+ text-transform: capitalize;
+}
+
#record-sheet > div {
/* padding: 0 2px; */
overflow-y: auto;
@@ -233,72 +237,20 @@ g#points g.hover use.counter {
r: 7px;
}
-g#points g.hover use.counter:not(.clone) {
- /* stroke: orange; */
- /* stroke-width: 2px; */
-}
-
-g#points use.counter[data-allegiance="davion"] {
- fill: red;
-}
-
-g#points use.counter[data-allegiance="liao"] {
- fill: green;
-}
-
g#points use.clone {
stroke: white;
stroke-width: 0.5px;
stroke-dasharray: 1;
}
-g#points use[data-allegiance="davion"].clone {
+g#points use[data-allegiance="defender"].clone {
fill: rgb(255, 126, 126);
}
-g#points use[data-allegiance="liao"].clone {
+g#points use[data-allegiance="attacker"].clone {
fill: rgb(130, 190, 130);
}
-
-/* ======================================================= */
-
-/* g#counters {
- pointer-events: none;
-} */
-
-/* g#counters use {
- r: 5px;
-}
-
-g#counters use:hover {
- stroke: orange;
- stroke-width: 2px;
- r: 8px;
-} */
-
-/* g#counters use[data-allegiance="davion"] {
- fill: red;
-}
-
-g#counters use[data-allegiance="liao"] {
- fill: green;
-} */
-
-/* g#counters use.clone {
- stroke: white;
- stroke-width: 0.5px;
- stroke-dasharray: 1;
-}
-
-g#counters use[data-allegiance="davion"].clone {
- fill: rgb(255, 126, 126);
-}
-
-g#counters use[data-allegiance="liao"].clone {
- fill: rgb(130, 190, 130);
-} */
-
text.counter, #troop-counter text {
font-size: 12px;
font-weight: bold;
@@ -314,11 +266,11 @@ text.counter, #troop-counter text {
user-select: none;
}
-polygon.firing-arc[data-allegiance="davion"] {
+polygon.firing-arc[data-allegiance="defender"] {
fill: red;
}
-polygon.firing-arc[data-allegiance="liao"] {
+polygon.firing-arc[data-allegiance="attacker"] {
fill: green;
}
@@ -353,11 +305,11 @@ button.set-firing-arc img {
background-color: white;
}
-.soldier-record[data-allegiance="liao"] [slot="troop-number"] svg {
+.soldier-record[data-allegiance="attacker"] [slot="troop-number"] svg {
fill: green;
}
-.soldier-record[data-allegiance="davion"] [slot="troop-number"] svg {
+.soldier-record[data-allegiance="defender"] [slot="troop-number"] svg {
fill: red;
}
@@ -377,11 +329,11 @@ button.set-firing-arc img {
font-family: monospace;
}
-.soldier-record[data-allegiance="davion"] [slot="troop-number"] img {
+.soldier-record[data-allegiance="defender"] [slot="troop-number"] img {
fill: red;
}
-.soldier-record[data-allegiance="liao"] [slot="troop-number"] img {
+.soldier-record[data-allegiance="attacker"] [slot="troop-number"] img {
fill: green;
}
@@ -419,6 +371,10 @@ img.logo {
display: none;
}
+#map-dialog {
+ border: 1px solid black;
+}
+
@media (width >= 1800px) {
#record-sheet {
flex-direction: row;
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';
+}