add wipe animation to sprite
This commit is contained in:
parent
66f6d6ef81
commit
54a8c219ed
|
@ -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 :)
|
||||
|
||||
|
|
25
src/Box.cpp
25
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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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>>&);
|
||||
|
|
Loading…
Reference in New Issue