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) {
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) {

View File

@@ -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);

View File

@@ -4,14 +4,16 @@
#include "entity_factory.h"
#include "game_state.h"
#include "map_layers.h"
#include "systems/systems.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;
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, &region);
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;
}

View File

@@ -4,10 +4,13 @@
#include <breeze.h>
#include <flecs.h>
#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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -2,6 +2,7 @@
#include <flecs.h>
#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;

View File

@@ -2,7 +2,7 @@
#include <raymath.h>
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;

View File

@@ -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 {

View File

@@ -11,9 +11,6 @@
#include <raymath.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);
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;

View File

@@ -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;

View File

@@ -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
**********************************/

View File

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

View File

@@ -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