raycaster/animate2.cpp

129 lines
3.5 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($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++;
frame_change = true;
}
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() {
$sequence.subframe += $transform.speed;
update_frame();
}
void Animate2::motion(sf::Vector2f& pos, sf::Vector2f& scale, float alpha) {
$transform.lerp($sequence, pos, scale, alpha);
}
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};
}
float Transform::twitching(Sequence& seq, float alpha) {
return easing(alpha);
}
void Transform::lerp(Sequence& seq, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float alpha) {
float tick = std::abs(twitching(seq, alpha));
return motion(*this, pos_out, scale_out, tick);
}
}