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