Compare commits
3 Commits
6c18870b6b
...
fbe48f925d
Author | SHA1 | Date | |
---|---|---|---|
fbe48f925d | |||
dd50d9b80d | |||
04a37732d9 |
BIN
public/img/icons/culture.png
Normal file
BIN
public/img/icons/culture.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 873 B |
@ -1,8 +1,57 @@
|
||||
<script lang="ts">
|
||||
import moves from "../moves";
|
||||
import type { BuildingType } from "../types";
|
||||
import { canPayBuildingCost } from "../utils";
|
||||
import village from "../village";
|
||||
|
||||
export let building: BuildingType;
|
||||
|
||||
|
||||
$: isUpgrading = $village.queue.find(q => q.id === building.id);
|
||||
$: canUpgrade = canPayBuildingCost($village, building);
|
||||
|
||||
|
||||
function upgradeBuilding() {
|
||||
moves.upgradeBuilding(building.id);
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<p>{ building.name }</p>
|
||||
<p>{ building.level }</p>
|
||||
<p>
|
||||
<button
|
||||
class="level"
|
||||
class:can-upgrade={ canUpgrade }
|
||||
class:is-upgrading={ isUpgrading }
|
||||
on:click|stopPropagation={ upgradeBuilding }
|
||||
>
|
||||
{ building.level }
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.level {
|
||||
aspect-ratio: 1;
|
||||
background-color: hsl(208, 100%, 97%);
|
||||
border: 0.4em solid hsl(0, 0%, 45%);
|
||||
border-radius: 100%;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 0 0.2em black;
|
||||
color: hsl(0, 0%, 10%);
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.level.can-upgrade {
|
||||
border-color: hsl(90, 99%, 36%);
|
||||
}
|
||||
|
||||
.level.is-upgrading {
|
||||
border-color: hsl(56, 99%, 43%);
|
||||
}
|
||||
|
||||
.level:hover.can-upgrade {
|
||||
border-color: hsl(90, 99%, 36%);
|
||||
}
|
||||
</style>
|
||||
|
@ -12,6 +12,7 @@
|
||||
import Queue from "./Queue.svelte";
|
||||
import Resources from "./Resources.svelte";
|
||||
import Units from "./Units.svelte";
|
||||
import Victory from "./Victory.svelte";
|
||||
|
||||
|
||||
onMount(() => {
|
||||
@ -53,6 +54,7 @@
|
||||
<section class="overlay">
|
||||
<BuildingCreator />
|
||||
<BuildingPanel />
|
||||
<Victory />
|
||||
</section>
|
||||
|
||||
<style>
|
||||
|
@ -28,6 +28,10 @@
|
||||
{ Math.floor($village.resources.food) } / { capacity.food }
|
||||
({ production.food >= 0 ? '+' : '' }{ production.food })
|
||||
</div>
|
||||
<div>
|
||||
<img src="/img/icons/culture.png" alt="Culture" />
|
||||
{ Math.floor($village.resources.culture) }
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
30
src/hud/Victory.svelte
Normal file
30
src/hud/Victory.svelte
Normal file
@ -0,0 +1,30 @@
|
||||
<script lang="ts">
|
||||
import village from "../village";
|
||||
|
||||
|
||||
function restart() {
|
||||
village.reset();
|
||||
}
|
||||
</script>
|
||||
|
||||
{ #if $village.victory }
|
||||
<section>
|
||||
<h1>Victory!</h1>
|
||||
<div>
|
||||
<button on:click={ restart }>Play again</button>
|
||||
</div>
|
||||
</section>
|
||||
{ /if }
|
||||
|
||||
<style>
|
||||
section {
|
||||
background-color: hsl(0, 0%, 10%, 0.9);
|
||||
display: grid;
|
||||
place-items: center;
|
||||
height: 100vh;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100vw;
|
||||
}
|
||||
</style>
|
@ -1,4 +1,4 @@
|
||||
import { enqueueBuilding } from "../utils";
|
||||
import { canPayBuildingCost, enqueueBuilding, getBuildingUpgradeCost } from "../utils";
|
||||
import type { VillageState } from "../village";
|
||||
|
||||
|
||||
@ -8,20 +8,12 @@ export default function upgradeBuilding(V: VillageState, buildingId: number) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ongoingUpgrades = V.queue.filter(q => q.id === building.id);
|
||||
const level = building.level + 1 + ongoingUpgrades.length;
|
||||
|
||||
const cost = building.cost(level);
|
||||
|
||||
if (
|
||||
cost.wood > V.resources.wood
|
||||
|| cost.stone > V.resources.stone
|
||||
|| cost.iron > V.resources.iron
|
||||
|| cost.food > V.resources.food
|
||||
) {
|
||||
if (!canPayBuildingCost(V, building)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const cost = getBuildingUpgradeCost(V, building);
|
||||
|
||||
V.resources.wood -= cost.wood;
|
||||
V.resources.stone -= cost.stone;
|
||||
V.resources.iron -= cost.iron;
|
||||
|
@ -15,6 +15,11 @@ export interface CostType {
|
||||
export type ProductionType = CostType;
|
||||
|
||||
|
||||
export interface ResourcesType extends CostType {
|
||||
culture: number;
|
||||
}
|
||||
|
||||
|
||||
export interface BuildingSource {
|
||||
name: string;
|
||||
type: string;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { produce } from 'immer';
|
||||
|
||||
import { getBuilding, getProduction, getStorage } from './utils';
|
||||
import { getBuilding, getProduction, getStorage, getUnitSource } from './utils';
|
||||
import village, { type VillageState } from "./village";
|
||||
import type { ProductionType } from './types';
|
||||
|
||||
@ -17,6 +17,10 @@ export default function update(timestamp: number) {
|
||||
const delta = timestamp - lastFrame;
|
||||
|
||||
village.update(state => {
|
||||
if (state.victory) {
|
||||
return state;
|
||||
}
|
||||
|
||||
return produce(state, (V: VillageState) => {
|
||||
// Advance building construction.
|
||||
if (V.queue.length) {
|
||||
@ -67,6 +71,17 @@ export default function update(timestamp: number) {
|
||||
}
|
||||
});
|
||||
|
||||
// Make philosophers produce culture.
|
||||
const philosopher = getUnitSource('philosopher');
|
||||
const outputPerMinute = philosopher.behavior.culturePerMinute;
|
||||
const outputPerMilisecond = outputPerMinute / 60.0 / 1000.0;
|
||||
V.resources.culture += outputPerMilisecond * delta * (V.units.philosopher || 0);
|
||||
|
||||
// Check if the game is won.
|
||||
if (V.resources.culture >= 2) {
|
||||
V.victory = true;
|
||||
}
|
||||
|
||||
return V;
|
||||
});
|
||||
});
|
||||
|
21
src/utils.ts
21
src/utils.ts
@ -1,5 +1,5 @@
|
||||
import units from "./data/units";
|
||||
import type { BuildingType, ProductionType } from "./types";
|
||||
import type { BuildingType, CostType, ProductionType } from "./types";
|
||||
import type { VillageState } from "./village";
|
||||
|
||||
|
||||
@ -109,3 +109,22 @@ export function enqueueBuilding(V: VillageState, building: BuildingType) {
|
||||
remainingTime,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export function getBuildingUpgradeCost(V: VillageState, building: BuildingType): CostType {
|
||||
const ongoingUpgrades = V.queue.filter(q => q.id === building.id);
|
||||
const level = building.level + ongoingUpgrades.length + 1;
|
||||
return building.cost(level);
|
||||
}
|
||||
|
||||
|
||||
export function canPayBuildingCost(V: VillageState, building: BuildingType): boolean {
|
||||
const cost = getBuildingUpgradeCost(V, building);
|
||||
|
||||
return !(
|
||||
cost.wood > V.resources.wood
|
||||
|| cost.stone > V.resources.stone
|
||||
|| cost.iron > V.resources.iron
|
||||
|| cost.food > V.resources.food
|
||||
);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import { writable } from "svelte/store";
|
||||
|
||||
import { createBuilding } from "./create";
|
||||
import { getTilesAtDistance, Hex } from "./hexgrid";
|
||||
import type { BuildingType } from "./types";
|
||||
import type { BuildingType, ResourcesType } from "./types";
|
||||
import { getKeysAsNumbers, shuffle } from "./utils";
|
||||
|
||||
|
||||
@ -24,16 +24,11 @@ export interface VillageState {
|
||||
units: {
|
||||
[key: string]: number;
|
||||
},
|
||||
resources: {
|
||||
wood: number;
|
||||
stone: number;
|
||||
iron: number;
|
||||
food: number;
|
||||
culture: number;
|
||||
};
|
||||
resources: ResourcesType;
|
||||
villageTiles: Board;
|
||||
outsideTiles: Board;
|
||||
queue: QueuedBuilding[];
|
||||
victory: boolean;
|
||||
}
|
||||
|
||||
|
||||
@ -89,6 +84,7 @@ function getInitialState() {
|
||||
villageTiles: getInitialVillageBoard(),
|
||||
outsideTiles: getInitialOutsideBoard(),
|
||||
queue: [],
|
||||
victory: false,
|
||||
};
|
||||
|
||||
// Create the Town hall.
|
||||
@ -128,4 +124,12 @@ function getInitialState() {
|
||||
const village = writable<VillageState>(getInitialState());
|
||||
|
||||
|
||||
export default village;
|
||||
function reset() {
|
||||
village.set(getInitialState());
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
...village,
|
||||
reset,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user