add wipe animation to sprite

This commit is contained in:
Frank DeMarco 2020-08-29 23:49:45 -04:00
parent 66f6d6ef81
commit 54a8c219ed
7 changed files with 139 additions and 35 deletions

View File

@ -12,9 +12,10 @@
changed, gradients, level select code input, logging, variable screen changed, gradients, level select code input, logging, variable screen
resolution, debug display, loading wheel animation, shadowed sprite, separate resolution, debug display, loading wheel animation, shadowed sprite, separate
update and draw, sprite movement cage, multiple windows, multiple renderers, update and draw, sprite movement cage, multiple windows, multiple renderers,
node children list, node animations list, copy constructor for node, private node children list, node animations list, copy constructor for all base
and public class members, pixel class iterator, sprite movement history, input classes, private and public class members, pixel class iterator, sprite
history movement history, input history, use seconds instead of milliseconds, store
a node's animations in list
:) SWEATY HANDS :) OILY SNACKS :) AND BAD HYGIENE :) :) SWEATY HANDS :) OILY SNACKS :) AND BAD HYGIENE :)

View File

@ -258,17 +258,36 @@ void Box::clear()
set_size(glm::vec2(0, 0)); 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(); glm::vec2 center = get_center();
set_w(get_w() * amount); set_size(get_size() * delta);
set_h(get_h() * amount);
if (preserve_center) if (preserve_center)
{ {
set_center(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) void Box::move(const glm::vec2& delta)
{ {
set_x(get_x() + delta.x); set_x(get_x() + delta.x);

View File

@ -60,7 +60,10 @@ struct Box : SDL_FRect
void set_center(const glm::vec2&); void set_center(const glm::vec2&);
operator SDL_Rect() const; operator SDL_Rect() const;
void clear(); void clear();
void scale(glm::vec2, bool = false);
void scale(float, bool = false); void scale(float, bool = false);
void grow(glm::vec2, bool = false);
void grow(float, bool = false);
void move(const glm::vec2&); void move(const glm::vec2&);
bool collide(const glm::vec2&) const; bool collide(const glm::vec2&) const;
bool collide(const Segment&, glm::vec2* = nullptr) const; bool collide(const Segment&, glm::vec2* = nullptr) const;

View File

@ -1,5 +1,8 @@
#include "Sprite.hpp" #include "Pixels.hpp"
#include "Game.hpp" #include "Game.hpp"
#include "extension.hpp"
#include "Game.hpp"
#include "Sprite.hpp"
Sprite::Sprite() : Sprite(NULL) {} Sprite::Sprite() : Sprite(NULL) {}
@ -19,6 +22,8 @@ void Sprite::reset()
{ {
Node::reset(); Node::reset();
activate(); activate();
wipe_animation.reset();
wipe_index = static_cast<int>(wipe_blinds.size() - 1);
} }
void Sprite::associate(std::string path) void Sprite::associate(std::string path)
@ -95,6 +100,8 @@ void Sprite::add_frames(SDL_Texture* frame)
frameset.set_size(); frameset.set_size();
} }
update_size(preserve_center); update_size(preserve_center);
wipe_blinds = sfw::get_blinds_boxes(get_size());
wipe_index = static_cast<int>(wipe_blinds.size() - 1);
} }
void Sprite::add_frames(const std::vector<SDL_Texture*>& frames) void Sprite::add_frames(const std::vector<SDL_Texture*>& frames)
@ -207,7 +214,7 @@ bool Sprite::is_loaded() const
return !frames.empty(); return !frames.empty();
} }
void Sprite::unload(bool leave_memory_allocated) void Sprite::unload()
{ {
while (!frames.empty()) while (!frames.empty())
{ {
@ -552,21 +559,21 @@ bool Sprite::collide(const Box& box, bool precise, Box* overlap, bool all, SDL_T
if (precise) if (precise)
{ {
int texture_access; 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) if (texture_access != SDL_TEXTUREACCESS_TARGET)
{ {
SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, SDL_LogWarn(SDL_LOG_CATEGORY_ERROR,
"can't do precise collision detection on texture without target access"); "can't do precise collision detection on texture without target access");
precise = false; 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) if (texture_access != SDL_TEXTUREACCESS_TARGET)
{ {
SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, SDL_LogWarn(SDL_LOG_CATEGORY_ERROR,
"can't use other texture in precise collision detection without target access"); "can't use other texture in precise collision detection without target access");
other_texture = NULL; other_texture = nullptr;
} }
} }
if (precise && overlap == NULL) 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_per_row = bytes_per_pixel * w;
int bytes_total = h * bytes_per_row; int bytes_total = h * bytes_per_row;
SDL_Rect rect; SDL_Rect rect;
Uint8* other_region = NULL; Uint8* other_region = nullptr;
if (other_texture != NULL) if (other_texture != nullptr)
{ {
rect.x = overlap->get_left() - box.get_left(); rect.x = overlap->get_left() - box.get_left();
rect.y = overlap->get_top() - box.get_top(); 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<SDL_Renderer*>(get_renderer()), &rect, format, region, bytes_per_row); const_cast<SDL_Renderer*>(get_renderer()), &rect, format, region, bytes_per_row);
for (int byte_index = 3; byte_index < bytes_total; byte_index += 4) 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; collision_detected = true;
break; break;
} }
} }
delete[] region; delete[] region;
if (other_region != NULL) if (other_region != nullptr)
{ {
delete[] other_region; 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 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) if (all_other)
{ {
for (const Box& box : sprite.get_boxes()) 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); return collide(sprite, precise, &overlap, all, all_other);
} }
void Sprite::wipe()
{
if (--wipe_index < 0)
{
wipe_index = static_cast<int>(wipe_blinds.size() - 1);
wipe_animation.reset();
hide();
}
}
const std::vector<Box>& Sprite::get_current_wipe_blinds()
{
return wipe_blinds[wipe_index];
}
void Sprite::update() void Sprite::update()
{ {
if (active) if (active)
@ -679,30 +701,54 @@ void Sprite::update()
} }
frame_animation.update(); frame_animation.update();
blink_animation.update(); blink_animation.update();
wipe_animation.update();
if (is_loaded() && !is_hidden() && get_current_frameset().get_frame_count()) if (is_loaded() && !is_hidden() && get_current_frameset().get_frame_count())
{ {
SDL_Texture* texture = get_current_frame(); SDL_Texture* texture = get_current_frame();
SDL_Renderer* renderer = get_root()->renderer; SDL_Renderer* renderer = get_root()->renderer;
SDL_SetTextureAlphaMod(texture, alpha_mod); SDL_SetTextureAlphaMod(texture, alpha_mod);
SDL_SetTextureColorMod(texture, color_mod.r, color_mod.g, color_mod.b); 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) if (wrap.x || wrap.y)
{ {
SDL_Rect wrap_frame_rect = wrap_frame; SDL_Rect wrap_frame_rect = wrap_frame;
SDL_RenderSetClipRect(renderer, &wrap_frame_rect); SDL_RenderSetClipRect(renderer, &wrap_frame_rect);
} }
for (auto ii = 0; ii < static_cast<int>(boxes.size()); ii++) for (auto box_ii = 0; box_ii < static_cast<int>(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) 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() : Frameset(NULL) {}
Frameset::Frameset(Sprite* sprite) : sprite(sprite) {} Frameset::Frameset(Sprite* sprite) : sprite(sprite) {}
@ -720,6 +766,10 @@ void Frameset::add_frame_indicies(const std::vector<int>& indicies)
void Frameset::set_frame_length(float length) void Frameset::set_frame_length(float length)
{ {
frame_length = length; frame_length = length;
if (&sprite->get_current_frameset() == this)
{
sprite->frame_animation.set_frame_length(length);
}
} }
float Frameset::get_frame_length() const float Frameset::get_frame_length() const

View File

@ -25,20 +25,25 @@ struct Sprite : Node
std::vector<SDL_Texture*> frames; std::vector<SDL_Texture*> frames;
std::vector<fs::path> frame_paths; std::vector<fs::path> frame_paths;
std::vector<Box> boxes = {{{0, 0}, {0, 0}}}; std::vector<Box> boxes = {{{0, 0}, {0, 0}}};
Animation frame_animation = Animation(&Sprite::advance_frame, this); Animation frame_animation = Animation(&Sprite::advance_frame, this),
Animation blink_animation = Animation(&Sprite::toggle_hidden, this, 500); blink_animation = Animation(&Sprite::toggle_hidden, this, 500),
wipe_animation = Animation(&Sprite::wipe, this, 40);
bool hidden = false; bool hidden = false;
glm::vec2 step = {0, 0}; glm::vec2 step = {0, 0};
float scale = 1; float scale = 1;
std::string scale_quality = "nearest"; std::string scale_quality = "nearest";
Uint8 alpha_mod = 255; std::uint8_t alpha_mod = 255;
SDL_Color color_mod = {255, 255, 255, 255}; SDL_Color color_mod = {255, 255, 255, 255};
std::map<std::string, Frameset> framesets; std::map<std::string, Frameset> framesets;
std::string current_frameset_name; std::string current_frameset_name;
glm::bvec2 wrap = {false, false}; glm::bvec2 wrap = {false, false};
int texture_access = SDL_TEXTUREACCESS_TARGET; 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<std::vector<Box>> wipe_blinds;
SDL_Rect subsection;
Sprite(); Sprite();
Sprite(Node*); Sprite(Node*);
Sprite(Node*, std::string); Sprite(Node*, std::string);
@ -64,7 +69,7 @@ struct Sprite : Node
void set_scale_quality(const std::string&); void set_scale_quality(const std::string&);
float get_scale() const; float get_scale() const;
bool is_loaded() const; bool is_loaded() const;
virtual void unload(bool = false); virtual void unload();
void advance_frame(); void advance_frame();
void hide(); void hide();
void unhide(); void unhide();
@ -118,7 +123,11 @@ struct Sprite : Node
bool collide(const Box&, Box&, bool = false, bool = false) const; 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&, bool = false, Box* = NULL, bool = false, bool = false) const;
bool collide(const Sprite&, Box&, bool = false, bool = false, bool = false) const; bool collide(const Sprite&, Box&, bool = false, bool = false, bool = false) const;
void wipe();
const std::vector<Box>& get_current_wipe_blinds();
virtual void update(); virtual void update();
void set_to_leave_memory_allocated();
void set_to_deallocate_memory();
virtual std::string get_class_name() { return "Sprite"; } virtual std::string get_class_name() { return "Sprite"; }
~Sprite() { unload(); } ~Sprite() { unload(); }
@ -157,8 +166,4 @@ struct Frameset
}; };
#include "Pixels.hpp"
#include "Game.hpp"
#include "extension.hpp"
#endif #endif

View File

@ -34,9 +34,34 @@ void sfw::set_magnitude(glm::vec2& vector, float magnitude)
Box sfw::get_texture_box(SDL_Texture* texture) Box sfw::get_texture_box(SDL_Texture* texture)
{ {
int w, h; int width, height;
SDL_QueryTexture(texture, NULL, NULL, &w, &h); SDL_QueryTexture(texture, nullptr, nullptr, &width, &height);
return Box(glm::vec2(0, 0), glm::vec2(w, h)); return Box(glm::vec2(0, 0), glm::vec2(width, height));
}
std::vector<std::vector<Box>> sfw::get_blinds_boxes(glm::vec2 size, float step, int count)
{
std::vector<Box> 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<std::vector<Box>> 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<std::vector<SDL_Color>>& pixels) void sfw::populate_pixel_2d_array(SDL_Renderer* renderer, SDL_Texture* texture, std::vector<std::vector<SDL_Color>>& pixels)
@ -48,7 +73,7 @@ void sfw::populate_pixel_2d_array(
SDL_Renderer* renderer, SDL_Texture* texture, std::vector<std::vector<SDL_Color>>& pixels, const Box& region) SDL_Renderer* renderer, SDL_Texture* texture, std::vector<std::vector<SDL_Color>>& pixels, const Box& region)
{ {
int access; 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"); print_sdl_error("Could not query texture for access flag");
} }

View File

@ -37,6 +37,7 @@ namespace sfw
std::vector<Segment> get_segments(const Segment&, int); std::vector<Segment> get_segments(const Segment&, int);
void set_magnitude(glm::vec2&, float); void set_magnitude(glm::vec2&, float);
Box get_texture_box(SDL_Texture*); Box get_texture_box(SDL_Texture*);
std::vector<std::vector<Box>> get_blinds_boxes(glm::vec2, float = 0.05f, int = 4);
void populate_pixel_2d_array(SDL_Renderer*, SDL_Texture*, std::vector<std::vector<SDL_Color>>&); void populate_pixel_2d_array(SDL_Renderer*, SDL_Texture*, std::vector<std::vector<SDL_Color>>&);
void populate_pixel_2d_array(SDL_Renderer*, SDL_Texture*, std::vector<std::vector<SDL_Color>>&, const Box&); void populate_pixel_2d_array(SDL_Renderer*, SDL_Texture*, std::vector<std::vector<SDL_Color>>&, const Box&);
void apply_array_to_texture(SDL_Renderer*, SDL_Texture*, std::vector<std::vector<SDL_Color>>&); void apply_array_to_texture(SDL_Renderer*, SDL_Texture*, std::vector<std::vector<SDL_Color>>&);