#ifndef PIXELDEFENSE_COMPONENTS_H #define PIXELDEFENSE_COMPONENTS_H #include #include #include "constants.h" #include "game_tileset.h" // Needed, so we can clean up all game created entities extern ECS_TAG_DECLARE(GameEntity); typedef enum ResourceType { RES_WOOD, RES_GOLD, RES_FOOD, RES_COUNT, } ResourceType; static const char *getResourceTypePrettyName(ResourceType type) { switch (type) { case RES_WOOD: return "Wood"; case RES_GOLD: return "Gold"; case RES_FOOD: return "Food"; default: return "Invalid"; } } typedef struct Resource { ResourceType type; i32 amount; } Resource; extern ECS_COMPONENT_DECLARE(Resource); typedef struct Owner { Player player; } Owner; extern ECS_COMPONENT_DECLARE(Owner); /********************************************************** * Particle components *********************************************************/ typedef struct FloatyTextParticle { Vector2 pos; Vector2 speed; Color color; Color targetColor; char text[12]; f32 txtSize; f32 duration; f32 elapsed; } FloatyTextParticle; extern ECS_COMPONENT_DECLARE(FloatyTextParticle); typedef struct EmitterAttachment { ecs_entity_t baseEntity; Vector2 offset; } EmitterAttachment; extern ECS_COMPONENT_DECLARE(EmitterAttachment); typedef struct ParticleEmitter { f32 emitterElapsed; f32 emitterLifetime; Vector2 pos; struct ParticleEmitterData { // emission f32 emmitRate; f32 emmitVariance; f32 emmitVarianceMin, emmitVarianceMax; // offset Vector2 minOffset, maxOffset; // startVel Vector2 minStartVel, maxStartVel; // endVel Vector2 minEndVel, maxEndVel; // startSize f32 minStartSize, maxStartSize; // endSize f32 minEndSize, maxEndSize; // startRotSpeed f32 minStartRotSpeed, maxStartRotSpeed; // endRotSpeed f32 minEndRotSpeed, maxEndRotSpeed; Color startColor, endColor; // lifetime f32 minLifetime, maxLifetime; BlendMode blend; BzTileID tileID; } data; ecs_entity_t targetParticles; // ParticleLayer0 / ParticleLayer1 } ParticleEmitter; extern ECS_COMPONENT_DECLARE(ParticleEmitter); static ParticleEmitter GET_FIREBALL_EMITTER() { return (ParticleEmitter) { .emitterLifetime = 2.0f, .data.minOffset = { -2.0f, -2.0f }, .data.maxOffset = { 2.0f, 2.0f }, .data.emmitRate = 2.2f, .data.emmitVariance = 1.0f, .data.emmitVarianceMin = 0.0f, .data.emmitVarianceMax = 1.0f, .data.startColor = { 210, 40, 40, 210 }, .data.endColor = { 110, 20, 20, 110 }, .data.minLifetime = 0.3f, .data.maxLifetime = 0.5f, .data.minStartSize = 4.0f, .data.maxStartSize = 6.0f, .data.tileID = getParticleTypeTile(PARTICLE_CIRCLE), .data.blend = BLEND_ADDITIVE }; } static ParticleEmitter GET_BLOOD_EMITTER() { return (ParticleEmitter) { .emitterLifetime = 0.3f, .data.emmitRate = 1.8f, .data.minOffset = { -3.6f, -3.6f }, .data.maxOffset = { 3.6f, 3.6f }, .data.minStartVel = { 4.5f, 7.3f }, .data.maxStartVel = { 2.5f, 3.3f }, .data.minEndVel = { -0.8f, 1.2f }, .data.maxEndVel = { -0.4f, 1.6f }, .data.minStartSize = 2.45f, .data.maxStartSize = 3.3f, .data.minEndSize = 0.8f, .data.maxEndSize = 1.1f, .data.minStartRotSpeed = 0.0f, .data.maxStartRotSpeed = 360.0f, .data.minEndRotSpeed = 400.5f, .data.maxEndRotSpeed = 600.2f, .data.startColor = { 210, 0, 0, 255 }, .data.endColor = { 110, 10, 10, 32 }, .data.minLifetime = 0.23, .data.maxLifetime = 0.37, .data.blend = BLEND_ALPHA, .data.tileID = getParticleTypeTile(PARTICLE_SMALL_SQUARE), }; } typedef struct Particle { Vector2 pos; f32 rotation; const Vector2 startVel, endVel; const f32 startSize, endSize; const f32 startRotSpeed, endRotSpeed; const Color startColor, endColor; const BlendMode blend: 8; const BzTileID tileID: 24; const f32 lifetime; f32 elapsed; } Particle; static_assert(sizeof(Particle) == 64, ""); // 2 Separate components (Before entity, After entity), so we don't need to sort typedef Particle ParticleLayer0, ParticleLayer1; extern ECS_COMPONENT_DECLARE(ParticleLayer0); extern ECS_COMPONENT_DECLARE(ParticleLayer1); /********************************************************** * Movement components *********************************************************/ typedef BzSpatialGridID SpatialGridID; extern ECS_COMPONENT_DECLARE(SpatialGridID); typedef Vector2 Position, Size, Velocity, TargetPosition, Steering; typedef f32 Rotation, Orientation; extern ECS_COMPONENT_DECLARE(Position); extern ECS_COMPONENT_DECLARE(Size); extern ECS_COMPONENT_DECLARE(Velocity); extern ECS_COMPONENT_DECLARE(Rotation); extern ECS_COMPONENT_DECLARE(Orientation); extern ECS_COMPONENT_DECLARE(Steering); extern ECS_COMPONENT_DECLARE(TargetPosition); #define PATH_DATA_SIZE 8 typedef struct PathData { Position waypoints[PATH_DATA_SIZE]; size_t numWaypoints; struct PathData *next; } PathData; typedef struct Path { PathData *paths; i32 curWaypoint; } Path; extern ECS_COMPONENT_DECLARE(Path); /********************************************************** * Render components *********************************************************/ typedef struct TextureRegion { Texture2D texture; Rectangle rec; bool flipX : 1; bool flipY : 1; } TextureRegion; extern ECS_COMPONENT_DECLARE(TextureRegion); /********************************************************** * Animation components *********************************************************/ typedef struct Animation { EntityType entityType; AnimType animType; AnimationFrame frame; AnimationSequence sequence; BzTileset *tileset; i32 curFrame; f32 elapsed; bool playInFull; } Animation; extern ECS_COMPONENT_DECLARE(Animation); typedef struct Easing { ecs_entity_t compID; size_t memberOffset; BzEaseType easingFunc; // start + target * (easeStart + (easeTarget * x) + easeOffset) + offset f32 target; f32 start; f32 offset; f32 easeTarget; f32 easeStart; f32 easeOffset; f32 x; f32 elapsed; f32 duration; //struct Easing *next; } Easing; extern ECS_COMPONENT_DECLARE(Easing); /********************************************************** * Event components *********************************************************/ typedef Rectangle HitBox; typedef struct DamageEvent { HitBox hitbox; f32 amount; } DamageEvent; typedef struct HarvestEvent { ResourceType type; i32 amount; } HarvestEvent; typedef struct DepositEvent { ResourceType type; i32 amount; } DepositEvent; /********************************************************** * Gameplay components *********************************************************/ extern ECS_COMPONENT_DECLARE(HitBox); extern ECS_COMPONENT_DECLARE(BzBTState); extern ECS_COMPONENT_DECLARE(AIBlackboard); extern ECS_TAG_DECLARE(Selectable); extern ECS_TAG_DECLARE(Selected); typedef struct AddPopCapacity { i32 amount; } AddPopCapacity; extern ECS_COMPONENT_DECLARE(AddPopCapacity); typedef struct ConsumePopCapacity { i32 amount; } 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 // - Work // - Attack (since it is also a unit) typedef struct Worker { // stats f32 collectSpeed; f32 depositSpeed; i32 carry; i32 carryCapacity; ResourceType carryRes; } Worker; extern ECS_COMPONENT_DECLARE(Worker); // Unit can: // - Attack typedef struct Unit { f32 attackCooldown; f32 attackElapsed; f32 minDamage; f32 maxDamage; f32 maxSpeed; f32 acceleration; f32 deceleration; EntityType unitType; } Unit; extern ECS_COMPONENT_DECLARE(Unit); typedef struct Tower { f32 range; f32 projMinDamage; f32 projMaxDamage; f32 projMinLifespan; f32 projMaxLifespan; f32 projSpeed; f32 projRadius; i32 projDamageCount; f32 fireCooldown; f32 fireElapsed; } Tower; extern ECS_COMPONENT_DECLARE(Tower); typedef struct Projectile { Vector2 target; f32 radius; f32 damage; ecs_entity_t lastDamaged; i32 damageCount; } Projectile; extern ECS_COMPONENT_DECLARE(Projectile); #define BUILDING_MAX_RECRUIT_SLOTS 4 typedef struct BuildingRecruitSlot { EntityType entityType; i32 numRecruiting; f32 recruitTime; f32 elapsed; } BuildingRecruitSlot; typedef struct BuildingRecruitInfo { BuildingRecruitSlot slots[BUILDING_MAX_RECRUIT_SLOTS]; i32 numSlots; } BuildingRecruitInfo; extern ECS_COMPONENT_DECLARE(BuildingRecruitInfo); typedef struct Building { BuildingType type; Vec2i pos; Vec2i size; } Building; typedef struct Storage { bool stores[RES_COUNT]; } Storage; extern ECS_COMPONENT_DECLARE(Storage); extern ECS_COMPONENT_DECLARE(Building); typedef struct Harvestable { i32 harvestLimit; i32 harvestCount; } Harvestable; extern ECS_COMPONENT_DECLARE(Harvestable); extern ECS_TAG_DECLARE(Buildable); extern ECS_TAG_DECLARE(Attackable); /********************************************************** * 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 { f32 time; f32 elapsed; } DelayDelete; extern ECS_COMPONENT_DECLARE(DelayDelete); void initComponentIDs(ecs_world_t *ecs); void igTagCheckbox(const char *label, ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t tag); 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 igOwner(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp); void igSpatialGridID(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp); void igVec2Comp(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp); void igFloat(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp); void igPath(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp); void igTextureRegion(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp); void igAnimation(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp); void igEasing(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp); void igArms(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp); void igArm(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp); void igVisualizeBTState(const BzBTNode *node, const BzBTNodeState *state); void igBzBTState(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp); void igAIBlackboard(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp); void igWorker(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp); void igUnit(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp); #endif //PIXELDEFENSE_COMPONENTS_H