From 364f66bffb07c332ed4cfa3a3bbc3d30db82a9d3 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Fri, 20 Feb 2026 00:15:19 -0500 Subject: [PATCH] Camera is now using Animate2 and it's mostly working, but there's a few more refactors needed. --- animate2.cpp | 35 +++++++++++++++++++++++++-------- animate2.hpp | 9 +++++---- animation.cpp | 3 ++- assets/animate2.json | 7 ++++++- assets/cameras.json | 12 ++++++++---- camera.cpp | 22 ++++++++++++--------- camera.hpp | 1 + ease2.cpp | 46 ++++++++++++++++++++++---------------------- ease2.hpp | 22 ++++++++++----------- scene.cpp | 1 + storyboard/ui.cpp | 4 ++++ storyboard/ui.hpp | 1 + tools/arena.cpp | 1 + tools/storyboard.cpp | 4 +++- 14 files changed, 106 insertions(+), 62 deletions(-) diff --git a/animate2.cpp b/animate2.cpp index 8ccf469..11416f7 100644 --- a/animate2.cpp +++ b/animate2.cpp @@ -50,6 +50,23 @@ namespace animate2 { sprite.setTextureRect(rect); } + void Animate2::motion(sf::View& view_out, sf::Vector2f pos, sf::Vector2f size) { + dbc::check(size.x > 1.0f && size.y > 1.0f, "motion size must be above 1.0 since it's not a ratio"); + dbc::check(transform.flipped == false, "transform must be false, has no effect on View"); + + sf::Vector2f scale{transform.min_x, transform.min_y}; + + transform.apply(sequence, pos, scale); + + view_out.setCenter(pos); + + if(transform.scaled) { + view_out.setSize({size.x * scale.x, size.y * scale.y}); + } else { + view_out.setSize(size); + } + } + void Animate2::apply_effect(std::shared_ptr effect) { dbc::check(effect != nullptr, "can't apply null effect"); effect->setUniform("u_time", sequence.timer.getElapsedTime().asSeconds()); @@ -70,6 +87,12 @@ namespace animate2 { } } + /* REFACTOR: I believe this is wrong still. If ::commit() determines number of ticks+alpha since last + * render then update needs to be called 1/tick. The Timer will keep track of alpha as the error + * between commit calls, so this function only really needs to care about ticks. But, I'm still + * calling getElapsedTime() when I already did that in commit(), so should I just ignore that and assume + * elapsed is DELTA, or use elapsed here? + */ void Animate2::update() { 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()"); @@ -105,8 +128,8 @@ namespace animate2 { dbc::check(sequence.current < sequence.frame_count, "onLoop fail: current frame out of frames.size()"); } - void Animate2::motion(sf::Sprite& sprite, sf::Vector2f pos, sf::Vector2f scale) { - transform.lerp(sequence, pos, scale); + void Animate2::motion(sf::Transformable& sprite, sf::Vector2f pos, sf::Vector2f scale) { + transform.apply(sequence, pos, scale); if(transform.flipped) { scale.x *= -1; @@ -166,11 +189,11 @@ namespace animate2 { return {int(tick_count), alpha}; } - void Transform::lerp(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.subframe); - motion_func(*this, pos_out, scale_out, tick); + 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, @@ -206,10 +229,6 @@ namespace animate2 { transform.motion_func = ease2::get_motion(transform.motion); } - void Animate2::apply(sf::View& view_out, sf::Vector2f pos, sf::Vector2f size) { - - } - Animate2 load(const std::string &file, const std::string &anim_name) { using nlohmann::json; std::ifstream infile(file); diff --git a/animate2.hpp b/animate2.hpp index 8d19933..3601da9 100644 --- a/animate2.hpp +++ b/animate2.hpp @@ -57,6 +57,7 @@ namespace animate2 { bool flipped{false}; float ease_rate{0.5f}; bool scaled{false}; + bool relative{false}; // handled by onLoop bool toggled{false}; @@ -70,7 +71,7 @@ namespace animate2 { std::shared_ptr shader{nullptr}; - void lerp(Sequence& seq, sf::Vector2f& pos_out, sf::Vector2f& scale_out); + void apply(Sequence& seq, sf::Vector2f& pos_out, sf::Vector2f& scale_out); }; /* Gets the number of times it looped, and returns if it should stop. */ @@ -118,10 +119,10 @@ namespace animate2 { bool has_form(const std::string& as_form); void set_form(const std::string& form); void apply(sf::Sprite& sprite); - void apply(sf::View& view_out, sf::Vector2f pos, sf::Vector2f size); void apply_effect(std::shared_ptr effect); void update(); - void motion(sf::Sprite& 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); std::pair commit(); }; @@ -130,6 +131,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, toggled, looped, easing, motion); + flipped, ease_rate, scaled, relative, toggled, looped, easing, motion); ENROLL_COMPONENT(Animate2, sheet, sequences, transforms, forms, sounds); } diff --git a/animation.cpp b/animation.cpp index 408a6bc..e6fc5c9 100644 --- a/animation.cpp +++ b/animation.cpp @@ -252,10 +252,11 @@ namespace animation { void configure(DinkyECS::World& world, DinkyECS::Entity entity) { auto sprite = world.get_if(entity); + if(sprite != nullptr && animation::has(sprite->name)) { world.set(entity, animation::load(sprite->name)); + } } -} void step_animation(DinkyECS::World& world, DinkyECS::Entity entity, sf::Vector2f& scale_out, sf::Vector2f& pos_out, sf::IntRect& rect_out) { if(auto animation = world.get_if(entity)) { diff --git a/assets/animate2.json b/assets/animate2.json index 4269585..c2722a7 100644 --- a/assets/animate2.json +++ b/assets/animate2.json @@ -21,6 +21,7 @@ "scaled": true, "toggled": false, "looped": true, + "relative": false, "easing": "in_out_back", "motion": "move_rush" }, @@ -34,8 +35,9 @@ "scaled": true, "toggled": false, "looped": false, + "relative": true, "easing": "normal_dist", - "motion": "move_shake" + "motion": "move_slide" }, "breathe": { "min_x": 0, @@ -47,6 +49,7 @@ "scaled": false, "toggled": false, "looped": true, + "relative": true, "easing": "sine", "motion": "move_bounce" } @@ -84,6 +87,7 @@ "scaled": false, "toggled": false, "looped": true, + "relative": true, "easing": "none", "motion": "move_none" } @@ -119,6 +123,7 @@ "scaled": true, "toggled": false, "looped": true, + "relative": false, "easing": "sine", "motion": "move_none" } diff --git a/assets/cameras.json b/assets/cameras.json index f3a1519..dd75c5d 100644 --- a/assets/cameras.json +++ b/assets/cameras.json @@ -22,8 +22,9 @@ "ease_rate": 5.0, "scaled": false, "toggled": false, - "looped": false, + "looped": true, "easing": "linear", + "relative": false, "motion": "move_slide" }, "shake": { @@ -35,7 +36,8 @@ "ease_rate": 5.0, "scaled": false, "toggled": false, - "looped": false, + "looped": true, + "relative": true, "easing": "normal_dist", "motion": "move_shake" }, @@ -48,8 +50,9 @@ "ease_rate": 3.0, "scaled": false, "toggled": false, - "looped": false, + "looped": true, "easing": "sine", + "relative": true, "motion": "move_rush" }, "bounce": { @@ -61,7 +64,8 @@ "ease_rate": 3.0, "scaled": false, "toggled": false, - "looped": false, + "looped": true, + "relative": true, "easing": "in_out_back", "motion": "move_bounce" } diff --git a/camera.cpp b/camera.cpp index 3647cfa..48361b0 100644 --- a/camera.cpp +++ b/camera.cpp @@ -1,5 +1,4 @@ #include "camera.hpp" -#include #include #include "components.hpp" #include "config.hpp" @@ -72,13 +71,12 @@ namespace cinematic { going_to.x = clamp(x, camera_bounds.position.x, camera_bounds.size.x); going_to.y = clamp(y, camera_bounds.position.y, camera_bounds.size.y); - // BUG: annoying special case - //if(anim.motion == ease::SLIDE) { - // anim.min_x = aimed_at.x; - // anim.min_y = aimed_at.y; - // anim.max_x = going_to.x; - // anim.max_y = going_to.y; - //} + if(!anim.transform.relative) { + anim.transform.min_x = aimed_at.x; + anim.transform.min_y = aimed_at.y; + anim.transform.max_x = going_to.x; + anim.transform.max_y = going_to.y; + } } void Camera::reset(sf::RenderTexture& target) { @@ -94,11 +92,17 @@ namespace cinematic { void Camera::render(sf::RenderTexture& target) { if(anim.playing) { - anim.apply(view, going_to, size); + anim.motion(view, going_to, size); target.setView(view); } } + void Camera::update() { + // REFACTOR: there's no connection between anim.commit() and anim.update() + auto [ticks, alpha] = anim.commit(); + if(anim.playing) anim.update(); + } + bool Camera::playing() { return anim.playing; } diff --git a/camera.hpp b/camera.hpp index f7d1e67..3cf8834 100644 --- a/camera.hpp +++ b/camera.hpp @@ -20,6 +20,7 @@ namespace cinematic { void position(float x, float y); void move(float x, float y); bool playing(); + void update(); void render(sf::RenderTexture& target); void play(); void style(const std::string &name); diff --git a/ease2.cpp b/ease2.cpp index 1217c12..9ddbff4 100644 --- a/ease2.cpp +++ b/ease2.cpp @@ -60,47 +60,47 @@ namespace ease2 { return Random::normal(0.5f, 0.1f); } - void move_shake(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick) { - pos_out.x += std::lerp(tr.min_x, tr.max_x, tick); + void move_shake(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative) { + pos_out.x = std::lerp(tr.min_x, tr.max_x, tick) + (pos_out.x * relative); } - void move_bounce(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick) { - pos_out.y -= std::lerp(tr.min_y, tr.max_y, tick); + void move_bounce(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative) { + pos_out.y = std::lerp(tr.min_y, tr.max_y, tick) + (pos_out.y * relative); } - void move_rush(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick) { - scale_out.x = std::lerp(tr.min_x, tr.max_x, tick); - scale_out.y = std::lerp(tr.min_y, tr.max_y, tick); - pos_out.y = pos_out.y - (pos_out.y * scale_out.y - pos_out.y); + void move_rush(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative) { + scale_out.x = std::lerp(tr.min_x, tr.max_x, tick) + (scale_out.x * relative); + scale_out.y = std::lerp(tr.min_y, tr.max_y, tick) + (scale_out.y * relative); + pos_out.y = pos_out.y - (pos_out.y * scale_out.y - pos_out.y) + (pos_out.y * relative); } - void scale_squeeze(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick) { - scale_out.x = std::lerp(tr.min_x, tr.max_x, tick); + void scale_squeeze(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative) { + scale_out.x = std::lerp(tr.min_x, tr.max_x, tick) + (scale_out.x * relative); } - void scale_squash(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick) { - scale_out.y = std::lerp(tr.min_y, tr.max_y, tick); + void scale_squash(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative) { + scale_out.y = std::lerp(tr.min_y, tr.max_y, tick) + (scale_out.y * relative); } - void scale_stretch(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick) { - scale_out.x = std::lerp(tr.min_x, tr.max_x, tick); + void scale_stretch(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative) { + scale_out.x = std::lerp(tr.min_x, tr.max_x, tick) + (scale_out.x * relative); } - void scale_grow(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick) { - scale_out.y = std::lerp(tr.min_y, tr.max_y, tick); + void scale_grow(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative) { + scale_out.y = std::lerp(tr.min_y, tr.max_y, tick) + (scale_out.y * relative); } - void move_slide(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick) { - pos_out.x += std::lerp(tr.min_x, tr.max_x, tick); - pos_out.y += std::lerp(tr.min_y, tr.max_y, tick); + void move_slide(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative) { + pos_out.x = std::lerp(tr.min_x, tr.max_x, tick) + (pos_out.x * relative); + pos_out.y = std::lerp(tr.min_y, tr.max_y, tick) + (pos_out.y * relative); } - void move_none(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick) { + void move_none(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative) { } - void scale_only(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick) { - scale_out.x = std::lerp(scale_out.x * tr.min_x, scale_out.x * tr.max_x, tick); - scale_out.y = std::lerp(scale_out.y * tr.min_y, scale_out.y * tr.max_y, tick); + void scale_only(Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative) { + scale_out.x = std::lerp(scale_out.x * tr.min_x, scale_out.x * tr.max_x, tick) + (scale_out.x * relative); + scale_out.y = std::lerp(scale_out.y * tr.min_y, scale_out.y * tr.max_y, tick) + (scale_out.y * relative); } std::unordered_map map_of_easings{ diff --git a/ease2.hpp b/ease2.hpp index 391ab8c..c76a51b 100644 --- a/ease2.hpp +++ b/ease2.hpp @@ -7,7 +7,7 @@ namespace animate2 { namespace ease2 { using EaseFunc = std::function; - using MotionFunc = std::function; + using MotionFunc = std::function; EaseFunc get_easing(const std::string& name); MotionFunc get_motion(const std::string& name); @@ -19,14 +19,14 @@ namespace ease2 { double random(double tick); double normal_dist(double tick); - void move_bounce(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick); - void move_rush(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick); - void scale_squeeze(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick); - void scale_squash(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick); - void scale_stretch(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick); - void scale_grow(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick); - void move_slide(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick); - void move_none(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick); - void scale_only(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick); - void move_shake(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick); + void move_bounce(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative); + void move_rush(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative); + void scale_squeeze(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative); + void scale_squash(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative); + void scale_stretch(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative); + void scale_grow(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative); + void move_slide(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative); + void move_none(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative); + void scale_only(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative); + void move_shake(animate2::Transform &tr, sf::Vector2f& pos_out, sf::Vector2f& scale_out, float tick, bool relative); } diff --git a/scene.cpp b/scene.cpp index 77d4b50..e7552a3 100644 --- a/scene.cpp +++ b/scene.cpp @@ -190,6 +190,7 @@ namespace scene { void Engine::tick() { for(auto& actor : $actors) { + dbc::log("IDIOT! you need to use the ticks to all update ticks number of times"); auto [ticks, alpha] = actor.anim.commit(); } } diff --git a/storyboard/ui.cpp b/storyboard/ui.cpp index a6d95c3..bf9318a 100644 --- a/storyboard/ui.cpp +++ b/storyboard/ui.cpp @@ -61,6 +61,10 @@ namespace storyboard { return sf::Time(out); } + void UI::update() { + $camera.update(); + } + void UI::track_audio() { auto& beat = $story.beats[cur_beat % $story.beats.size()]; auto track_head = $audio->getPlayingOffset(); diff --git a/storyboard/ui.hpp b/storyboard/ui.hpp index 4339197..8737dea 100644 --- a/storyboard/ui.hpp +++ b/storyboard/ui.hpp @@ -22,6 +22,7 @@ namespace storyboard { UI(const std::string& story_name); void init(); + void update(); void render(sf::RenderWindow &window); bool mouse(float x, float y, guecs::Modifiers mods); void zoom(const std::string &cell_name); diff --git a/tools/arena.cpp b/tools/arena.cpp index c06e783..14d598d 100644 --- a/tools/arena.cpp +++ b/tools/arena.cpp @@ -50,6 +50,7 @@ int main(int, char*[]) { dbc::check(main->$world == world, "GameDB::current_world doesn't match boss fight world."); while(!main->in_state(boss::State::END)) { + dbc::log("IDIOT! make this an update."); main->$ui.$arena.tick(); main->render(window); diff --git a/tools/storyboard.cpp b/tools/storyboard.cpp index 995cf4f..c7aab57 100644 --- a/tools/storyboard.cpp +++ b/tools/storyboard.cpp @@ -30,6 +30,9 @@ int main(int, char*[]) { main.init(); while(main.playing()) { + main.update(); + main.render(window); + while(const auto ev = window.pollEvent()) { auto gui_ev = router.process_event(ev); auto mouse_pos = window.mapPixelToCoords(router.position); @@ -41,7 +44,6 @@ int main(int, char*[]) { } } - main.render(window); window.display(); }