diff --git a/demo/Demo.cpp b/demo/Demo.cpp index afc3076..c6dda1d 100644 --- a/demo/Demo.cpp +++ b/demo/Demo.cpp @@ -10,7 +10,7 @@ config parameters on command line, effects chain, asset dict with metadata, move added sprite locations by offset when location is changed, gradients, level select code input, logging, variable screen resolution, debug display, - loading wheel animation + loading wheel animation, shadowed sprite :) SWEATY HANDS :) OILY SNACKS :) AND BAD HYGIENE :) diff --git a/src/Animation.cpp b/src/Animation.cpp index 5f0181b..88857c5 100644 --- a/src/Animation.cpp +++ b/src/Animation.cpp @@ -15,9 +15,9 @@ void Animation::play(float delay, bool play_once) } } -void Animation::set_frame_length(float frame_length) +void Animation::set_frame_length(float length) { - this->frame_length = frame_length; + frame_length = length; } void Animation::play_once(float delay) diff --git a/src/Box.cpp b/src/Box.cpp index 1ab0a15..5e9ba12 100644 --- a/src/Box.cpp +++ b/src/Box.cpp @@ -51,7 +51,7 @@ glm::vec2 Box::get_size() const return glm::vec2(get_w(), get_h()); } -void Box::set_size(glm::vec2 size) +void Box::set_size(const glm::vec2& size) { set_w(size.x); set_h(size.y); @@ -127,33 +127,33 @@ glm::vec2 Box::get_center() const return glm::vec2(get_x() + get_w() / 2, get_y() + get_h() / 2); } -void Box::set_nw(glm::vec2 nw) +void Box::set_nw(const glm::vec2& nw) { set_x(nw.x); set_y(nw.y); } -void Box::set_north(glm::vec2 n) +void Box::set_north(const glm::vec2& n) { move(n - get_north()); } -void Box::set_east(glm::vec2 e) +void Box::set_east(const glm::vec2& e) { move(e - get_east()); } -void Box::set_south(glm::vec2 s) +void Box::set_south(const glm::vec2& s) { move(s - get_south()); } -void Box::set_west(glm::vec2 w) +void Box::set_west(const glm::vec2& w) { move(w - get_west()); } -void Box::set_center(glm::vec2 center) +void Box::set_center(const glm::vec2& center) { move(center - get_center()); } @@ -169,7 +169,7 @@ void Box::zero() set_size(glm::vec2(0, 0)); } -void Box::move(glm::vec2 delta) +void Box::move(const glm::vec2& delta) { set_x(get_x() + delta.x); set_y(get_y() + delta.y); diff --git a/src/Box.hpp b/src/Box.hpp index d789d48..330ed56 100644 --- a/src/Box.hpp +++ b/src/Box.hpp @@ -23,7 +23,7 @@ struct Box void set_w(float); void set_h(float); glm::vec2 get_size() const; - void set_size(glm::vec2); + void set_size(const glm::vec2&); float get_top() const; float get_right() const; float get_bottom() const; @@ -38,21 +38,21 @@ struct Box glm::vec2 get_south() const; glm::vec2 get_west() const; glm::vec2 get_center() const; - void set_nw(glm::vec2); - void set_north(glm::vec2); - void set_east(glm::vec2); - void set_south(glm::vec2); - void set_west(glm::vec2); - void set_center(glm::vec2); + void set_nw(const glm::vec2&); + void set_north(const glm::vec2&); + void set_east(const glm::vec2&); + void set_south(const glm::vec2&); + void set_west(const glm::vec2&); + void set_center(const glm::vec2&); SDL_FRect* get_rect(); void zero(); - void move(glm::vec2); + void move(const glm::vec2&); std::string get_class_name() { return "Box"; } std::ostream& to_string (std::ostream&) const; }; -std::ostream& operator<< (std::ostream&, const Box&); +std::ostream& operator<<(std::ostream&, const Box&); #include "extension.hpp" diff --git a/src/Configuration.cpp b/src/Configuration.cpp index 5c03fe3..7eb58e4 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -53,6 +53,9 @@ void Configuration::set_defaults() {"background", {255, 255, 255}}, {"foreground", {0, 0, 0}} }; + sys_config["animation"] = { + {"all-frames-frameset-name", "all"} + }; } void Configuration::load() diff --git a/src/Node.cpp b/src/Node.cpp index 170dfb1..76f6011 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -30,7 +30,7 @@ void Node::deactivate() active = false; } -bool Node::is_active() +bool Node::is_active() const { return active; } @@ -42,7 +42,7 @@ nlohmann::json& Node::get_configuration() Game* Node::get_root() { - Node *current = this; + Node* current = this; while (current->parent != NULL) { current = current->parent; diff --git a/src/Node.hpp b/src/Node.hpp index cf483d7..51c526d 100644 --- a/src/Node.hpp +++ b/src/Node.hpp @@ -20,11 +20,11 @@ struct Node bool active; Node(); - Node(Node*, bool = true); + Node(Node*, bool=true); void set_parent(Node*); void activate(); void deactivate(); - bool is_active(); + bool is_active() const; Game* get_root(); nlohmann::json& get_configuration(); Delegate& get_delegate(); diff --git a/src/Recorder.cpp b/src/Recorder.cpp index 0c21d8c..6b42572 100644 --- a/src/Recorder.cpp +++ b/src/Recorder.cpp @@ -7,7 +7,7 @@ Recorder::Recorder(Node* parent) : Node(parent) get_delegate().subscribe(&Recorder::respond, this); animation.play(); Mix_SetPostMix(&process_audio, this); - if (not get_configuration()["recording"]["enabled"]) + if (!get_configuration()["recording"]["enabled"]) { deactivate(); } @@ -31,7 +31,7 @@ void Recorder::respond(SDL_Event& event) { end_recording(); } - else if (not writing_recording) + else if (!writing_recording) { start_recording(); } @@ -69,7 +69,7 @@ void Recorder::capture_screen() void Recorder::grab_stash() { - if (not is_recording and not writing_recording) + if (!is_recording and !writing_recording) { int length = get_configuration()["recording"]["max-stash-length"]; SDL_Log("Stashing most recent %i seconds of video...", length / 1000); @@ -92,7 +92,7 @@ void Recorder::write_most_recent_frames() make_directory(); write_stash_frames(&most_recent_stash); open_audio_file(); - while (not most_recent_stash.audio_buffers.empty()) + while (!most_recent_stash.audio_buffers.empty()) { write_audio(most_recent_stash.audio_buffers.front(), most_recent_stash.audio_buffer_lengths.front()); @@ -112,7 +112,7 @@ void Recorder::write_most_recent_frames() void Recorder::start_recording() { - if (not writing_recording) + if (!writing_recording) { SDL_Log("Starting recording..."); is_recording = true; diff --git a/src/Sprite.cpp b/src/Sprite.cpp index 21164f2..b8b5ef1 100644 --- a/src/Sprite.cpp +++ b/src/Sprite.cpp @@ -3,8 +3,10 @@ Sprite::Sprite() : Sprite(NULL) {} -Sprite::Sprite(Node* parent) : Node(parent, true) +Sprite::Sprite(Node* parent) : + Node(parent, true), current_frameset_name(get_configuration()["animation"]["all-frames-frameset-name"]) { + add_frameset(current_frameset_name); frame_animation.play(); } @@ -32,7 +34,6 @@ void Sprite::associate(std::string path) std::sort(paths.begin(), paths.end()); for (const fs::path &name : paths) { - std::cout << "associating " << name << std::endl; frame_paths.push_back(name); } } @@ -68,22 +69,59 @@ void Sprite::load_file(fs::path path) void Sprite::add_frame(SDL_Texture* texture) { - int w, h; - SDL_QueryTexture(texture, NULL, NULL, &w, &h); - if (box.get_w() < w) - { - box.set_w(w); - } - if (box.get_h() < h) - { - box.set_h(h); - } frames.push_back(texture); + Frameset& all_frames_frameset = get_all_frames_frameset(); + all_frames_frameset.clear(); + for (int ii = 0; ii < frames.size(); ii++) + { + all_frames_frameset.add_frame_index(ii); + } + for (auto& member : framesets) + { + member.second.set_size(); + } + update_size(); +} + +Frameset& Sprite::get_all_frames_frameset() +{ + return framesets[get_configuration()["animation"]["all-frames-frameset-name"]]; +} + +Frameset& Sprite::add_frameset(std::string name) +{ + if (framesets.find(name) == framesets.end()) + { + framesets[name] = Frameset(this); + } + return framesets[name]; +} + +void Sprite::set_frameset(std::string name) +{ + current_frameset_name = name; + frame_animation.set_frame_length(get_current_frameset().get_frame_length()); + update_size(); +} + +Frameset& Sprite::get_current_frameset() +{ + return framesets[current_frameset_name]; +} + +void Sprite::update_size() +{ + box.set_size(get_current_frameset().get_size()); +} + +bool Sprite::is_loaded() const +{ + return !frames.empty(); } void Sprite::unload() { - while (not frames.empty()) + while (!frames.empty()) { SDL_DestroyTexture(frames.back()); frames.pop_back(); @@ -93,10 +131,7 @@ void Sprite::unload() void Sprite::advance_frame() { - if (++frame_ii >= frames.size()) - { - frame_ii = 0; - } + get_current_frameset().step(); } void Sprite::hide() @@ -170,7 +205,7 @@ glm::vec2 Sprite::get_west() const return box.get_west(); } -void Sprite::set_nw(glm::vec2 nw) +void Sprite::set_nw(const glm::vec2& nw) { box.set_nw(nw); } @@ -192,9 +227,10 @@ void Sprite::update() move(step); frame_animation.update(); blink_animation.update(); - if (frames.size() && !is_hidden) + if (is_loaded() && !is_hidden && get_current_frameset().get_frame_count()) { - SDL_Texture* texture = frames[frame_ii]; + int index = get_current_frameset().get_current_frame_index(); + SDL_Texture* texture = frames[index]; SDL_Renderer* renderer = get_root()->renderer; SDL_SetTextureAlphaMod(texture, alpha_mod); SDL_SetRenderTarget(renderer, NULL); @@ -202,3 +238,111 @@ void Sprite::update() } } } + +Frameset::Frameset() : Frameset(NULL) {} + +Frameset::Frameset(Sprite* sprite) : sprite(sprite) {} + +void Frameset::add_frame_index(int index) +{ + add_frame_indicies({index}); +} + +void Frameset::add_frame_indicies(const std::vector& indicies) +{ + order.insert(order.end(), indicies.begin(), indicies.end()); +} + +void Frameset::set_frame_length(float length) +{ + frame_length = length; +} + +float Frameset::get_frame_length() const +{ + return frame_length; +} + +void Frameset::reset() +{ + current_index = 0; +} + +void Frameset::clear() +{ + order.clear(); + reset(); +} + +int Frameset::get_current_frame_index() const +{ + return order[current_index]; +} + +glm::vec2 Frameset::measure() const +{ + glm::vec2 s(0, 0); + int w, h; + for (int index : order) + { + if (index < sprite->frames.size()) + { + SDL_QueryTexture(sprite->frames[index], NULL, NULL, &w, &h); + s.x = std::max(static_cast(w), s.x); + s.y = std::max(static_cast(h), s.y); + } + } + return s; +} + +void Frameset::set_size() +{ + set_size(measure()); +} + +void Frameset::set_size(const glm::vec2& s) +{ + size = s; +} + +const glm::vec2& Frameset::get_size() const +{ + return size; +} + +void Frameset::step() +{ + if (order.size() > 0) + { + increment_index(); + } +} + +void Frameset::increment_index() +{ + int increment; + if (!reversed) + { + increment = 1; + } + else + { + increment = -1; + } + increment_index(increment); +} + +void Frameset::increment_index(int increment) +{ + current_index = (current_index + increment) % order.size(); +} + +int Frameset::get_frame_count() const +{ + return order.size(); +} + +void Frameset::reverse() +{ + reversed = !reversed; +} diff --git a/src/Sprite.hpp b/src/Sprite.hpp index c150ea7..74797b2 100644 --- a/src/Sprite.hpp +++ b/src/Sprite.hpp @@ -1,6 +1,7 @@ #ifndef Sprite_h_ #define Sprite_h_ +#include #include #include #include @@ -13,19 +14,23 @@ #include "Game.hpp" #include "Box.hpp" #include "Animation.hpp" +#include "extension.hpp" + +struct Frameset; struct Sprite : Node { std::vector frames; std::vector frame_paths; - int frame_ii = 0; Box box; Animation frame_animation = Animation(&Sprite::advance_frame, this); Animation blink_animation = Animation(&Sprite::toggle_hidden, this, 500); bool is_hidden = false; glm::vec2 step = {0, 0}; Uint8 alpha_mod = 255; + std::map framesets; + std::string current_frameset_name; Sprite(); Sprite(Node*); @@ -35,6 +40,12 @@ struct Sprite : Node void load(); void load_file(fs::path); void add_frame(SDL_Texture*); + Frameset& get_all_frames_frameset(); + Frameset& add_frameset(std::string); + void set_frameset(std::string); + Frameset& get_current_frameset(); + void update_size(); + bool is_loaded() const; void unload(); void advance_frame(); void hide(); @@ -51,7 +62,7 @@ struct Sprite : Node glm::vec2 get_nw() const; glm::vec2 get_north() const; glm::vec2 get_west() const; - void set_nw(glm::vec2); + void set_nw(const glm::vec2&); void move(glm::vec2, bool = true); void update(); std::string get_class_name() { return "Sprite"; } @@ -59,4 +70,35 @@ struct Sprite : Node }; +struct Frameset +{ + + Sprite* sprite; + std::vector order; + int current_index = 0; + float frame_length = 0; + bool reversed = false; + glm::vec2 size; + + Frameset(); + Frameset(Sprite*); + void add_frame_index(int); + void add_frame_indicies(const std::vector&); + void set_frame_length(float); + float get_frame_length() const; + void reset(); + void clear(); + int get_current_frame_index() const; + glm::vec2 measure() const; + void set_size(); + void set_size(const glm::vec2&); + const glm::vec2& get_size() const; + void step(); + void increment_index(); + void increment_index(int); + int get_frame_count() const; + void reverse(); + +}; + #endif diff --git a/src/extension.cpp b/src/extension.cpp index a2ad0f5..46984dd 100644 --- a/src/extension.cpp +++ b/src/extension.cpp @@ -97,3 +97,9 @@ fs::path sfw::get_next_file_name( while (fs::exists(path)); return path; } + +std::ostream& operator<<(std::ostream& out, const glm::vec2& vector) +{ + out << "{" << vector.x << ", " << vector.y << "}"; + return out; +} diff --git a/src/extension.hpp b/src/extension.hpp index 4b81cc8..e9138a5 100644 --- a/src/extension.hpp +++ b/src/extension.hpp @@ -41,4 +41,6 @@ namespace sfw } } +std::ostream& operator<<(std::ostream&, const glm::vec2&); + #endif