#include "systems.h" #include "../game_state.h" #include "../input.h" #include "../map_init.h" #include "../ui_widgets.h" #include "../buildings.h" #include "../utils.h" void drawGameUI(Game *game, f32 dt) { // UI i32 width = GetScreenWidth(); i32 height = GetScreenHeight(); bzUIBegin(UI, width, height); bzUISetParentLayout(UI, (BzUILayout) { .type = BZ_UI_LAYOUT_FLEX_BOX, .flags = BZ_UI_FLEX_DIR_COLUMN | BZ_UI_FLEX_JUSTIFY_SPACE_BETWEEN | BZ_UI_FLEX_ALIGN_CENTER }); // top bar BzUINode *topBar = bzUINodeMake(UI, bzUIGetUniqueKey(UI), &(BzUINodeDesc) { .semanticSize[BZ_UI_AXIS_X] = {BZ_UI_SIZE_AS_PARENT}, .semanticSize[BZ_UI_AXIS_Y] = {BZ_UI_SIZE_CHILD_MAX}, }); bzUIPushParent(UI, topBar); bzUISetParentLayout(UI, (BzUILayout) { .type = BZ_UI_LAYOUT_FLEX_BOX, .flags = BZ_UI_FLEX_DIR_ROW | BZ_UI_FLEX_ALIGN_CENTER | BZ_UI_FLEX_JUSTIFY_START }); Color topBarBG = {0, 0, 0, 50}; bzUISetBackgroundStyle(UI, topBar, (BzUIBackgroundStyle) { .normal = topBarBG, .hover = topBarBG, .active = topBarBG, }); BzTileset *tileset = &game->tileset; Rectangle woodRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_WOOD)); Rectangle foodRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_APPLE)); Rectangle goldRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_GOLD)); Rectangle popRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_POP)); 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); InputState *input = ecs_singleton_get_mut(ECS, InputState); const BuildingType buildingOrder[] = { BUILDING_HOUSE_01, BUILDING_GRANARY, BUILDING_WAREHOUSE, BUILDING_MARKET, BUILDING_MILL, BUILDING_WHEAT_0, BUILDING_BARRACKS, BUILDING_ARCHERY_RANGE }; const char *buildingNames[] = { "House", "Granary", "Warehouse", "Market", "Mill", "Farm", "Barracks", "Archery Range" }; i32 numBuildings = sizeof(buildingOrder) / sizeof(*buildingOrder); BzUINode *menu = bzUINodeMake(UI, bzUIGetUniqueKey(UI), &(BzUINodeDesc) { .semanticSize[BZ_UI_AXIS_X] = {BZ_UI_SIZE_REL_PARENT, 0.98f}, .semanticSize[BZ_UI_AXIS_Y] = {BZ_UI_SIZE_PIXELS, 140.0f * uiGetScale()}, .margin[BZ_UI_AXIS_Y + 2] = 10.0f * uiGetScale(), }); bzUISetBackgroundStyle(UI, menu, (BzUIBackgroundStyle) { .normal = DARKBROWN, .hover = DARKBROWN, .active = DARKBROWN, .roundness = 0.2f * uiGetScale() }); bzUISetBorderStyle(UI, menu, (BzUIBorderStyle) { .roundness = 0.2f * uiGetScale(), .thickness = 6.0f * uiGetScale(), .normal = BLACK, .hover = BLACK, .active = BLACK, }); bzUIPushParent(UI, menu); bzUISetParentLayout(UI, (BzUILayout) { .type = BZ_UI_LAYOUT_FLEX_BOX, .flags = BZ_UI_FLEX_DIR_ROW | BZ_UI_FLEX_ALIGN_CENTER | BZ_UI_FLEX_JUSTIFY_START }); Texture2D tex = tileset->tiles; switch (input->state) { case INPUT_NONE: case INPUT_BUILDING: { for (i32 i = 0; i < numBuildings; i++) { BuildingType buildingType = buildingOrder[i]; Rectangle rec = bzTilesetGetTileRegion(tileset, getBuildingTile(buildingType)); // Adjust for size i32 sizeX = 1, sizeY = 1; getBuildingSize(buildingType, &sizeX, &sizeY); rec.width *= sizeX; rec.height *= sizeY; bool selected = input->building == buildingOrder[i]; 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; } } break; } case INPUT_SELECTED_UNITS: { typedef struct UnitPair { i32 count; Rectangle rec; } UnitPair; UnitPair unitTypes[ENTITY_COUNT] = {0, }; ecs_iter_t it = ecs_query_iter(ECS, input->queries.selected); while (ecs_query_next(&it)) { for (i32 i = 0; i < it.count; i++) { ecs_entity_t entity = it.entities[i]; if (!ecs_has(ECS, entity, Unit)) continue; Unit unit = *ecs_get(ECS, entity, Unit); if (unitTypes[unit.unitType].count == 0) { unitTypes[unit.unitType].rec = ecs_get(ECS, entity, TextureRegion)->rec; } unitTypes[unit.unitType].count++; } } i32 filterUnit = -1; for (i32 i = 0; i < ENTITY_COUNT; i++) { i32 count = unitTypes[i].count; if (count == 0) continue; const char *label = getEntityStr(i); if (uiGameUnit(label, count, unitTypes[i].rec, tex)) { filterUnit = i; } } if (filterUnit != -1) { ecs_defer_begin(ECS); it = ecs_query_iter(ECS, input->queries.selected); while (ecs_query_next(&it)) { for (i32 i = 0; i < it.count; i++) { ecs_entity_t entity = it.entities[i]; if (ecs_has(ECS, entity, Unit)) { Unit unit = *ecs_get(ECS, entity, Unit); if (unit.unitType == filterUnit) continue; } ecs_remove(ECS, entity, Selected); } } ecs_defer_end(ECS); } break; } case INPUT_SELECTED_OBJECT: break; case INPUT_SELECTED_BUILDING: break; } bzUIEnd(UI); } void drawPauseUI(Game *game, f32 dt) { i32 width = GetScreenWidth(); i32 height = GetScreenHeight(); bzUIBegin(UI, width, height); bzUISetParentLayout(UI, (BzUILayout) { .type = BZ_UI_LAYOUT_FLEX_BOX, .flags = BZ_UI_FLEX_DIR_COLUMN }); uiPushDivParentPercentage(1.0f, 0.4f); bzUISetParentLayout(UI, (BzUILayout) { .type = BZ_UI_LAYOUT_FLEX_BOX, .flags = BZ_UI_FLEX_DIR_COLUMN | BZ_UI_FLEX_JUSTIFY_CENTER | BZ_UI_FLEX_ALIGN_CENTER }); uiMainMenuLabel("Paused"); bzUIPopParent(UI); uiPushDivParentPercentage(1.0f, 0.6f); bzUISetParentLayout(UI, (BzUILayout) { .type = BZ_UI_LAYOUT_FLEX_BOX, .flags = BZ_UI_FLEX_DIR_COLUMN | BZ_UI_FLEX_ALIGN_CENTER }); if (uiMainMenuButton("Resume", true)) { setScreen(game, SCREEN_GAME); } if (uiMainMenuButton("Exit", true)) { setScreen(game, SCREEN_MAIN_MENU); unloadMap(game); loadMap(game, "assets/maps/main_menu_01.tmj"); } bzUIPopParent(UI); bzUIEnd(UI); } void drawMainMenuUI(Game *game, f32 dt) { i32 width = GetScreenWidth(); i32 height = GetScreenHeight(); game->camera.zoom = 3 * uiGetScale(); bzUIBegin(UI, width, height); bzUISetParentLayout(UI, (BzUILayout) { .type = BZ_UI_LAYOUT_FLEX_BOX, .flags = BZ_UI_FLEX_DIR_COLUMN }); uiPushDivParentPercentage(1.0f, 0.4f); bzUISetParentLayout(UI, (BzUILayout) { .type = BZ_UI_LAYOUT_FLEX_BOX, .flags = BZ_UI_FLEX_DIR_COLUMN | BZ_UI_FLEX_JUSTIFY_CENTER | BZ_UI_FLEX_ALIGN_CENTER }); uiMainMenuLabel("Pixel Defense"); bzUIPopParent(UI); uiPushDivParentPercentage(1.0f, 0.6f); bzUISetParentLayout(UI, (BzUILayout) { .type = BZ_UI_LAYOUT_FLEX_BOX, .flags = BZ_UI_FLEX_DIR_COLUMN | BZ_UI_FLEX_ALIGN_CENTER }); if (uiMainMenuButton("Continue", false)) { } if (uiMainMenuButton("Play", true)) { setScreen(game, SCREEN_GAME); unloadMap(game); loadMap(game, "assets/maps/tree_test.tmj"); //loadMap(game, "assets/maps/map_01.tmj"); } if (uiMainMenuButton("Settings", true)) { setScreen(game, SCREEN_SETTINGS); } if (uiMainMenuButton("Exit", true)) { bzGameExit(); } bzUIPopParent(UI); bzUIEnd(UI); } void drawSettingsUI(Game *game, f32 dt) { i32 width = GetScreenWidth(); i32 height = GetScreenHeight(); game->camera.zoom = 3 * uiGetScale(); bzUIBegin(UI, width, height); bzUISetParentLayout(UI, (BzUILayout) { .type = BZ_UI_LAYOUT_FLEX_BOX, .flags = BZ_UI_FLEX_DIR_COLUMN | BZ_UI_FLEX_JUSTIFY_CENTER | BZ_UI_FLEX_ALIGN_CENTER }); bzUIPushDiv(UI, (BzUISize) { BZ_UI_SIZE_REL_PARENT, 0.8f}, (BzUISize) { BZ_UI_SIZE_REL_PARENT, 0.8f}); bzUISetParentLayout(UI, (BzUILayout) { .type = BZ_UI_LAYOUT_FLEX_BOX, .flags = BZ_UI_FLEX_DIR_COLUMN | BZ_UI_FLEX_JUSTIFY_CENTER | BZ_UI_FLEX_ALIGN_CENTER }); static Options opts; if (game->screenPrevFrame != SCREEN_SETTINGS) opts = game->options; uiSettingsLabel("Video"); uiSettingsCheckbox("Fullscreen", &opts.fullscreen); uiSettingsCheckbox("V-Sync", &opts.vsync); uiSettingsLabel("Audio"); uiSettingsSlider("Master: ", &opts.master); uiSettingsSlider("Music: ", &opts.music); uiSettingsSlider("Sound: ", &opts.sound); bzUIPopParent(UI); bzUIPushDiv(UI, (BzUISize) {BZ_UI_SIZE_REL_PARENT, 0.8f}, (BzUISize) {BZ_UI_SIZE_REL_PARENT, 0.2f}); bzUISetParentLayout(UI, (BzUILayout) { .type = BZ_UI_LAYOUT_FLEX_BOX, .flags = BZ_UI_FLEX_DIR_ROW | BZ_UI_FLEX_JUSTIFY_CENTER | BZ_UI_FLEX_ALIGN_CENTER }); if (uiSettingsButton("Back")) { setScreen(game, SCREEN_MAIN_MENU); } if (uiSettingsButton("Reset")) { opts = game->options; } if (uiSettingsButton("Apply")) { serializeOptions(SETTINGS_PATH, &opts); game->options = opts; setScreen(game, SCREEN_MAIN_MENU); } bzUIEnd(UI); }