Files
aee-arcade/source/game/entities/animation_component.cpp
T

60 lines
2.0 KiB
C++

#include "game/entities/animation_component.hpp"
#include <cmath>
#include <utility>
AnimationComponent::AnimationComponent(std::vector<int> frames, float fps, bool loop)
: AnimationComponent(std::move(frames), fps, loop, false, false) {}
AnimationComponent::AnimationComponent(std::vector<int> frames, float fps, bool loop, bool flip_h, bool flip_v)
: frames_(std::move(frames)),
fps_(fps > 0.0F ? fps : 1.0F),
loop_(loop),
flip_h_(flip_h),
flip_v_(flip_v) {
// Una animació d'1 sol frame amb loop=false és una animació que ja s'ha
// acabat de reproduir: no hi ha cap transició per mostrar. Marcant-la
// com a completada des de l'inici permet als consumidors (p.ex. Door)
// usar `completed()` com a temporitzador de transició d'estat.
if (frames_.size() <= 1 && !loop_) { completed_ = true; }
}
void AnimationComponent::tick(float delta_time) {
if (frames_.size() <= 1 || completed_) { return; }
accumulator_ += delta_time;
const float FRAME_TIME = 1.0F / fps_;
while (accumulator_ >= FRAME_TIME) {
accumulator_ -= FRAME_TIME;
++current_;
if (static_cast<std::size_t>(current_) >= frames_.size()) {
if (loop_) {
current_ = 0;
} else {
current_ = static_cast<int>(frames_.size()) - 1;
completed_ = true;
return;
}
}
}
}
void AnimationComponent::reset() {
current_ = 0;
accumulator_ = 0.0F;
// Invariant: animacions d'1 frame no-loop neixen completades i tornen
// a aquest estat després de reset (no hi ha progressió que desfer).
completed_ = (frames_.size() <= 1 && !loop_);
}
auto AnimationComponent::currentFrame() const -> int {
if (frames_.empty()) { return 0; }
return frames_[static_cast<std::size_t>(current_)];
}
auto AnimationComponent::flipMode() const -> SDL_FlipMode {
if (flip_h_) { return SDL_FLIP_HORIZONTAL; }
if (flip_v_) { return SDL_FLIP_VERTICAL; }
return SDL_FLIP_NONE;
}