From 19081506353f40c3b5ea1b52da38577becb51d2a Mon Sep 17 00:00:00 2001 From: Klemen Plestenjak Date: Sat, 11 Nov 2023 07:01:49 +0100 Subject: [PATCH] Place buildings --- .gitignore | 4 +- CMakeLists.txt | 3 - engine/breeze/map/tileset.h | 2 +- engine/tests/CMakeLists.txt | 2 + engine/tests/window_test.c | 2 - game/main.c | 81 +++++++++++++++++--- game/utils/{buildings.h => building_types.h} | 51 ++++++++++++ scripts/extract_tileset_classes.py | 55 +++++++++++-- 8 files changed, 173 insertions(+), 27 deletions(-) rename game/utils/{buildings.h => building_types.h} (75%) diff --git a/.gitignore b/.gitignore index 58cc378..0b6f643 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,8 @@ *~ .idea/ - cmake-build-debug/ +tiled/PixelDefense.tiled-session venv/ -tiled/PixelDefense.tiled-session +imgui.ini diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f6fa69..8e456f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,9 +9,6 @@ add_subdirectory(engine/) add_executable(PixelDefense - ${lib_sources} - - game/utils/buildings.h game/common.h game/components.h diff --git a/engine/breeze/map/tileset.h b/engine/breeze/map/tileset.h index 0f06a97..3f059aa 100644 --- a/engine/breeze/map/tileset.h +++ b/engine/breeze/map/tileset.h @@ -5,7 +5,7 @@ #include -typedef i16 BzTile; +typedef i32 BzTile; typedef struct BzTilesetDesc { const char *path; diff --git a/engine/tests/CMakeLists.txt b/engine/tests/CMakeLists.txt index 1cb08b3..0d50248 100644 --- a/engine/tests/CMakeLists.txt +++ b/engine/tests/CMakeLists.txt @@ -1,5 +1,7 @@ project(BreezeTests) +set(CMAKE_C_STANDARD 11) + add_executable(window_test window_test.c) target_link_libraries(window_test LINK_PRIVATE Breeze) diff --git a/engine/tests/window_test.c b/engine/tests/window_test.c index ae376c6..5f412df 100644 --- a/engine/tests/window_test.c +++ b/engine/tests/window_test.c @@ -2,9 +2,7 @@ #include #include -#define CIMGUI_DEFINE_ENUMS_AND_STRUCTS #include -#include bool init(int *game) { rlImGuiSetup(true); diff --git a/game/main.c b/game/main.c index 51456be..a84b843 100644 --- a/game/main.c +++ b/game/main.c @@ -1,12 +1,12 @@ #include #include - - #define BZ_ENTRYPOINT #include -#include "utils/buildings.h" +#include +#include +#include "utils/building_types.h" #include "components.h" typedef enum Layers { @@ -31,6 +31,7 @@ typedef struct Game { } Game; static Game GAME = {}; +static int selectedBuilding = 0; bool handleGameObjects(BzTileObjectGroup *objectLayer, BzTileObject *objects, i32 objectCount) { for (i32 i = 0; i < objectLayer->objectCount; i++) { @@ -152,7 +153,40 @@ bool canBuildOn(BzTileMap *map, i32 tileX, i32 tileY, i32 sizeX, i32 sizeY) { return true; } +void placeBuilding(BzTileMap *map, BuildingType type, i32 posX, i32 posY, i32 sizeX, i32 sizeY) { + ECS_COMPONENT(ECS, TilePosition); + ECS_COMPONENT(ECS, TileSize); + ECS_COMPONENT(ECS, Owner); + + BzTileLayer *buildingLayer = bzTileMapGetLayer(map, LAYER_BUILDINGS); + BzTileset *buildingTileset = bzTileLayerGetTileset(map, buildingLayer); + BzTile buildingTile = getBuildingTile(type); + BZ_ASSERT(buildingTile != -1); + + // Create entity + ecs_entity_t e = ecs_new_id(ECS); + ecs_set(ECS, e, TilePosition, {.x=posX, .y=posY}); + ecs_set(ECS, e, TileSize, {.w=sizeX, .h=sizeY}); + ecs_set(ECS, e, Owner, {.playerID=BUILDINGS_PLAYER_RED}); + + for (i32 y = posY; y < posY + sizeY; y++) { + for (i32 x = posX; x < posX + sizeX; x++) { + BzTile layerTile = buildingTile + buildingTileset->startID; + bzTileLayerSetTile(buildingLayer, layerTile, x, y, 1, 1); + buildingTile++; + + entityMap[y * buildingLayer->width + x] = e; + + bzTileMapUpdateCollider(map, x, y); + } + buildingTile += buildingTileset->width - sizeX; + } + + +} + bool init(Game *game) { + rlImGuiSetup(true); int screenWidth = 1280; int screenHeight = 720; @@ -199,11 +233,9 @@ void deinit(Game *game) { bzTilesetDestroy(&game->terrainTileset); bzTilesetDestroy(&game->buildingsTileset); bzTileMapDestroy(&game->map); + rlImGuiShutdown(); } -int sizeX = 1; -int sizeY = 1; - void render(float dt, Game *game) { Camera2D *camera = &game->camera; @@ -227,15 +259,42 @@ void render(float dt, Game *game) { int tileX = (int) worldPos.x / 16; int tileY = (int) worldPos.y / 16; - bool canPlace = canBuildOn(&game->map, tileX, tileY, sizeX, sizeY); - Color placeColor = canPlace ? - (Color) {0, 255, 0, 200} : - (Color) {255, 0, 0, 200}; + if (selectedBuilding) { + BzTile sizeX = 0, sizeY = 0; + getBuildingSize(selectedBuilding, &sizeX, &sizeY); - DrawRectangleLines(tileX * 16, tileY * 16, sizeX * 16, sizeY * 16, placeColor); + bool canPlace = canBuildOn(&game->map, tileX, tileY, sizeX, sizeY); + Color placeColor = canPlace ? + (Color) {0, 255, 0, 200} : + (Color) {255, 0, 0, 200}; + + DrawRectangleLines(tileX * 16, tileY * 16, sizeX * 16, sizeY * 16, placeColor); + + if (canPlace && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { + placeBuilding(&game->map, selectedBuilding, tileX, tileY, sizeX, sizeY); + } + + } EndMode2D(); + rlImGuiBegin(); + igSetNextWindowSize((ImVec2){300, 400}, ImGuiCond_FirstUseEver); + igBegin("Debug Menu", NULL, 0); + if (igCollapsingHeader_TreeNodeFlags("BuildMenu", 0)) { + for (int i = 0; i < BUILDINGS_COUNT; i++) { + if (igSelectable_Bool(getBuildingStr(i), selectedBuilding == i, 0, (ImVec2){0,0})) + selectedBuilding = i; + } + + } + if (igCollapsingHeader_TreeNodeFlags("Entities", 0)) { + + } + igEnd(); + igShowDemoWindow(NULL); + rlImGuiEnd(); + } diff --git a/game/utils/buildings.h b/game/utils/building_types.h similarity index 75% rename from game/utils/buildings.h rename to game/utils/building_types.h index 2964040..242d8d8 100644 --- a/game/utils/buildings.h +++ b/game/utils/building_types.h @@ -100,6 +100,31 @@ static BuildingType getTileBuilding(BzTile tile) { } } +static BzTile getBuildingTile(BuildingType type) { + switch (type) { + case BUILDINGS_KEEP: return 0; + case BUILDINGS_GRANARY: return 3; + case BUILDINGS_ARMORY: return 4; + case BUILDINGS_WAREHOUSE: return 5; + case BUILDINGS_MINE: return 6; + case BUILDINGS_BARACKS: return 8; + case BUILDINGS_ORCHARD: return 10; + case BUILDINGS_ANIMAL_FARM: return 12; + case BUILDINGS_PLAYER_RED: return 31; + case BUILDINGS_FLETCHER: return 35; + case BUILDINGS_PLAYER_BLUE: return 63; + case BUILDINGS_SMITHY: return 67; + case BUILDINGS_WORKSHOP: return 72; + case BUILDINGS_FARM: return 74; + case BUILDINGS_ROAD: return 96; + case BUILDINGS_WALL: return 97; + case BUILDINGS_GATEHOUSE: return 98; + case BUILDINGS_TOWER: return 128; + case BUILDINGS_SMALL_TOWER: return 130; + default: return -1; + } +} + static BuildingType getBuildingFromStr(const char *str) { if (strncmp("keep", str, 4) == 0) return BUILDINGS_KEEP; if (strncmp("granary", str, 7) == 0) return BUILDINGS_GRANARY; @@ -122,6 +147,32 @@ static BuildingType getBuildingFromStr(const char *str) { if (strncmp("small_tower", str, 11) == 0) return BUILDINGS_SMALL_TOWER; else return BUILDINGS_NONE; } +static const char *getBuildingStr(BuildingType type) { + switch (type) { + case BUILDINGS_NONE: return "none"; + case BUILDINGS_KEEP: return "keep"; + case BUILDINGS_GRANARY: return "granary"; + case BUILDINGS_ARMORY: return "armory"; + case BUILDINGS_WAREHOUSE: return "warehouse"; + case BUILDINGS_MINE: return "mine"; + case BUILDINGS_BARACKS: return "baracks"; + case BUILDINGS_ORCHARD: return "orchard"; + case BUILDINGS_ANIMAL_FARM: return "animal_farm"; + case BUILDINGS_PLAYER_RED: return "player_red"; + case BUILDINGS_FLETCHER: return "fletcher"; + case BUILDINGS_PLAYER_BLUE: return "player_blue"; + case BUILDINGS_SMITHY: return "smithy"; + case BUILDINGS_WORKSHOP: return "workshop"; + case BUILDINGS_FARM: return "farm"; + case BUILDINGS_ROAD: return "road"; + case BUILDINGS_WALL: return "wall"; + case BUILDINGS_GATEHOUSE: return "gatehouse"; + case BUILDINGS_TOWER: return "tower"; + case BUILDINGS_SMALL_TOWER: return "small_tower"; + default: return NULL; + } +} + static void getBuildingSize(BuildingType type, BzTile *outWidth, BzTile *outHeight) { switch (type) { case BUILDINGS_KEEP: diff --git a/scripts/extract_tileset_classes.py b/scripts/extract_tileset_classes.py index f9cd490..e0aa12a 100755 --- a/scripts/extract_tileset_classes.py +++ b/scripts/extract_tileset_classes.py @@ -23,10 +23,10 @@ for tile in tiles: type = tile["type"] types[type].append(id) -enum_identifier = os.path.basename(path).split(".")[0].capitalize() -enum_name = enum_identifier.upper() +enum_type = os.path.basename(path).split(".")[0].capitalize() +enum_name = enum_type.upper() if sys.argv[2]: - enum_identifier = sys.argv[2] + enum_type = sys.argv[2] indent_level = 0 indent_offset = 4 @@ -53,21 +53,21 @@ print() enum_none = enum_string("none") enum_count = enum_string("count") -print(f"{indent()}typedef enum {enum_identifier} {{") +print(f"{indent()}typedef enum {enum_type} {{") indent_level += indent_offset print(f"{indent()}{enum_none},") for enum in types: print(f"{indent()}{enum_string(enum)},") print(f"{indent()}{enum_count}") indent_level -= indent_offset -print(f"{indent()}}} {enum_identifier};") +print(f"{indent()}}} {enum_type};") print() print() # ============================ -print(f"{indent()}static {enum_identifier} getTileBuilding(BzTile tile) {{") +print(f"{indent()}static {enum_type} getTileBuilding(BzTile tile) {{") indent_level += indent_offset print(f"{indent()}switch (tile) {{") for enum, ids in types.items(): @@ -95,7 +95,26 @@ print() # ============================ -print(f"{indent()}static {enum_identifier} getBuildingFromStr(const char *str) {{") +print(f"{indent()}static BzTile getBuildingTile({enum_type} type) {{") +indent_level += indent_offset +print(f"{indent()}switch (type) {{") +indent_level += indent_offset +for type, ids in types.items(): + min_id = min(ids) + print(f"{indent()}case {enum_string(type)}: return {min_id};") + +print(f"{indent()}default: return -1;") +indent_level -= indent_offset +print(f"{indent()}}}") + +indent_level -= indent_offset + +print(f"{indent()}}}") +print() + +# ============================ + +print(f"{indent()}static {enum_type} getBuildingFromStr(const char *str) {{") indent_level += indent_offset # trie would be much better @@ -108,7 +127,27 @@ print(f"{indent()}}}") # ============================ -print(f"{indent()}static void getBuildingSize({enum_identifier} type, BzTile *outWidth, BzTile *outHeight) {{") +print(f"{indent()}static const char *getBuildingStr({enum_type} type) {{") +indent_level += indent_offset + +print(f"{indent()}switch (type) {{") +indent_level += indent_offset + +print(f"{indent()}case {enum_string('none')}: return \"none\";") +for type in types: + print(f"{indent()}case {enum_string(type)}: return \"{type}\";") +print(f"{indent()}default: return NULL;") +indent_level -= indent_offset +print(f"{indent()}}}") + +indent_level -= indent_offset +print(f"{indent()}}}") +print() + + +# ============================ + +print(f"{indent()}static void getBuildingSize({enum_type} type, BzTile *outWidth, BzTile *outHeight) {{") indent_level += indent_offset print(f"{indent()} switch (type) {{") indent_level += indent_offset