collide box/box, box/line, box/point; sprite/sprite and sprite/box precise alpha collision
This commit is contained in:
parent
2b9dd44ff7
commit
ae644b7138
49
src/Box.cpp
49
src/Box.cpp
|
@ -271,6 +271,55 @@ void Box::move(const glm::vec2& delta)
|
|||
set_y(get_y() + delta.y);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
bool Box::collide(const Segment& segment, glm::vec2* intersection) const
|
||||
{
|
||||
if (collide(segment.get_box()))
|
||||
{
|
||||
return segment.intersect({get_nw(), get_ne()}, intersection) ||
|
||||
segment.intersect({get_ne(), get_se()}, intersection) ||
|
||||
segment.intersect({get_sw(), get_se()}, intersection) ||
|
||||
segment.intersect({get_nw(), get_sw()}, intersection);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Box::collide(const Segment& segment, glm::vec2& intersection) const
|
||||
{
|
||||
return collide(segment, &intersection);
|
||||
}
|
||||
|
||||
bool Box::collide(const Box& box, Box* overlap) const
|
||||
{
|
||||
float top = std::max(get_top(), box.get_top());
|
||||
float right = std::min(get_right(), box.get_right());
|
||||
float bottom = std::min(get_bottom(), box.get_bottom());
|
||||
float left = std::max(get_left(), box.get_left());
|
||||
float w = right - left;
|
||||
float h = bottom - top;
|
||||
bool collide = w > 0 && h > 0;
|
||||
if (collide && overlap != NULL)
|
||||
{
|
||||
overlap->set_x(left);
|
||||
overlap->set_y(top);
|
||||
overlap->set_w(w);
|
||||
overlap->set_h(h);
|
||||
}
|
||||
return collide;
|
||||
}
|
||||
|
||||
bool Box::collide(const Box& box, Box& overlap) const
|
||||
{
|
||||
return collide(box, &overlap);
|
||||
}
|
||||
|
||||
std::ostream& Box::to_string (std::ostream& out) const
|
||||
{
|
||||
out << "{(" << rect.x << ", " << rect.y << "), (" << rect.w << ", " << rect.h << ")}";
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define Box_h_
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
|
@ -9,6 +10,8 @@
|
|||
#include "glm/common.hpp"
|
||||
#include "glm/vec2.hpp"
|
||||
|
||||
struct Segment;
|
||||
|
||||
struct Box
|
||||
{
|
||||
SDL_FRect rect;
|
||||
|
@ -61,6 +64,11 @@ struct Box
|
|||
void clear();
|
||||
void scale(float, bool = false);
|
||||
void move(const glm::vec2&);
|
||||
bool collide(const glm::vec2&) const;
|
||||
bool collide(const Segment&, glm::vec2* = NULL) const;
|
||||
bool collide(const Segment&, glm::vec2&) const;
|
||||
bool collide(const Box&, Box* = NULL) const;
|
||||
bool collide(const Box&, Box&) const;
|
||||
std::string get_class_name() { return "Box"; }
|
||||
std::ostream& to_string (std::ostream&) const;
|
||||
|
||||
|
@ -69,5 +77,6 @@ struct Box
|
|||
std::ostream& operator<<(std::ostream&, const Box&);
|
||||
|
||||
#include "extension.hpp"
|
||||
#include "Segment.hpp"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,7 +20,7 @@ void Delegate::dispatch()
|
|||
{
|
||||
for (auto iter = subscribers.begin(); iter != subscribers.end(); iter++)
|
||||
{
|
||||
if (event.type == iter->first)
|
||||
if (static_cast<int>(event.type) == iter->first)
|
||||
{
|
||||
cancelling_propagation = false;
|
||||
for (Subscriber s : iter->second)
|
||||
|
|
|
@ -45,14 +45,14 @@ struct Delegate : Node
|
|||
template<typename T>
|
||||
void unsubscribe(T* p)
|
||||
{
|
||||
const std::type_info& info = typeid(p);
|
||||
for (auto t = subscribers.begin(); t != subscribers.end(); t++)
|
||||
{
|
||||
for (auto s = t->second.begin(); s != t->second.end();)
|
||||
{
|
||||
std::cout << p << " " << s->o << " " << s->f.target_type().name() << " " << info.name() << " " <<
|
||||
std::type_index(info).name() << " " <<
|
||||
(s->f.target_type() == info) << std::endl;
|
||||
// const std::type_info& info = typeid(p);
|
||||
// std::cout << p << " " << s->o << " " << s->f.target_type().name() << " " << info.name() << " " <<
|
||||
// std::type_index(info).name() << " " <<
|
||||
// (s->f.target_type() == info) << std::endl;
|
||||
if (p == s->o)
|
||||
{
|
||||
s = t->second.erase(s);
|
||||
|
|
|
@ -450,6 +450,11 @@ SDL_Window* Game::get_window()
|
|||
return window;
|
||||
}
|
||||
|
||||
const SDL_Renderer* Game::get_renderer() const
|
||||
{
|
||||
return renderer;
|
||||
}
|
||||
|
||||
SDL_Renderer* Game::get_renderer()
|
||||
{
|
||||
return renderer;
|
||||
|
@ -505,6 +510,7 @@ void Game::frame(float ticks)
|
|||
framerate_indicator.update();
|
||||
if (!is_gl_context)
|
||||
{
|
||||
SDL_SetRenderTarget(renderer, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ struct Game : Node
|
|||
void log_surface_format(SDL_Surface*, std::string = "surface");
|
||||
std::string get_pixel_format_string(Uint32);
|
||||
SDL_Window* get_window();
|
||||
const SDL_Renderer* get_renderer() const;
|
||||
SDL_Renderer* get_renderer();
|
||||
glm::vec2 weight(glm::vec2);
|
||||
void run();
|
||||
|
|
19
src/Node.cpp
19
src/Node.cpp
|
@ -44,6 +44,11 @@ Display& Node::get_display()
|
|||
return get_root()->display;
|
||||
}
|
||||
|
||||
const SDL_Renderer* Node::get_renderer() const
|
||||
{
|
||||
return get_root()->get_renderer();
|
||||
}
|
||||
|
||||
SDL_Renderer* Node::get_renderer()
|
||||
{
|
||||
return get_root()->get_renderer();
|
||||
|
@ -54,6 +59,16 @@ SDL_Window* Node::get_window()
|
|||
return get_root()->get_window();
|
||||
}
|
||||
|
||||
const Game* Node::get_root() const
|
||||
{
|
||||
const Node* root = this;
|
||||
while (root->parent != NULL)
|
||||
{
|
||||
root = parent;
|
||||
}
|
||||
return dynamic_cast<const Game*>(root);
|
||||
}
|
||||
|
||||
void Node::suppress_input_temporarily(int length)
|
||||
{
|
||||
get_root()->input.suppress();
|
||||
|
@ -84,7 +99,7 @@ void Node::print_branch()
|
|||
|
||||
Node::~Node()
|
||||
{
|
||||
std::cout << "Destructing ";
|
||||
print_branch();
|
||||
// std::cout << "Destructing ";
|
||||
// print_branch();
|
||||
get_delegate().unsubscribe(this);
|
||||
}
|
||||
|
|
|
@ -29,8 +29,10 @@ struct Node
|
|||
nlohmann::json& get_configuration();
|
||||
Delegate& get_delegate();
|
||||
Display& get_display();
|
||||
const SDL_Renderer* get_renderer() const;
|
||||
SDL_Renderer* get_renderer();
|
||||
SDL_Window* get_window();
|
||||
const Game* get_root() const;
|
||||
void suppress_input_temporarily(int = 0);
|
||||
void print_branch();
|
||||
virtual std::string get_class_name() { return "Node"; };
|
||||
|
|
|
@ -26,26 +26,98 @@ void Segment::set_end(const glm::vec2& e)
|
|||
end = e;
|
||||
}
|
||||
|
||||
bool Segment::intersect(const Segment& segment)
|
||||
// taken from http://www.realtimerendering.com/resources/GraphicsGems/gemsii/xlines.c
|
||||
bool Segment::intersect(const Segment& segment, glm::vec2* intersection) const
|
||||
{
|
||||
return sfw::segments_intersect(*this, segment);
|
||||
float x1 = start.x, y1 = start.y, x2 = end.x, y2 = end.y, x3 = segment.start.x,
|
||||
y3 = segment.start.y, x4 = segment.end.x, y4 = segment.end.y;
|
||||
|
||||
float a1, a2, b1, b2, c1, c2; // Coefficients of line eqns.
|
||||
float r1, r2, r3, r4; // 'Sign' values
|
||||
float denom, num; // Intermediate values
|
||||
|
||||
// Compute a1, b1, c1, where line joining points 1 and 2 is "a1 x + b1 y + c1 = 0"
|
||||
a1 = y2 - y1;
|
||||
b1 = x1 - x2;
|
||||
c1 = x2 * y1 - x1 * y2;
|
||||
|
||||
// Compute r3 and r4
|
||||
r3 = a1 * x3 + b1 * y3 + c1;
|
||||
r4 = a1 * x4 + b1 * y4 + c1;
|
||||
|
||||
// Check signs of r3 and r4. If both point 3 and point 4 lie on same side of
|
||||
// line 1, the line segments do not intersect
|
||||
if (r3 != 0 && r4 != 0 && std::copysign(1, r3) == std::copysign(1, r4))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute a2, b2, c2
|
||||
a2 = y4 - y3;
|
||||
b2 = x3 - x4;
|
||||
c2 = x4 * y3 - x3 * y4;
|
||||
|
||||
// Compute r1 and r2
|
||||
r1 = a2 * x1 + b2 * y1 + c2;
|
||||
r2 = a2 * x2 + b2 * y2 + c2;
|
||||
|
||||
// Check signs of r1 and r2. If both point 1 and point 2 lie on same side
|
||||
// of second line segment, the line segments do not intersect
|
||||
if (r1 != 0 && r2 != 0 && std::copysign(1, r1) == std::copysign(1, r2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Line segments intersect: compute intersection point
|
||||
denom = a1 * b2 - a2 * b1;
|
||||
if (denom == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
num = b1 * c2 - b2 * c1;
|
||||
if (intersection != NULL)
|
||||
{
|
||||
intersection->x = num / denom;
|
||||
}
|
||||
num = a2 * c1 - a1 * c2;
|
||||
if (intersection != NULL)
|
||||
{
|
||||
intersection->y = num / denom;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Segment::intersect(const Segment& segment, glm::vec2& intersection)
|
||||
bool Segment::intersect(const Segment& segment, glm::vec2& intersection) const
|
||||
{
|
||||
return sfw::segments_intersect(*this, segment, intersection);
|
||||
return intersect(segment, &intersection);
|
||||
}
|
||||
|
||||
float Segment::get_dx()
|
||||
float Segment::get_dx() const
|
||||
{
|
||||
return end.x - start.x;
|
||||
}
|
||||
|
||||
float Segment::get_length()
|
||||
float Segment::get_dy() const
|
||||
{
|
||||
return end.y - start.y;
|
||||
}
|
||||
|
||||
float Segment::get_length() const
|
||||
{
|
||||
return glm::distance(start, end);
|
||||
}
|
||||
|
||||
Box Segment::get_box() const
|
||||
{
|
||||
float x = std::min(start.x, end.x);
|
||||
float y = std::min(start.y, end.y);
|
||||
float w = std::abs(get_dx());
|
||||
float h = std::abs(get_dy());
|
||||
return Box({x, y}, {w, h});
|
||||
}
|
||||
|
||||
void Segment::move(const glm::vec2& delta)
|
||||
{
|
||||
start += delta;
|
||||
|
|
|
@ -2,10 +2,14 @@
|
|||
#define Segment_h_
|
||||
|
||||
#include <ostream>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include "glm/vec2.hpp"
|
||||
#include "glm/geometric.hpp"
|
||||
|
||||
struct Box;
|
||||
|
||||
struct Segment
|
||||
{
|
||||
|
||||
|
@ -18,10 +22,12 @@ struct Segment
|
|||
void set_start(const glm::vec2&);
|
||||
glm::vec2 get_end() const;
|
||||
void set_end(const glm::vec2&);
|
||||
bool intersect(const Segment&);
|
||||
bool intersect(const Segment&, glm::vec2&);
|
||||
float get_dx();
|
||||
float get_length();
|
||||
bool intersect(const Segment&, glm::vec2* = NULL) const;
|
||||
bool intersect(const Segment&, glm::vec2&) const;
|
||||
float get_dx() const;
|
||||
float get_dy() const;
|
||||
float get_length() const;
|
||||
Box get_box() const;
|
||||
void move(const glm::vec2&);
|
||||
glm::vec2 get_center();
|
||||
|
||||
|
@ -30,5 +36,6 @@ struct Segment
|
|||
std::ostream& operator<<(std::ostream&, const Segment&);
|
||||
|
||||
#include "extension.hpp"
|
||||
#include "Box.hpp"
|
||||
|
||||
#endif
|
||||
|
|
200
src/Sprite.cpp
200
src/Sprite.cpp
|
@ -118,17 +118,27 @@ Frameset& Sprite::set_frameset(std::string name)
|
|||
|
||||
Frameset& Sprite::get_current_frameset()
|
||||
{
|
||||
return framesets[current_frameset_name];
|
||||
return framesets.at(current_frameset_name);
|
||||
}
|
||||
|
||||
SDL_Texture* Sprite::get_current_frame()
|
||||
const Frameset& Sprite::get_current_frameset() const
|
||||
{
|
||||
return framesets.at(current_frameset_name);
|
||||
}
|
||||
|
||||
SDL_Texture* Sprite::get_current_frame() const
|
||||
{
|
||||
return frames[get_current_frameset().get_current_frame_index()];
|
||||
}
|
||||
|
||||
Box& Sprite::get_box(int index)
|
||||
const Box& Sprite::get_box(int index) const
|
||||
{
|
||||
return boxes[index];
|
||||
return get_boxes()[index];
|
||||
}
|
||||
|
||||
const std::vector<Box>& Sprite::get_boxes() const
|
||||
{
|
||||
return boxes;
|
||||
}
|
||||
|
||||
void Sprite::add_box(glm::vec2 position, bool absolute)
|
||||
|
@ -144,10 +154,10 @@ void Sprite::update_size(bool preserve_center)
|
|||
{
|
||||
for (int ii = 0; ii < boxes.size(); ii++)
|
||||
{
|
||||
get_box(ii).set_size(get_current_frameset().get_size(), preserve_center);
|
||||
boxes[ii].set_size(get_current_frameset().get_size(), preserve_center);
|
||||
if (scale != 1)
|
||||
{
|
||||
get_box(ii).scale(scale, preserve_center);
|
||||
boxes[ii].scale(scale, preserve_center);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -227,6 +237,16 @@ Uint8 Sprite::get_alpha_mod() const
|
|||
return alpha_mod;
|
||||
}
|
||||
|
||||
void Sprite::set_color_mod(const SDL_Color& color)
|
||||
{
|
||||
color_mod = color;
|
||||
}
|
||||
|
||||
const SDL_Color& Sprite::get_color_mod() const
|
||||
{
|
||||
return color_mod;
|
||||
}
|
||||
|
||||
float Sprite::get_w()
|
||||
{
|
||||
return get_box().get_w();
|
||||
|
@ -439,6 +459,171 @@ glm::vec2 Sprite::move(glm::vec2 delta, bool weighted)
|
|||
return delta;
|
||||
}
|
||||
|
||||
bool Sprite::collide(const glm::vec2& point, bool all) const
|
||||
{
|
||||
if (!all)
|
||||
{
|
||||
return get_box().collide(point);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const Box& box : boxes)
|
||||
{
|
||||
if (box.collide(point))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Sprite::collide(const Segment& segment, glm::vec2* intersection, bool all) const
|
||||
{
|
||||
if (!all)
|
||||
{
|
||||
return get_box().collide(segment, intersection);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const Box& box : boxes)
|
||||
{
|
||||
if (box.collide(segment, intersection))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Sprite::collide(const Segment& segment, glm::vec2& intersection, bool all) const
|
||||
{
|
||||
return collide(segment, &intersection, all);
|
||||
}
|
||||
|
||||
bool Sprite::collide(const Box& box, bool precise, Box* overlap, bool all, SDL_Texture* other_texture) const
|
||||
{
|
||||
if (precise)
|
||||
{
|
||||
int texture_access;
|
||||
SDL_QueryTexture(get_current_frame(), NULL, &texture_access, NULL, NULL);
|
||||
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)
|
||||
{
|
||||
SDL_QueryTexture(other_texture, NULL, &texture_access, NULL, NULL);
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (precise && overlap == NULL)
|
||||
{
|
||||
Box o;
|
||||
overlap = &o;
|
||||
}
|
||||
}
|
||||
for (int ii = 0; ii < get_boxes().size(); ii++)
|
||||
{
|
||||
if (get_box(ii).collide(box, overlap))
|
||||
{
|
||||
if (precise)
|
||||
{
|
||||
bool collision_detected = false;
|
||||
int w = overlap->get_w(), h = overlap->get_h();
|
||||
Uint32 format = SDL_PIXELFORMAT_RGBA32;
|
||||
int bytes_per_pixel = SDL_BYTESPERPIXEL(format);
|
||||
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)
|
||||
{
|
||||
rect.x = overlap->get_left() - box.get_left();
|
||||
rect.y = overlap->get_top() - box.get_top();
|
||||
rect.w = w;
|
||||
rect.h = h;
|
||||
other_region = new Uint8[bytes_total];
|
||||
SDL_SetRenderTarget(const_cast<SDL_Renderer*>(get_renderer()), other_texture);
|
||||
SDL_RenderReadPixels(
|
||||
const_cast<SDL_Renderer*>(get_renderer()), &rect, format, other_region, bytes_per_row);
|
||||
}
|
||||
rect.x = overlap->get_left() - get_box(ii).get_left();
|
||||
rect.y = overlap->get_top() - get_box(ii).get_top();
|
||||
rect.w = w;
|
||||
rect.h = h;
|
||||
Uint8* region = new Uint8[bytes_total];
|
||||
SDL_SetRenderTarget(const_cast<SDL_Renderer*>(get_renderer()), get_current_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)
|
||||
{
|
||||
if (region[byte_index] > 0 && (other_texture == NULL || other_region[byte_index] > 0))
|
||||
{
|
||||
collision_detected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete[] region;
|
||||
if (other_region != NULL)
|
||||
{
|
||||
delete[] other_region;
|
||||
}
|
||||
if (collision_detected)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!all)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Sprite::collide(const Box& box, Box& overlap, bool precise, bool all) const
|
||||
{
|
||||
return collide(box, precise, &overlap, all);
|
||||
}
|
||||
|
||||
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;
|
||||
if (all_other)
|
||||
{
|
||||
for (const Box& box : sprite.get_boxes())
|
||||
{
|
||||
if (collide(box, precise, overlap, all, other_sprite_texture))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return collide(sprite.get_box(), precise, overlap, all, other_sprite_texture);
|
||||
}
|
||||
}
|
||||
|
||||
bool Sprite::collide(const Sprite& sprite, Box& overlap, bool precise, bool all, bool all_other) const
|
||||
{
|
||||
return collide(sprite, precise, &overlap, all, all_other);
|
||||
}
|
||||
|
||||
void Sprite::update()
|
||||
{
|
||||
if (active)
|
||||
|
@ -451,6 +636,7 @@ void Sprite::update()
|
|||
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);
|
||||
if (wrap.x || wrap.y)
|
||||
{
|
||||
|
@ -459,7 +645,7 @@ void Sprite::update()
|
|||
}
|
||||
for (int ii = 0; ii < boxes.size(); ii++)
|
||||
{
|
||||
SDL_RenderCopyF(renderer, texture, NULL, get_box(ii).get_rect());
|
||||
SDL_RenderCopyF(renderer, texture, NULL, boxes[ii].get_rect());
|
||||
}
|
||||
if (wrap.x || wrap.y)
|
||||
{
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_image.h>
|
||||
|
@ -31,6 +32,7 @@ struct Sprite : Node
|
|||
float scale = 1;
|
||||
std::string scale_quality = "nearest";
|
||||
Uint8 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};
|
||||
|
@ -48,8 +50,10 @@ struct Sprite : Node
|
|||
Frameset& add_frameset(std::string);
|
||||
Frameset& set_frameset(std::string);
|
||||
Frameset& get_current_frameset();
|
||||
SDL_Texture* get_current_frame();
|
||||
Box& get_box(int = 0);
|
||||
const Frameset& get_current_frameset() const;
|
||||
SDL_Texture* get_current_frame() const;
|
||||
const Box& get_box(int = 0) const;
|
||||
const std::vector<Box>& get_boxes() const;
|
||||
void add_box(glm::vec2, bool = false);
|
||||
void update_size(bool = false);
|
||||
void set_scale(float);
|
||||
|
@ -65,6 +69,8 @@ struct Sprite : Node
|
|||
void set_step(glm::vec2);
|
||||
void set_alpha_mod(Uint8);
|
||||
Uint8 get_alpha_mod() const;
|
||||
void set_color_mod(const SDL_Color&);
|
||||
const SDL_Color& get_color_mod() const;
|
||||
float get_w();
|
||||
float get_h();
|
||||
glm::vec2 get_size();
|
||||
|
@ -98,6 +104,13 @@ struct Sprite : Node
|
|||
void add_wrap(bool, bool);
|
||||
void add_wrap(bool, bool, Box);
|
||||
glm::vec2 move(glm::vec2, bool = true);
|
||||
bool collide(const glm::vec2&, bool = false) const;
|
||||
bool collide(const Segment&, glm::vec2* = NULL, bool = false) const;
|
||||
bool collide(const Segment&, glm::vec2&, bool = false) const;
|
||||
bool collide(const Box&, bool = false, Box* = NULL, bool = false, SDL_Texture* = NULL) 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&, Box&, bool = false, bool = false, bool = false) const;
|
||||
void update();
|
||||
std::string get_class_name() { return "Sprite"; }
|
||||
~Sprite() { unload(); }
|
||||
|
|
|
@ -32,70 +32,6 @@ void sfw::set_magnitude(glm::vec2& vector, float magnitude)
|
|||
vector = glm::normalize(vector) * magnitude;
|
||||
}
|
||||
|
||||
bool sfw::segments_intersect(const Segment& segment_a, const Segment& segment_b)
|
||||
{
|
||||
glm::vec2 intersection;
|
||||
return segments_intersect(segment_a, segment_b, intersection);
|
||||
}
|
||||
|
||||
// ---
|
||||
// from http://www.realtimerendering.com/resources/GraphicsGems/gemsii/xlines.c
|
||||
// ---
|
||||
bool sfw::segments_intersect(const Segment& segment_a, const Segment& segment_b, glm::vec2& intersection)
|
||||
{
|
||||
float x1 = segment_a.start.x, y1 = segment_a.start.y, x2 = segment_a.end.x,
|
||||
y2 = segment_a.end.y, x3 = segment_b.start.x, y3 = segment_b.start.y,
|
||||
x4 = segment_b.end.x, y4 = segment_b.end.y;
|
||||
|
||||
float a1, a2, b1, b2, c1, c2; // Coefficients of line eqns.
|
||||
float r1, r2, r3, r4; // 'Sign' values
|
||||
float denom, num; // Intermediate values
|
||||
|
||||
// Compute a1, b1, c1, where line joining points 1 and 2 is "a1 x + b1 y + c1 = 0"
|
||||
a1 = y2 - y1;
|
||||
b1 = x1 - x2;
|
||||
c1 = x2 * y1 - x1 * y2;
|
||||
|
||||
// Compute r3 and r4
|
||||
r3 = a1 * x3 + b1 * y3 + c1;
|
||||
r4 = a1 * x4 + b1 * y4 + c1;
|
||||
|
||||
// Check signs of r3 and r4. If both point 3 and point 4 lie on same side of
|
||||
// line 1, the line segments do not intersect
|
||||
if (r3 != 0 && r4 != 0 && std::copysign(1, r3) == std::copysign(1, r4))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute a2, b2, c2
|
||||
a2 = y4 - y3;
|
||||
b2 = x3 - x4;
|
||||
c2 = x4 * y3 - x3 * y4;
|
||||
|
||||
// Compute r1 and r2
|
||||
r1 = a2 * x1 + b2 * y1 + c2;
|
||||
r2 = a2 * x2 + b2 * y2 + c2;
|
||||
|
||||
// Check signs of r1 and r2. If both point 1 and point 2 lie on same side
|
||||
// of second line segment, the line segments do not intersect
|
||||
if (r1 != 0 && r2 != 0 && std::copysign(1, r1) == std::copysign(1, r2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Line segments intersect: compute intersection point
|
||||
denom = a1 * b2 - a2 * b1;
|
||||
if (denom == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
num = b1 * c2 - b2 * c1;
|
||||
intersection.x = num / denom;
|
||||
num = a2 * c1 - a1 * c2;
|
||||
intersection.y = num / denom;
|
||||
return true;
|
||||
}
|
||||
|
||||
Box sfw::get_texture_box(SDL_Texture* texture)
|
||||
{
|
||||
int w, h;
|
||||
|
|
|
@ -33,8 +33,6 @@ namespace sfw
|
|||
glm::vec2 get_step_relative(const Segment&, float);
|
||||
std::vector<Segment> get_segments(const Segment&, int);
|
||||
void set_magnitude(glm::vec2&, float);
|
||||
bool segments_intersect(const Segment&, const Segment&);
|
||||
bool segments_intersect(const Segment&, const Segment&, glm::fvec2&);
|
||||
Box get_texture_box(SDL_Texture*);
|
||||
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&);
|
||||
|
|
Loading…
Reference in New Issue