From d6466b8f554b88ba27f764751ebaae9413ddd3e5 Mon Sep 17 00:00:00 2001 From: Klemen Plestenjak Date: Wed, 7 Feb 2024 16:12:45 +0100 Subject: [PATCH] Add health --- game/building_factory.c | 12 ++++++++++++ game/components.c | 2 ++ game/components.h | 7 +++++++ game/entity_factory.c | 6 ++++++ game/systems/s_entity.c | 38 +++++++++++++++++++++++++++++++++++++- game/systems/systems.c | 1 + game/systems/systems.h | 7 +++++++ 7 files changed, 72 insertions(+), 1 deletion(-) diff --git a/game/building_factory.c b/game/building_factory.c index 99ec63c..c78bc38 100644 --- a/game/building_factory.c +++ b/game/building_factory.c @@ -90,6 +90,12 @@ ecs_entity_t placeBuilding(Game *game, BuildingType type, bool hasCollision = true; + Health health = { + .startHP = 100.0f, + .hp = 100.0f, + .lastChanged = -1.0f, + }; + switch (type) { case BUILDING_KEEP: ecs_set(ECS, building, AddPopCapacity, {10}); @@ -103,6 +109,8 @@ ecs_entity_t placeBuilding(Game *game, BuildingType type, .elapsed = 0.0f, } }); + health.startHP = 1000.0f; + health.hp = health.startHP; break; case BUILDING_BARRACKS: ecs_set(ECS, building, BuildingRecruitInfo, { @@ -137,11 +145,15 @@ ecs_entity_t placeBuilding(Game *game, BuildingType type, .harvestLimit = 1 }); ecs_set(ECS, building, Resource, {RES_FOOD, INT32_MAX}); + health.startHP = 20.0f; + health.hp = health.startHP; break; default: break; } + ecs_set_ptr(ECS, building, Health, &health); + if (hasCollision) bzTileMapSetCollisions(&game->map, true, COLL_LAYER_BUILDINGS, posX, posY, sizeX, sizeY); diff --git a/game/components.c b/game/components.c index acccb33..de5b56c 100644 --- a/game/components.c +++ b/game/components.c @@ -37,6 +37,7 @@ ECS_TAG_DECLARE(Selected); ECS_COMPONENT_DECLARE(AddPopCapacity); ECS_COMPONENT_DECLARE(ConsumePopCapacity); +ECS_COMPONENT_DECLARE(Health); ECS_COMPONENT_DECLARE(Worker); ECS_COMPONENT_DECLARE(Building); ECS_COMPONENT_DECLARE(Unit); @@ -83,6 +84,7 @@ void initComponentIDs(ecs_world_t *ecs) { ECS_COMPONENT_DEFINE(ecs, AddPopCapacity); ECS_COMPONENT_DEFINE(ecs, ConsumePopCapacity); + ECS_COMPONENT_DEFINE(ecs, Health); ECS_COMPONENT_DEFINE(ecs, Worker); ECS_COMPONENT_DEFINE(ecs, Building); ECS_COMPONENT_DEFINE(ecs, Unit); diff --git a/game/components.h b/game/components.h index 4100119..392a3e1 100644 --- a/game/components.h +++ b/game/components.h @@ -214,6 +214,13 @@ typedef struct ConsumePopCapacity { } ConsumePopCapacity; extern ECS_COMPONENT_DECLARE(ConsumePopCapacity); +typedef struct Health { + f32 startHP; + f32 hp; + f32 lastChanged; +} Health; +extern ECS_COMPONENT_DECLARE(Health); + // Worker can: // - Harvest // - Build diff --git a/game/entity_factory.c b/game/entity_factory.c index e5fd207..8291b1a 100644 --- a/game/entity_factory.c +++ b/game/entity_factory.c @@ -80,6 +80,12 @@ ecs_entity_t entityCreateWorker(const Position position, Player player, Game *ga .carryCapacity = 5, }); + ecs_set(ECS, e, Health, { + .startHP = 20.0f, + .hp = 20.0f, + .lastChanged = -1.0f + }); + return e; } diff --git a/game/systems/s_entity.c b/game/systems/s_entity.c index ac29748..8887f9c 100644 --- a/game/systems/s_entity.c +++ b/game/systems/s_entity.c @@ -270,9 +270,45 @@ void updateBuildingRecruitment(ecs_iter_t *it) { } } +void renderHealth(ecs_iter_t *it) { + Position *pos = ecs_field(it, Position, 1); + HitBox *hitbox = ecs_field(it, HitBox, 2); + Health *health = ecs_field(it, Health, 3); + + for (i32 i = 0; i < it->count; i++) { + HitBox hb = entityTransformHitBox(pos[i], hitbox[i]); + const f32 HP_WIDTH = 10.0f; + const f32 HP_HEIGHT = 1.8f; + const f32 HP_OFFSET = 2.0f; + + const Color BG_COLOR = {0, 0, 0, 60}; + const Color HP_COLOR = {255, 0, 0, 220}; + + const f32 PADDING = 0.15f; + + Vector2 hpPos = { + hb.x + (hb.width - HP_WIDTH) * 0.5f, + hb.y - HP_OFFSET - HP_HEIGHT + }; + Vector2 size = { + HP_WIDTH, HP_HEIGHT + }; + f32 hpPercent = health[i].hp / health[i].startHP; + Vector2 hpSize = { + HP_WIDTH * hpPercent - PADDING * 2.0f, + HP_HEIGHT - PADDING * 2.0f + }; + + DrawRectangleV(hpPos, size, BG_COLOR); + hpPos.x += PADDING; + hpPos.y += PADDING; + DrawRectangleV(hpPos, hpSize, HP_COLOR); + } +} + void renderColliders(ecs_iter_t *it) { Position *pos = ecs_field(it, Position, 1); - HitBox *hitbox = ecs_field(it, HitBox , 2); + HitBox *hitbox = ecs_field(it, HitBox, 2); for (i32 i = 0; i < it->count; i++) { HitBox hb = entityTransformHitBox(pos[i], hitbox[i]); diff --git a/game/systems/systems.c b/game/systems/systems.c index 0ac7eb5..aebb9b5 100644 --- a/game/systems/systems.c +++ b/game/systems/systems.c @@ -113,6 +113,7 @@ void setupSystems() { ECS_SYSTEM(ECS, updateAnimation, EcsOnUpdate, Animation, TextureRegion); ECS_SYSTEM(ECS, updateEasingSystem, EcsOnUpdate, Easing, Position, HitBox, Rotation); + ECS_SYSTEM(ECS, renderHealth, EcsOnUpdate, Position, HitBox, Health); ECS_SYSTEM(ECS, renderDebugPath, EcsOnUpdate, Path); ECS_SYSTEM(ECS, renderColliders, EcsOnUpdate, Position, HitBox); diff --git a/game/systems/systems.h b/game/systems/systems.h index c8e4944..2b60102 100644 --- a/game/systems/systems.h +++ b/game/systems/systems.h @@ -147,6 +147,13 @@ void entityFollowPath(ecs_iter_t *it); */ void updateBuildingRecruitment(ecs_iter_t *it); +/* + * 1: Position + * 2: HitBox + * 3: Health + */ +void renderHealth(ecs_iter_t *it); + /* * 1: Position * 2: HitBox