fix sprite wipe and precision collision for scaled sprites; box move and return copy function
This commit is contained in:
parent
3a571adaa3
commit
877d63cf4e
|
@ -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 :)
|
||||
|
||||
|
|
26
src/Box.cpp
26
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<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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"; }
|
||||
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 << "}";
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue