diff --git a/game/buildings.c b/game/buildings.c index 6c9d8ed..c9fa970 100644 --- a/game/buildings.c +++ b/game/buildings.c @@ -13,6 +13,9 @@ bool canPlaceBuilding(Game *game, BuildingType type, BzTile tileX, BzTile tileY) getBuildingSize(type, &sizeX, &sizeY); if (sizeX == 0 || sizeY == 0) return false; + if (!canAffordBuilding(type, game->playerResources[game->player])) + return false; + BzTileMap *map = &game->map; // Ensure that it is within the map if (tileX < 0 || tileX + sizeX > map->width || @@ -92,6 +95,67 @@ ecs_entity_t placeBuilding(Game *game, BuildingType type, } +void getBuildingCost(BuildingType type, i32 cost[RES_COUNT]) { + for (i32 i = 0; i < RES_COUNT; i++) { + cost[i] = 0; + } + switch (type) { + case BUILDING_ARCHERY_RANGE: + cost[RES_WOOD] = 400; + cost[RES_FOOD] = 400; + cost[RES_GOLD] = 200; + break; + case BUILDING_BARRACKS: + cost[RES_WOOD] = 200; + cost[RES_FOOD] = 400; + cost[RES_GOLD] = 500; + break; + case BUILDING_GRANARY: + cost[RES_WOOD] = 80; + break; + case BUILDING_HOUSE_01: + case BUILDING_HOUSE_02: + case BUILDING_HOUSE_03: + case BUILDING_HOUSE_04: + case BUILDING_HOUSE_05: + case BUILDING_HOUSE_06: + case BUILDING_HOUSE_07: + case BUILDING_HOUSE_08: + case BUILDING_HOUSE_09: + case BUILDING_HOUSE_10: + case BUILDING_HOUSE_11: + case BUILDING_HOUSE_12: + cost[RES_WOOD] = 50; + break; + case BUILDING_MARKET: + cost[RES_WOOD] = 200; + cost[RES_FOOD] = 200; + cost[RES_GOLD] = 200; + break; + case BUILDING_MILL: + cost[RES_WOOD] = 200; + cost[RES_GOLD] = 50; + break; + case BUILDING_WAREHOUSE: + cost[RES_WOOD] = 100; + break; + case BUILDING_NONE: + case BUILDING_KEEP: + case BUILDING_COUNT: + // NA + break; + } +} +bool canAffordBuilding(BuildingType type, PlayerResources res) { + i32 needed[RES_COUNT] = {0, }; + getBuildingCost(type, needed); + + if (needed[RES_WOOD] > res.wood) return false; + if (needed[RES_FOOD] > res.food) return false; + if (needed[RES_GOLD] > res.gold) return false; + return true; +} + Vector2 getPositionNearBuilding(ecs_entity_t building, Vector2 fromPos) { BZ_ASSERT(ecs_is_alive(ECS, building)); BZ_ASSERT(ecs_has(ECS, building, Position)); diff --git a/game/buildings.h b/game/buildings.h index 9b79208..2a0d53e 100644 --- a/game/buildings.h +++ b/game/buildings.h @@ -7,11 +7,16 @@ #include "components.h" #include "game_tileset.h" +#include "game_state.h" + typedef struct Game Game; bool canPlaceBuilding(Game *game, BuildingType type, i32 tileX, i32 tileY); ecs_entity_t placeBuilding(Game *game, BuildingType type, i32 posX, i32 posY, Owner owner); +void getBuildingCost(BuildingType type, i32 cost[RES_COUNT]); +bool canAffordBuilding(BuildingType type, PlayerResources res); + Vector2 getPositionNearBuilding(ecs_entity_t building, Vector2 fromPos); #endif //PIXELDEFENSE_BUILDINGS_H diff --git a/game/components.h b/game/components.h index b3d8bc3..6968753 100644 --- a/game/components.h +++ b/game/components.h @@ -4,6 +4,7 @@ #include #include +#include "constants.h" #include "game_tileset.h" // Needed, so we can clean up all game created entities @@ -33,12 +34,6 @@ typedef struct Resource { } Resource; extern ECS_COMPONENT_DECLARE(Resource); -typedef enum Player { - PLAYER_RED = 0, - PLAYER_BLUE = 1, - PLAYER_COUNT -} Player; - typedef struct Owner { Player player; } Owner; diff --git a/game/constants.h b/game/constants.h index 80cee0c..479824f 100644 --- a/game/constants.h +++ b/game/constants.h @@ -7,4 +7,11 @@ enum { COLL_LAYER_TRANSPARENCY = 7, }; +typedef enum Player { + PLAYER_RED = 0, + PLAYER_BLUE = 1, + PLAYER_COUNT +} Player; + + #endif //PIXELDEFENSE_CONSTANTS_H diff --git a/game/game_state.h b/game/game_state.h index 620d8f5..71b1299 100644 --- a/game/game_state.h +++ b/game/game_state.h @@ -42,6 +42,14 @@ static Options getDefaultOptions() { }; } +typedef struct PlayerResources { + i64 wood; + i64 food; + i64 gold; + i64 pop; + i64 popCapacity; +} PlayerResources; + typedef struct Game { GameScreen screen; GameScreen nextScreen; @@ -56,13 +64,8 @@ typedef struct Game { Options options; - struct { - i64 wood; - i64 iron; - i64 food; - i64 gold; - i64 pop; - } resources; + PlayerResources playerResources[PLAYER_COUNT]; + Player player; BzStackAlloc stackAlloc; struct { BzBTNode *workerHarvest; diff --git a/game/main.c b/game/main.c index 32a43aa..f0ce1d5 100644 --- a/game/main.c +++ b/game/main.c @@ -616,11 +616,12 @@ void imguiRender(float dt, void *userData) { } if (igCollapsingHeader_TreeNodeFlags("Resources", 0)) { - igText("Wood: %lld", game->resources.wood); - igText("Iron: %lld", game->resources.iron); - igText("Food: %lld", game->resources.food); - igText("Gold: %lld", game->resources.gold); - igText("Population: %lld", game->resources.pop); + PlayerResources resources = game->playerResources[game->player]; + igText("Wood: %lld", resources.wood); + igText("Food: %lld", resources.food); + igText("Gold: %lld", resources.gold); + igText("Pop: %lld", resources.pop); + igText("Pop Capacity: %lld", resources.pop); } if (igCollapsingHeader_TreeNodeFlags("BuildMenu", 0)) { for (int i = BUILDING_NONE; i < BUILDING_COUNT; i++) { diff --git a/game/systems/s_ui.c b/game/systems/s_ui.c index 4989e8a..177fb5c 100644 --- a/game/systems/s_ui.c +++ b/game/systems/s_ui.c @@ -4,6 +4,7 @@ #include "../input.h" #include "../map_init.h" #include "../ui_widgets.h" +#include "../buildings.h" void drawGameUI(Game *game, f32 dt) { // UI @@ -37,15 +38,15 @@ void drawGameUI(Game *game, f32 dt) { }); BzTileset *tileset = &game->tileset; Rectangle woodRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_WOOD)); - Rectangle stoneRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_STONE)); Rectangle foodRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_APPLE)); Rectangle goldRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_GOLD)); Rectangle popRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_POP)); - uiGameResCount(100, -1, woodRec, tileset->tiles); - uiGameResCount(100, -1, stoneRec, tileset->tiles); - uiGameResCount(100, -1, foodRec, tileset->tiles); - uiGameResCount(250, -1, goldRec, tileset->tiles); - uiGameResCount(1, 10, popRec, tileset->tiles); + + PlayerResources resources = game->playerResources[game->player]; + uiGameResCount(resources.wood, -1, woodRec, tileset->tiles); + uiGameResCount(resources.food, -1, foodRec, tileset->tiles); + uiGameResCount(resources.gold, -1, goldRec, tileset->tiles); + uiGameResCount(resources.pop, resources.popCapacity, popRec, tileset->tiles); bzUIPopParent(UI); @@ -97,7 +98,11 @@ void drawGameUI(Game *game, f32 dt) { rec.height *= sizeY; Texture2D tex = tileset->tiles; bool selected = input->building == buildingOrder[i]; - uiGameBuild(buildingNames[i], rec, tex, &selected); + PlayerResources *res = &game->playerResources[game->player]; + bool canAfford = canAffordBuilding(buildingType, *res); + uiGameBuild(buildingNames[i], rec, tex, canAfford, &selected); + if (!canAfford) + selected = false; if (selected) { input->building = buildingOrder[i]; input->state = INPUT_BUILDING; diff --git a/game/ui_widgets.c b/game/ui_widgets.c index fce0f13..c76fa82 100644 --- a/game/ui_widgets.c +++ b/game/ui_widgets.c @@ -242,7 +242,7 @@ void uiGameResCount(i32 amount, i32 capacity, Rectangle icon, Texture2D texture) bzUIPopParent(UI); } -void uiGameBuild(const char *label, Rectangle rec, Texture2D tex, bool *selected) { +void uiGameBuild(const char *label, Rectangle rec, Texture2D tex, bool canAfford, bool *selected) { f32 scl = uiGetScale(); BzUINode *btn = bzUINodeMake(UI, bzUIKeyFromString(label), &(BzUINodeDesc) { .flags = BZ_UI_CLICKABLE | BZ_UI_ALIGN_CENTER | BZ_UI_DRAW_BORDER, @@ -255,10 +255,10 @@ void uiGameBuild(const char *label, Rectangle rec, Texture2D tex, bool *selected BzUIInteraction inter = bzUIGetInteraction(UI, btn); - Color bgColor = DARKBROWN; + Color bgColor = canAfford ? DARKBROWN : MAROON; if (*selected || inter.hovering) - bgColor = BROWN; - if (inter.clicked) + bgColor = canAfford ? BROWN : RED; + if (inter.clicked && canAfford) *selected = true; bzUISetBackgroundStyle(UI, btn, (BzUIBackgroundStyle) { diff --git a/game/ui_widgets.h b/game/ui_widgets.h index b826389..20fe123 100644 --- a/game/ui_widgets.h +++ b/game/ui_widgets.h @@ -27,6 +27,6 @@ void uiSettingsSlider(const char *txt, f32 *value); void uiGameResCount(i32 amount, i32 capacity, Rectangle icon, Texture2D texture); -void uiGameBuild(const char *label, Rectangle rec, Texture2D tex, bool *selected); +void uiGameBuild(const char *label, Rectangle rec, Texture2D tex, bool canAfford, bool *selected); #endif //PIXELDEFENSE_UI_WIDGETS_H