Add a building panel to upgrade them.
This commit is contained in:
parent
5a7fb8ddcb
commit
25f281028c
7
src/board/BuildingTile.svelte
Normal file
7
src/board/BuildingTile.svelte
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { Building } from "../types";
|
||||||
|
|
||||||
|
export let building: Building;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p>{ building.name }</p>
|
@ -1,5 +1,4 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export let empty = false;
|
|
||||||
export let onTileClick: () => void;
|
export let onTileClick: () => void;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -7,10 +6,7 @@
|
|||||||
class="invisible"
|
class="invisible"
|
||||||
on:click={ onTileClick }
|
on:click={ onTileClick }
|
||||||
>
|
>
|
||||||
<div
|
<div class="hexagon">
|
||||||
class={ "hexagon" }
|
|
||||||
class:empty
|
|
||||||
>
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
@ -18,70 +14,33 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* Source: https://codepen.io/gpyne/pen/iElhp */
|
|
||||||
.hexagon {
|
.hexagon {
|
||||||
|
aspect-ratio: 1;
|
||||||
background-color: hsl(220, 75%, 75%);
|
background-color: hsl(220, 75%, 75%);
|
||||||
|
border-radius: 100%;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: inline-block;
|
|
||||||
font-size: 1.2vmin;
|
font-size: 1.2vmin;
|
||||||
margin: -0.8em 2.7em;
|
height: 12em;
|
||||||
position: relative;
|
margin: -0.8em 0.2em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
rotate: 90deg;
|
position: relative;
|
||||||
}
|
|
||||||
.hexagon,
|
|
||||||
.hexagon::before,
|
|
||||||
.hexagon::after {
|
|
||||||
width: 6.7em;
|
|
||||||
height: 11.6em;
|
|
||||||
border-radius: 20%/5%;
|
|
||||||
}
|
|
||||||
.hexagon::before {
|
|
||||||
background-color: inherit;
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
transform: rotate(-60deg);
|
|
||||||
}
|
|
||||||
.hexagon::after {
|
|
||||||
background-color: inherit;
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
transform: rotate(60deg);
|
|
||||||
}
|
|
||||||
.hexagon:nth-child(even) {
|
|
||||||
top: 5.9em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hexagon:hover {
|
.hexagon:hover {
|
||||||
background-color: hsl(60, 75%, 75%);
|
background-color: hsl(60, 75%, 75%);
|
||||||
z-index: 105;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hexagon:active {
|
.hexagon:active {
|
||||||
background-color: hsl(60, 75%, 50%);
|
background-color: hsl(60, 75%, 50%);
|
||||||
z-index: 110;
|
|
||||||
}
|
|
||||||
.hexagon.empty {
|
|
||||||
position: relative;
|
|
||||||
display: none;
|
|
||||||
width: 6.7em;
|
|
||||||
height: 11.6em;
|
|
||||||
margin: 0.1em 1.8em;
|
|
||||||
}
|
|
||||||
.hexagon.empty:nth-child(even) {
|
|
||||||
top: 5.9em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hexagon .content {
|
.hexagon .content {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: grid;
|
height: 100%;
|
||||||
top: 5%;
|
|
||||||
left: -40%;
|
|
||||||
font-size: 4vmin;
|
|
||||||
height: 90%;
|
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
width: 180%;
|
width: 100%;
|
||||||
z-index: 100;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hexagon .content > * {
|
.hexagon .content > * {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
import { Hex } from "../hexgrid";
|
import { Hex } from "../hexgrid";
|
||||||
import moves from "../moves";
|
import moves from "../moves";
|
||||||
import showBuildingCreator from "../stores/showBuildingCreator";
|
import showBuildingCreator from "../stores/showBuildingCreator";
|
||||||
import { getKeysAsNumbers } from "../utils";
|
import showBuildingPanel from "../stores/showBuildingPanel";
|
||||||
|
import { getBuilding, getKeysAsNumbers } from "../utils";
|
||||||
import village from "../village";
|
import village from "../village";
|
||||||
|
import BuildingTile from "./BuildingTile.svelte";
|
||||||
import Tile from "./Tile.svelte";
|
import Tile from "./Tile.svelte";
|
||||||
|
|
||||||
|
|
||||||
@ -11,10 +13,13 @@
|
|||||||
moves.upgradeBuilding(id);
|
moves.upgradeBuilding(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function openBuildingCreator(tile: Hex) {
|
function openBuildingCreator(tile: Hex) {
|
||||||
showBuildingCreator.set(tile);
|
showBuildingCreator.set(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openBuildingPanel(buildingId: number) {
|
||||||
|
showBuildingPanel.set(buildingId);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="village-map">
|
<section class="village-map">
|
||||||
@ -24,9 +29,9 @@
|
|||||||
{ #each getKeysAsNumbers($village.villageTiles[y]) as x }
|
{ #each getKeysAsNumbers($village.villageTiles[y]) as x }
|
||||||
{ #if $village.villageTiles[y][x] >= 0 }
|
{ #if $village.villageTiles[y][x] >= 0 }
|
||||||
<Tile
|
<Tile
|
||||||
onTileClick={ () => {} }
|
onTileClick={ () => openBuildingPanel($village.villageTiles[y][x]) }
|
||||||
>
|
>
|
||||||
<p>{ $village.buildings.find(b => b.id === $village.villageTiles[y][x])?.name }</p>
|
<BuildingTile building={ getBuilding($village, $village.villageTiles[y][x]) } />
|
||||||
</Tile>
|
</Tile>
|
||||||
{ :else }
|
{ :else }
|
||||||
<Tile
|
<Tile
|
||||||
|
74
src/hud/BuildingPanel.svelte
Normal file
74
src/hud/BuildingPanel.svelte
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import buildings from "../buildings";
|
||||||
|
import moves from "../moves";
|
||||||
|
import showBuildingPanel from "../stores/showBuildingPanel";
|
||||||
|
import { getBuilding } from "../utils";
|
||||||
|
import village from "../village";
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
showBuildingPanel.set(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function upgrade() {
|
||||||
|
if ($showBuildingPanel === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moves.upgradeBuilding($showBuildingPanel)) {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$: building = ($showBuildingPanel !== null) ? getBuilding($village, $showBuildingPanel) : null;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{ #if building !== null }
|
||||||
|
<section>
|
||||||
|
<div class="building-panel">
|
||||||
|
<header>
|
||||||
|
<h1>Building</h1>
|
||||||
|
<span class="close">
|
||||||
|
<button on:click={ close }>X</button>
|
||||||
|
</span>
|
||||||
|
</header>
|
||||||
|
<div class="building">
|
||||||
|
<div>
|
||||||
|
<p>{ building.name } ({ building.level })</p>
|
||||||
|
<button on:click={ () => upgrade() }>Upgrade</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{ /if }
|
||||||
|
|
||||||
|
<style>
|
||||||
|
section {
|
||||||
|
background-color: hsl(0, 0%, 10%, 0.8);
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
left: 0;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 100vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.building-panel {
|
||||||
|
background-color: hsl(0, 0%, 20%);
|
||||||
|
border: 0.2em solid grey;
|
||||||
|
border-radius: .4em;
|
||||||
|
width: 80%;
|
||||||
|
height: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.building-panel header {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.building-panel header .close {
|
||||||
|
position: absolute;
|
||||||
|
right: 1em;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
</style>
|
@ -5,6 +5,7 @@
|
|||||||
import update from "../update";
|
import update from "../update";
|
||||||
import BuildingCreator from "./BuildingCreator.svelte";
|
import BuildingCreator from "./BuildingCreator.svelte";
|
||||||
import Resources from "./Resources.svelte";
|
import Resources from "./Resources.svelte";
|
||||||
|
import BuildingPanel from "./BuildingPanel.svelte";
|
||||||
|
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
@ -32,6 +33,7 @@
|
|||||||
</section>
|
</section>
|
||||||
<section class="overlay">
|
<section class="overlay">
|
||||||
<BuildingCreator />
|
<BuildingCreator />
|
||||||
|
<BuildingPanel />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
4
src/stores/showBuildingPanel.ts
Normal file
4
src/stores/showBuildingPanel.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
|
|
||||||
|
export default writable<number | null>(null);
|
11
src/utils.ts
11
src/utils.ts
@ -1,4 +1,4 @@
|
|||||||
import type { Production } from "./types";
|
import type { Building, Production } from "./types";
|
||||||
import type { VillageState } from "./village";
|
import type { VillageState } from "./village";
|
||||||
|
|
||||||
|
|
||||||
@ -46,6 +46,15 @@ export function getStorage(villageState: VillageState): Production {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function getBuilding(V: VillageState, buildingId: number): Building {
|
||||||
|
const building = V.buildings.find(b => b.id === buildingId);
|
||||||
|
if (!building) {
|
||||||
|
throw new Error(`Cannot find building with id "${buildingId}"`);
|
||||||
|
}
|
||||||
|
return building;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getKeysAsNumbers(dict: Object): Array<number> {
|
export function getKeysAsNumbers(dict: Object): Array<number> {
|
||||||
return Object.keys(dict).map(i => parseInt(i)).sort((a, b) => a - b);
|
return Object.keys(dict).map(i => parseInt(i)).sort((a, b) => a - b);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user