Proper build UI

This commit is contained in:
2024-01-23 16:54:39 +01:00
parent f3acb1a0a3
commit b6e54a7fcb
9 changed files with 110 additions and 30 deletions

View File

@@ -13,6 +13,9 @@ bool canPlaceBuilding(Game *game, BuildingType type, BzTile tileX, BzTile tileY)
getBuildingSize(type, &sizeX, &sizeY); getBuildingSize(type, &sizeX, &sizeY);
if (sizeX == 0 || sizeY == 0) return false; if (sizeX == 0 || sizeY == 0) return false;
if (!canAffordBuilding(type, game->playerResources[game->player]))
return false;
BzTileMap *map = &game->map; BzTileMap *map = &game->map;
// Ensure that it is within the map // Ensure that it is within the map
if (tileX < 0 || tileX + sizeX > map->width || 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) { Vector2 getPositionNearBuilding(ecs_entity_t building, Vector2 fromPos) {
BZ_ASSERT(ecs_is_alive(ECS, building)); BZ_ASSERT(ecs_is_alive(ECS, building));
BZ_ASSERT(ecs_has(ECS, building, Position)); BZ_ASSERT(ecs_has(ECS, building, Position));

View File

@@ -7,11 +7,16 @@
#include "components.h" #include "components.h"
#include "game_tileset.h" #include "game_tileset.h"
#include "game_state.h"
typedef struct Game Game; typedef struct Game Game;
bool canPlaceBuilding(Game *game, BuildingType type, i32 tileX, i32 tileY); bool canPlaceBuilding(Game *game, BuildingType type, i32 tileX, i32 tileY);
ecs_entity_t placeBuilding(Game *game, BuildingType type, i32 posX, i32 posY, Owner owner); 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); Vector2 getPositionNearBuilding(ecs_entity_t building, Vector2 fromPos);
#endif //PIXELDEFENSE_BUILDINGS_H #endif //PIXELDEFENSE_BUILDINGS_H

View File

@@ -4,6 +4,7 @@
#include <breeze.h> #include <breeze.h>
#include <flecs.h> #include <flecs.h>
#include "constants.h"
#include "game_tileset.h" #include "game_tileset.h"
// Needed, so we can clean up all game created entities // Needed, so we can clean up all game created entities
@@ -33,12 +34,6 @@ typedef struct Resource {
} Resource; } Resource;
extern ECS_COMPONENT_DECLARE(Resource); extern ECS_COMPONENT_DECLARE(Resource);
typedef enum Player {
PLAYER_RED = 0,
PLAYER_BLUE = 1,
PLAYER_COUNT
} Player;
typedef struct Owner { typedef struct Owner {
Player player; Player player;
} Owner; } Owner;

View File

@@ -7,4 +7,11 @@ enum {
COLL_LAYER_TRANSPARENCY = 7, COLL_LAYER_TRANSPARENCY = 7,
}; };
typedef enum Player {
PLAYER_RED = 0,
PLAYER_BLUE = 1,
PLAYER_COUNT
} Player;
#endif //PIXELDEFENSE_CONSTANTS_H #endif //PIXELDEFENSE_CONSTANTS_H

View File

@@ -42,6 +42,14 @@ static Options getDefaultOptions() {
}; };
} }
typedef struct PlayerResources {
i64 wood;
i64 food;
i64 gold;
i64 pop;
i64 popCapacity;
} PlayerResources;
typedef struct Game { typedef struct Game {
GameScreen screen; GameScreen screen;
GameScreen nextScreen; GameScreen nextScreen;
@@ -56,13 +64,8 @@ typedef struct Game {
Options options; Options options;
struct { PlayerResources playerResources[PLAYER_COUNT];
i64 wood; Player player;
i64 iron;
i64 food;
i64 gold;
i64 pop;
} resources;
BzStackAlloc stackAlloc; BzStackAlloc stackAlloc;
struct { struct {
BzBTNode *workerHarvest; BzBTNode *workerHarvest;

View File

@@ -616,11 +616,12 @@ void imguiRender(float dt, void *userData) {
} }
if (igCollapsingHeader_TreeNodeFlags("Resources", 0)) { if (igCollapsingHeader_TreeNodeFlags("Resources", 0)) {
igText("Wood: %lld", game->resources.wood); PlayerResources resources = game->playerResources[game->player];
igText("Iron: %lld", game->resources.iron); igText("Wood: %lld", resources.wood);
igText("Food: %lld", game->resources.food); igText("Food: %lld", resources.food);
igText("Gold: %lld", game->resources.gold); igText("Gold: %lld", resources.gold);
igText("Population: %lld", game->resources.pop); igText("Pop: %lld", resources.pop);
igText("Pop Capacity: %lld", resources.pop);
} }
if (igCollapsingHeader_TreeNodeFlags("BuildMenu", 0)) { if (igCollapsingHeader_TreeNodeFlags("BuildMenu", 0)) {
for (int i = BUILDING_NONE; i < BUILDING_COUNT; i++) { for (int i = BUILDING_NONE; i < BUILDING_COUNT; i++) {

View File

@@ -4,6 +4,7 @@
#include "../input.h" #include "../input.h"
#include "../map_init.h" #include "../map_init.h"
#include "../ui_widgets.h" #include "../ui_widgets.h"
#include "../buildings.h"
void drawGameUI(Game *game, f32 dt) { void drawGameUI(Game *game, f32 dt) {
// UI // UI
@@ -37,15 +38,15 @@ void drawGameUI(Game *game, f32 dt) {
}); });
BzTileset *tileset = &game->tileset; BzTileset *tileset = &game->tileset;
Rectangle woodRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_WOOD)); Rectangle woodRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_WOOD));
Rectangle stoneRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_STONE));
Rectangle foodRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_APPLE)); Rectangle foodRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_APPLE));
Rectangle goldRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_GOLD)); Rectangle goldRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_GOLD));
Rectangle popRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_POP)); Rectangle popRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_POP));
uiGameResCount(100, -1, woodRec, tileset->tiles);
uiGameResCount(100, -1, stoneRec, tileset->tiles); PlayerResources resources = game->playerResources[game->player];
uiGameResCount(100, -1, foodRec, tileset->tiles); uiGameResCount(resources.wood, -1, woodRec, tileset->tiles);
uiGameResCount(250, -1, goldRec, tileset->tiles); uiGameResCount(resources.food, -1, foodRec, tileset->tiles);
uiGameResCount(1, 10, popRec, tileset->tiles); uiGameResCount(resources.gold, -1, goldRec, tileset->tiles);
uiGameResCount(resources.pop, resources.popCapacity, popRec, tileset->tiles);
bzUIPopParent(UI); bzUIPopParent(UI);
@@ -97,7 +98,11 @@ void drawGameUI(Game *game, f32 dt) {
rec.height *= sizeY; rec.height *= sizeY;
Texture2D tex = tileset->tiles; Texture2D tex = tileset->tiles;
bool selected = input->building == buildingOrder[i]; 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) { if (selected) {
input->building = buildingOrder[i]; input->building = buildingOrder[i];
input->state = INPUT_BUILDING; input->state = INPUT_BUILDING;

View File

@@ -242,7 +242,7 @@ void uiGameResCount(i32 amount, i32 capacity, Rectangle icon, Texture2D texture)
bzUIPopParent(UI); 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(); f32 scl = uiGetScale();
BzUINode *btn = bzUINodeMake(UI, bzUIKeyFromString(label), &(BzUINodeDesc) { BzUINode *btn = bzUINodeMake(UI, bzUIKeyFromString(label), &(BzUINodeDesc) {
.flags = BZ_UI_CLICKABLE | BZ_UI_ALIGN_CENTER | BZ_UI_DRAW_BORDER, .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); BzUIInteraction inter = bzUIGetInteraction(UI, btn);
Color bgColor = DARKBROWN; Color bgColor = canAfford ? DARKBROWN : MAROON;
if (*selected || inter.hovering) if (*selected || inter.hovering)
bgColor = BROWN; bgColor = canAfford ? BROWN : RED;
if (inter.clicked) if (inter.clicked && canAfford)
*selected = true; *selected = true;
bzUISetBackgroundStyle(UI, btn, (BzUIBackgroundStyle) { bzUISetBackgroundStyle(UI, btn, (BzUIBackgroundStyle) {

View File

@@ -27,6 +27,6 @@ void uiSettingsSlider(const char *txt, f32 *value);
void uiGameResCount(i32 amount, i32 capacity, Rectangle icon, Texture2D texture); 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 #endif //PIXELDEFENSE_UI_WIDGETS_H