200 lines
6.8 KiB
C
200 lines
6.8 KiB
C
#include "systems.h"
|
|
|
|
#include "../game_state.h"
|
|
#include "../utils.h"
|
|
|
|
#include <raymath.h>
|
|
#include <stdlib.h>
|
|
|
|
void updateParticleEmitter(ecs_iter_t *it) {
|
|
ParticleEmitter *emitter = ecs_field(it, ParticleEmitter, 1);
|
|
f32 dt = GetFrameTime();
|
|
|
|
for (i32 i = 0; i < it->count; i++) {
|
|
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)) {
|
|
ecs_delete(ECS, entity);
|
|
continue;
|
|
}
|
|
Vector2 pos = *ecs_get(ECS, entity, Position);
|
|
pos = Vector2Add(pos, attachment.offset);
|
|
emitter->pos = pos;
|
|
}
|
|
|
|
emitter[i].emitterElapsed += dt;
|
|
if (emitter[i].emitterElapsed >= emitter[i].emitterLifetime)
|
|
ecs_delete(ECS, entity);
|
|
}
|
|
}
|
|
|
|
static inline int lerpInt(int start, int end, int amount)
|
|
{
|
|
float result = start + amount*(end - start);
|
|
|
|
return result;
|
|
}
|
|
bool updateParticle(const Texture2D tex, Particle *particle, f32 dt) {
|
|
f32 alpha = particle->elapsed / particle->lifetime;
|
|
|
|
Vector2 vel = Vector2Lerp(particle->startVel, particle->endVel, alpha);
|
|
f32 size = Lerp(particle->startSize, particle->endSize, alpha);
|
|
f32 rot = Lerp(particle->startRotSpeed, particle->endRotSpeed, alpha);
|
|
Color startC = particle->startColor;
|
|
Color endC = particle->endColor;
|
|
Color color = {
|
|
.r = lerpInt(startC.r, endC.r, alpha),
|
|
.g = lerpInt(startC.g, endC.g, alpha),
|
|
.b = lerpInt(startC.b, endC.b, alpha),
|
|
.a = lerpInt(startC.a, endC.a, alpha)
|
|
};
|
|
|
|
BeginBlendMode(particle->blend);
|
|
f32 hSize = size * 0.5f;
|
|
Vector2 center = particle->pos;
|
|
Rectangle src = getTextureRect(particle->tileID);
|
|
src.x += 0.1f;
|
|
src.y += 0.1f;
|
|
src.width -= 0.2f;
|
|
src.height -= 0.2f;
|
|
DrawTexturePro(tex, src, (Rectangle) {
|
|
center.x,
|
|
center.y,
|
|
size, size
|
|
}, (Vector2) {hSize, hSize}, rot, color);
|
|
EndBlendMode();
|
|
|
|
particle->pos = Vector2Add(particle->pos, Vector2Scale(vel, dt));
|
|
particle->elapsed += dt;
|
|
return alpha >= 1.0f;
|
|
}
|
|
static inline Vector2 randVector2Range(Vector2 from, Vector2 to) {
|
|
return (Vector2) {
|
|
randFloatRange(from.x, to.x),
|
|
randFloatRange(from.y, to.y)
|
|
};
|
|
}
|
|
static inline Color randColorRange(Color from, Color to) {
|
|
return (Color) {
|
|
.r = GetRandomValue(from.r, to.r),
|
|
.g = GetRandomValue(from.g, to.g),
|
|
.b = GetRandomValue(from.b, to.b),
|
|
.a = GetRandomValue(from.a, to.a),
|
|
};
|
|
}
|
|
Particle spawnParticle(const ParticleEmitter *emitter) {
|
|
const struct ParticleEmitterData *data = &emitter->data;
|
|
return (Particle) {
|
|
.pos = Vector2Add(emitter->pos, randVector2Range(data->minOffset, data->maxOffset)),
|
|
.rotation = 0.0f,
|
|
.startVel = randVector2Range(data->minStartVel, data->maxStartVel),
|
|
.endVel = randVector2Range(data->minEndVel, data->maxEndVel),
|
|
.startSize = randFloatRange(data->minStartSize, data->maxStartSize),
|
|
.endSize = randFloatRange(data->minEndSize, data->maxEndSize),
|
|
.startRotSpeed = randFloatRange(data->minStartRotSpeed, data->maxStartRotSpeed),
|
|
.endRotSpeed = randFloatRange(data->minEndRotSpeed, data->maxEndRotSpeed),
|
|
.startColor = data->startColor,
|
|
.endColor = data->endColor,
|
|
.blend = data->blend,
|
|
.tileID = data->tileID,
|
|
.elapsed = 0.0f,
|
|
.lifetime = randFloatRange(data->minLifetime, data->maxLifetime),
|
|
};
|
|
}
|
|
|
|
void animationSetState(Animation *anim, AnimType type, bool playInFull) {
|
|
anim->animType = type;
|
|
anim->sequence = entityGetAnimationSequence(anim->entityType, type);
|
|
anim->curFrame = 0;
|
|
anim->elapsed = 0;
|
|
anim->playInFull = playInFull;
|
|
}
|
|
void updateAnimationState(ecs_iter_t *it) {
|
|
Animation *anim = ecs_field(it, Animation, 1);
|
|
TextureRegion *text = ecs_field(it, TextureRegion, 2);
|
|
for (i32 i = 0; i < it->count; i++) {
|
|
if (anim->playInFull) continue;
|
|
ecs_entity_t entity = it->entities[i];
|
|
AnimType type = ANIM_IDLE;
|
|
if (ecs_has(ECS, entity, Velocity)) {
|
|
Velocity vel = *ecs_get(ECS, entity, Velocity);
|
|
f32 len = Vector2Length(vel);
|
|
if (len > 1.0f) {
|
|
type = ANIM_WALK;
|
|
text[i].flipX = vel.x < 0;
|
|
}
|
|
}
|
|
|
|
if (type != anim[i].animType) {
|
|
animationSetState(&anim[i], type, false);
|
|
}
|
|
}
|
|
}
|
|
void updateAnimation(ecs_iter_t *it) {
|
|
Animation *anim = ecs_field(it, Animation, 1);
|
|
TextureRegion *texture = ecs_field(it, TextureRegion, 2);
|
|
|
|
float dt = GetFrameTime();
|
|
|
|
for (i32 i = 0; i < it->count; i++) {
|
|
ecs_entity_t entity = it->entities[i];
|
|
AnimationFrame frame = anim[i].frame;
|
|
AnimationSequence seq = anim[i].sequence;
|
|
|
|
anim[i].elapsed += dt;
|
|
if (anim[i].elapsed < frame.duration) continue;
|
|
|
|
i32 nextFrame = (anim[i].curFrame + 1) % seq.frameCount;
|
|
if (nextFrame == 0) anim[i].playInFull = false;
|
|
anim[i].curFrame = nextFrame;
|
|
anim[i].frame = entityGetAnimationFrame(anim[i].entityType, anim[i].animType, nextFrame);
|
|
anim[i].elapsed = 0.0f;
|
|
|
|
texture[i].rec = getTextureRect(anim[i].frame.frame);
|
|
if (ecs_has(ECS, entity, Owner)) {
|
|
Owner owner = *ecs_get(ECS, entity, Owner);
|
|
BzTileID base = anim[i].frame.frame;
|
|
Vector2 offset = getTileOffset(base, owner.player);
|
|
texture[i].rec.x += offset.x;
|
|
texture[i].rec.y += offset.y;
|
|
}
|
|
}
|
|
}
|
|
|
|
void updateEasingSystem(ecs_iter_t *it) {
|
|
Easing *easing = ecs_field(it, Easing, 1);
|
|
|
|
f32 dt = GetFrameTime();
|
|
|
|
for (i32 i = 0; i < it->count; i++) {
|
|
ecs_entity_t entity = it->entities[i];
|
|
if (easing[i].elapsed > easing[i].duration) {
|
|
ecs_remove(ECS, entity, Easing);
|
|
continue;
|
|
}
|
|
if (!ecs_has_id(ECS, entity, easing[i].compID))
|
|
continue;
|
|
easing[i].elapsed += dt;
|
|
f32 alpha = easing[i].elapsed / easing[i].duration;
|
|
alpha = BZ_MIN(1.0f, alpha);
|
|
f32 prevX = easing[i].x;
|
|
easing[i].x = bzEase(easing[i].easingFunc, alpha);
|
|
|
|
const Easing *e = &easing[i];
|
|
f32 x = e->x;
|
|
// Inner
|
|
x = e->easeStart + e->easeTarget * x + e->easeOffset;
|
|
// Outer
|
|
x = e->start + e->target * x + e->offset;
|
|
easing[i].x = x;
|
|
|
|
u8 *compData = ecs_get_mut_id(ECS, entity, easing[i].compID);
|
|
compData += easing[i].memberOffset;
|
|
f32 *out = (f32 *) compData;
|
|
|
|
*out -= prevX;
|
|
*out += x;
|
|
}
|
|
}
|