diff --git a/engine/breeze/map/map.c b/engine/breeze/map/map.c index 17191ee..b088241 100644 --- a/engine/breeze/map/map.c +++ b/engine/breeze/map/map.c @@ -288,9 +288,11 @@ void bzTileMapDestroy(BzTileMap *map) { } -void bzTileMapPosToTile(BzTileMap *map, Vector2 pos, BzTile *x, BzTile *y) { - if (x) *x = (BzTile) (pos.x / (f32) map->tileWidth); - if (y) *y = (BzTile) (pos.y / (f32) map->tileHeight); +Vec2i bzTileMapPosToTile(BzTileMap *map, Vector2 pos) { + return (Vec2i) { + .x = (i32) (pos.x / (f32) map->tileWidth), + .y = (i32) (pos.y / (f32) map->tileHeight) + }; } void bzTileMapOverrideLayer(BzTileMap *map, i32 slotID, BzTileLayerFunc func) { diff --git a/engine/breeze/map/map.h b/engine/breeze/map/map.h index 1c04c26..5a8e204 100644 --- a/engine/breeze/map/map.h +++ b/engine/breeze/map/map.h @@ -2,6 +2,7 @@ #define BREEZE_MAP_H #include "tileset.h" +#include "../math/vec2i.h" #include "../util/string.h" #define BZ_MAP_MAX_LAYERS 8 @@ -116,7 +117,7 @@ BzTileset *bzTileObjectGroupGetTileset(BzTileMap *map, BzTileObjectGroup *object BzTileMap bzTileMapCreate(const BzTileMapDesc *desc); void bzTileMapDestroy(BzTileMap *map); -void bzTileMapPosToTile(BzTileMap *map, Vector2 pos, BzTile *x, BzTile *y); +Vec2i bzTileMapPosToTile(BzTileMap *map, Vector2 pos); void bzTileMapOverrideLayer(BzTileMap *map, i32 slotID, BzTileLayerFunc func); void bzTileMapOverrideObjectGroup(BzTileMap *map, i32 slotID, BzTileObjectsFunc func); diff --git a/game/buildings.c b/game/buildings.c index 3b40018..d472a14 100644 --- a/game/buildings.c +++ b/game/buildings.c @@ -4,14 +4,16 @@ #include "entity_factory.h" #include "game_state.h" #include "map_layers.h" +#include "systems/systems.h" #include -bool canPlaceBuilding(BzTileMap *map, BuildingType type, BzTile tileX, BzTile tileY) { +bool canPlaceBuilding(Game *game, BuildingType type, BzTile tileX, BzTile tileY) { i32 sizeX, sizeY; getBuildingSize(type, &sizeX, &sizeY); if (sizeX == 0 || sizeY == 0) return false; + BzTileMap *map = &game->map; // Ensure that it is within the map if (tileX < 0 || tileX + sizeX > map->width || tileY < 0 || tileY + sizeY > map->height) @@ -20,60 +22,65 @@ bool canPlaceBuilding(BzTileMap *map, BuildingType type, BzTile tileX, BzTile ti Rectangle buildArea = {tileX * map->tileWidth, tileY * map->tileHeight, sizeX * map->tileWidth, sizeY * map->tileHeight}; - // Need to check neighbour tiles - //tileX -= 1; - //tileY -= 1; - //sizeX += 2; - //sizeY += 2; + BzSpatialGridIter it = bzSpatialGridIter(game->entityGrid, buildArea.x, buildArea.y, buildArea.width, buildArea.height); + while (bzSpatialGridQueryNext(&it)) { ecs_entity_t entity = *(ecs_entity_t *) it.data; + Rectangle bounds; + if (!getEntityBounds(entity, NULL, NULL, &bounds)) continue; - BzTileLayer *buildLayer = bzTileMapGetLayer(map, LAYER_BUILDINGS); - BzTileset *tileset = bzTileLayerGetTileset(map, buildLayer); - - for (i32 y = tileY; y < tileY + sizeY; y++) { - for (i32 x = tileX; x < tileX + sizeX; x++) { - BzTile tile = bzTileLayerGetTile(buildLayer, x, y); - tile = bzTilesetGetTileID(tileset, tile); - tile = getTileBuilding(tile); - //if (tile == BUILDINGS_ROAD) - // return false; - if (bzTileMapHasCollision(map, x, y)) { - return false; - } - } + if (CheckCollisionRecs(buildArea, bounds)) + return false; } - return true; } -ecs_entity_t placeBuilding(BzTileMap *map, BuildingType type, BzTile tileX, BzTile tileY) { - Game *game = ecs_singleton_get_mut(ECS, Game); +ecs_entity_t placeBuilding(Game *game, BuildingType type, + BzTile tileX, BzTile tileY, Owner owner) { + if (type <= BUILDING_NONE || type >= BUILDING_COUNT) + return 0; i32 sizeX, sizeY; getBuildingSize(type, &sizeX, &sizeY); - BzTileLayer *buildingLayer = bzTileMapGetLayer(map, LAYER_BUILDINGS); - BzTileset *buildingTileset = bzTileLayerGetTileset(map, buildingLayer); - BzTile buildingTile = getBuildingTile(type); - BZ_ASSERT(buildingTile != -1); + const i32 tileWidth = game->map.tileWidth; + const i32 tileHeight = game->map.tileHeight; // Create entity - ecs_entity_t e = entityCreateEmpty(); + ecs_entity_t building = entityCreateEmpty(); + Position pos = { + .x = tileX * tileWidth + sizeX * tileWidth * 0.5f, + .y = tileY * tileHeight + sizeY * tileHeight * 0.5f + }; + Size size = { + .x = sizeX * tileWidth, + .y = sizeY * tileHeight + }; - ecs_set(ECS, e, TilePosition, { .x = tileX, .y = tileY }); - ecs_set(ECS, e, TileSize, { .sizeX = sizeX, .sizeY = sizeY }); - //ecs_set(ECS, e, Owner, { .playerID = BUILDINGS_PLAYER_RED }); + ecs_set_ptr(ECS, building, Position, &pos); + ecs_set_ptr(ECS, building, Size, &size); + ecs_set(ECS, building, Rotation, {0}); - for (i32 y = tileY; y < tileY + sizeY; y++) { - for (i32 x = tileX; x < tileX + sizeX; x++) { - BzTile layerTile = buildingTile + buildingTileset->startID; - bzTileLayerSetTile(buildingLayer, layerTile, x, y, 1, 1); - buildingTile++; + SpatialGridID gridID = bzSpatialGridInsert(game->entityGrid, &building, + pos.x, pos.y, + size.x, size.y); + ecs_set_ptr(ECS, building, SpatialGridID, &gridID); + ecs_set_ptr(ECS, building, Owner, &owner); + BzTileset *tileset = &game->tileset; + TextureRegion region = { + tileset->tiles, + bzTilesetGetTileRegion(tileset, getBuildingTile(type)) + }; + region.rec.width *= sizeX; + region.rec.height *= sizeY; + ecs_set_ptr(ECS, building, TextureRegion, ®ion); - bzTileMapUpdateCollisions(map, x, y, 1, 1); - } - buildingTile += buildingTileset->width - sizeX; + switch (type) { + case BUILDING_KEEP: + ecs_add_id(ECS, building, Storage); + break; + default: + break; } - return e; + return building; } diff --git a/game/buildings.h b/game/buildings.h index 3819bae..6405e37 100644 --- a/game/buildings.h +++ b/game/buildings.h @@ -4,10 +4,13 @@ #include #include +#include "components.h" #include "game_tileset.h" -bool canPlaceBuilding(BzTileMap *map, BuildingType type, i32 tileX, i32 tileY); -ecs_entity_t placeBuilding(BzTileMap *map, BuildingType type, i32 tileX, i32 tileY); +typedef struct Game Game; + +bool canPlaceBuilding(Game *game, BuildingType type, i32 tileX, i32 tileY); +ecs_entity_t placeBuilding(Game *game, BuildingType type, i32 tileX, i32 tileY, Owner owner); Vector2 getPositionNearBuilding(ecs_entity_t building, Vector2 fromPos); diff --git a/game/components.c b/game/components.c index 5ee5256..0b3a107 100644 --- a/game/components.c +++ b/game/components.c @@ -7,8 +7,6 @@ ECS_TAG_DECLARE(GameEntity); ECS_COMPONENT_DECLARE(Resource); -ECS_COMPONENT_DECLARE(TilePosition); -ECS_COMPONENT_DECLARE(TileSize); ECS_COMPONENT_DECLARE(Owner); ECS_COMPONENT_DECLARE(SpatialGridID); @@ -47,8 +45,6 @@ void initComponentIDs(ecs_world_t *ecs) { ECS_COMPONENT_DEFINE(ecs, Resource); - ECS_COMPONENT_DEFINE(ecs, TilePosition); - ECS_COMPONENT_DEFINE(ecs, TileSize); ECS_COMPONENT_DEFINE(ecs, Owner); ECS_COMPONENT_DEFINE(ecs, SpatialGridID); @@ -106,18 +102,6 @@ void igResource(ecs_world_t *ecs, res->type = curType; igInputInt("Amount", &res->amount, 1, 10, 0); } -void igTilePosition(ecs_world_t *ecs, - ecs_entity_t entity, ecs_entity_t comp) { - TilePosition *tilePos = ecs_get_mut_id(ecs, entity, comp); - igInputInt("X", &tilePos->x, 1, 4, 0); - igInputInt("Y", &tilePos->y, 1, 4, 0); -} -void igTileSize(ecs_world_t *ecs, - ecs_entity_t entity, ecs_entity_t comp) { - TileSize *tileSize = ecs_get_mut_id(ecs, entity, comp); - igInputInt("X", &tileSize->sizeX, 1, 1, 0); - igInputInt("Y", &tileSize->sizeY, 1, 1, 0); -} void igOwner(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp) { Owner *owner = ecs_get_mut_id(ecs, entity, comp); diff --git a/game/components.h b/game/components.h index acf51f9..e6c9fe1 100644 --- a/game/components.h +++ b/game/components.h @@ -33,18 +33,6 @@ typedef struct Resource { } Resource; extern ECS_COMPONENT_DECLARE(Resource); -typedef struct TilePosition { - BzTile x; - BzTile y; -} TilePosition; -extern ECS_COMPONENT_DECLARE(TilePosition); - -typedef struct TileSize { - BzTile sizeX; - BzTile sizeY; -} TileSize; -extern ECS_COMPONENT_DECLARE(TileSize); - typedef struct Owner { int32_t playerID; } Owner; @@ -215,10 +203,6 @@ void igTagCheckbox(const char *label, ecs_world_t *ecs, typedef void(*ImGuiCompFn)(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp); void igResource(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp); -void igTilePosition(ecs_world_t *ecs, - ecs_entity_t entity, ecs_entity_t comp); -void igTileSize(ecs_world_t *ecs, - ecs_entity_t entity, ecs_entity_t comp); void igOwner(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp); diff --git a/game/game_tileset.h b/game/game_tileset.h index 86e4ee8..f51875c 100644 --- a/game/game_tileset.h +++ b/game/game_tileset.h @@ -17,8 +17,8 @@ typedef struct AnimationFrame { } AnimationFrame; typedef enum TerrainType { + TERRAIN_NONE = -1, TERRAIN_COUNT, - TERRAIN_NONE, } TerrainType; static bool terrainHasAnimation(BzTileID tile) { @@ -257,9 +257,9 @@ static AnimationFrame terrainGetAnimationFrame(BzTileID tile, i32 frameIdx) { typedef enum BuildingType { + BUILDING_NONE = -1, BUILDING_KEEP, BUILDING_COUNT, - BUILDING_NONE, } BuildingType; static BuildingType getTileBuilding(BzTileID tile) { @@ -275,7 +275,7 @@ static BuildingType getTileBuilding(BzTileID tile) { case 6406: return BUILDING_KEEP; default: - return BUILDING_NONE; + return BUILDING_COUNT; } } @@ -288,7 +288,7 @@ static BzTileID getBuildingTile(BuildingType type) { static BuildingType getBuildingFromStr(const char *str) { if (strncmp("keep", str, 4) == 0) return BUILDING_KEEP; - return BUILDING_NONE; + return BUILDING_COUNT; } static const char *getBuildingStr(BuildingType type) { @@ -313,6 +313,7 @@ static BuildingType getBuildingSize(BuildingType type, BzTileID *outWidth, BzTil typedef enum EntityType { + ENTITY_NONE = -1, ENTITY_WORKER, ENTITY_WOOD, ENTITY_STONE, @@ -320,7 +321,6 @@ typedef enum EntityType { ENTITY_GOLD, ENTITY_POP, ENTITY_COUNT, - ENTITY_NONE, } EntityType; typedef enum AnimType { @@ -329,7 +329,7 @@ typedef enum AnimType { ANIM_HURT, ANIM_DIE, ANIM_COUNT, - ANIM_NONE, + ANIM_NONE = -1, } AnimType; static BzTileID getEntityTile(EntityType type) { @@ -394,6 +394,7 @@ static AnimationFrame entityGetAnimationFrame(EntityType entity, AnimType type, } typedef enum ItemType { + ITEM_NONE = -1, ITEM_STAFF, ITEM_PICKAXE, ITEM_AXE, @@ -415,7 +416,6 @@ typedef enum ItemType { ITEM_SPEAR, ITEM_TRIDENT, ITEM_COUNT, - ITEM_NONE, } ItemType; static BzTileID getItemTile(ItemType type) { diff --git a/game/input.h b/game/input.h index 5115171..740dd79 100644 --- a/game/input.h +++ b/game/input.h @@ -50,8 +50,8 @@ typedef struct InputState { // INPUT_BUILDING int building; bool buildingCanPlace; - TilePosition buildingPos; - TileSize buildingSize; + Vec2i buildingPos; + Vec2i buildingSize; // SELECTED_UNITS Rectangle pickArea; diff --git a/game/main.c b/game/main.c index c142885..f097e18 100644 --- a/game/main.c +++ b/game/main.c @@ -103,9 +103,9 @@ void loadMap(Game *game, const char *path) { .layers[LAYER_TERRAIN]=(BzTileLayerDesc) {"terrain", .renderer=terrainRender, .applyColliders=true}, .layers[LAYER_ROCKS]=(BzTileLayerDesc) {"rocks"}, .layers[LAYER_ROCKS2]=(BzTileLayerDesc) {"rocks_s"}, - .layers[LAYER_TREES]=(BzTileLayerDesc) {"trees"}, - .layers[LAYER_TREES2]=(BzTileLayerDesc) {"trees_s"}, - .layers[LAYER_BUILDINGS]=(BzTileLayerDesc) {"buildings", .applyColliders=true}, + .layers[LAYER_TREES]=(BzTileLayerDesc) {"trees", BZ_TILE_LAYER_SKIP_RENDER}, + .layers[LAYER_TREES2]=(BzTileLayerDesc) {"trees_s", BZ_TILE_LAYER_SKIP_RENDER}, + .layers[LAYER_BUILDINGS]=(BzTileLayerDesc) {"buildings", BZ_TILE_LAYER_SKIP_RENDER}, .layers[LAYER_BUILDING_OWNER]=(BzTileLayerDesc) {"building_ownership", BZ_TILE_LAYER_SKIP_RENDER}, .objectGroups[OBJECTS_GAME]=(BzTileObjectsDesc) {"game"}, @@ -129,6 +129,7 @@ void loadMap(Game *game, const char *path) { bzTileMapOverrideLayer(&game->map, LAYER_TREES2, initTreesLayer); bzTileMapOverrideLayer(&game->map, LAYER_BUILDING_OWNER, initBuildingsLayer); + bzTileMapOverrideLayer(&game->map, LAYER_BUILDINGS, BZ_TILE_LAYER_CLEAR); bzTileMapOverrideObjectGroup(&game->map, OBJECTS_GAME, initGameObjectsLayer); bzTileMapOverrideObjectGroup(&game->map, OBJECTS_ENTITIES, initEntityObjectsLayer); @@ -197,6 +198,8 @@ bool init(void *userData) { {ecs_id(Selected)} } }); + + input->building = BUILDING_NONE; } { InitAudioDevice(); @@ -652,8 +655,6 @@ void igInspectWindow(ecs_entity_t entity, bool *open) { igTagCheckbox("Attackable", ECS, entity, Attackable); } igInspectComp("Resource", entity, ecs_id(Resource), igResource); - igInspectComp("TilePosition", entity, ecs_id(TilePosition), igTilePosition); - igInspectComp("TileSize", entity, ecs_id(TileSize), igTileSize); igInspectComp("Owner", entity, ecs_id(Owner), igOwner); igInspectComp("SpatialGridID", entity, ecs_id(SpatialGridID), igSpatialGridID); igInspectComp("Position", entity, ecs_id(Position), igVec2Comp); @@ -735,11 +736,13 @@ void imguiRender(float dt, void *userData) { igText("Population: %lld", game->resources.pop); } if (igCollapsingHeader_TreeNodeFlags("BuildMenu", 0)) { - for (int i = 0; i < BUILDING_COUNT; i++) { - if (igSelectable_Bool(getBuildingStr(i), input->building == i, 0, (ImVec2){0, 0})) + for (int i = BUILDING_NONE; i < BUILDING_COUNT; i++) { + const char *buildingStr = getBuildingStr(i); + if (!buildingStr) buildingStr = "NONE"; + if (igSelectable_Bool(buildingStr, input->building == i, 0, (ImVec2){0, 0})) input->building = i; } - if (input->building) + if (input->building > BUILDING_NONE && input->building < BUILDING_COUNT) input->state = INPUT_BUILDING; } diff --git a/game/map_init.c b/game/map_init.c index a0da6f4..eba098c 100644 --- a/game/map_init.c +++ b/game/map_init.c @@ -2,6 +2,7 @@ #include +#include "buildings.h" #include "components.h" #include "entity_factory.h" #include "game_state.h" @@ -60,40 +61,24 @@ bool initBuildingsLayer(BzTileMap *map, BzTileLayer *layer) { BzTileset *buildingTileset = bzTileLayerGetTileset(map, buildingLayer); BzTile *data = layer->data; BzTile *buildingData = buildingLayer->data; + BZ_ASSERT(ownershipLayer->tilesetIdx == buildingLayer->tilesetIdx); for (i32 y = 0; y < layer->height; y++) { for (i32 x = 0; x < layer->width; x++) { - BzTile ownerTile = data[y * layer->width + x]; + BzTile ownerRawTile = data[y * layer->width + x]; + BzTileID owner = bzTilesetGetTileID(buildingTileset, ownerRawTile); BzTile buildingRawTile = buildingData[y * layer->width + x]; - BzTile buildingTile = bzTilesetGetTileID(buildingTileset, buildingRawTile); - buildingTile = getTileBuilding(buildingTile); - if (buildingTile == BUILDING_NONE || ownerTile == 0) continue; - // We have a building - TileSize tileSize = {}; - getBuildingSize(buildingTile, &tileSize.sizeX, &tileSize.sizeY); - bzTileLayerSetTile(ownershipLayer, 0, x, y, tileSize.sizeX, tileSize.sizeY); + BzTile buildingType = bzTilesetGetTileID(buildingTileset, buildingRawTile); + buildingType = getTileBuilding(buildingType); + if (buildingType <= BUILDING_NONE || buildingType >= BUILDING_COUNT) + continue; + placeBuilding(game, buildingType, x, y, (Owner) {owner}); - const i32 tileWidth = map->tileWidth; - const i32 tileHeight = map->tileHeight; - ecs_entity_t e = entityCreateEmpty(); - Size size = {.x = tileSize.sizeX * tileWidth, .y = tileSize.sizeY * tileHeight }; - ecs_set_ptr(ECS, e, Size, &size); - ecs_set(ECS, e, Position, { - .x = x * tileWidth + size.x * 0.5f, - .y = y * tileHeight + size.y * 0.5f - }); - ownerTile = bzTilesetGetTileID(buildingTileset, ownerTile); - ownerTile = getTileBuilding(ownerTile); - ecs_set(ECS, e, Owner, {.playerID=ownerTile}); - ecs_add_id(ECS, e, Selectable); - //if (buildingTile == BUILDINGS_WAREHOUSE) { - // ecs_set(ECS, e, Storage, {}); - //} - if (buildingTile == BUILDING_KEEP) { - ecs_add_id(ECS, e, Storage); - } - - //bzTileMapUpdateCollider(&GAME.map, x, y); + i32 sizeX = 1; + i32 sizeY = 1; + getBuildingSize(buildingType, &sizeX, &sizeY); + x += sizeX - 1; + y += sizeY - 1; } } return true; diff --git a/game/pathfinding.c b/game/pathfinding.c index 940ab27..a4ff2ed 100644 --- a/game/pathfinding.c +++ b/game/pathfinding.c @@ -2,7 +2,7 @@ #include -static i32 dst(TilePosition a, TilePosition b) { +static i32 dst(Vec2i a, Vec2i b) { //i32 dX = a.x - b.x; //i32 dY = a.y - b.y; //return dX * dX + dY * dY; @@ -126,9 +126,8 @@ bool pathfindAStar(const PathfindingDesc *desc) { BZ_ASSERT(desc->alloc); BzTileMap *map = desc->map; - TilePosition start = {0}, target = {0}; - bzTileMapPosToTile(map, desc->start, &start.x, &start.y); - bzTileMapPosToTile(map, desc->target, &target.x, &target.y); + Vec2i start = bzTileMapPosToTile(map, desc->start); + Vec2i target = bzTileMapPosToTile(map, desc->target); BZ_ASSERT(start.x >= 0 && start.x < map->width); BZ_ASSERT(start.y >= 0 && start.y < map->height); @@ -178,7 +177,7 @@ bool pathfindAStar(const PathfindingDesc *desc) { foundPath = true; break; } - TilePosition pos = node.pos; + Vec2i pos = node.pos; PathNodeRecord *nodeRecord = &closedSet[pos.y * map->width + pos.x]; nodeRecord->visited = true; nodeRecord->open = false; @@ -199,7 +198,7 @@ bool pathfindAStar(const PathfindingDesc *desc) { if (curRecord->visited) continue; - TilePosition curPos = {x, y}; + Vec2i curPos = {x, y}; i32 gCost = node.gCost + dst(node.pos, curPos); if (curRecord->open) { i32 nodeIdx = curRecord->nodeIdx; @@ -234,7 +233,7 @@ bool pathfindAStar(const PathfindingDesc *desc) { i32 pathLen = 0; if (foundPath && desc->outPath) { - TilePosition pos = target; + Vec2i pos = target; Path *out = desc->outPath; out->curWaypoint = 0; BZ_ASSERT(desc->pool); @@ -282,8 +281,8 @@ static void heapSwap(Heap *heap, i32 left, i32 right) { heap->arr[left] = heap->arr[right]; heap->arr[right] = tmp; - TilePosition leftPos = heap->arr[left].pos; - TilePosition rightPos = heap->arr[right].pos; + Vec2i leftPos = heap->arr[left].pos; + Vec2i rightPos = heap->arr[right].pos; i32 leftIdx = leftPos.y * heap->mapWidth + leftPos.x; i32 rightIdx = rightPos.y * heap->mapWidth + rightPos.x; @@ -339,7 +338,7 @@ static void heapPush(Heap *heap, PathNode node) { heap->arr[heap->size] = node; heap->size++; - TilePosition pos = node.pos; + Vec2i pos = node.pos; PathNodeRecord *record = &heap->records[pos.y * heap->mapWidth + pos.x]; record->nodeIdx = heap->size - 1; diff --git a/game/pathfinding.h b/game/pathfinding.h index 93618b8..a7207f4 100644 --- a/game/pathfinding.h +++ b/game/pathfinding.h @@ -9,7 +9,7 @@ typedef struct PathNode { i32 weight; // fCost = g + h i32 gCost; // from start cost i32 hCost; // to target cost - TilePosition pos; + Vec2i pos; } PathNode; typedef struct PathNodeRecord { diff --git a/game/systems/s_input.c b/game/systems/s_input.c index 073004f..aff9a29 100644 --- a/game/systems/s_input.c +++ b/game/systems/s_input.c @@ -11,9 +11,6 @@ #include #include -Rectangle calculateEntityBounds(Position pos, Size size); -bool getEntityBounds(ecs_entity_t entity, Position *outPos, Size *outSize, Rectangle *outBounds); - ecs_entity_t queryEntity(BzSpatialGrid *entityGrid, Vector2 point, ecs_entity_t tag); bool selectEntity(BzSpatialGrid *entityGrid, Vector2 point, ecs_entity_t tag); @@ -29,7 +26,7 @@ void placeUnits(i32 numUnits, f32 unitSpacing, Vector2 start, Vector2 end, BzTil void resetInputState(InputState *input) { input->cursor = CURSOR_NONE; input->state = INPUT_NONE; - input->building = 0; + input->building = BUILDING_NONE; } void inputPrimaryAction(Game *game, InputState *input) { @@ -218,8 +215,9 @@ void updatePlayerInput() { BzTileMap *map = &game->map; - BzTile tileX = 0, tileY = 0; - bzTileMapPosToTile(map, input->mouseWorld, &tileX, &tileY); + Vec2i tileXY = bzTileMapPosToTile(map, input->mouseWorld); + BzTile tileX = tileXY.x; + BzTile tileY = tileXY.y; const MouseButton primaryBtn = input->mapping.primaryBtn; const MouseButton secondaryBtn = input->mapping.secondaryBtn; @@ -230,16 +228,19 @@ void updatePlayerInput() { break; } case INPUT_BUILDING: { - BZ_ASSERT(input->building); + if (input->building <= BUILDING_NONE || input->building >= BUILDING_COUNT) { + input->state = INPUT_NONE; + return; + } BzTile sizeX = 0, sizeY = 0; getBuildingSize(input->building, &sizeX, &sizeY); - bool canPlace = canPlaceBuilding(&game->map, input->building, tileX, tileY); + bool canPlace = canPlaceBuilding(game, input->building, tileX, tileY); if (canPlace && isInputBtnDown(input, primaryBtn)) { - placeBuilding(&game->map, input->building, tileX, tileY); + placeBuilding(game, input->building, tileX, tileY, (Owner) {-1}); } input->buildingCanPlace = canPlace; - input->buildingPos = (TilePosition) {tileX, tileY}; - input->buildingSize = (TileSize) {sizeX, sizeY}; + input->buildingPos = (Vec2i) {tileX, tileY}; + input->buildingSize = (Vec2i) {sizeX, sizeY}; break; } case INPUT_SELECTED_UNITS: { @@ -278,8 +279,8 @@ void drawPlayerInputUIGround() { const BzTile height = game->map.tileHeight; DrawRectangleLines(input->buildingPos.x * width, input->buildingPos.y * height, - input->buildingSize.sizeX * width, - input->buildingSize.sizeY * height, placeColor); + input->buildingSize.x * width, + input->buildingSize.y * height, placeColor); break; } default: break; @@ -323,41 +324,6 @@ void drawPlayerInputUI() { } - -Rectangle calculateEntityBounds(Position pos, Size size) { - return (Rectangle) { - pos.x - size.x * 0.5f, - pos.y - size.x * 0.5f, - size.x, size.y - }; -} - -bool getEntityBounds(ecs_entity_t entity, Position *outPos, Size *outSize, Rectangle *outBounds) { - if (!ecs_is_alive(ECS, entity)) - return false; - const Position *pos = ecs_get(ECS, entity, Position); - if (!pos) - return false; - const Size *size = ecs_get(ECS, entity, Size); - if (!size) - return false; - - if (outPos) { - *outPos = *pos; - } - if (outSize) { - *outSize = *size; - } - if (outBounds) { - *outBounds = (Rectangle) { - pos->x - size->x * 0.5f, - pos->y - size->y * 0.5f, - size->x, size->y - }; - } - return true; -} - ecs_entity_t queryEntity(BzSpatialGrid *entityGrid, Vector2 point, ecs_entity_t tag) { BzSpatialGridIter it = bzSpatialGridIter(entityGrid, point.x, point.y, 0.0f, 0.0f); f32 closestDst = INFINITY; diff --git a/game/systems/systems.c b/game/systems/systems.c index 7da1cd8..fd7cff0 100644 --- a/game/systems/systems.c +++ b/game/systems/systems.c @@ -2,6 +2,40 @@ #include "../game_state.h" +Rectangle calculateEntityBounds(Position pos, Size size) { + return (Rectangle) { + pos.x - size.x * 0.5f, + pos.y - size.x * 0.5f, + size.x, size.y + }; +} + +bool getEntityBounds(ecs_entity_t entity, Position *outPos, Size *outSize, Rectangle *outBounds) { + if (!ecs_is_alive(ECS, entity)) + return false; + const Position *pos = ecs_get(ECS, entity, Position); + if (!pos) + return false; + const Size *size = ecs_get(ECS, entity, Size); + if (!size) + return false; + + if (outPos) { + *outPos = *pos; + } + if (outSize) { + *outSize = *size; + } + if (outBounds) { + *outBounds = (Rectangle) { + pos->x - size->x * 0.5f, + pos->y - size->y * 0.5f, + size->x, size->y + }; + } + return true; +} + ecs_entity_t renderCollidersSystem; ecs_entity_t renderOrientDirSystem; ecs_entity_t renderArmPositionSystem; @@ -37,6 +71,7 @@ ECS_DTOR(Arms, arms, { ecs_delete(ECS, arms->secondary); arms->secondary = 0; } + }) ECS_MOVE(Arms, dst, src, { *dst = *src; diff --git a/game/systems/systems.h b/game/systems/systems.h index 76d0c9e..d120d5c 100644 --- a/game/systems/systems.h +++ b/game/systems/systems.h @@ -171,6 +171,13 @@ void drawPlayerInputUI(); * UI systems **********************************/ +/********************************** + * Utils + **********************************/ + +Rectangle calculateEntityBounds(Position pos, Size size); +bool getEntityBounds(ecs_entity_t entity, Position *outPos, Size *outSize, Rectangle *outBounds); + /********************************** * MISC **********************************/ diff --git a/game/ui_widgets.c b/game/ui_widgets.c index 753c929..3e49200 100644 --- a/game/ui_widgets.c +++ b/game/ui_widgets.c @@ -5,7 +5,10 @@ #include f32 uiGetScale() { - return GetScreenHeight() / 720.0f; + // Assuming 16:9 aspect + f32 scaleX = GetScreenWidth() / 1280.0f; + f32 scaleY = GetScreenHeight() / 720.0f; + return BZ_MIN(scaleX, scaleY); } Font getFont() { diff --git a/scripts/extract_common.py b/scripts/extract_common.py index 4ef46b1..57a3511 100644 --- a/scripts/extract_common.py +++ b/scripts/extract_common.py @@ -62,7 +62,10 @@ class ExtractFileWriter: def enum_list(self, name, enums): self.enum_start(name) for enum in enums: - self.content += f"{self.indention}{enum},\n" + if enum.endswith("_NONE"): + self.content += f"{self.indention}{enum} = -1,\n" + else: + self.content += f"{self.indention}{enum},\n" self.enum_stop(name) def enum_dict(self, name, enums): @@ -107,9 +110,9 @@ class EnumWriter: self.all_tiles = tiles self.tiles = group_by_class(tiles) self.enums = [] + self.enums.append(self.to_enum("none")) self.enums += [self.to_enum(x) for x in self.tiles.keys()] self.enums.append(self.to_enum("count")) - self.enums.append(self.to_enum("none")) self.enum_type = f"{prefix.capitalize()}Type" if anim_prefix: self.anim_prefix = anim_prefix