149 lines
4.2 KiB
C++
149 lines
4.2 KiB
C++
#include "animate2.hpp"
|
|
#include <memory>
|
|
#include <chrono>
|
|
#include "dbc.hpp"
|
|
#include "rand.hpp"
|
|
|
|
namespace animate2 {
|
|
std::vector<sf::IntRect> Animate2::calc_frames() {
|
|
std::vector<sf::IntRect> frames;
|
|
|
|
for(int frame_i : $sequence.frames) {
|
|
frames.emplace_back(
|
|
sf::Vector2i{$sheet.frame_width * frame_i, 0}, // NOTE: one row only for now
|
|
sf::Vector2i{$sheet.frame_width,
|
|
$sheet.frame_height});
|
|
}
|
|
|
|
return frames;
|
|
}
|
|
|
|
void Animate2::play() {
|
|
dbc::check(!playing, "can't call play while playing?");
|
|
$sequence.current = 0;
|
|
$sequence.subframe = 0.0f;
|
|
$sequence.loop_count = 0;
|
|
playing = true;
|
|
$sequence.timer.start();
|
|
}
|
|
|
|
void Animate2::stop() {
|
|
playing = false;
|
|
$sequence.timer.reset();
|
|
}
|
|
|
|
// need one for each kind of thing to animate
|
|
// NOTE: possibly find a way to only run apply on frame change?
|
|
void Animate2::apply(sf::Sprite& sprite) {
|
|
dbc::check(!$transform.simple, "can't call ::apply() on a simple animation, only ::motion()");
|
|
|
|
dbc::check($sequence.current < $frame_rects.size(), "current frame past $frame_rects");
|
|
// NOTE: pos is not updated yet
|
|
auto& rect = $frame_rects.at($sequence.current);
|
|
sprite.setTextureRect(rect);
|
|
}
|
|
|
|
// replaces step
|
|
void Animate2::update_frame() {
|
|
dbc::check(playing, "attempt to update animation that's not playing");
|
|
dbc::check($sequence.frame_count == $sequence.frames.size(), "frame_count doesn't match frame.size()");
|
|
|
|
auto duration = $sequence.durations.at($sequence.current);
|
|
bool frame_change = false;
|
|
|
|
if($sequence.timer.getElapsedTime() >= duration) {
|
|
$sequence.timer.restart();
|
|
$sequence.current++;
|
|
if($sequence.subframe > 0.9) $sequence.subframe = 0.0f;
|
|
frame_change = true;
|
|
} else {
|
|
$sequence.subframe = std::lerp($sequence.subframe, 1.0, $sequence.timer.DELTA * $transform.ease_rate);
|
|
fmt::println("subframe: {}, alpha: {}", $sequence.subframe, $sequence.timer.alpha);
|
|
}
|
|
|
|
if($sequence.current >= $sequence.frame_count) {
|
|
$sequence.loop_count++;
|
|
playing = onLoop($sequence, $transform);
|
|
}
|
|
|
|
if(frame_change && onFrame != nullptr) onFrame();
|
|
|
|
dbc::check($sequence.current < $sequence.frame_count, "onLoop fail: current frame out of frames.size()");
|
|
}
|
|
|
|
void Animate2::update() {
|
|
update_frame();
|
|
}
|
|
|
|
void Animate2::motion(sf::Sprite& sprite, sf::Vector2f pos, sf::Vector2f scale) {
|
|
$transform.lerp($sequence, pos, scale);
|
|
|
|
if($transform.flipped) {
|
|
scale.x *= -1;
|
|
}
|
|
|
|
sprite.setPosition(pos);
|
|
|
|
if($transform.scaled) {
|
|
sprite.setScale(scale);
|
|
}
|
|
}
|
|
|
|
std::pair<int, double> Animate2::commit() {
|
|
return $sequence.timer.commit();
|
|
}
|
|
|
|
void Timer::start() {
|
|
clock.start();
|
|
prev_time = clock.getElapsedTime().asSeconds();
|
|
}
|
|
|
|
void Timer::reset() {
|
|
clock.reset();
|
|
}
|
|
|
|
void Timer::restart() {
|
|
clock.restart();
|
|
prev_time = clock.getElapsedTime().asSeconds();
|
|
}
|
|
|
|
sf::Time Timer::getElapsedTime() {
|
|
return clock.getElapsedTime();
|
|
}
|
|
|
|
std::pair<int, double> Timer::commit() {
|
|
// determine frame duration based on previous time
|
|
current_time = clock.getElapsedTime().asSeconds();
|
|
frame_duration = current_time - prev_time;
|
|
|
|
// update prev_time for the next call
|
|
prev_time = current_time;
|
|
|
|
// update accumulator, retaining previous errors
|
|
accumulator += frame_duration;
|
|
|
|
// find the tick count based on DELTA
|
|
double tick_count = floor(accumulator / DELTA);
|
|
|
|
// reduce accumulator by the number of DELTAS
|
|
accumulator -= tick_count * DELTA;
|
|
// that leaves the remaining errors for next loop
|
|
|
|
// alpha is then what we lerp...but WHY?!
|
|
alpha = accumulator / DELTA;
|
|
|
|
// return the number of even DELTA ticks and the alpha
|
|
return {int(tick_count), alpha};
|
|
}
|
|
|
|
void Transform::lerp(Sequence& seq, sf::Vector2f& pos_out, sf::Vector2f& scale_out) {
|
|
// float dt = 1 - std::powf(ease_rate, seq.subframe + 0.0001);
|
|
float tick = easing(seq.subframe);
|
|
|
|
motion(*this, pos_out, scale_out, tick);
|
|
|
|
fmt::println("sub: {}, tick: {}, tr: {},{}; pos: {},{}; scale: {},{}",
|
|
seq.subframe, tick, min_y, max_y, pos_out.x, pos_out.y,
|
|
scale_out.x, scale_out.y);
|
|
}
|
|
}
|