Partial tower implementation
This commit is contained in:
@@ -146,6 +146,44 @@ ecs_entity_t placeBuilding(Game *game, BuildingType type,
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
case BUILDING_TOWER: {
|
||||||
|
ecs_entity_t mage = entityCreateEmpty();
|
||||||
|
const Vector2 mageSize = { 8.0f, 16.0f };
|
||||||
|
Vector2 magePos = {
|
||||||
|
pos.x + (size.x - mageSize.x) * 0.5f,
|
||||||
|
pos.y - size.y * 0.5f
|
||||||
|
};
|
||||||
|
ecs_set_ptr(ECS, mage, Position, &magePos);
|
||||||
|
ecs_set_ptr(ECS, mage, Size, &mageSize);
|
||||||
|
ecs_set(ECS, mage, Rotation, { 0 });
|
||||||
|
ecs_set(ECS, mage, TextureRegion, {
|
||||||
|
tileset->tiles,
|
||||||
|
getTextureRect(getEntityTile(ENTITY_MAGE))
|
||||||
|
});
|
||||||
|
ecs_set(ECS, mage, Animation, {
|
||||||
|
.entityType = ENTITY_MAGE,
|
||||||
|
.animType = ANIM_IDLE,
|
||||||
|
|
||||||
|
.sequence = entityGetAnimationSequence(ENTITY_MAGE, ANIM_IDLE),
|
||||||
|
.tileset = tileset,
|
||||||
|
.curFrame = 0,
|
||||||
|
.elapsed = 0.0f
|
||||||
|
});
|
||||||
|
ecs_set(ECS, mage, DrawLayer, { 1 });
|
||||||
|
|
||||||
|
ecs_set(ECS, building, AttachedEntity, {mage});
|
||||||
|
ecs_set(ECS, building, Tower, {
|
||||||
|
.range = 46.0f,
|
||||||
|
.minDamage = 40.0f,
|
||||||
|
.maxDamage = 80.0f,
|
||||||
|
.damageFalloff = 8.0f,
|
||||||
|
.damageRadius = 28.0f,
|
||||||
|
.projectileSpeed = 10.0f,
|
||||||
|
.fireCooldown = 1.2f,
|
||||||
|
.fireElapsed = 0.0f,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
case BUILDING_HOUSE_01:
|
case BUILDING_HOUSE_01:
|
||||||
case BUILDING_HOUSE_02:
|
case BUILDING_HOUSE_02:
|
||||||
case BUILDING_HOUSE_03:
|
case BUILDING_HOUSE_03:
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ ECS_COMPONENT_DECLARE(Health);
|
|||||||
ECS_COMPONENT_DECLARE(Worker);
|
ECS_COMPONENT_DECLARE(Worker);
|
||||||
ECS_COMPONENT_DECLARE(Building);
|
ECS_COMPONENT_DECLARE(Building);
|
||||||
ECS_COMPONENT_DECLARE(Unit);
|
ECS_COMPONENT_DECLARE(Unit);
|
||||||
|
ECS_COMPONENT_DECLARE(Tower);
|
||||||
ECS_COMPONENT_DECLARE(BuildingRecruitInfo);
|
ECS_COMPONENT_DECLARE(BuildingRecruitInfo);
|
||||||
ECS_COMPONENT_DECLARE(Storage);
|
ECS_COMPONENT_DECLARE(Storage);
|
||||||
ECS_COMPONENT_DECLARE(Harvestable);
|
ECS_COMPONENT_DECLARE(Harvestable);
|
||||||
@@ -49,6 +50,8 @@ ECS_TAG_DECLARE(Buildable);
|
|||||||
ECS_TAG_DECLARE(Workable);
|
ECS_TAG_DECLARE(Workable);
|
||||||
ECS_TAG_DECLARE(Attackable);
|
ECS_TAG_DECLARE(Attackable);
|
||||||
|
|
||||||
|
ECS_COMPONENT_DECLARE(DrawLayer);
|
||||||
|
ECS_COMPONENT_DECLARE(AttachedEntity);
|
||||||
ECS_COMPONENT_DECLARE(DelayDelete);
|
ECS_COMPONENT_DECLARE(DelayDelete);
|
||||||
|
|
||||||
void initComponentIDs(ecs_world_t *ecs) {
|
void initComponentIDs(ecs_world_t *ecs) {
|
||||||
@@ -92,6 +95,7 @@ void initComponentIDs(ecs_world_t *ecs) {
|
|||||||
ECS_COMPONENT_DEFINE(ecs, Worker);
|
ECS_COMPONENT_DEFINE(ecs, Worker);
|
||||||
ECS_COMPONENT_DEFINE(ecs, Building);
|
ECS_COMPONENT_DEFINE(ecs, Building);
|
||||||
ECS_COMPONENT_DEFINE(ecs, Unit);
|
ECS_COMPONENT_DEFINE(ecs, Unit);
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, Tower);
|
||||||
ECS_COMPONENT_DEFINE(ecs, BuildingRecruitInfo);
|
ECS_COMPONENT_DEFINE(ecs, BuildingRecruitInfo);
|
||||||
ECS_COMPONENT_DEFINE(ecs, Storage);
|
ECS_COMPONENT_DEFINE(ecs, Storage);
|
||||||
ECS_COMPONENT_DEFINE(ecs, Harvestable);
|
ECS_COMPONENT_DEFINE(ecs, Harvestable);
|
||||||
@@ -99,6 +103,8 @@ void initComponentIDs(ecs_world_t *ecs) {
|
|||||||
ECS_TAG_DEFINE(ecs, Workable);
|
ECS_TAG_DEFINE(ecs, Workable);
|
||||||
ECS_TAG_DEFINE(ecs, Attackable);
|
ECS_TAG_DEFINE(ecs, Attackable);
|
||||||
|
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, DrawLayer);
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, AttachedEntity);
|
||||||
ECS_COMPONENT_DEFINE(ecs, DelayDelete);
|
ECS_COMPONENT_DEFINE(ecs, DelayDelete);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -270,6 +270,19 @@ typedef struct Unit {
|
|||||||
EntityType unitType;
|
EntityType unitType;
|
||||||
} Unit;
|
} Unit;
|
||||||
extern ECS_COMPONENT_DECLARE(Unit);
|
extern ECS_COMPONENT_DECLARE(Unit);
|
||||||
|
|
||||||
|
typedef struct Tower {
|
||||||
|
f32 range;
|
||||||
|
f32 minDamage;
|
||||||
|
f32 maxDamage;
|
||||||
|
f32 damageFalloff;
|
||||||
|
f32 damageRadius;
|
||||||
|
f32 projectileSpeed;
|
||||||
|
f32 fireCooldown;
|
||||||
|
f32 fireElapsed;
|
||||||
|
} Tower;
|
||||||
|
extern ECS_COMPONENT_DECLARE(Tower);
|
||||||
|
|
||||||
#define BUILDING_MAX_RECRUIT_SLOTS 4
|
#define BUILDING_MAX_RECRUIT_SLOTS 4
|
||||||
typedef struct BuildingRecruitSlot {
|
typedef struct BuildingRecruitSlot {
|
||||||
EntityType entityType;
|
EntityType entityType;
|
||||||
@@ -301,8 +314,17 @@ extern ECS_TAG_DECLARE(Buildable);
|
|||||||
extern ECS_TAG_DECLARE(Attackable);
|
extern ECS_TAG_DECLARE(Attackable);
|
||||||
|
|
||||||
/**********************************************************
|
/**********************************************************
|
||||||
* DelayDelete components
|
* Misc components
|
||||||
*********************************************************/
|
*********************************************************/
|
||||||
|
|
||||||
|
typedef u8 DrawLayer;
|
||||||
|
extern ECS_COMPONENT_DECLARE(DrawLayer);
|
||||||
|
|
||||||
|
typedef struct AttachedEntity {
|
||||||
|
ecs_entity_t entity;
|
||||||
|
} AttachedEntity;
|
||||||
|
extern ECS_COMPONENT_DECLARE(AttachedEntity);
|
||||||
|
|
||||||
typedef struct DelayDelete {
|
typedef struct DelayDelete {
|
||||||
f32 time;
|
f32 time;
|
||||||
f32 elapsed;
|
f32 elapsed;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ typedef struct DrawData {
|
|||||||
Rectangle dst;
|
Rectangle dst;
|
||||||
Vector2 origin;
|
Vector2 origin;
|
||||||
f32 rotation;
|
f32 rotation;
|
||||||
u8 layer;
|
u8 layer;
|
||||||
bool canHaveAlpha;
|
bool canHaveAlpha;
|
||||||
} DrawData;
|
} DrawData;
|
||||||
|
|
||||||
|
|||||||
10
game/main.c
10
game/main.c
@@ -88,10 +88,13 @@ bool bzMain(BzAppDesc *appDesc, int argc, const char **argv) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmpDrawData(const void *a, const void *b) {
|
static int cmpDrawData(const void *a, const void *b) {
|
||||||
const DrawData *lhs = (DrawData *) a;
|
const DrawData *lhs = (DrawData *) a;
|
||||||
const DrawData *rhs = (DrawData *) b;
|
const DrawData *rhs = (DrawData *) b;
|
||||||
|
|
||||||
|
if (lhs->layer != rhs->layer)
|
||||||
|
return lhs->layer - rhs->layer;
|
||||||
|
|
||||||
f32 dif = (rhs->dst.y) - (lhs->dst.y);
|
f32 dif = (rhs->dst.y) - (lhs->dst.y);
|
||||||
int cmpVal = 0;
|
int cmpVal = 0;
|
||||||
if (dif < 0) cmpVal = 1;
|
if (dif < 0) cmpVal = 1;
|
||||||
@@ -499,11 +502,16 @@ static void renderGame(Game *game, float dt) {
|
|||||||
src.height -= 0.02f;
|
src.height -= 0.02f;
|
||||||
if (t[i].flipX) src.width *= -1.0f;
|
if (t[i].flipX) src.width *= -1.0f;
|
||||||
if (t[i].flipY) src.height *= -1.0f;
|
if (t[i].flipY) src.height *= -1.0f;
|
||||||
|
u8 drawLayer = 0;
|
||||||
|
if (ecs_has(ECS, it.entities[i], DrawLayer)) {
|
||||||
|
drawLayer = *ecs_get(ECS, it.entities[i], DrawLayer);
|
||||||
|
}
|
||||||
DrawData draw = (DrawData) {
|
DrawData draw = (DrawData) {
|
||||||
.src = src,
|
.src = src,
|
||||||
.dst = dst,
|
.dst = dst,
|
||||||
.origin = origin,
|
.origin = origin,
|
||||||
.rotation = r[i],
|
.rotation = r[i],
|
||||||
|
.layer = drawLayer,
|
||||||
.canHaveAlpha = true,
|
.canHaveAlpha = true,
|
||||||
};
|
};
|
||||||
if (ecs_has_id(ECS, it.entities[i], ecs_id(Unit))) {
|
if (ecs_has_id(ECS, it.entities[i], ecs_id(Unit))) {
|
||||||
|
|||||||
@@ -310,6 +310,75 @@ void updateBuildingRecruitment(ecs_iter_t *it) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateTower(ecs_iter_t *it) {
|
||||||
|
Game *game = ecs_singleton_get_mut(ECS, Game);
|
||||||
|
Owner *owner = ecs_field(it, Owner, 1);
|
||||||
|
Tower *tower = ecs_field(it, Tower, 2);
|
||||||
|
Position *position = ecs_field(it, Position, 3);
|
||||||
|
Size *size = ecs_field(it, Size, 4);
|
||||||
|
|
||||||
|
f32 dt = GetFrameTime();
|
||||||
|
|
||||||
|
for (i32 i = 0; i < it->count; i++) {
|
||||||
|
tower[i].fireElapsed += dt;
|
||||||
|
if (tower[i].fireElapsed < tower[i].fireCooldown)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Vector2 center = {
|
||||||
|
position[i].x + size[i].x * 0.5f,
|
||||||
|
position[i].y - size[i].y * 0.5f,
|
||||||
|
};
|
||||||
|
f32 range = tower[i].range;
|
||||||
|
Rectangle bounds = {
|
||||||
|
center.x - range,
|
||||||
|
center.y - range,
|
||||||
|
range * 2,
|
||||||
|
range * 2,
|
||||||
|
};
|
||||||
|
BzSpatialGridIter spatialIt = bzSpatialGridIter(game->entityGrid,
|
||||||
|
bounds.x, bounds.y,
|
||||||
|
bounds.width, bounds.height);
|
||||||
|
|
||||||
|
ecs_entity_t target = 0;
|
||||||
|
Vector2 targetPos = Vector2Zero();
|
||||||
|
f32 targetDst = INFINITY;
|
||||||
|
while (bzSpatialGridQueryNext(&spatialIt)) {
|
||||||
|
ecs_entity_t other = *(ecs_entity_t *) spatialIt.data;
|
||||||
|
if (!ecs_has(ECS, other, Owner))
|
||||||
|
continue;
|
||||||
|
Owner otherOwner = *ecs_get(ECS, other, Owner);
|
||||||
|
if (owner[i].player == otherOwner.player)
|
||||||
|
continue;
|
||||||
|
if (other == it->entities[i]) continue;
|
||||||
|
Position otherPos;
|
||||||
|
Rectangle otherBounds;
|
||||||
|
if (!entityGetHitBox(other, &otherPos, &otherBounds))
|
||||||
|
continue;
|
||||||
|
Vector2 otherCenter = {
|
||||||
|
otherBounds.x + otherBounds.width * 0.5f,
|
||||||
|
otherBounds.y - otherBounds.height * 0.5f
|
||||||
|
};
|
||||||
|
f32 dst = Vector2Distance(center, otherCenter);
|
||||||
|
if (dst > range)
|
||||||
|
continue;
|
||||||
|
if (targetDst == INFINITY || dst < targetDst) {
|
||||||
|
target = other;
|
||||||
|
targetPos = otherCenter;
|
||||||
|
targetDst = dst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target == 0) continue;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
tower[i].fireElapsed = 0.0f;
|
||||||
|
|
||||||
|
bzLogInfo("FIRE!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void renderHealthBar(ecs_iter_t *it) {
|
void renderHealthBar(ecs_iter_t *it) {
|
||||||
Position *pos = ecs_field(it, Position, 1);
|
Position *pos = ecs_field(it, Position, 1);
|
||||||
HitBox *hitbox = ecs_field(it, HitBox, 2);
|
HitBox *hitbox = ecs_field(it, HitBox, 2);
|
||||||
|
|||||||
@@ -90,6 +90,16 @@ ECS_MOVE(Building, dst, src, {
|
|||||||
*src = (Building) {.type = 0};
|
*src = (Building) {.type = 0};
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ECS_DTOR(AttachedEntity, attacked, {
|
||||||
|
if (ecs_is_alive(ECS, attacked->entity))
|
||||||
|
ecs_delete(ECS, attacked->entity);
|
||||||
|
attacked->entity = 0;
|
||||||
|
})
|
||||||
|
ECS_MOVE(AttachedEntity, dst, src, {
|
||||||
|
*dst = *src;
|
||||||
|
src->entity = 0;
|
||||||
|
})
|
||||||
|
|
||||||
void delayDeleteUpdate(ecs_iter_t *it) {
|
void delayDeleteUpdate(ecs_iter_t *it) {
|
||||||
DelayDelete *delay = ecs_field(it, DelayDelete, 1);
|
DelayDelete *delay = ecs_field(it, DelayDelete, 1);
|
||||||
|
|
||||||
@@ -117,6 +127,10 @@ void setupSystems() {
|
|||||||
.dtor = ecs_dtor(Building),
|
.dtor = ecs_dtor(Building),
|
||||||
.move_dtor = ecs_move(Building)
|
.move_dtor = ecs_move(Building)
|
||||||
});
|
});
|
||||||
|
ecs_set_hooks(ECS, AttachedEntity, {
|
||||||
|
.dtor = ecs_dtor(AttachedEntity),
|
||||||
|
.move_dtor = ecs_move(AttachedEntity)
|
||||||
|
});
|
||||||
|
|
||||||
ECS_OBSERVER(ECS, entityPathRemove, EcsOnRemove, Path);
|
ECS_OBSERVER(ECS, entityPathRemove, EcsOnRemove, Path);
|
||||||
|
|
||||||
@@ -140,6 +154,8 @@ void setupSystems() {
|
|||||||
ECS_SYSTEM(ECS, resetHarvestCount, EcsOnUpdate, Harvestable);
|
ECS_SYSTEM(ECS, resetHarvestCount, EcsOnUpdate, Harvestable);
|
||||||
ECS_SYSTEM(ECS, updateAISystem, EcsOnUpdate, BzBTState);
|
ECS_SYSTEM(ECS, updateAISystem, EcsOnUpdate, BzBTState);
|
||||||
|
|
||||||
|
ECS_SYSTEM(ECS, updateTower, EcsOnUpdate, Owner, Tower, Position, Size);
|
||||||
|
|
||||||
ECS_SYSTEM(ECS, updateAnimationState, EcsOnUpdate, Animation, TextureRegion);
|
ECS_SYSTEM(ECS, updateAnimationState, EcsOnUpdate, Animation, TextureRegion);
|
||||||
ECS_SYSTEM(ECS, updateAnimation, EcsOnUpdate, Animation, TextureRegion);
|
ECS_SYSTEM(ECS, updateAnimation, EcsOnUpdate, Animation, TextureRegion);
|
||||||
ECS_SYSTEM(ECS, updateEasingSystem, EcsOnUpdate, Easing, Position, HitBox, Rotation);
|
ECS_SYSTEM(ECS, updateEasingSystem, EcsOnUpdate, Easing, Position, HitBox, Rotation);
|
||||||
|
|||||||
@@ -157,6 +157,15 @@ void entityFollowPath(ecs_iter_t *it);
|
|||||||
*/
|
*/
|
||||||
void updateBuildingRecruitment(ecs_iter_t *it);
|
void updateBuildingRecruitment(ecs_iter_t *it);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 0: Game (singleton for querying entities)
|
||||||
|
* 1: Owner
|
||||||
|
* 2: Tower
|
||||||
|
* 3: Position
|
||||||
|
* 4: Size
|
||||||
|
*/
|
||||||
|
void updateTower(ecs_iter_t *it);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 1: Position
|
* 1: Position
|
||||||
* 2: HitBox
|
* 2: HitBox
|
||||||
|
|||||||
Reference in New Issue
Block a user