fix sprite wipe and precision collision for scaled sprites; box move and return copy function

This commit is contained in:
Frank DeMarco 2020-09-02 23:32:01 -04:00
parent 3a571adaa3
commit 877d63cf4e
14 changed files with 153 additions and 64 deletions

View File

@ -16,7 +16,7 @@
classes, private and public class members, pixel class iterator, sprite classes, private and public class members, pixel class iterator, sprite
movement history, input history, use seconds instead of milliseconds, store movement history, input history, use seconds instead of milliseconds, store
a node's animations in list, frame object for sprite class, inline short 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 :) :) SWEATY HANDS :) OILY SNACKS :) AND BAD HYGIENE :)

View File

@ -246,16 +246,7 @@ void Box::set_center(const glm::vec2& center)
Box::operator SDL_Rect() const Box::operator SDL_Rect() const
{ {
float rounded_x = std::round(get_x()); return {static_cast<int>(get_x()), static_cast<int>(get_y()), static_cast<int>(get_w()), static_cast<int>(get_h())};
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<int>(rounded_x), static_cast<int>(rounded_y),
static_cast<int>(std::round(adjusted_width)), static_cast<int>(std::round(adjusted_height))
};
} }
void Box::clear() void Box::clear()
@ -276,10 +267,10 @@ void Box::scale(glm::vec2 delta, bool preserve_center)
void Box::scale(float 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(); glm::vec2 center = get_center();
set_size(get_size() + delta); 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) void Box::move(const glm::vec2& delta)
@ -300,6 +291,13 @@ void Box::move(const glm::vec2& delta)
set_y(get_y() + delta.y); 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 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(); return point.x >= get_left() && point.x <= get_right() && point.y >= get_top() && point.y <= get_bottom();

View File

@ -62,9 +62,10 @@ struct Box : SDL_FRect
void clear(); void clear();
void scale(glm::vec2, bool = false); void scale(glm::vec2, bool = false);
void scale(float, bool = false); void scale(float, bool = false);
void grow(glm::vec2, bool = false); void expand(glm::vec2, bool = false);
void grow(float, bool = false); void expand(float, bool = false);
void move(const glm::vec2&); void move(const glm::vec2&);
Box stamp(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;
bool collide(const Segment&, glm::vec2&) const; bool collide(const Segment&, glm::vec2&) const;

View File

@ -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); 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) void Color::shift_hue(float offset)
{ {
float hue, saturation, value; float hue, saturation, value;
float red_percent = r / 255.0f, green_percent = g / 255.0f, blue_percent = b / 255.0f; 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); 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); HSVtoRGB(red_percent, green_percent, blue_percent, hue, saturation, value);
set_percent(red_percent, green_percent, blue_percent); set_percent(red_percent, green_percent, blue_percent);
} }

View File

@ -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&);
void set_percent(const float&, 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); void set_hsv(const float&, const float& = 1.0f, const float& = 1.0f);
float get_hue() const;
void shift_hue(float); void shift_hue(float);
operator std::uint32_t() const; operator std::uint32_t() const;
operator std::uint16_t() const; operator std::uint16_t() const;

View File

@ -1,10 +1,12 @@
#include "Input.hpp"
#include "Game.hpp"
#include "Delegate.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) {} 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) if (subscribers.count(type) == 0)
{ {
@ -18,9 +20,13 @@ void Delegate::dispatch()
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&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++) for (auto iter = subscribers.begin(); iter != subscribers.end(); iter++)
{ {
if (static_cast<int>(event.type) == iter->first) if (event.type == iter->first)
{ {
cancelling_propagation = false; cancelling_propagation = false;
for (Subscriber s : iter->second) for (Subscriber s : iter->second)

View File

@ -8,10 +8,10 @@
#include <typeinfo> #include <typeinfo>
#include <typeindex> #include <typeindex>
#include "Node.hpp"
#include "SDL.h" #include "SDL.h"
#include "Node.hpp"
struct Subscriber struct Subscriber
{ {
std::function<void(SDL_Event&)> f; std::function<void(SDL_Event&)> f;
@ -21,12 +21,12 @@ struct Subscriber
struct Delegate : Node struct Delegate : Node
{ {
std::map<int, std::vector<Subscriber>> subscribers; std::map<std::uint32_t, std::vector<Subscriber>> subscribers;
static int command_event_type; static std::uint32_t command_event_type;
bool cancelling_propagation = false; bool cancelling_propagation = false;
Delegate(Node*); Delegate(Node*);
void add_subscriber(Subscriber, int); void add_subscriber(Subscriber, std::uint32_t);
void dispatch(); void dispatch();
bool compare(SDL_Event&, const std::vector<std::string>&, bool = false, bool = false); bool compare(SDL_Event&, const std::vector<std::string>&, bool = false, bool = false);
bool compare(SDL_Event&, const std::string& = "", 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; bool get_event_cancel_state(SDL_Event&) const;
template<typename T> template<typename T>
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<Node*>(o)}, type); add_subscriber({std::bind(f, o, std::placeholders::_1), static_cast<Node*>(o)}, type);
} }

View File

@ -77,7 +77,7 @@ void Input::add_to_key_map(
void Input::respond(SDL_Event &event) void Input::respond(SDL_Event &event)
{ {
if (!is_suppressed) if (!is_suppressed())
{ {
SDL_Keymod mod = SDL_GetModState(); SDL_Keymod mod = SDL_GetModState();
SDL_Keycode sym = event.key.keysym.sym; 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() void Input::suppress()
{ {
is_suppressed = true; suppressed = true;
} }
void Input::unsuppress() void Input::unsuppress()
{ {
is_suppressed = false; suppressed = false;
}
bool Input::is_suppressed()
{
return suppressed;
} }

View File

@ -47,7 +47,7 @@ struct Input : Node
}; };
std::vector<KeyCombination> key_map; std::vector<KeyCombination> key_map;
static std::string any; static std::string any;
bool is_suppressed = false; bool suppressed = false;
Animation unsuppress_animation = Animation(&Input::unsuppress, this); Animation unsuppress_animation = Animation(&Input::unsuppress, this);
Input(Node*); Input(Node*);
@ -60,6 +60,7 @@ struct Input : Node
void post_command(std::string&, const bool&) const; void post_command(std::string&, const bool&) const;
void suppress(); void suppress();
void unsuppress(); void unsuppress();
bool is_suppressed();
std::string get_class_name() { return "Input"; } std::string get_class_name() { return "Input"; }
}; };

View File

@ -59,6 +59,11 @@ const Input& Node::get_input() const
return get_root()->get_input(); return get_root()->get_input();
} }
Input& Node::get_input()
{
return get_root()->get_input();
}
const Game* Node::get_root() const const Game* Node::get_root() const
{ {
const Node* r = this; const Node* r = this;

View File

@ -4,7 +4,7 @@
#include "Game.hpp" #include "Game.hpp"
#include "Sprite.hpp" #include "Sprite.hpp"
Sprite::Sprite() : Sprite(NULL) {} Sprite::Sprite() : Sprite(nullptr) {}
Sprite::Sprite(Node* parent) : Sprite::Sprite(Node* parent) :
Node(parent), current_frameset_name(get_configuration()["animation"]["all-frames-frameset-name"]) Node(parent), current_frameset_name(get_configuration()["animation"]["all-frames-frameset-name"])
@ -24,6 +24,7 @@ void Sprite::reset()
activate(); activate();
wipe_animation.reset(); wipe_animation.reset();
reset_wipe_index(); reset_wipe_index();
unhide();
} }
void Sprite::associate(std::string path) void Sprite::associate(std::string path)
@ -100,7 +101,6 @@ 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());
reset_wipe_index(); reset_wipe_index();
} }
@ -191,6 +191,7 @@ void Sprite::update_size(bool preserve_center)
boxes[ii].scale(scale, preserve_center); boxes[ii].scale(scale, preserve_center);
} }
} }
wipe_blinds = sfw::get_blinds_boxes(get_size());
} }
void Sprite::set_scale(float s) 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; other_texture = nullptr;
} }
} }
if (precise && overlap == NULL) if (precise && overlap == nullptr)
{ {
Box o; Box o;
overlap = &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.w = w;
rect.h = h; rect.h = h;
Uint8* region = new Uint8[bytes_total]; Uint8* region = new Uint8[bytes_total];
SDL_SetRenderTarget(const_cast<SDL_Renderer*>(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<SDL_Renderer*>(get_renderer()), get_current_frame(), get_box(ii).get_size());
}
SDL_SetRenderTarget(const_cast<SDL_Renderer*>(get_renderer()), collision_check_frame);
SDL_RenderReadPixels( SDL_RenderReadPixels(
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)
@ -628,6 +639,10 @@ bool Sprite::collide(const Box& box, bool precise, Box* overlap, bool all, SDL_T
{ {
delete[] other_region; delete[] other_region;
} }
if (get_scale() != 1)
{
SDL_DestroyTexture(collision_check_frame);
}
if (collision_detected) if (collision_detected)
{ {
return true; 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 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) if (all_other)
{ {
for (const Box& box : sprite.get_boxes()) limit = sprite.get_boxes().size();
{
if (collide(box, precise, overlap, all, other_sprite_texture))
{
return true;
}
}
return false;
} }
else 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<SDL_Renderer*>(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 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); return collide(sprite, precise, &overlap, all, all_other);
} }
void Sprite::wipe() void Sprite::advance_wipe_frame()
{ {
wipe_index += wipe_increment; wipe_index += wipe_increment;
if (wipe_index < 0 || wipe_index >= static_cast<int>(wipe_blinds.size())) if (wipe_index < 0 || wipe_index >= static_cast<int>(wipe_blinds.size()))
@ -756,6 +785,13 @@ void Sprite::update()
subsection_destination = subsection; subsection_destination = subsection;
subsection_destination.x += get_left(); subsection_destination.x += get_left();
subsection_destination.y += get_top(); 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); SDL_RenderCopy(renderer, texture, &subsection, &subsection_destination);
} }
} }

View File

@ -27,7 +27,7 @@ struct Sprite : Node
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),
blink_animation = Animation(&Sprite::toggle_hidden, this, 500), 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; bool hidden = false;
glm::vec2 step = {0, 0}; glm::vec2 step = {0, 0};
float scale = 1; float scale = 1;
@ -123,7 +123,7 @@ 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(); void advance_wipe_frame();
const std::vector<Box>& get_current_wipe_blinds(); const std::vector<Box>& get_current_wipe_blinds();
void reverse_wipe_direction(); void reverse_wipe_direction();
void reset_wipe_index(); void reset_wipe_index();

View File

@ -32,7 +32,7 @@ std::vector<std::vector<Box>> sfw::get_blinds_boxes(glm::vec2 size, float step,
for (Box& blind : blinds) for (Box& blind : blinds)
{ {
bottom_save = blind.get_bottom(); bottom_save = blind.get_bottom();
blind.grow({0, inflate_per_frame}); blind.expand({0, inflate_per_frame});
blind.set_bottom(bottom_save); blind.set_bottom(bottom_save);
frames.back().push_back(blind); 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; 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) std::ostream& operator<<(std::ostream& out, const glm::vec2& vector)
{ {
out << "{" << vector.x << ", " << vector.y << "}"; out << "{" << vector.x << ", " << vector.y << "}";

View File

@ -19,6 +19,7 @@
#include "glm/vec2.hpp" #include "glm/vec2.hpp"
#include "glm/gtx/vector_angle.hpp" #include "glm/gtx/vector_angle.hpp"
#include "json/json.hpp" #include "json/json.hpp"
#include "sdl2-gfx/SDL2_gfxPrimitives.h"
#include "Box.hpp" #include "Box.hpp"
#include "Segment.hpp" #include "Segment.hpp"
@ -165,21 +166,6 @@ namespace sfw
} }
template <typename T>
std::ostream& operator<<(std::ostream& out, const std::vector<T>& 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 namespace glm
{ {
template <typename T> template <typename T>
@ -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 <typename T>
std::ostream& operator<<(std::ostream& out, const std::vector<T>& 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 #endif