Buildings as entities instead of map layer

This commit is contained in:
2024-01-08 14:41:26 +01:00
parent 03dc3774e7
commit c08fca9670
17 changed files with 168 additions and 186 deletions

View File

@@ -288,9 +288,11 @@ void bzTileMapDestroy(BzTileMap *map) {
} }
void bzTileMapPosToTile(BzTileMap *map, Vector2 pos, BzTile *x, BzTile *y) { Vec2i bzTileMapPosToTile(BzTileMap *map, Vector2 pos) {
if (x) *x = (BzTile) (pos.x / (f32) map->tileWidth); return (Vec2i) {
if (y) *y = (BzTile) (pos.y / (f32) map->tileHeight); .x = (i32) (pos.x / (f32) map->tileWidth),
.y = (i32) (pos.y / (f32) map->tileHeight)
};
} }
void bzTileMapOverrideLayer(BzTileMap *map, i32 slotID, BzTileLayerFunc func) { void bzTileMapOverrideLayer(BzTileMap *map, i32 slotID, BzTileLayerFunc func) {

View File

@@ -2,6 +2,7 @@
#define BREEZE_MAP_H #define BREEZE_MAP_H
#include "tileset.h" #include "tileset.h"
#include "../math/vec2i.h"
#include "../util/string.h" #include "../util/string.h"
#define BZ_MAP_MAX_LAYERS 8 #define BZ_MAP_MAX_LAYERS 8
@@ -116,7 +117,7 @@ BzTileset *bzTileObjectGroupGetTileset(BzTileMap *map, BzTileObjectGroup *object
BzTileMap bzTileMapCreate(const BzTileMapDesc *desc); BzTileMap bzTileMapCreate(const BzTileMapDesc *desc);
void bzTileMapDestroy(BzTileMap *map); 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 bzTileMapOverrideLayer(BzTileMap *map, i32 slotID, BzTileLayerFunc func);
void bzTileMapOverrideObjectGroup(BzTileMap *map, i32 slotID, BzTileObjectsFunc func); void bzTileMapOverrideObjectGroup(BzTileMap *map, i32 slotID, BzTileObjectsFunc func);

View File

@@ -4,14 +4,16 @@
#include "entity_factory.h" #include "entity_factory.h"
#include "game_state.h" #include "game_state.h"
#include "map_layers.h" #include "map_layers.h"
#include "systems/systems.h"
#include <raymath.h> #include <raymath.h>
bool canPlaceBuilding(BzTileMap *map, BuildingType type, BzTile tileX, BzTile tileY) { bool canPlaceBuilding(Game *game, BuildingType type, BzTile tileX, BzTile tileY) {
i32 sizeX, sizeY; i32 sizeX, sizeY;
getBuildingSize(type, &sizeX, &sizeY); getBuildingSize(type, &sizeX, &sizeY);
if (sizeX == 0 || sizeY == 0) return false; if (sizeX == 0 || sizeY == 0) return false;
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 ||
tileY < 0 || tileY + sizeY > map->height) 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, Rectangle buildArea = {tileX * map->tileWidth, tileY * map->tileHeight,
sizeX * map->tileWidth, sizeY * map->tileHeight}; sizeX * map->tileWidth, sizeY * map->tileHeight};
// Need to check neighbour tiles BzSpatialGridIter it = bzSpatialGridIter(game->entityGrid, buildArea.x, buildArea.y, buildArea.width, buildArea.height);
//tileX -= 1; while (bzSpatialGridQueryNext(&it)) { ecs_entity_t entity = *(ecs_entity_t *) it.data;
//tileY -= 1; Rectangle bounds;
//sizeX += 2; if (!getEntityBounds(entity, NULL, NULL, &bounds)) continue;
//sizeY += 2;
BzTileLayer *buildLayer = bzTileMapGetLayer(map, LAYER_BUILDINGS); if (CheckCollisionRecs(buildArea, bounds))
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; return false;
} }
}
}
return true; return true;
} }
ecs_entity_t placeBuilding(BzTileMap *map, BuildingType type, BzTile tileX, BzTile tileY) { ecs_entity_t placeBuilding(Game *game, BuildingType type,
Game *game = ecs_singleton_get_mut(ECS, Game); BzTile tileX, BzTile tileY, Owner owner) {
if (type <= BUILDING_NONE || type >= BUILDING_COUNT)
return 0;
i32 sizeX, sizeY; i32 sizeX, sizeY;
getBuildingSize(type, &sizeX, &sizeY); getBuildingSize(type, &sizeX, &sizeY);
BzTileLayer *buildingLayer = bzTileMapGetLayer(map, LAYER_BUILDINGS); const i32 tileWidth = game->map.tileWidth;
BzTileset *buildingTileset = bzTileLayerGetTileset(map, buildingLayer); const i32 tileHeight = game->map.tileHeight;
BzTile buildingTile = getBuildingTile(type);
BZ_ASSERT(buildingTile != -1);
// Create entity // 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_ptr(ECS, building, Position, &pos);
ecs_set(ECS, e, TileSize, { .sizeX = sizeX, .sizeY = sizeY }); ecs_set_ptr(ECS, building, Size, &size);
//ecs_set(ECS, e, Owner, { .playerID = BUILDINGS_PLAYER_RED }); ecs_set(ECS, building, Rotation, {0});
for (i32 y = tileY; y < tileY + sizeY; y++) { SpatialGridID gridID = bzSpatialGridInsert(game->entityGrid, &building,
for (i32 x = tileX; x < tileX + sizeX; x++) { pos.x, pos.y,
BzTile layerTile = buildingTile + buildingTileset->startID; size.x, size.y);
bzTileLayerSetTile(buildingLayer, layerTile, x, y, 1, 1); ecs_set_ptr(ECS, building, SpatialGridID, &gridID);
buildingTile++; 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, &region);
bzTileMapUpdateCollisions(map, x, y, 1, 1); switch (type) {
} case BUILDING_KEEP:
buildingTile += buildingTileset->width - sizeX; ecs_add_id(ECS, building, Storage);
break;
default:
break;
} }
return e; return building;
} }

View File

@@ -4,10 +4,13 @@
#include <breeze.h> #include <breeze.h>
#include <flecs.h> #include <flecs.h>
#include "components.h"
#include "game_tileset.h" #include "game_tileset.h"
bool canPlaceBuilding(BzTileMap *map, BuildingType type, i32 tileX, i32 tileY); typedef struct Game Game;
ecs_entity_t placeBuilding(BzTileMap *map, 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 tileX, i32 tileY, Owner owner);
Vector2 getPositionNearBuilding(ecs_entity_t building, Vector2 fromPos); Vector2 getPositionNearBuilding(ecs_entity_t building, Vector2 fromPos);

View File

@@ -7,8 +7,6 @@ ECS_TAG_DECLARE(GameEntity);
ECS_COMPONENT_DECLARE(Resource); ECS_COMPONENT_DECLARE(Resource);
ECS_COMPONENT_DECLARE(TilePosition);
ECS_COMPONENT_DECLARE(TileSize);
ECS_COMPONENT_DECLARE(Owner); ECS_COMPONENT_DECLARE(Owner);
ECS_COMPONENT_DECLARE(SpatialGridID); ECS_COMPONENT_DECLARE(SpatialGridID);
@@ -47,8 +45,6 @@ void initComponentIDs(ecs_world_t *ecs) {
ECS_COMPONENT_DEFINE(ecs, Resource); ECS_COMPONENT_DEFINE(ecs, Resource);
ECS_COMPONENT_DEFINE(ecs, TilePosition);
ECS_COMPONENT_DEFINE(ecs, TileSize);
ECS_COMPONENT_DEFINE(ecs, Owner); ECS_COMPONENT_DEFINE(ecs, Owner);
ECS_COMPONENT_DEFINE(ecs, SpatialGridID); ECS_COMPONENT_DEFINE(ecs, SpatialGridID);
@@ -106,18 +102,6 @@ void igResource(ecs_world_t *ecs,
res->type = curType; res->type = curType;
igInputInt("Amount", &res->amount, 1, 10, 0); 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, void igOwner(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) { ecs_entity_t entity, ecs_entity_t comp) {
Owner *owner = ecs_get_mut_id(ecs, entity, comp); Owner *owner = ecs_get_mut_id(ecs, entity, comp);

View File

@@ -33,18 +33,6 @@ typedef struct Resource {
} Resource; } Resource;
extern ECS_COMPONENT_DECLARE(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 { typedef struct Owner {
int32_t playerID; int32_t playerID;
} Owner; } 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); typedef void(*ImGuiCompFn)(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp);
void igResource(ecs_world_t *ecs, void igResource(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp); 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, void igOwner(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp); ecs_entity_t entity, ecs_entity_t comp);

View File

@@ -17,8 +17,8 @@ typedef struct AnimationFrame {
} AnimationFrame; } AnimationFrame;
typedef enum TerrainType { typedef enum TerrainType {
TERRAIN_NONE = -1,
TERRAIN_COUNT, TERRAIN_COUNT,
TERRAIN_NONE,
} TerrainType; } TerrainType;
static bool terrainHasAnimation(BzTileID tile) { static bool terrainHasAnimation(BzTileID tile) {
@@ -257,9 +257,9 @@ static AnimationFrame terrainGetAnimationFrame(BzTileID tile, i32 frameIdx) {
typedef enum BuildingType { typedef enum BuildingType {
BUILDING_NONE = -1,
BUILDING_KEEP, BUILDING_KEEP,
BUILDING_COUNT, BUILDING_COUNT,
BUILDING_NONE,
} BuildingType; } BuildingType;
static BuildingType getTileBuilding(BzTileID tile) { static BuildingType getTileBuilding(BzTileID tile) {
@@ -275,7 +275,7 @@ static BuildingType getTileBuilding(BzTileID tile) {
case 6406: case 6406:
return BUILDING_KEEP; return BUILDING_KEEP;
default: default:
return BUILDING_NONE; return BUILDING_COUNT;
} }
} }
@@ -288,7 +288,7 @@ static BzTileID getBuildingTile(BuildingType type) {
static BuildingType getBuildingFromStr(const char *str) { static BuildingType getBuildingFromStr(const char *str) {
if (strncmp("keep", str, 4) == 0) return BUILDING_KEEP; if (strncmp("keep", str, 4) == 0) return BUILDING_KEEP;
return BUILDING_NONE; return BUILDING_COUNT;
} }
static const char *getBuildingStr(BuildingType type) { static const char *getBuildingStr(BuildingType type) {
@@ -313,6 +313,7 @@ static BuildingType getBuildingSize(BuildingType type, BzTileID *outWidth, BzTil
typedef enum EntityType { typedef enum EntityType {
ENTITY_NONE = -1,
ENTITY_WORKER, ENTITY_WORKER,
ENTITY_WOOD, ENTITY_WOOD,
ENTITY_STONE, ENTITY_STONE,
@@ -320,7 +321,6 @@ typedef enum EntityType {
ENTITY_GOLD, ENTITY_GOLD,
ENTITY_POP, ENTITY_POP,
ENTITY_COUNT, ENTITY_COUNT,
ENTITY_NONE,
} EntityType; } EntityType;
typedef enum AnimType { typedef enum AnimType {
@@ -329,7 +329,7 @@ typedef enum AnimType {
ANIM_HURT, ANIM_HURT,
ANIM_DIE, ANIM_DIE,
ANIM_COUNT, ANIM_COUNT,
ANIM_NONE, ANIM_NONE = -1,
} AnimType; } AnimType;
static BzTileID getEntityTile(EntityType type) { static BzTileID getEntityTile(EntityType type) {
@@ -394,6 +394,7 @@ static AnimationFrame entityGetAnimationFrame(EntityType entity, AnimType type,
} }
typedef enum ItemType { typedef enum ItemType {
ITEM_NONE = -1,
ITEM_STAFF, ITEM_STAFF,
ITEM_PICKAXE, ITEM_PICKAXE,
ITEM_AXE, ITEM_AXE,
@@ -415,7 +416,6 @@ typedef enum ItemType {
ITEM_SPEAR, ITEM_SPEAR,
ITEM_TRIDENT, ITEM_TRIDENT,
ITEM_COUNT, ITEM_COUNT,
ITEM_NONE,
} ItemType; } ItemType;
static BzTileID getItemTile(ItemType type) { static BzTileID getItemTile(ItemType type) {

View File

@@ -50,8 +50,8 @@ typedef struct InputState {
// INPUT_BUILDING // INPUT_BUILDING
int building; int building;
bool buildingCanPlace; bool buildingCanPlace;
TilePosition buildingPos; Vec2i buildingPos;
TileSize buildingSize; Vec2i buildingSize;
// SELECTED_UNITS // SELECTED_UNITS
Rectangle pickArea; Rectangle pickArea;

View File

@@ -103,9 +103,9 @@ void loadMap(Game *game, const char *path) {
.layers[LAYER_TERRAIN]=(BzTileLayerDesc) {"terrain", .renderer=terrainRender, .applyColliders=true}, .layers[LAYER_TERRAIN]=(BzTileLayerDesc) {"terrain", .renderer=terrainRender, .applyColliders=true},
.layers[LAYER_ROCKS]=(BzTileLayerDesc) {"rocks"}, .layers[LAYER_ROCKS]=(BzTileLayerDesc) {"rocks"},
.layers[LAYER_ROCKS2]=(BzTileLayerDesc) {"rocks_s"}, .layers[LAYER_ROCKS2]=(BzTileLayerDesc) {"rocks_s"},
.layers[LAYER_TREES]=(BzTileLayerDesc) {"trees"}, .layers[LAYER_TREES]=(BzTileLayerDesc) {"trees", BZ_TILE_LAYER_SKIP_RENDER},
.layers[LAYER_TREES2]=(BzTileLayerDesc) {"trees_s"}, .layers[LAYER_TREES2]=(BzTileLayerDesc) {"trees_s", BZ_TILE_LAYER_SKIP_RENDER},
.layers[LAYER_BUILDINGS]=(BzTileLayerDesc) {"buildings", .applyColliders=true}, .layers[LAYER_BUILDINGS]=(BzTileLayerDesc) {"buildings", BZ_TILE_LAYER_SKIP_RENDER},
.layers[LAYER_BUILDING_OWNER]=(BzTileLayerDesc) {"building_ownership", BZ_TILE_LAYER_SKIP_RENDER}, .layers[LAYER_BUILDING_OWNER]=(BzTileLayerDesc) {"building_ownership", BZ_TILE_LAYER_SKIP_RENDER},
.objectGroups[OBJECTS_GAME]=(BzTileObjectsDesc) {"game"}, .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_TREES2, initTreesLayer);
bzTileMapOverrideLayer(&game->map, LAYER_BUILDING_OWNER, initBuildingsLayer); 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_GAME, initGameObjectsLayer);
bzTileMapOverrideObjectGroup(&game->map, OBJECTS_ENTITIES, initEntityObjectsLayer); bzTileMapOverrideObjectGroup(&game->map, OBJECTS_ENTITIES, initEntityObjectsLayer);
@@ -197,6 +198,8 @@ bool init(void *userData) {
{ecs_id(Selected)} {ecs_id(Selected)}
} }
}); });
input->building = BUILDING_NONE;
} }
{ {
InitAudioDevice(); InitAudioDevice();
@@ -652,8 +655,6 @@ void igInspectWindow(ecs_entity_t entity, bool *open) {
igTagCheckbox("Attackable", ECS, entity, Attackable); igTagCheckbox("Attackable", ECS, entity, Attackable);
} }
igInspectComp("Resource", entity, ecs_id(Resource), igResource); 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("Owner", entity, ecs_id(Owner), igOwner);
igInspectComp("SpatialGridID", entity, ecs_id(SpatialGridID), igSpatialGridID); igInspectComp("SpatialGridID", entity, ecs_id(SpatialGridID), igSpatialGridID);
igInspectComp("Position", entity, ecs_id(Position), igVec2Comp); igInspectComp("Position", entity, ecs_id(Position), igVec2Comp);
@@ -735,11 +736,13 @@ void imguiRender(float dt, void *userData) {
igText("Population: %lld", game->resources.pop); igText("Population: %lld", game->resources.pop);
} }
if (igCollapsingHeader_TreeNodeFlags("BuildMenu", 0)) { if (igCollapsingHeader_TreeNodeFlags("BuildMenu", 0)) {
for (int i = 0; i < BUILDING_COUNT; i++) { for (int i = BUILDING_NONE; i < BUILDING_COUNT; i++) {
if (igSelectable_Bool(getBuildingStr(i), input->building == i, 0, (ImVec2){0, 0})) const char *buildingStr = getBuildingStr(i);
if (!buildingStr) buildingStr = "NONE";
if (igSelectable_Bool(buildingStr, input->building == i, 0, (ImVec2){0, 0}))
input->building = i; input->building = i;
} }
if (input->building) if (input->building > BUILDING_NONE && input->building < BUILDING_COUNT)
input->state = INPUT_BUILDING; input->state = INPUT_BUILDING;
} }

View File

@@ -2,6 +2,7 @@
#include <flecs.h> #include <flecs.h>
#include "buildings.h"
#include "components.h" #include "components.h"
#include "entity_factory.h" #include "entity_factory.h"
#include "game_state.h" #include "game_state.h"
@@ -60,40 +61,24 @@ bool initBuildingsLayer(BzTileMap *map, BzTileLayer *layer) {
BzTileset *buildingTileset = bzTileLayerGetTileset(map, buildingLayer); BzTileset *buildingTileset = bzTileLayerGetTileset(map, buildingLayer);
BzTile *data = layer->data; BzTile *data = layer->data;
BzTile *buildingData = buildingLayer->data; BzTile *buildingData = buildingLayer->data;
BZ_ASSERT(ownershipLayer->tilesetIdx == buildingLayer->tilesetIdx);
for (i32 y = 0; y < layer->height; y++) { for (i32 y = 0; y < layer->height; y++) {
for (i32 x = 0; x < layer->width; x++) { 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 buildingRawTile = buildingData[y * layer->width + x];
BzTile buildingTile = bzTilesetGetTileID(buildingTileset, buildingRawTile); BzTile buildingType = bzTilesetGetTileID(buildingTileset, buildingRawTile);
buildingTile = getTileBuilding(buildingTile); buildingType = getTileBuilding(buildingType);
if (buildingTile == BUILDING_NONE || ownerTile == 0) continue; if (buildingType <= BUILDING_NONE || buildingType >= BUILDING_COUNT)
// We have a building continue;
TileSize tileSize = {}; placeBuilding(game, buildingType, x, y, (Owner) {owner});
getBuildingSize(buildingTile, &tileSize.sizeX, &tileSize.sizeY);
bzTileLayerSetTile(ownershipLayer, 0, x, y, tileSize.sizeX, tileSize.sizeY);
const i32 tileWidth = map->tileWidth; i32 sizeX = 1;
const i32 tileHeight = map->tileHeight; i32 sizeY = 1;
ecs_entity_t e = entityCreateEmpty(); getBuildingSize(buildingType, &sizeX, &sizeY);
Size size = {.x = tileSize.sizeX * tileWidth, .y = tileSize.sizeY * tileHeight }; x += sizeX - 1;
ecs_set_ptr(ECS, e, Size, &size); y += sizeY - 1;
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);
} }
} }
return true; return true;

View File

@@ -2,7 +2,7 @@
#include <raymath.h> #include <raymath.h>
static i32 dst(TilePosition a, TilePosition b) { static i32 dst(Vec2i a, Vec2i b) {
//i32 dX = a.x - b.x; //i32 dX = a.x - b.x;
//i32 dY = a.y - b.y; //i32 dY = a.y - b.y;
//return dX * dX + dY * dY; //return dX * dX + dY * dY;
@@ -126,9 +126,8 @@ bool pathfindAStar(const PathfindingDesc *desc) {
BZ_ASSERT(desc->alloc); BZ_ASSERT(desc->alloc);
BzTileMap *map = desc->map; BzTileMap *map = desc->map;
TilePosition start = {0}, target = {0}; Vec2i start = bzTileMapPosToTile(map, desc->start);
bzTileMapPosToTile(map, desc->start, &start.x, &start.y); Vec2i target = bzTileMapPosToTile(map, desc->target);
bzTileMapPosToTile(map, desc->target, &target.x, &target.y);
BZ_ASSERT(start.x >= 0 && start.x < map->width); BZ_ASSERT(start.x >= 0 && start.x < map->width);
BZ_ASSERT(start.y >= 0 && start.y < map->height); BZ_ASSERT(start.y >= 0 && start.y < map->height);
@@ -178,7 +177,7 @@ bool pathfindAStar(const PathfindingDesc *desc) {
foundPath = true; foundPath = true;
break; break;
} }
TilePosition pos = node.pos; Vec2i pos = node.pos;
PathNodeRecord *nodeRecord = &closedSet[pos.y * map->width + pos.x]; PathNodeRecord *nodeRecord = &closedSet[pos.y * map->width + pos.x];
nodeRecord->visited = true; nodeRecord->visited = true;
nodeRecord->open = false; nodeRecord->open = false;
@@ -199,7 +198,7 @@ bool pathfindAStar(const PathfindingDesc *desc) {
if (curRecord->visited) if (curRecord->visited)
continue; continue;
TilePosition curPos = {x, y}; Vec2i curPos = {x, y};
i32 gCost = node.gCost + dst(node.pos, curPos); i32 gCost = node.gCost + dst(node.pos, curPos);
if (curRecord->open) { if (curRecord->open) {
i32 nodeIdx = curRecord->nodeIdx; i32 nodeIdx = curRecord->nodeIdx;
@@ -234,7 +233,7 @@ bool pathfindAStar(const PathfindingDesc *desc) {
i32 pathLen = 0; i32 pathLen = 0;
if (foundPath && desc->outPath) { if (foundPath && desc->outPath) {
TilePosition pos = target; Vec2i pos = target;
Path *out = desc->outPath; Path *out = desc->outPath;
out->curWaypoint = 0; out->curWaypoint = 0;
BZ_ASSERT(desc->pool); 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[left] = heap->arr[right];
heap->arr[right] = tmp; heap->arr[right] = tmp;
TilePosition leftPos = heap->arr[left].pos; Vec2i leftPos = heap->arr[left].pos;
TilePosition rightPos = heap->arr[right].pos; Vec2i rightPos = heap->arr[right].pos;
i32 leftIdx = leftPos.y * heap->mapWidth + leftPos.x; i32 leftIdx = leftPos.y * heap->mapWidth + leftPos.x;
i32 rightIdx = rightPos.y * heap->mapWidth + rightPos.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->arr[heap->size] = node;
heap->size++; heap->size++;
TilePosition pos = node.pos; Vec2i pos = node.pos;
PathNodeRecord *record = &heap->records[pos.y * heap->mapWidth + pos.x]; PathNodeRecord *record = &heap->records[pos.y * heap->mapWidth + pos.x];
record->nodeIdx = heap->size - 1; record->nodeIdx = heap->size - 1;

View File

@@ -9,7 +9,7 @@ typedef struct PathNode {
i32 weight; // fCost = g + h i32 weight; // fCost = g + h
i32 gCost; // from start cost i32 gCost; // from start cost
i32 hCost; // to target cost i32 hCost; // to target cost
TilePosition pos; Vec2i pos;
} PathNode; } PathNode;
typedef struct PathNodeRecord { typedef struct PathNodeRecord {

View File

@@ -11,9 +11,6 @@
#include <raymath.h> #include <raymath.h>
#include <rlgl.h> #include <rlgl.h>
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); ecs_entity_t queryEntity(BzSpatialGrid *entityGrid, Vector2 point, ecs_entity_t tag);
bool selectEntity(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) { void resetInputState(InputState *input) {
input->cursor = CURSOR_NONE; input->cursor = CURSOR_NONE;
input->state = INPUT_NONE; input->state = INPUT_NONE;
input->building = 0; input->building = BUILDING_NONE;
} }
void inputPrimaryAction(Game *game, InputState *input) { void inputPrimaryAction(Game *game, InputState *input) {
@@ -218,8 +215,9 @@ void updatePlayerInput() {
BzTileMap *map = &game->map; BzTileMap *map = &game->map;
BzTile tileX = 0, tileY = 0; Vec2i tileXY = bzTileMapPosToTile(map, input->mouseWorld);
bzTileMapPosToTile(map, input->mouseWorld, &tileX, &tileY); BzTile tileX = tileXY.x;
BzTile tileY = tileXY.y;
const MouseButton primaryBtn = input->mapping.primaryBtn; const MouseButton primaryBtn = input->mapping.primaryBtn;
const MouseButton secondaryBtn = input->mapping.secondaryBtn; const MouseButton secondaryBtn = input->mapping.secondaryBtn;
@@ -230,16 +228,19 @@ void updatePlayerInput() {
break; break;
} }
case INPUT_BUILDING: { 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; BzTile sizeX = 0, sizeY = 0;
getBuildingSize(input->building, &sizeX, &sizeY); 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)) { if (canPlace && isInputBtnDown(input, primaryBtn)) {
placeBuilding(&game->map, input->building, tileX, tileY); placeBuilding(game, input->building, tileX, tileY, (Owner) {-1});
} }
input->buildingCanPlace = canPlace; input->buildingCanPlace = canPlace;
input->buildingPos = (TilePosition) {tileX, tileY}; input->buildingPos = (Vec2i) {tileX, tileY};
input->buildingSize = (TileSize) {sizeX, sizeY}; input->buildingSize = (Vec2i) {sizeX, sizeY};
break; break;
} }
case INPUT_SELECTED_UNITS: { case INPUT_SELECTED_UNITS: {
@@ -278,8 +279,8 @@ void drawPlayerInputUIGround() {
const BzTile height = game->map.tileHeight; const BzTile height = game->map.tileHeight;
DrawRectangleLines(input->buildingPos.x * width, DrawRectangleLines(input->buildingPos.x * width,
input->buildingPos.y * height, input->buildingPos.y * height,
input->buildingSize.sizeX * width, input->buildingSize.x * width,
input->buildingSize.sizeY * height, placeColor); input->buildingSize.y * height, placeColor);
break; break;
} }
default: 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) { ecs_entity_t queryEntity(BzSpatialGrid *entityGrid, Vector2 point, ecs_entity_t tag) {
BzSpatialGridIter it = bzSpatialGridIter(entityGrid, point.x, point.y, 0.0f, 0.0f); BzSpatialGridIter it = bzSpatialGridIter(entityGrid, point.x, point.y, 0.0f, 0.0f);
f32 closestDst = INFINITY; f32 closestDst = INFINITY;

View File

@@ -2,6 +2,40 @@
#include "../game_state.h" #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 renderCollidersSystem;
ecs_entity_t renderOrientDirSystem; ecs_entity_t renderOrientDirSystem;
ecs_entity_t renderArmPositionSystem; ecs_entity_t renderArmPositionSystem;
@@ -37,6 +71,7 @@ ECS_DTOR(Arms, arms, {
ecs_delete(ECS, arms->secondary); ecs_delete(ECS, arms->secondary);
arms->secondary = 0; arms->secondary = 0;
} }
}) })
ECS_MOVE(Arms, dst, src, { ECS_MOVE(Arms, dst, src, {
*dst = *src; *dst = *src;

View File

@@ -171,6 +171,13 @@ void drawPlayerInputUI();
* UI systems * UI systems
**********************************/ **********************************/
/**********************************
* Utils
**********************************/
Rectangle calculateEntityBounds(Position pos, Size size);
bool getEntityBounds(ecs_entity_t entity, Position *outPos, Size *outSize, Rectangle *outBounds);
/********************************** /**********************************
* MISC * MISC
**********************************/ **********************************/

View File

@@ -5,7 +5,10 @@
#include <stdio.h> #include <stdio.h>
f32 uiGetScale() { 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() { Font getFont() {

View File

@@ -62,6 +62,9 @@ class ExtractFileWriter:
def enum_list(self, name, enums): def enum_list(self, name, enums):
self.enum_start(name) self.enum_start(name)
for enum in enums: for enum in enums:
if enum.endswith("_NONE"):
self.content += f"{self.indention}{enum} = -1,\n"
else:
self.content += f"{self.indention}{enum},\n" self.content += f"{self.indention}{enum},\n"
self.enum_stop(name) self.enum_stop(name)
@@ -107,9 +110,9 @@ class EnumWriter:
self.all_tiles = tiles self.all_tiles = tiles
self.tiles = group_by_class(tiles) self.tiles = group_by_class(tiles)
self.enums = [] self.enums = []
self.enums.append(self.to_enum("none"))
self.enums += [self.to_enum(x) for x in self.tiles.keys()] 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("count"))
self.enums.append(self.to_enum("none"))
self.enum_type = f"{prefix.capitalize()}Type" self.enum_type = f"{prefix.capitalize()}Type"
if anim_prefix: if anim_prefix:
self.anim_prefix = anim_prefix self.anim_prefix = anim_prefix