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

View File

@ -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<int>(rounded_x), static_cast<int>(rounded_y),
static_cast<int>(std::round(adjusted_width)), static_cast<int>(std::round(adjusted_height))
};
return {static_cast<int>(get_x()), static_cast<int>(get_y()), static_cast<int>(get_w()), static_cast<int>(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();

View File

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

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

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&, 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;

View File

@ -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<int>(event.type) == iter->first)
if (event.type == iter->first)
{
cancelling_propagation = false;
for (Subscriber s : iter->second)

View File

@ -8,10 +8,10 @@
#include <typeinfo>
#include <typeindex>
#include "Node.hpp"
#include "SDL.h"
#include "Node.hpp"
struct Subscriber
{
std::function<void(SDL_Event&)> f;
@ -21,12 +21,12 @@ struct Subscriber
struct Delegate : Node
{
std::map<int, std::vector<Subscriber>> subscribers;
static int command_event_type;
std::map<std::uint32_t, std::vector<Subscriber>> 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<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;
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);
}

View File

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

View File

@ -47,7 +47,7 @@ struct Input : Node
};
std::vector<KeyCombination> 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"; }
};

View File

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

View File

@ -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<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(
const_cast<SDL_Renderer*>(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<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
@ -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<int>(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);
}
}

View File

@ -27,7 +27,7 @@ struct Sprite : Node
std::vector<Box> 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<Box>& get_current_wipe_blinds();
void reverse_wipe_direction();
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)
{
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 << "}";

View File

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