From 877d63cf4e9c6f7798bfbf3ee71d187430376aea Mon Sep 17 00:00:00 2001 From: Frank DeMarco Date: Wed, 2 Sep 2020 23:32:01 -0400 Subject: [PATCH] fix sprite wipe and precision collision for scaled sprites; box move and return copy function --- demo/Demo.cpp | 2 +- src/Box.cpp | 26 +++++++++---------- src/Box.hpp | 5 ++-- src/Color.cpp | 10 ++++++- src/Color.hpp | 1 + src/Delegate.cpp | 12 ++++++--- src/Delegate.hpp | 12 ++++----- src/Input.cpp | 11 +++++--- src/Input.hpp | 3 ++- src/Node.cpp | 5 ++++ src/Sprite.cpp | 66 ++++++++++++++++++++++++++++++++++++----------- src/Sprite.hpp | 4 +-- src/extension.cpp | 25 +++++++++++++++++- src/extension.hpp | 35 ++++++++++++++----------- 14 files changed, 153 insertions(+), 64 deletions(-) diff --git a/demo/Demo.cpp b/demo/Demo.cpp index 229e088..f39a388 100644 --- a/demo/Demo.cpp +++ b/demo/Demo.cpp @@ -16,7 +16,7 @@ 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, frame object for sprite class, inline short - functions + functions, add box2d to library :) SWEATY HANDS :) OILY SNACKS :) AND BAD HYGIENE :) diff --git a/src/Box.cpp b/src/Box.cpp index d0abe54..f48a8c4 100644 --- a/src/Box.cpp +++ b/src/Box.cpp @@ -246,16 +246,7 @@ void Box::set_center(const glm::vec2& center) Box::operator SDL_Rect() const { - float rounded_x = std::round(get_x()); - float dx = rounded_x - get_x(); - float adjusted_width = get_w() + dx; - float rounded_y = std::round(get_y()); - float dy = rounded_y - get_y(); - float adjusted_height = get_h() + dy; - return { - static_cast(rounded_x), static_cast(rounded_y), - static_cast(std::round(adjusted_width)), static_cast(std::round(adjusted_height)) - }; + return {static_cast(get_x()), static_cast(get_y()), static_cast(get_w()), static_cast(get_h())}; } void Box::clear() @@ -276,10 +267,10 @@ void Box::scale(glm::vec2 delta, bool preserve_center) void Box::scale(float delta, bool preserve_center) { - Box::scale({delta, delta}, preserve_center); + scale({delta, delta}, preserve_center); } -void Box::grow(glm::vec2 delta, bool preserve_center) +void Box::expand(glm::vec2 delta, bool preserve_center) { glm::vec2 center = get_center(); set_size(get_size() + delta); @@ -289,9 +280,9 @@ void Box::grow(glm::vec2 delta, bool preserve_center) } } -void Box::grow(float delta, bool preserve_center) +void Box::expand(float delta, bool preserve_center) { - Box::grow({delta, delta}, preserve_center); + expand({delta, delta}, preserve_center); } void Box::move(const glm::vec2& delta) @@ -300,6 +291,13 @@ void Box::move(const glm::vec2& delta) set_y(get_y() + delta.y); } +Box Box::stamp(const glm::vec2& delta) +{ + Box clone = *this; + clone.move(delta); + return clone; +} + bool Box::collide(const glm::vec2& point) const { return point.x >= get_left() && point.x <= get_right() && point.y >= get_top() && point.y <= get_bottom(); diff --git a/src/Box.hpp b/src/Box.hpp index 5af48e4..2aa59a1 100644 --- a/src/Box.hpp +++ b/src/Box.hpp @@ -62,9 +62,10 @@ struct Box : SDL_FRect 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 expand(glm::vec2, bool = false); + void expand(float, bool = false); void move(const glm::vec2&); + Box stamp(const glm::vec2&); bool collide(const glm::vec2&) const; bool collide(const Segment&, glm::vec2* = nullptr) const; bool collide(const Segment&, glm::vec2&) const; diff --git a/src/Color.cpp b/src/Color.cpp index dfcd0fc..30f7df8 100644 --- a/src/Color.cpp +++ b/src/Color.cpp @@ -24,12 +24,20 @@ void Color::set_hsv(const float& hue, const float& saturation, const float& valu set_percent(red_percent, green_percent, blue_percent); } +float Color::get_hue() const +{ + float hue, saturation, value; + float red_percent = r / 255.0f, green_percent = g / 255.0f, blue_percent = b / 255.0f; + RGBtoHSV(red_percent, green_percent, blue_percent, hue, saturation, value); + return hue; +} + void Color::shift_hue(float offset) { float hue, saturation, value; float red_percent = r / 255.0f, green_percent = g / 255.0f, blue_percent = b / 255.0f; RGBtoHSV(red_percent, green_percent, blue_percent, hue, saturation, value); - hue = std::fmod(hue + offset, 360.0); + hue = std::fmod(hue + offset, 360.0f); HSVtoRGB(red_percent, green_percent, blue_percent, hue, saturation, value); set_percent(red_percent, green_percent, blue_percent); } diff --git a/src/Color.hpp b/src/Color.hpp index 87dc068..620dfc2 100644 --- a/src/Color.hpp +++ b/src/Color.hpp @@ -17,6 +17,7 @@ struct Color : SDL_Color void set_percent(const float&, const float&, const float&); void set_percent(const float&, const float&, const float&, const float&); void set_hsv(const float&, const float& = 1.0f, const float& = 1.0f); + float get_hue() const; void shift_hue(float); operator std::uint32_t() const; operator std::uint16_t() const; diff --git a/src/Delegate.cpp b/src/Delegate.cpp index 3f5c911..85062bf 100644 --- a/src/Delegate.cpp +++ b/src/Delegate.cpp @@ -1,10 +1,12 @@ +#include "Input.hpp" +#include "Game.hpp" #include "Delegate.hpp" -int Delegate::command_event_type = SDL_RegisterEvents(1); +std::uint32_t Delegate::command_event_type = SDL_RegisterEvents(1); Delegate::Delegate(Node* parent) : Node(parent) {} -void Delegate::add_subscriber(Subscriber s, int type) +void Delegate::add_subscriber(Subscriber s, std::uint32_t type) { if (subscribers.count(type) == 0) { @@ -18,9 +20,13 @@ void Delegate::dispatch() SDL_Event event; while (SDL_PollEvent(&event)) { + if (get_input().is_suppressed() && (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)) + { + continue; + } for (auto iter = subscribers.begin(); iter != subscribers.end(); iter++) { - if (static_cast(event.type) == iter->first) + if (event.type == iter->first) { cancelling_propagation = false; for (Subscriber s : iter->second) diff --git a/src/Delegate.hpp b/src/Delegate.hpp index d3ba54b..dba8760 100644 --- a/src/Delegate.hpp +++ b/src/Delegate.hpp @@ -8,10 +8,10 @@ #include #include -#include "Node.hpp" - #include "SDL.h" +#include "Node.hpp" + struct Subscriber { std::function f; @@ -21,12 +21,12 @@ struct Subscriber struct Delegate : Node { - std::map> subscribers; - static int command_event_type; + std::map> subscribers; + static std::uint32_t command_event_type; bool cancelling_propagation = false; Delegate(Node*); - void add_subscriber(Subscriber, int); + void add_subscriber(Subscriber, std::uint32_t); void dispatch(); bool compare(SDL_Event&, const std::vector&, bool = false, bool = false); bool compare(SDL_Event&, const std::string& = "", bool = false, bool = false); @@ -37,7 +37,7 @@ struct Delegate : Node bool get_event_cancel_state(SDL_Event&) const; template - void subscribe(void(T::*f)(SDL_Event&), T* o, int type = command_event_type) + void subscribe(void(T::*f)(SDL_Event&), T* o, std::uint32_t type = command_event_type) { add_subscriber({std::bind(f, o, std::placeholders::_1), static_cast(o)}, type); } diff --git a/src/Input.cpp b/src/Input.cpp index 11183d4..865fd32 100644 --- a/src/Input.cpp +++ b/src/Input.cpp @@ -77,7 +77,7 @@ void Input::add_to_key_map( void Input::respond(SDL_Event &event) { - if (!is_suppressed) + if (!is_suppressed()) { SDL_Keymod mod = SDL_GetModState(); SDL_Keycode sym = event.key.keysym.sym; @@ -123,10 +123,15 @@ void Input::post_command(std::string& name, const bool& cancel) const void Input::suppress() { - is_suppressed = true; + suppressed = true; } void Input::unsuppress() { - is_suppressed = false; + suppressed = false; +} + +bool Input::is_suppressed() +{ + return suppressed; } diff --git a/src/Input.hpp b/src/Input.hpp index 592aeb4..edfc264 100644 --- a/src/Input.hpp +++ b/src/Input.hpp @@ -47,7 +47,7 @@ struct Input : Node }; std::vector key_map; static std::string any; - bool is_suppressed = false; + bool suppressed = false; Animation unsuppress_animation = Animation(&Input::unsuppress, this); Input(Node*); @@ -60,6 +60,7 @@ struct Input : Node void post_command(std::string&, const bool&) const; void suppress(); void unsuppress(); + bool is_suppressed(); std::string get_class_name() { return "Input"; } }; diff --git a/src/Node.cpp b/src/Node.cpp index 6f5c92b..af3399a 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -59,6 +59,11 @@ const Input& Node::get_input() const return get_root()->get_input(); } +Input& Node::get_input() +{ + return get_root()->get_input(); +} + const Game* Node::get_root() const { const Node* r = this; diff --git a/src/Sprite.cpp b/src/Sprite.cpp index da254dc..8486a75 100644 --- a/src/Sprite.cpp +++ b/src/Sprite.cpp @@ -4,7 +4,7 @@ #include "Game.hpp" #include "Sprite.hpp" -Sprite::Sprite() : Sprite(NULL) {} +Sprite::Sprite() : Sprite(nullptr) {} Sprite::Sprite(Node* parent) : Node(parent), current_frameset_name(get_configuration()["animation"]["all-frames-frameset-name"]) @@ -24,6 +24,7 @@ void Sprite::reset() activate(); wipe_animation.reset(); reset_wipe_index(); + unhide(); } void Sprite::associate(std::string path) @@ -100,7 +101,6 @@ void Sprite::add_frames(SDL_Texture* frame) frameset.set_size(); } update_size(preserve_center); - wipe_blinds = sfw::get_blinds_boxes(get_size()); reset_wipe_index(); } @@ -191,6 +191,7 @@ void Sprite::update_size(bool preserve_center) boxes[ii].scale(scale, preserve_center); } } + wipe_blinds = sfw::get_blinds_boxes(get_size()); } void Sprite::set_scale(float s) @@ -576,7 +577,7 @@ bool Sprite::collide(const Box& box, bool precise, Box* overlap, bool all, SDL_T other_texture = nullptr; } } - if (precise && overlap == NULL) + if (precise && overlap == nullptr) { Box o; overlap = &o; @@ -612,7 +613,17 @@ bool Sprite::collide(const Box& box, bool precise, Box* overlap, bool all, SDL_T rect.w = w; rect.h = h; Uint8* region = new Uint8[bytes_total]; - SDL_SetRenderTarget(const_cast(get_renderer()), get_current_frame()); + SDL_Texture* collision_check_frame; + if (get_scale() == 1) + { + collision_check_frame = get_current_frame(); + } + else + { + collision_check_frame = sfw::duplicate_texture( + const_cast(get_renderer()), get_current_frame(), get_box(ii).get_size()); + } + SDL_SetRenderTarget(const_cast(get_renderer()), collision_check_frame); SDL_RenderReadPixels( const_cast(get_renderer()), &rect, format, region, bytes_per_row); for (int byte_index = 3; byte_index < bytes_total; byte_index += 4) @@ -628,6 +639,10 @@ bool Sprite::collide(const Box& box, bool precise, Box* overlap, bool all, SDL_T { delete[] other_region; } + if (get_scale() != 1) + { + SDL_DestroyTexture(collision_check_frame); + } if (collision_detected) { return true; @@ -653,22 +668,36 @@ 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() : nullptr; + SDL_Texture* other_sprite_collision_check_texture = nullptr; + int limit; if (all_other) { - for (const Box& box : sprite.get_boxes()) - { - if (collide(box, precise, overlap, all, other_sprite_texture)) - { - return true; - } - } - return false; + limit = sprite.get_boxes().size(); } else { - return collide(sprite.get_box(), precise, overlap, all, other_sprite_texture); + limit = 1; } + for (int ii = 0; ii < limit; ii++) + { + if (precise) + { + if (sprite.get_scale() == 1) + { + other_sprite_collision_check_texture = sprite.get_current_frame(); + } + else + { + other_sprite_collision_check_texture = sfw::duplicate_texture( + const_cast(get_renderer()), sprite.get_current_frame(), sprite.get_box(ii).get_size()); + } + } + if (collide(sprite.get_box(ii), precise, overlap, all, other_sprite_collision_check_texture)) + { + return true; + } + } + return false; } bool Sprite::collide(const Sprite& sprite, Box& overlap, bool precise, bool all, bool all_other) const @@ -676,7 +705,7 @@ bool Sprite::collide(const Sprite& sprite, Box& overlap, bool precise, bool all, return collide(sprite, precise, &overlap, all, all_other); } -void Sprite::wipe() +void Sprite::advance_wipe_frame() { wipe_index += wipe_increment; if (wipe_index < 0 || wipe_index >= static_cast(wipe_blinds.size())) @@ -756,6 +785,13 @@ void Sprite::update() subsection_destination = subsection; subsection_destination.x += get_left(); subsection_destination.y += get_top(); + if (get_scale() != 1) + { + Box full_size = blind; + full_size.set_nw(full_size.get_nw() / get_scale()); + full_size.set_size(full_size.get_size() / get_scale()); + subsection = full_size; + } SDL_RenderCopy(renderer, texture, &subsection, &subsection_destination); } } diff --git a/src/Sprite.hpp b/src/Sprite.hpp index 78f3d0a..7ac3992 100644 --- a/src/Sprite.hpp +++ b/src/Sprite.hpp @@ -27,7 +27,7 @@ struct Sprite : Node std::vector boxes = {{{0, 0}, {0, 0}}}; Animation frame_animation = Animation(&Sprite::advance_frame, this), blink_animation = Animation(&Sprite::toggle_hidden, this, 500), - wipe_animation = Animation(&Sprite::wipe, this, 40); + wipe_animation = Animation(&Sprite::advance_wipe_frame, this, 40); bool hidden = false; glm::vec2 step = {0, 0}; float scale = 1; @@ -123,7 +123,7 @@ 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(); + void advance_wipe_frame(); const std::vector& get_current_wipe_blinds(); void reverse_wipe_direction(); void reset_wipe_index(); diff --git a/src/extension.cpp b/src/extension.cpp index fa226bf..59f83b6 100644 --- a/src/extension.cpp +++ b/src/extension.cpp @@ -32,7 +32,7 @@ std::vector> sfw::get_blinds_boxes(glm::vec2 size, float step, for (Box& blind : blinds) { bottom_save = blind.get_bottom(); - blind.grow({0, inflate_per_frame}); + blind.expand({0, inflate_per_frame}); blind.set_bottom(bottom_save); frames.back().push_back(blind); } @@ -556,6 +556,29 @@ void sfw::print_sdl_error(const std::string& message) std::cerr << message << " " << SDL_GetError() << std::endl; } +int SDL_SetRenderDrawColor(SDL_Renderer* renderer, const Color& color) +{ + return SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a); +} + +int SDL_RenderFillRect(SDL_Renderer* renderer, const Box& box) +{ + SDL_Rect rect = box; + return SDL_RenderFillRect(renderer, &rect); +} + +int lineColor(SDL_Renderer* renderer, const Segment& segment, const Color& color, std::uint8_t thickness) +{ + if (thickness == 1) + { + return lineColor(renderer, segment.start.x, segment.start.y, segment.end.x, segment.end.y, color); + } + else + { + return thickLineColor(renderer, segment.start.x, segment.start.y, segment.end.x, segment.end.y, thickness, color); + } +} + std::ostream& operator<<(std::ostream& out, const glm::vec2& vector) { out << "{" << vector.x << ", " << vector.y << "}"; diff --git a/src/extension.hpp b/src/extension.hpp index 4947aab..f1e02dd 100644 --- a/src/extension.hpp +++ b/src/extension.hpp @@ -19,6 +19,7 @@ #include "glm/vec2.hpp" #include "glm/gtx/vector_angle.hpp" #include "json/json.hpp" +#include "sdl2-gfx/SDL2_gfxPrimitives.h" #include "Box.hpp" #include "Segment.hpp" @@ -165,21 +166,6 @@ namespace sfw } -template -std::ostream& operator<<(std::ostream& out, const std::vector& members) -{ - out << "{ "; - for (const T& member : members) - { - out << member << " "; - } - out << "}"; - return out; -} - -std::ostream& operator<<(std::ostream&, const glm::vec2&); -std::ostream& operator<<(std::ostream&, const SDL_Color&); - namespace glm { template @@ -196,4 +182,23 @@ namespace glm } } +int SDL_SetRenderDrawColor(SDL_Renderer*, const Color&); +int SDL_RenderFillRect(SDL_Renderer*, const Box&); +int lineColor(SDL_Renderer*, const Segment&, const Color&, std::uint8_t = 1); + +template +std::ostream& operator<<(std::ostream& out, const std::vector& members) +{ + out << "{ "; + for (const T& member : members) + { + out << member << " "; + } + out << "}"; + return out; +} + +std::ostream& operator<<(std::ostream&, const glm::vec2&); +std::ostream& operator<<(std::ostream&, const SDL_Color&); + #endif