From 1487d67a3bcc6caef35d0fbf9e560ac21353712b Mon Sep 17 00:00:00 2001 From: Klemen Plestenjak Date: Sat, 10 Feb 2024 11:39:01 +0100 Subject: [PATCH] Add fireball particles, add max lifespan to fireball --- game/building_factory.c | 12 +++++++----- game/components.h | 32 +++++++++++++++++++++++++++----- game/main.c | 20 +++----------------- game/systems/s_animation.c | 10 ++++++---- game/systems/s_entity.c | 21 ++++++++++++++------- 5 files changed, 57 insertions(+), 38 deletions(-) diff --git a/game/building_factory.c b/game/building_factory.c index 9849903..d1a6a01 100644 --- a/game/building_factory.c +++ b/game/building_factory.c @@ -174,11 +174,13 @@ ecs_entity_t placeBuilding(Game *game, BuildingType type, ecs_set(ECS, building, AttachedEntity, {mage}); ecs_set(ECS, building, Tower, { .range = 46.0f, - .minDamage = 40.0f, - .maxDamage = 80.0f, - .projectileSpeed = 100.0f, - .projectileRadius = 4.0f, - .projectileDamageCount = 3, + .projMinDamage = 40.0f, + .projMaxDamage = 80.0f, + .projMinLifespan = 2.6f, + .projMaxLifespan = 3.2f, + .projSpeed = 100.0f, + .projRadius = 4.0f, + .projDamageCount = 3, .fireCooldown = 1.2f, .fireElapsed = 0.0f, }); diff --git a/game/components.h b/game/components.h index e63128a..8840e06 100644 --- a/game/components.h +++ b/game/components.h @@ -96,6 +96,26 @@ typedef struct ParticleEmitter { } 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 = 1.2f, + .data.emmitVariance = 1.0f, + .data.emmitVarianceMin = 0.0f, + .data.emmitVarianceMax = 1.0f, + .data.startColor = { 210, 0, 0, 210 }, + .data.endColor = { 110, 10, 10, 110 }, + .data.minLifetime = 1.0f, + .data.maxLifetime = 2.2f, + .data.minStartSize = 4.0f, + .data.maxStartSize = 6.0f, + .data.tileID = getParticleTypeTile(PARTICLE_CIRCLE), + .data.blend = BLEND_ADDITIVE + }; +} + typedef struct Particle { Vector2 pos; f32 rotation; @@ -278,11 +298,13 @@ extern ECS_COMPONENT_DECLARE(Unit); typedef struct Tower { f32 range; - f32 minDamage; - f32 maxDamage; - f32 projectileSpeed; - f32 projectileRadius; - i32 projectileDamageCount; + f32 projMinDamage; + f32 projMaxDamage; + f32 projMinLifespan; + f32 projMaxLifespan; + f32 projSpeed; + f32 projRadius; + i32 projDamageCount; f32 fireCooldown; f32 fireElapsed; } Tower; diff --git a/game/main.c b/game/main.c index ef82f8b..c8d0420 100644 --- a/game/main.c +++ b/game/main.c @@ -570,23 +570,9 @@ static void renderGame(Game *game, float dt) { InputState *input = ecs_singleton_get_mut(ECS, InputState); if (IsKeyReleased(KEY_SPACE)) { - ParticleEmitter emitter = { - .emitterLifetime = 2.0f, - .targetParticles = ecs_id(ParticleLayer1), - .data.emmitRate = 1.2f, - .data.emmitVariance = 1.0f, - .data.emmitVarianceMin = 0.0f, - .data.emmitVarianceMax = 1.0f, - .pos = input->mouseWorld, - .data.startColor = { 210, 0, 0, 210 }, - .data.endColor = { 110, 10, 10, 110 }, - .data.minLifetime = 1.0f, - .data.maxLifetime = 2.2f, - .data.minStartSize = 4.0f, - .data.maxStartSize = 6.0f, - .data.tileID = getParticleTypeTile(PARTICLE_CIRCLE), - .data.blend = BLEND_ADDITIVE - }; + ParticleEmitter emitter = GET_FIREBALL_EMITTER(); + emitter.pos = input->mouseWorld; + emitter.targetParticles = ecs_id(ParticleLayer1); ecs_entity_t e = entityCreateEmpty(); ecs_set_ptr(ECS, e, ParticleEmitter, &emitter); diff --git a/game/systems/s_animation.c b/game/systems/s_animation.c index a6ba8ed..c80f99a 100644 --- a/game/systems/s_animation.c +++ b/game/systems/s_animation.c @@ -58,11 +58,13 @@ void updateParticleEmitter(ecs_iter_t *it) { ecs_entity_t entity = it->entities[i]; if (ecs_has(ECS, entity, EmitterAttachment)) { EmitterAttachment attachment = *ecs_get(ECS, entity, EmitterAttachment); - if (ecs_is_alive(ECS, attachment.baseEntity)) { - Vector2 pos = *ecs_get(ECS, entity, Position); - pos = Vector2Add(pos, attachment.offset); - emitter[i].pos = pos; + if (!ecs_is_alive(ECS, attachment.baseEntity)) { + ecs_delete(ECS, attachment.baseEntity); + continue; } + Vector2 pos = *ecs_get(ECS, attachment.baseEntity, Position); + pos = Vector2Add(pos, attachment.offset); + emitter[i].pos = pos; } const struct ParticleEmitterData data = emitter[i].data; diff --git a/game/systems/s_entity.c b/game/systems/s_entity.c index 0d3f11f..ecda112 100644 --- a/game/systems/s_entity.c +++ b/game/systems/s_entity.c @@ -376,19 +376,29 @@ void updateTower(ecs_iter_t *it) { Vector2 dir = Vector2Subtract(targetPos, center); dir = Vector2Normalize(dir); - dir = Vector2Scale(dir, tower[i].projectileSpeed); + dir = Vector2Scale(dir, tower[i].projSpeed); ecs_entity_t proj = entityCreateEmpty(); ecs_set(ECS, proj, Position, { center.x, center.y }); ecs_set(ECS, proj, Velocity, { dir.x, dir.y }); ecs_set(ECS, proj, Projectile, { - .damage = randFloatRange(tower[i].minDamage, tower[i].maxDamage), + .damage = randFloatRange(tower[i].projMinDamage, tower[i].projMaxDamage), .target = targetPos, - .radius = tower[i].projectileRadius, - .damageCount = tower[i].projectileDamageCount + .radius = tower[i].projRadius, + .damageCount = tower[i].projDamageCount }); ecs_set(ECS, proj, Owner, { owner[i].player }); + f32 lifespan = randFloatRange(tower[i].projMinLifespan, tower[i].projMaxLifespan); + ecs_set(ECS, proj, DelayDelete, { .time = lifespan }); + + ecs_entity_t projEmitter = entityCreateEmpty(); + ParticleEmitter emitter = GET_FIREBALL_EMITTER(); + emitter.targetParticles = ecs_id(ParticleLayer1); + emitter.pos = center; + ecs_set_ptr(ECS, projEmitter, ParticleEmitter, &emitter); + ecs_set(ECS, projEmitter, EmitterAttachment, { .baseEntity = proj }); + tower[i].fireElapsed = 0.0f; } @@ -453,9 +463,6 @@ void updateProjectile(ecs_iter_t *it) { continue; } - DrawRectangleV((Vector2) {bounds.x, bounds.y}, (Vector2) {bounds.width, bounds.height}, - RED); - pos[i] = Vector2Add(pos[i], Vector2Scale(vel[i], dt)); if (pos[i].x < 0.0f || pos[i].y < 0.0f || pos[i].x >= game->map.width * game->map.tileWidth ||