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
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 :)

View File

@ -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);

View File

@ -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;

View File

@ -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<int>(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<int>(wipe_blinds.size() - 1);
}
void Sprite::add_frames(const std::vector<SDL_Texture*>& 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<SDL_Renderer*>(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<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()
{
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<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)
{
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<int>& 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

View File

@ -25,20 +25,25 @@ struct Sprite : Node
std::vector<SDL_Texture*> frames;
std::vector<fs::path> frame_paths;
std::vector<Box> 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<std::string, Frameset> 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<std::vector<Box>> 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<Box>& 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

View File

@ -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<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)
@ -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)
{
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");
}

View File

@ -37,6 +37,7 @@ namespace sfw
std::vector<Segment> get_segments(const Segment&, int);
void set_magnitude(glm::vec2&, float);
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>>&, const Box&);
void apply_array_to_texture(SDL_Renderer*, SDL_Texture*, std::vector<std::vector<SDL_Color>>&);