Sorted out the animation vs. easing contradiction I believe. Now there's a separate easing_duration that's calculated from the total duration of all frames. Then a easing_position determines where in the total the animation is, which is fed to the asing functions as a ration of easing_position / easing_duration.
This commit is contained in:
parent
0c798c9e0d
commit
1baca783fc
9 changed files with 47 additions and 75 deletions
45
animate2.cpp
45
animate2.cpp
|
|
@ -10,6 +10,8 @@
|
|||
constexpr float SUB_FRAME_SENSITIVITY = 0.999f;
|
||||
|
||||
namespace animate2 {
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
std::vector<sf::IntRect> Animate2::calc_frames() {
|
||||
dbc::check(sequence.frames.size() == sequence.durations.size(), "sequence.frames.size() != sequence.durations.size()");
|
||||
|
||||
|
|
@ -94,30 +96,28 @@ namespace animate2 {
|
|||
* elapsed is DELTA, or use elapsed here?
|
||||
*/
|
||||
void Animate2::update() {
|
||||
dbc::check(sequence.easing_duration > 0.0, "bad easing duration");
|
||||
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);
|
||||
auto elapsed = sequence.timer.getElapsedTime().toDuration();
|
||||
// std::cout << "subframe: " << sequence.subframe << " elapsed: " << elapsed << " duration: " << duration << std::endl;
|
||||
auto [ticks, alpha] = sequence.timer.commit();
|
||||
int duration = sequence.durations.at(sequence.current);
|
||||
sequence.subframe += ticks;
|
||||
|
||||
sequence.easing_position += ticks;
|
||||
|
||||
bool frame_change = false;
|
||||
|
||||
if(elapsed < duration) {
|
||||
// BUG: subframe will just run crazy because I don't actually do delta time difference here
|
||||
sequence.subframe = std::lerp(sequence.subframe, 1.0, sequence.timer.DELTA * transform.ease_rate);
|
||||
} else {
|
||||
if(sequence.subframe >= duration) {
|
||||
sequence.timer.restart();
|
||||
sequence.current++;
|
||||
|
||||
if(sequence.subframe > SUB_FRAME_SENSITIVITY) {
|
||||
sequence.subframe = 0.0f;
|
||||
}
|
||||
|
||||
sequence.subframe = 0;
|
||||
frame_change = true;
|
||||
}
|
||||
|
||||
if(sequence.current >= sequence.frame_count) {
|
||||
sequence.loop_count++;
|
||||
sequence.easing_position = 0;
|
||||
playing = onLoop(sequence, transform);
|
||||
}
|
||||
|
||||
|
|
@ -142,20 +142,18 @@ namespace animate2 {
|
|||
}
|
||||
}
|
||||
|
||||
std::pair<int, double> Animate2::commit() {
|
||||
return sequence.timer.commit();
|
||||
}
|
||||
|
||||
void Timer::start() {
|
||||
clock.start();
|
||||
prev_time = clock.getElapsedTime().asSeconds();
|
||||
}
|
||||
|
||||
void Timer::reset() {
|
||||
elapsed_ticks = 0;
|
||||
clock.reset();
|
||||
}
|
||||
|
||||
void Timer::restart() {
|
||||
elapsed_ticks = 0;
|
||||
clock.restart();
|
||||
prev_time = clock.getElapsedTime().asSeconds();
|
||||
}
|
||||
|
|
@ -182,6 +180,8 @@ namespace animate2 {
|
|||
accumulator -= tick_count * DELTA;
|
||||
// that leaves the remaining errors for next loop
|
||||
|
||||
elapsed_ticks += tick_count;
|
||||
|
||||
// alpha is then what we lerp...but WHY?!
|
||||
alpha = accumulator / DELTA;
|
||||
|
||||
|
|
@ -190,14 +190,9 @@ namespace animate2 {
|
|||
}
|
||||
|
||||
void Transform::apply(Sequence& seq, sf::Vector2f& pos_out, sf::Vector2f& scale_out) {
|
||||
// float dt = 1 - std::powf(ease_rate, seq.subframe + 0.0001);
|
||||
float tick = easing_func(seq.subframe);
|
||||
float tick = easing_func(seq.easing_position / seq.easing_duration);
|
||||
|
||||
motion_func(*this, pos_out, scale_out, tick, relative);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
bool Animate2::has_form(const std::string& as_form) {
|
||||
|
|
@ -224,6 +219,12 @@ namespace animate2 {
|
|||
sequence = sequences.at(seq_name);
|
||||
transform = transforms.at(tr_name);
|
||||
|
||||
// BUG: should this be configurable instead?
|
||||
for(auto duration : sequence.durations) {
|
||||
sequence.easing_duration += float(duration);
|
||||
}
|
||||
dbc::check(sequence.easing_duration > 0.0, "bad easing duration");
|
||||
|
||||
$frame_rects = calc_frames();
|
||||
transform.easing_func = ease2::get_easing(transform.easing);
|
||||
transform.motion_func = ease2::get_motion(transform.motion);
|
||||
|
|
|
|||
11
animate2.hpp
11
animate2.hpp
|
|
@ -29,6 +29,7 @@ namespace animate2 {
|
|||
double current_time = 0.0;
|
||||
double frame_duration = 0.0;
|
||||
double alpha = 0.0;
|
||||
int elapsed_ticks = 0;
|
||||
sf::Clock clock{};
|
||||
|
||||
std::pair<int, double> commit();
|
||||
|
|
@ -40,12 +41,14 @@ namespace animate2 {
|
|||
|
||||
struct Sequence {
|
||||
std::vector<int> frames{};
|
||||
std::vector<std::chrono::milliseconds> durations{};
|
||||
std::vector<int> durations{}; // in ticks
|
||||
size_t current{0};
|
||||
int loop_count{0};
|
||||
size_t frame_count{0};
|
||||
Timer timer{};
|
||||
float subframe{0.0f};
|
||||
int subframe{0};
|
||||
float easing_duration{0.0f};
|
||||
float easing_position{0.0f};
|
||||
};
|
||||
|
||||
struct Transform {
|
||||
|
|
@ -55,7 +58,6 @@ namespace animate2 {
|
|||
float max_x{1.0f};
|
||||
float max_y{1.0f};
|
||||
bool flipped{false};
|
||||
float ease_rate{0.5f};
|
||||
bool scaled{false};
|
||||
bool relative{false};
|
||||
|
||||
|
|
@ -123,7 +125,6 @@ namespace animate2 {
|
|||
void update();
|
||||
void motion(sf::Transformable& sprite, sf::Vector2f pos, sf::Vector2f scale);
|
||||
void motion(sf::View& view_out, sf::Vector2f pos, sf::Vector2f scale);
|
||||
std::pair<int, double> commit();
|
||||
};
|
||||
|
||||
Animate2 load(const std::string &file, const std::string &anim_name);
|
||||
|
|
@ -131,6 +132,6 @@ namespace animate2 {
|
|||
ENROLL_COMPONENT(Sheet, frames, frame_width, frame_height);
|
||||
ENROLL_COMPONENT(Sequence, frames, durations);
|
||||
ENROLL_COMPONENT(Transform, min_x, min_y, max_x, max_y,
|
||||
flipped, ease_rate, scaled, relative, toggled, looped, easing, motion);
|
||||
flipped, scaled, relative, toggled, looped, easing, motion);
|
||||
ENROLL_COMPONENT(Animate2, sheet, sequences, transforms, forms, sounds);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@
|
|||
"frame_height": 720
|
||||
},
|
||||
"sequences": {
|
||||
"idle": {"frames": [0], "durations": [800] },
|
||||
"hurt": {"frames": [1, 1], "durations": [800, 240] },
|
||||
"attack": {"frames": [1, 0], "durations": [800, 200] }
|
||||
"idle": {"frames": [0], "durations": [47] },
|
||||
"hurt": {"frames": [0, 1], "durations": [5, 57] },
|
||||
"attack": {"frames": [0, 1, 0, 1], "durations": [35, 15, 5, 5] }
|
||||
},
|
||||
"transforms": {
|
||||
"rushing": {
|
||||
|
|
@ -17,7 +17,6 @@
|
|||
"max_x": 0.8,
|
||||
"max_y": 0.8,
|
||||
"flipped": false,
|
||||
"ease_rate": 5.0,
|
||||
"scaled": true,
|
||||
"toggled": false,
|
||||
"looped": true,
|
||||
|
|
@ -31,7 +30,6 @@
|
|||
"max_x": 20.0,
|
||||
"max_y": 20.0,
|
||||
"flipped": true,
|
||||
"ease_rate": 5.0,
|
||||
"scaled": true,
|
||||
"toggled": false,
|
||||
"looped": false,
|
||||
|
|
@ -45,7 +43,6 @@
|
|||
"max_x": 0,
|
||||
"max_y": -10,
|
||||
"flipped": false,
|
||||
"ease_rate": 3.0,
|
||||
"scaled": false,
|
||||
"toggled": false,
|
||||
"looped": true,
|
||||
|
|
@ -72,9 +69,9 @@
|
|||
"frame_height": 540
|
||||
},
|
||||
"sequences": {
|
||||
"idle": {"frames": [0], "durations": [800] },
|
||||
"hurt": {"frames": [0], "durations": [800] },
|
||||
"attack": {"frames": [0], "durations": [800] }
|
||||
"idle": {"frames": [0], "durations": [47] },
|
||||
"hurt": {"frames": [0], "durations": [47] },
|
||||
"attack": {"frames": [0], "durations": [47] }
|
||||
},
|
||||
"transforms": {
|
||||
"breathe": {
|
||||
|
|
@ -83,7 +80,6 @@
|
|||
"max_x": 0,
|
||||
"max_y": -10,
|
||||
"flipped": false,
|
||||
"ease_rate": 3.0,
|
||||
"scaled": false,
|
||||
"toggled": false,
|
||||
"looped": true,
|
||||
|
|
@ -110,7 +106,7 @@
|
|||
"frame_height": 256
|
||||
},
|
||||
"sequences": {
|
||||
"idle": {"frames": [0,1,2], "durations": [100, 100, 100] }
|
||||
"idle": {"frames": [0,1,2], "durations": [10, 10, 10] }
|
||||
},
|
||||
"transforms": {
|
||||
"render": {
|
||||
|
|
@ -119,7 +115,6 @@
|
|||
"max_x": 0,
|
||||
"max_y": 0,
|
||||
"flipped": false,
|
||||
"ease_rate": 3.0,
|
||||
"scaled": true,
|
||||
"toggled": false,
|
||||
"looped": true,
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@
|
|||
"frame_height": 768
|
||||
},
|
||||
"sequences": {
|
||||
"idle": {"frames": [0], "durations": [800] },
|
||||
"pan": {"frames": [0], "durations": [800] },
|
||||
"shake": {"frames": [0], "durations": [800] },
|
||||
"dolly": {"frames": [0], "durations": [800] },
|
||||
"bounce": {"frames": [0], "durations": [800] }
|
||||
"idle": {"frames": [0], "durations": [60] },
|
||||
"pan": {"frames": [0], "durations": [60] },
|
||||
"shake": {"frames": [0], "durations": [60] },
|
||||
"dolly": {"frames": [0], "durations": [60] },
|
||||
"bounce": {"frames": [0], "durations": [60] }
|
||||
},
|
||||
"transforms": {
|
||||
"pan": {
|
||||
|
|
@ -19,7 +19,6 @@
|
|||
"max_x": 0.0,
|
||||
"max_y": 0.0,
|
||||
"flipped": false,
|
||||
"ease_rate": 5.0,
|
||||
"scaled": false,
|
||||
"toggled": false,
|
||||
"looped": true,
|
||||
|
|
@ -33,7 +32,6 @@
|
|||
"max_x": 10.0,
|
||||
"max_y": 10.0,
|
||||
"flipped": false,
|
||||
"ease_rate": 5.0,
|
||||
"scaled": false,
|
||||
"toggled": false,
|
||||
"looped": true,
|
||||
|
|
@ -47,7 +45,6 @@
|
|||
"max_x": 1.0,
|
||||
"max_y": 1.0,
|
||||
"flipped": false,
|
||||
"ease_rate": 3.0,
|
||||
"scaled": false,
|
||||
"toggled": false,
|
||||
"looped": true,
|
||||
|
|
@ -61,7 +58,6 @@
|
|||
"max_x": 0,
|
||||
"max_y": 0,
|
||||
"flipped": false,
|
||||
"ease_rate": 3.0,
|
||||
"scaled": false,
|
||||
"toggled": false,
|
||||
"looped": true,
|
||||
|
|
|
|||
|
|
@ -98,8 +98,6 @@ namespace cinematic {
|
|||
}
|
||||
|
||||
void Camera::update() {
|
||||
// REFACTOR: there's no connection between anim.commit() and anim.update()
|
||||
auto [ticks, alpha] = anim.commit();
|
||||
if(anim.playing) anim.update();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -131,7 +131,6 @@ namespace scene {
|
|||
inline void this_is_stupid_refactor(std::vector<Element>& elements) {
|
||||
for(auto& element : elements) {
|
||||
if(element.anim.playing) {
|
||||
auto [ticks, alpha] = element.anim.commit();
|
||||
element.anim.update();
|
||||
element.anim.motion(*element.st.sprite, element.pos, element.scale);
|
||||
element.anim.apply(*element.st.sprite);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ Animate2 load_animation(const string& name) {
|
|||
anim.set_form("attack");
|
||||
|
||||
anim.transform.looped = false;
|
||||
anim.sequence.durations = {Random::milliseconds(5, 33), Random::milliseconds(5, 33)};
|
||||
anim.sequence.durations = {Random::uniform(1, 5), Random::uniform(1, 5)};
|
||||
return anim;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,20 +54,11 @@ namespace animator {
|
|||
}
|
||||
|
||||
void FSM::START(Event ev) {
|
||||
switch(ev) {
|
||||
case Event::TICK:
|
||||
state(State::ANIMATE);
|
||||
break;
|
||||
default:
|
||||
state(State::START);
|
||||
}
|
||||
}
|
||||
|
||||
void FSM::ANIMATE(Event ev) {
|
||||
switch(ev) {
|
||||
case Event::TICK:
|
||||
run_animation();
|
||||
break;
|
||||
case Event::PLAY_STOP:
|
||||
if($anim.playing) {
|
||||
$anim.stop();
|
||||
|
|
@ -122,7 +113,7 @@ namespace animator {
|
|||
$anim.play();
|
||||
}
|
||||
|
||||
void FSM::run_animation() {
|
||||
void FSM::update() {
|
||||
if($anim.playing) {
|
||||
$anim.update();
|
||||
$anim.apply(*$ui.sprite);
|
||||
|
|
@ -131,14 +122,6 @@ namespace animator {
|
|||
}
|
||||
}
|
||||
|
||||
void FSM::tick() {
|
||||
auto [ticks, alpha] = $anim.commit();
|
||||
|
||||
for(int i = 0; i < ticks; i++) {
|
||||
event(animator::Event::TICK, {});
|
||||
}
|
||||
}
|
||||
|
||||
void FSM::check_update() {
|
||||
if($timer.getElapsedTime().toDuration() > 500ms) {
|
||||
try {
|
||||
|
|
@ -356,9 +339,9 @@ int main(int argc, char* argv[]) {
|
|||
main.init(sprite_name, anim_name, background);
|
||||
|
||||
while(main.active()) {
|
||||
main.tick();
|
||||
main.check_update();
|
||||
main.update();
|
||||
main.render();
|
||||
main.check_update();
|
||||
main.handle_keyboard_mouse();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,8 +66,7 @@ namespace animator {
|
|||
void handle_keyboard_mouse();
|
||||
void render();
|
||||
bool active();
|
||||
void run_animation();
|
||||
void tick();
|
||||
void update();
|
||||
void reload();
|
||||
void check_update();
|
||||
void change_form(int direction);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue