index : btroops | |
Virtual board game-aid for BattleTroops, an infantry combat simulator wargame published by FASA in 1989. |
aboutsummaryrefslogtreecommitdiff |
diff options
author | Catalin Mititiuc <webdevcat@proton.me> | 2024-06-23 19:23:33 -0700 |
---|---|---|
committer | Catalin Mititiuc <webdevcat@proton.me> | 2024-06-23 19:23:33 -0700 |
commit | dd8e7f04aaea205d2a3809d0ca1e26eb0a511c5e (patch) | |
tree | 6bb41ba0bf0bd9b8c2dbb41e0d7b4c6830e59f54 | |
parent | af7f149ab5cde2a520b41c262279ab931db4f1fd (diff) |
WIP: add building structure
-rw-r--r-- | public/radial.html | 140 | ||||
-rw-r--r-- | src/radial.js | 160 |
2 files changed, 257 insertions, 43 deletions
diff --git a/public/radial.html b/public/radial.html index 2be7903..4d08f43 100644 --- a/public/radial.html +++ b/public/radial.html @@ -85,7 +85,8 @@ /* fill: green; */ } - .elevation-1, .elevation-2 { + .elevation-1, + .elevation-2 { display: inline; } @@ -141,8 +142,8 @@ display: inline; } - [data-view-elevation="1"] > .elevation-0, - [data-view-elevation="1"] > .elevation-1 { + [data-view-elevation="1"]>.elevation-0, + [data-view-elevation="1"]>.elevation-1 { display: inline; } @@ -220,7 +221,7 @@ display: none; } - input:checked + label { + input:checked+label { border: 1px solid salmon; border-radius: 3px; background-color: #cdd9e9; @@ -276,17 +277,126 @@ <use y="15" x="-15" transform="rotate(-60, -15, 15)" href="#ast-line" /> </pattern> - <g class="building2"> - <g data-grid-footprint="0,0,0:1,0,-1:-1,0,1:1,-1,0:-1,1,0:0,1,-1:0,-1,1:2,0,-2:2,-1,-1:1,1,-2:-2,0,2:-2,1,1:-1,-1,2:2,-2,0:1,-2,1:-2,2,0:-1,2,-1:0,2,-2:0,-2,2:3,-2,-1:1,2,-3:-3,2,1:-1,-2,3:3,-3,0:2,-3,1:1,-3,2:-3,3,0:-2,3,-1:-1,3,-2:0,3,-3:0,-3,3:4,-4,0:3,-4,1:2,-4,2:1,-4,3:-4,4,0:-3,4,-1:-2,4,-2:-1,4,-3:0,4,-4:0,-4,4:3,0,-3:2,1,-3:3,-1,-2:2,2,-4:1,3,-4:-3,0,3:-2,-1,3:-3,1,2:-4,2,2:-4,3,1"> - <path id="building2-floor" class="floor" - d="m 38.786985,67.5 17.32,-30 v -45 l -17.32,-30 v -30 h -77.94 v 30 l -17.32,30 v 45 l 17.32,30 z" /> - <path id="building2-outer-wall" class="outer-wall" - d="m -21.833015,67.5 v -60 m 17.3200004,-75 v 30 M 17.136985,15 4.146985,7.5 m 51.96,30 -12.99,-7.5 m -38.97,-67.5 v 45 h -60.62 m 17.32,-45 h 77.94 m -69.28,105 h 69.28 l 17.32,-30 v -45 l -17.32,-30 v -30 h -77.94 v 30 l -17.32,30 v 45 l 17.32,30 z" /> - <path id="building2-inner-wall" class="inner-wall" - d="m -21.833015,67.5 v -60 m 17.3200004,-75 v 30 M 17.136985,15 4.146985,7.5 m 51.96,30 -12.99,-7.5 m -38.97,-67.5 v 45 h -60.62 m 17.32,-45 h 77.94 m -69.28,105 h 69.28 l 17.32,-30 v -45 l -17.32,-30 v -30 h -77.94 v 30 l -17.32,30 v 45 l 17.32,30 z" /> - <path id="building2-doors" class="doors" - d="m 3.698745,-67.5 h 9.55648 m 7.76351,30 h 9.55648 M -4.9612546,67.5 H 4.595225 m -18.71725,-60 h 9.5564804 m -35.0357204,0 h 9.55648 m 33.74353,-75 h 9.55648 m -35.53648,30 h 9.55648 m 7.7635204,105 H 4.595225 m -18.71725,-60 h 9.5564804 m -35.0357204,0 h 9.55648" /> - </g> + <g id="building1" class="building"> + <rect id="building1-floor" class="floor" x="-33.25" y="-62.25" width="66.5" height="124.5"/> + <path id="building1-outer-wall" class="outer-wall" d=" + M -33.25 -62.25 V 62.25 H 33.25 V -62.25 Z + M -6.75 -37.75 V 6.25 H 2.25 V 62.25 + M -33.25 16.25 H -7.75 V 62.25 + M 2.25 39.25 H 33.25 + M 13.75 6.25 V -1.25 H 33.25 + "/> + <path id="building1-inner-wall" class="inner-wall" d=" + M -33.25 -62.25 V 62.25 H 33.25 V -62.25 Z + M -6.75 -37.75 V 6.25 H 2.25 V 62.25 + M -33.25 16.25 H -7.75 V 62.25 + M 2.25 39.25 H 33.25 + M 13.75 6.25 V -1.25 H 33.25 + "/> + <path id="building1-windows" class="windows" d=" + M -33.25 -45.74 V -33.25 + M -33.25 40.75 V 53.75 + M 11.75 62.25 H 31.25 + "/> + <path id="building1-door-edges" class="door-edges" d=" + M -33.25 -16.25 V -13.75 M -33.25 -5.75 V -3.25 + M -7.75 26.25 V 29.25 M -7.75 36.25 V 39.25 + M 2.25 13.75 V 16.25 M 2.25 24.25 V 26.75 + M 2.25 40.25 V 42.75 M 2.25 50.75 V 53.25 + M -3.25 -62.25 H -0.75 M 11.25 -62.25 H 13.25 + "/> + <path id="building1-doors" class="doors" d=" + M -33.25 -13.75 V -5.75 + M -7.75 29.25 V 36.25 + M 2.25 16.25 V 24.25 + M 2.25 42.75 V 50.75 + M -0.75 -62.25 H 11.25 + "/> + </g> + + <g id="building2" class="building"> + <path id="building2-floor" class="floor" + d="m 38.786985,67.5 17.32,-30 v -45 l -17.32,-30 v -30 h -77.94 v 30 l -17.32,30 v 45 l 17.32,30 z" /> + <path id="building2-outer-wall" class="outer-wall" + d="m -21.833015,67.5 v -60 m 17.3200004,-75 v 30 M 17.136985,15 4.146985,7.5 m 51.96,30 -12.99,-7.5 m -38.97,-67.5 v 45 h -60.62 m 17.32,-45 h 77.94 m -69.28,105 h 69.28 l 17.32,-30 v -45 l -17.32,-30 v -30 h -77.94 v 30 l -17.32,30 v 45 l 17.32,30 z" /> + <path id="building2-inner-wall" class="inner-wall" + d="m -21.833015,67.5 v -60 m 17.3200004,-75 v 30 M 17.136985,15 4.146985,7.5 m 51.96,30 -12.99,-7.5 m -38.97,-67.5 v 45 h -60.62 m 17.32,-45 h 77.94 m -69.28,105 h 69.28 l 17.32,-30 v -45 l -17.32,-30 v -30 h -77.94 v 30 l -17.32,30 v 45 l 17.32,30 z" /> + <path id="building2-doors" class="doors" + d="m 3.698745,-67.5 h 9.55648 m 7.76351,30 h 9.55648 M -4.9612546,67.5 H 4.595225 m -18.71725,-60 h 9.5564804 m -35.0357204,0 h 9.55648 m 33.74353,-75 h 9.55648 m -35.53648,30 h 9.55648 m 7.7635204,105 H 4.595225 m -18.71725,-60 h 9.5564804 m -35.0357204,0 h 9.55648" /> + </g> + + <g id="building6" class="building"> + <rect id="building6-floor" class="floor" x="-23" y="-58.75" width="46" height="117.5" /> + <path id="building6-outer-wall" class="outer-wall" d=" + M -23 -58.75 h 46 v 117.5 h -46 z + m 19.5 0 v 44 h 26.5 + M -23 26.25 h 46 + m -18.5 0 v -16 + " /> + <path id="building6-inner-wall" class="inner-wall" d=" + M -23 -58.75 h 46 v 117.5 h -46 z + m 19.5 0 v 44 h 26.5 + M -23 26.25 h 46 + m -18.5 0 v -16 + " /> + <path id="building6-windows" class="windows" d=" + M 3.5 -58.75 h 10 + m 9.5 56 v 10.5 + m 0 20.5 v 10.5 + M -23 -31 v 10.5 + m 0 18 v 10.5 + " /> + <path id="building6-door-edges" class="door-edges" d=" + M -23 -46.5 v 10 + m 23.5 21.75 h 16.5 + m -30.75 41 h 10 + m -10 32.5 h 10 + " /> + <path id="building6-door-doors" class="doors" d=" + M -23 -44 v 5 + m 26 24.25 h 11.5 + m -26 41 h 5.5 + m -5 32.5 h 5 + " /> + </g> + + <g id="building3" class="building"> + <rect id="building3-floor" class="floor" x="-32.25" y="-44" width="64.5" height="88"/> + <path id="building3-outer-wall" class="outer-wall" d=" + M -32.25 -44 h 64.5 v 88 h -64 z + m 37.5 0 v 18 + m -37.5 0 h 64.5 + m -36.5 0 v 10.5 + m 0 21 V 44 + m 24.5 -34.5 h 12 + "/> + <path id="building3-inner-wall" class="inner-wall" d=" + M -32.25 -44 h 64.5 v 88 h -64 z + m 37.5 0 v 18 + m -37.5 0 h 64.5 + m -36.5 0 v 10.5 + m 0 21 V 44 + m 24.5 -34.5 h 12 + "/> + <path id="building3-windows" class="windows" d=" + M -13.75 -44 h 10.5 + M 32.25 -10 v 10 + M 23 44 h -10.5 + M -32.25 29 v -10.5 + m 0 -21 v -10 + "/> + <path id="building3-door-edges" class="door-edges" d=" + M 12 -44 h 10.5 + m -45 18 h 10.5 + m 24.5 0 h 10.5 + M -22 44 h 10.5 + "/> + <path id="building3-doors" class="doors" d=" + M 15 -44 h 5 + m -40 18 h 5.5 + m 29 0 h 5.5 + M -19.5 44 h 5.5 + "/> </g> </defs> diff --git a/src/radial.js b/src/radial.js index 5771099..9349bd1 100644 --- a/src/radial.js +++ b/src/radial.js @@ -328,10 +328,87 @@ const gameboard = svg.querySelector('.gameboard'); let mapsheet1 = { id: 'mapsheet1', - grid: mapsheet1hexCoords, + grid: new Map(mapsheetHexCoords), buildings: mapsheet1BuildingCoords }; +let mapsheet10 = { + id: 'mapsheet1', + grid: new Map(mapsheetHexCoords), + buildings: [ + { + type: 'building2', + grid: buildingHexes.bld2, + position: ({ q, r, s }) => ({ q: q + 7, r: r + 7, s: s - 14 }) + } + ] +}; + +let mapsheet20 = { + id: 'mapsheet2', + grid: new Map(mapsheetHexCoords), + buildings: [ + { + type: 'building2', + grid: new Map(buildingHexes.bld2), + position: ({ q, r, s }) => ({ q: q + 7, r: r + 7, s: s - 14 }) + }, + { + type: 'building6', + grid: new Map(buildingHexes.bld6), + position: ({ q, r, s }) => ({ q: q + 7, r: r - 6, s: s - 1 }) + }, + { + type: 'building1', + grid: new Map(buildingHexes.bld1), + position: ({ q, r, s }) => ({ q: q, r: r + 7, s: s - 7 }) + }, + { + type: 'building3', + grid: new Map(buildingHexes.bld3), + position: ({ q, r, s }) => ({ q: q - 14, r: r + 5, s: s + 9 }) + } + ] +}; + +let mapsheet30 = { + id: 'mapsheet3', + grid: new Map(mapsheetHexCoords), + buildings: [ + { + type: 'building2', + grid: new Map(buildingHexes.bld2), + position: reflectR({ q: 9, r: -6, s: -3 }) + }, + { + type: 'building6', + grid: new Map(buildingHexes.bld6), + position: reflectR({ q: 1, r: 6, s: -7 }) + }, + { + type: 'building1', + grid: new Map(buildingHexes.bld1), + position: ({ q, r, s }) => ({ q: q - 2, r: r - 5, s: s + 7 }) + }, + { + type: 'building3', + grid: new Map(buildingHexes.bld3), + position: reflectR({ q: 17, r: -7, s: -10 }) + } + ] +}; + +function reflectR(coords) { + return function ({ q, r, s }) { + return { + q: -s + coords.q, + r: -r + coords.r, + s: -q + coords.s, + transform: "scale(-1)" + }; + }; +} + let mapsheet2 = { id: 'mapsheet2', grid: mapsheet2hexCoords, @@ -350,7 +427,7 @@ let mapsheet4 = { buildings: mapsheet4BuildingCoords }; -function drawMapsheet(gameboard, { id, grid, buildings }) { +function drawMapsheet(gameboard, { id, grid, buildings }, { q: pq, r: pr, s: ps }) { const container = document.createElementNS(xmlns, 'g'); container.id = id; gameboard.appendChild(container); @@ -358,40 +435,64 @@ function drawMapsheet(gameboard, { id, grid, buildings }) { const gridContainer = document.createElementNS(xmlns, 'g'); gridContainer.classList.add('elevation-0'); container.appendChild(gridContainer); - drawHexes(gridContainer, grid, true); - const buildingHexes = buildings.reduce((acc, buildingCoords, index) => { + const buildingHexes = buildings.reduce((acc, building) => { const buildingContainer = document.createElementNS(xmlns, 'g'); buildingContainer.classList.add(`building`); - buildingContainer.classList.add(`building${index}`); + buildingContainer.classList.add(building.type); container.appendChild(buildingContainer); + let buildingGrid = translateCoords(building.grid, building.position); + buildingGrid = translateCoords(buildingGrid, ({ q, r, s }) => ({ q: q + pq, r: r + pr, s: s + ps })); + [-1, 0, 1].forEach(elevationLevel => { const hexContainer = document.createElementNS(xmlns, 'g'); hexContainer.classList.add(`elevation-${elevationLevel === -1 ? 'basement' : elevationLevel}`); buildingContainer.appendChild(hexContainer); - const hexes = translateCoords(buildingCoords, ({ q, r, s }) => ({ q, r, s, t: elevationLevel })); - drawHexes(hexContainer, hexes, true); - acc = new Map([...acc, ...hexes]); + buildingGrid = translateCoords(buildingGrid, ({ q, r, s }) => ({ q, r, s, t: elevationLevel })); + drawHexes(hexContainer, buildingGrid, true); + acc = new Map([...acc, ...buildingGrid]); }); + const buildingTemplate = document.querySelector(`defs #${building.type}`); + const origin = building.position({ q: 0, r: 0, s: 0 }); + const { x, y } = radialToScreenCoords({ q: origin.q + pq, r: origin.r + pr, s: origin.s + ps }); + + const buildingStructure = document.createElementNS(xmlns, 'g'); + buildingStructure.classList.add('structure'); + buildingStructure.setAttributeNS(null, 'transform', `translate(${x}, ${y}) ${origin.transform ? origin.transform : ''}`); + buildingContainer.appendChild(buildingStructure); + + for (let child of buildingTemplate.children) { + const use = document.createElementNS(xmlns, 'use'); + use.setAttributeNS(null, 'href', `#${child.id}`); + child.classList.forEach(className => use.classList.add(className)); + buildingStructure.appendChild(use); + } + return acc; }, new Map()); + grid = translateCoords(grid, ({ q, r, s }) => ({ q: q + pq, r: r + pr, s: s + ps })); + + for ([coords, v] of buildingHexes) grid.delete(coords); + drawHexes(gridContainer, grid, true); + return new Map([...grid, ...buildingHexes]); + // return { id, grid, buildings }; } -const horzMapVect = function(map) { - return vectorAdd(map, { q: 1, r: 0, s: -1 }, 33); +const horzMapVect = function(coords) { + return vectorAdd(coords, { q: 1, r: 0, s: -1 }, 33); } -const vertMapVect = function(map) { - return vectorAdd(map, { q: 1, r: -2, s: 1 }, 13); +const vertMapVect = function(coords) { + return vectorAdd(coords, { q: 1, r: -2, s: 1 }, 13); } -function vectorAdd(map, { q: dq, r: dr, s: ds }, scalar) { - return translateCoords(map, ({ q, r, s }) => ({ q: q - dq * scalar, r: r + dr * scalar, s: s - ds * scalar })); +function vectorAdd({ q, r, s }, { q: dq, r: dr, s: ds }, scalar) { + return ({ q: q - dq * scalar, r: r + dr * scalar, s: s - ds * scalar }); } function findMult(arr) { @@ -435,8 +536,16 @@ function findScalar(arr) { }); } -// const sheets = [[mapsheet2], [mapsheet3]]; -const sheets = [[mapsheet2], [mapsheet1], [mapsheet3]]; +// mapsheet10 = drawMapsheet(gameboard, mapsheet10, { q: -1, r: 0, s: 1 }); + +// const sheets = [[mapsheet10]]; + +// drawHexes(gameboard, buildingHexes.bld2, true); + +// drawHexes(addGroup(gameboard, 'part-1'), bld8, true); + +const sheets = [[mapsheet20], [mapsheet30]]; +// const sheets = [[mapsheet2], [mapsheet10], [mapsheet3]]; // const sheets = [[mapsheet4]]; // const sheets = [ @@ -444,24 +553,18 @@ const sheets = [[mapsheet2], [mapsheet1], [mapsheet3]]; // [mapsheet3, mapsheet4] // ]; -// mapsheet1 = drawMapsheet(gameboard, mapsheet1); - -// drawHexes(gameboard, buildingHexes.bld8, true); -// drawHexes(addGroup(gameboard, 'part-1'), bld8, true); - findScalar(findMult(sheets)).forEach(([vscalar, row]) => { - const vertMapVect = function(map) { - return vectorAdd(map, { q: 1, r: -2, s: 1 }, vscalar); + const vertMapVect = function(coords) { + return vectorAdd(coords, { q: 1, r: -2, s: 1 }, vscalar); } row.forEach(([hscalar, ms]) => { - const horzMapVect = function(map) { - return vectorAdd(map, { q: 1, r: 0, s: -1 }, hscalar); + const horzMapVect = function(coords) { + return vectorAdd(coords, { q: 1, r: 0, s: -1 }, hscalar); } - ms.grid = horzMapVect(vertMapVect(ms.grid)); - ms.buildings = ms.buildings.map(buildings => horzMapVect(vertMapVect(buildings))); - ms = drawMapsheet(gameboard, ms); + console.log(horzMapVect(vertMapVect({ q: 0, r: 0, s: 0 }))); + ms = drawMapsheet(gameboard, ms, horzMapVect(vertMapVect({ q: 0, r: 0, s: 0 }))); }) }); @@ -487,3 +590,4 @@ function addGroup(container, className) { container.appendChild(g); return g; } + |