From 54a8c219ed5e98b0f5b2c471d7fc353ded0d6e38 Mon Sep 17 00:00:00 2001 From: Frank DeMarco Date: Sat, 29 Aug 2020 23:49:45 -0400 Subject: [PATCH] add wipe animation to sprite --- demo/Demo.cpp | 7 +++-- src/Box.cpp | 25 +++++++++++++-- src/Box.hpp | 3 ++ src/Sprite.cpp | 80 ++++++++++++++++++++++++++++++++++++++--------- src/Sprite.hpp | 25 +++++++++------ src/extension.cpp | 33 ++++++++++++++++--- src/extension.hpp | 1 + 7 files changed, 139 insertions(+), 35 deletions(-) diff --git a/demo/Demo.cpp b/demo/Demo.cpp index 98352b1..953fa50 100644 --- a/demo/Demo.cpp +++ b/demo/Demo.cpp @@ -12,9 +12,10 @@ changed, gradients, level select code input, logging, variable screen resolution, debug display, loading wheel animation, shadowed sprite, separate update and draw, sprite movement cage, multiple windows, multiple renderers, - node children list, node animations list, copy constructor for node, private - and public class members, pixel class iterator, sprite movement history, input - history + node children list, node animations list, copy constructor for all base + classes, private and public class members, pixel class iterator, sprite + movement history, input history, use seconds instead of milliseconds, store + a node's animations in list :) SWEATY HANDS :) OILY SNACKS :) AND BAD HYGIENE :) diff --git a/src/Box.cpp b/src/Box.cpp index 1c35eb3..66fec48 100644 --- a/src/Box.cpp +++ b/src/Box.cpp @@ -258,17 +258,36 @@ void Box::clear() set_size(glm::vec2(0, 0)); } -void Box::scale(float amount, bool preserve_center) +void Box::scale(glm::vec2 delta, bool preserve_center) { glm::vec2 center = get_center(); - set_w(get_w() * amount); - set_h(get_h() * amount); + set_size(get_size() * delta); if (preserve_center) { set_center(center); } } +void Box::scale(float delta, bool preserve_center) +{ + Box::scale({delta, delta}, preserve_center); +} + +void Box::grow(glm::vec2 delta, bool preserve_center) +{ + glm::vec2 center = get_center(); + set_size(get_size() + delta); + if (preserve_center) + { + set_center(center); + } +} + +void Box::grow(float delta, bool preserve_center) +{ + Box::grow({delta, delta}, preserve_center); +} + void Box::move(const glm::vec2& delta) { set_x(get_x() + delta.x); diff --git a/src/Box.hpp b/src/Box.hpp index 76669c4..5af48e4 100644 --- a/src/Box.hpp +++ b/src/Box.hpp @@ -60,7 +60,10 @@ struct Box : SDL_FRect void set_center(const glm::vec2&); operator SDL_Rect() const; void clear(); + void scale(glm::vec2, bool = false); void scale(float, bool = false); + void grow(glm::vec2, bool = false); + void grow(float, bool = false); void move(const glm::vec2&); bool collide(const glm::vec2&) const; bool collide(const Segment&, glm::vec2* = nullptr) const; diff --git a/src/Sprite.cpp b/src/Sprite.cpp index b434f35..f363bd8 100644 --- a/src/Sprite.cpp +++ b/src/Sprite.cpp @@ -1,5 +1,8 @@ -#include "Sprite.hpp" +#include "Pixels.hpp" #include "Game.hpp" +#include "extension.hpp" +#include "Game.hpp" +#include "Sprite.hpp" Sprite::Sprite() : Sprite(NULL) {} @@ -19,6 +22,8 @@ void Sprite::reset() { Node::reset(); activate(); + wipe_animation.reset(); + wipe_index = static_cast(wipe_blinds.size() - 1); } void Sprite::associate(std::string path) @@ -95,6 +100,8 @@ void Sprite::add_frames(SDL_Texture* frame) frameset.set_size(); } update_size(preserve_center); + wipe_blinds = sfw::get_blinds_boxes(get_size()); + wipe_index = static_cast(wipe_blinds.size() - 1); } void Sprite::add_frames(const std::vector& frames) @@ -207,7 +214,7 @@ bool Sprite::is_loaded() const return !frames.empty(); } -void Sprite::unload(bool leave_memory_allocated) +void Sprite::unload() { while (!frames.empty()) { @@ -552,21 +559,21 @@ bool Sprite::collide(const Box& box, bool precise, Box* overlap, bool all, SDL_T if (precise) { int texture_access; - SDL_QueryTexture(get_current_frame(), NULL, &texture_access, NULL, NULL); + SDL_QueryTexture(get_current_frame(), nullptr, &texture_access, nullptr, nullptr); if (texture_access != SDL_TEXTUREACCESS_TARGET) { SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, "can't do precise collision detection on texture without target access"); precise = false; } - else if (other_texture != NULL) + else if (other_texture != nullptr) { - SDL_QueryTexture(other_texture, NULL, &texture_access, NULL, NULL); + SDL_QueryTexture(other_texture, nullptr, &texture_access, nullptr, nullptr); if (texture_access != SDL_TEXTUREACCESS_TARGET) { SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, "can't use other texture in precise collision detection without target access"); - other_texture = NULL; + other_texture = nullptr; } } if (precise && overlap == NULL) @@ -588,8 +595,8 @@ bool Sprite::collide(const Box& box, bool precise, Box* overlap, bool all, SDL_T int bytes_per_row = bytes_per_pixel * w; int bytes_total = h * bytes_per_row; SDL_Rect rect; - Uint8* other_region = NULL; - if (other_texture != NULL) + Uint8* other_region = nullptr; + if (other_texture != nullptr) { rect.x = overlap->get_left() - box.get_left(); rect.y = overlap->get_top() - box.get_top(); @@ -610,14 +617,14 @@ bool Sprite::collide(const Box& box, bool precise, Box* overlap, bool all, SDL_T const_cast(get_renderer()), &rect, format, region, bytes_per_row); for (int byte_index = 3; byte_index < bytes_total; byte_index += 4) { - if (region[byte_index] > 0 && (other_texture == NULL || other_region[byte_index] > 0)) + if (region[byte_index] > 0 && (other_texture == nullptr || other_region[byte_index] > 0)) { collision_detected = true; break; } } delete[] region; - if (other_region != NULL) + if (other_region != nullptr) { delete[] other_region; } @@ -646,7 +653,7 @@ bool Sprite::collide(const Box& box, Box& overlap, bool precise, bool all) const bool Sprite::collide(const Sprite& sprite, bool precise, Box* overlap, bool all, bool all_other) const { - SDL_Texture* other_sprite_texture = precise ? sprite.get_current_frame() : NULL; + SDL_Texture* other_sprite_texture = precise ? sprite.get_current_frame() : nullptr; if (all_other) { for (const Box& box : sprite.get_boxes()) @@ -669,6 +676,21 @@ bool Sprite::collide(const Sprite& sprite, Box& overlap, bool precise, bool all, return collide(sprite, precise, &overlap, all, all_other); } +void Sprite::wipe() +{ + if (--wipe_index < 0) + { + wipe_index = static_cast(wipe_blinds.size() - 1); + wipe_animation.reset(); + hide(); + } +} + +const std::vector& Sprite::get_current_wipe_blinds() +{ + return wipe_blinds[wipe_index]; +} + void Sprite::update() { if (active) @@ -679,30 +701,54 @@ void Sprite::update() } frame_animation.update(); blink_animation.update(); + wipe_animation.update(); if (is_loaded() && !is_hidden() && get_current_frameset().get_frame_count()) { SDL_Texture* texture = get_current_frame(); SDL_Renderer* renderer = get_root()->renderer; SDL_SetTextureAlphaMod(texture, alpha_mod); SDL_SetTextureColorMod(texture, color_mod.r, color_mod.g, color_mod.b); - SDL_SetRenderTarget(renderer, NULL); + SDL_SetRenderTarget(renderer, nullptr); if (wrap.x || wrap.y) { SDL_Rect wrap_frame_rect = wrap_frame; SDL_RenderSetClipRect(renderer, &wrap_frame_rect); } - for (auto ii = 0; ii < static_cast(boxes.size()); ii++) + for (auto box_ii = 0; box_ii < static_cast(boxes.size()); box_ii++) { - SDL_RenderCopyF(renderer, texture, NULL, &boxes[ii]); + if (!wipe_animation.is_playing()) + { + SDL_RenderCopyF(renderer, texture, nullptr, &boxes[box_ii]); + } + else + { + for (const Box& blind : get_current_wipe_blinds()) + { + subsection = blind; + subsection_destination = blind; + subsection_destination.move(get_nw(box_ii)); + SDL_RenderCopyF(renderer, texture, &subsection, &subsection_destination); + } + } } if (wrap.x || wrap.y) { - SDL_RenderSetClipRect(renderer, NULL); + SDL_RenderSetClipRect(renderer, nullptr); } } } } +void Sprite::set_to_leave_memory_allocated() +{ + leave_memory_allocated = true; +} + +void Sprite::set_to_deallocate_memory() +{ + leave_memory_allocated = false; +} + Frameset::Frameset() : Frameset(NULL) {} Frameset::Frameset(Sprite* sprite) : sprite(sprite) {} @@ -720,6 +766,10 @@ void Frameset::add_frame_indicies(const std::vector& indicies) void Frameset::set_frame_length(float length) { frame_length = length; + if (&sprite->get_current_frameset() == this) + { + sprite->frame_animation.set_frame_length(length); + } } float Frameset::get_frame_length() const diff --git a/src/Sprite.hpp b/src/Sprite.hpp index 77a52ff..1e9dc67 100644 --- a/src/Sprite.hpp +++ b/src/Sprite.hpp @@ -25,20 +25,25 @@ struct Sprite : Node std::vector frames; std::vector frame_paths; std::vector boxes = {{{0, 0}, {0, 0}}}; - Animation frame_animation = Animation(&Sprite::advance_frame, this); - Animation blink_animation = Animation(&Sprite::toggle_hidden, this, 500); + Animation frame_animation = Animation(&Sprite::advance_frame, this), + blink_animation = Animation(&Sprite::toggle_hidden, this, 500), + wipe_animation = Animation(&Sprite::wipe, this, 40); bool hidden = false; glm::vec2 step = {0, 0}; float scale = 1; std::string scale_quality = "nearest"; - Uint8 alpha_mod = 255; + std::uint8_t alpha_mod = 255; SDL_Color color_mod = {255, 255, 255, 255}; std::map framesets; std::string current_frameset_name; glm::bvec2 wrap = {false, false}; int texture_access = SDL_TEXTUREACCESS_TARGET; - Box wrap_frame; - + int wipe_index = 0; + Box wrap_frame, subsection_destination; + bool leave_memory_allocated = false; + std::vector> wipe_blinds; + SDL_Rect subsection; + Sprite(); Sprite(Node*); Sprite(Node*, std::string); @@ -64,7 +69,7 @@ struct Sprite : Node void set_scale_quality(const std::string&); float get_scale() const; bool is_loaded() const; - virtual void unload(bool = false); + virtual void unload(); void advance_frame(); void hide(); void unhide(); @@ -118,7 +123,11 @@ struct Sprite : Node bool collide(const Box&, Box&, bool = false, bool = false) const; bool collide(const Sprite&, bool = false, Box* = NULL, bool = false, bool = false) const; bool collide(const Sprite&, Box&, bool = false, bool = false, bool = false) const; + void wipe(); + const std::vector& get_current_wipe_blinds(); virtual void update(); + void set_to_leave_memory_allocated(); + void set_to_deallocate_memory(); virtual std::string get_class_name() { return "Sprite"; } ~Sprite() { unload(); } @@ -157,8 +166,4 @@ struct Frameset }; -#include "Pixels.hpp" -#include "Game.hpp" -#include "extension.hpp" - #endif diff --git a/src/extension.cpp b/src/extension.cpp index d3e95d2..bc085cb 100644 --- a/src/extension.cpp +++ b/src/extension.cpp @@ -34,9 +34,34 @@ void sfw::set_magnitude(glm::vec2& vector, float magnitude) Box sfw::get_texture_box(SDL_Texture* texture) { - int w, h; - SDL_QueryTexture(texture, NULL, NULL, &w, &h); - return Box(glm::vec2(0, 0), glm::vec2(w, h)); + int width, height; + SDL_QueryTexture(texture, nullptr, nullptr, &width, &height); + return Box(glm::vec2(0, 0), glm::vec2(width, height)); +} + +std::vector> sfw::get_blinds_boxes(glm::vec2 size, float step, int count) +{ + std::vector blinds; + float blind_height = size.y / count; + for (int ii = 1; ii <= count; ii++) + { + blinds.push_back(Box({0, blind_height * ii}, {size.x, 0})); + } + float inflate_per_frame = blind_height * step; + std::vector> frames; + float bottom_save; + while (blinds[0].get_h() < blind_height) + { + frames.push_back({}); + for (Box& blind : blinds) + { + bottom_save = blind.get_bottom(); + blind.grow({0, inflate_per_frame}); + blind.set_bottom(bottom_save); + frames.back().push_back(blind); + } + } + return frames; } void sfw::populate_pixel_2d_array(SDL_Renderer* renderer, SDL_Texture* texture, std::vector>& pixels) @@ -48,7 +73,7 @@ void sfw::populate_pixel_2d_array( SDL_Renderer* renderer, SDL_Texture* texture, std::vector>& pixels, const Box& region) { int access; - if (SDL_QueryTexture(texture, NULL, &access, NULL, NULL) < 0) + if (SDL_QueryTexture(texture, nullptr, &access, nullptr, nullptr) < 0) { print_sdl_error("Could not query texture for access flag"); } diff --git a/src/extension.hpp b/src/extension.hpp index 2cb6778..b58f40e 100644 --- a/src/extension.hpp +++ b/src/extension.hpp @@ -37,6 +37,7 @@ namespace sfw std::vector get_segments(const Segment&, int); void set_magnitude(glm::vec2&, float); Box get_texture_box(SDL_Texture*); + std::vector> get_blinds_boxes(glm::vec2, float = 0.05f, int = 4); void populate_pixel_2d_array(SDL_Renderer*, SDL_Texture*, std::vector>&); void populate_pixel_2d_array(SDL_Renderer*, SDL_Texture*, std::vector>&, const Box&); void apply_array_to_texture(SDL_Renderer*, SDL_Texture*, std::vector>&);