box documentation, remove get/set prefixes from Box and Segment

This commit is contained in:
frank 2021-08-14 19:53:39 -04:00
parent fe3e0bf27f
commit ba44b8e8d5
21 changed files with 545 additions and 430 deletions

View File

@ -143,8 +143,8 @@ Mushroom::Mushroom(Node *parent) : Sprite(parent, "resource/shrooms")
void Mushroom::update() void Mushroom::update()
{ {
move(direction); move(direction);
int x = box.get_x(); int x = box.left();
glm::ivec2 resolution = get_display().get_window_size(); glm::ivec2 resolution = get_display().window_size();
if (x > resolution.x or x < 0) if (x > resolution.x or x < 0)
{ {
direction = -direction; direction = -direction;
@ -234,7 +234,7 @@ void Demo::load_gl_context()
vertices.insert(vertices.end(), background_vertices.begin(), background_vertices.end()); vertices.insert(vertices.end(), background_vertices.begin(), background_vertices.end());
vertices.insert(vertices.end(), framerate_indicator_vertices.begin(), vertices.insert(vertices.end(), framerate_indicator_vertices.begin(),
framerate_indicator_vertices.end()); framerate_indicator_vertices.end());
glm::ivec2 resolution = get_display().get_window_size(); glm::ivec2 resolution = get_display().window_size();
projection = glm::perspective( projection = glm::perspective(
glm::radians(45.0f), resolution.x / (float) resolution.y, 0.1f, glm::radians(45.0f), resolution.x / (float) resolution.y, 0.1f,
100.0f); 100.0f);

View File

@ -46,7 +46,7 @@ struct Mushroom : Sprite
Mushroom(Node*); Mushroom(Node*);
void update(); void update();
virtual std::string get_class_name() const { return "Mushroom"; } virtual std::string class_name() const { return "Mushroom"; }
}; };
@ -71,6 +71,6 @@ struct Demo : Game
void load_gl_context(); void load_gl_context();
void respond(SDL_Event&); void respond(SDL_Event&);
void update(); void update();
virtual std::string get_class_name() const { return "Demo"; } virtual std::string class_name() const { return "Demo"; }
}; };

View File

@ -57,9 +57,9 @@ void SoundEffect::load_chunk(const fs::path& path)
void SoundEffect::play(float location) void SoundEffect::play(float location)
{ {
play(); play();
Box window_box = get_window_box(); Box window = window_box();
location = std::clamp(location, window_box.get_left(), window_box.get_right()); location = std::clamp(location, window.left(), window.right());
float location_relative = (location - window_box.get_left()) / window_box.get_w(); float location_relative = (location - window.left()) / window.width();
int angle = 270 - location_relative * 180; int angle = 270 - location_relative * 180;
Mix_SetPosition(channel, angle, 0); Mix_SetPosition(channel, angle, 0);
} }

View File

@ -2,6 +2,7 @@
#include "Segment.hpp" #include "Segment.hpp"
#include "Box.hpp" #include "Box.hpp"
/* Construct a Box by giving the (x, y) coordinate of the NW point and the size as a 2D vector (width, height) */
Box::Box(const glm::vec2& nw, const glm::vec2& size) Box::Box(const glm::vec2& nw, const glm::vec2& size)
{ {
x = nw.x; x = nw.x;
@ -10,127 +11,138 @@ Box::Box(const glm::vec2& nw, const glm::vec2& size)
h = size.y; h = size.y;
} }
/* Construct a Box by passing an SDL_Rect struct, which is of the form {x, y, w, h} and limited to int arguments */
Box::Box(const SDL_Rect& rect) : Box({rect.x, rect.y}, {rect.w, rect.h}) {} Box::Box(const SDL_Rect& rect) : Box({rect.x, rect.y}, {rect.w, rect.h}) {}
float Box::get_x() const /* Return the width */
{ float Box::width() const
return x;
}
float Box::get_y() const
{
return y;
}
float Box::get_w() const
{ {
return w; return w;
} }
float Box::get_h() const /* Set the width. Negative values will be clamped to zero. */
void Box::width(float width)
{
w = std::max(width, 0.0f);
}
/* Return the height */
float Box::height() const
{ {
return h; return h;
} }
void Box::set_x(float x) /* Set the height. Negative values will be clamped to zero. */
void Box::height(float height)
{ {
this->x = x; h = std::max(height, 0.0f);
} }
void Box::set_y(float y) /* Return the size as a vector {width, height} */
glm::vec2 Box::size() const
{ {
this->y = y; return glm::vec2(width(), height());
} }
void Box::set_w(float width) /* Set the size. Negative values will be clamped to zero. */
void Box::size(const glm::vec2& size, bool preserve_center)
{ {
w = width; glm::vec2 center = this->center();
} width(size.x);
height(size.y);
void Box::set_h(float height)
{
h = height;
}
glm::vec2 Box::get_size() const
{
return glm::vec2(get_w(), get_h());
}
void Box::set_size(const glm::vec2& size, bool preserve_center)
{
glm::vec2 center = get_center();
set_w(size.x);
set_h(size.y);
if (preserve_center) if (preserve_center)
{ {
set_center(center); this->center(center);
} }
} }
/* Returns width divided by height regardless of which side is longer */ /* Returns width divided by height. Returns a value regardless of which side is longer, so it can return values
* greater or less than 0. */
float Box::aspect() const float Box::aspect() const
{ {
return get_w() / get_h(); return width() / height();
} }
float Box::get_area() const /* Return the area of the box (width * height) */
float Box::area() const
{ {
return get_w() * get_h(); return width() * height();
} }
float Box::get_top() const /* Return the y coordinate representing the top of the box */
float Box::top() const
{ {
return get_y(); return y;
} }
float Box::get_right() const /* Return the x coordinate representing the right side of the box */
float Box::right() const
{ {
return get_x() + get_w(); return left() + width();
} }
float Box::get_bottom() const /* Return the y coordinate representing the bottom of the box */
float Box::bottom() const
{ {
return get_y() + get_h(); return top() + height();
} }
float Box::get_left() const /* Return the x coordinate representing the left side of the box */
float Box::left() const
{ {
return get_x(); return x;
} }
float Box::get_center_x() const /* Return the x component of the center coordinates */
float Box::cx() const
{ {
return get_left() + get_w() / 2; return left() + width() / 2;
} }
float Box::get_center_y() const /* Return the y component of the center coordinates */
float Box::cy() const
{ {
return get_top() + get_h() / 2; return top() + height() / 2;
} }
void Box::set_top(float top, bool drag) /* Set the y coordinate of the top of the box. If drag is set, the other sides of the box will remain in the
* same position, and the top will be moved, altering the size of the box. Otherwise, the box will remain the
* same size, and the bottom location will change, moving the box but preserving the size. */
void Box::top(float top, bool drag)
{ {
if (!drag) if (!drag)
{ {
set_y(top); y = top;
} }
else else
{ {
drag_top(top - get_top()); drag_top(top - this->top());
} }
} }
/* Drag the top delta amount, leaving the bottom in the same position and altering the size of the box. The top
* can be dragged past the bottom, in which case the current bottom will become the new top value. */
void Box::drag_top(float delta) void Box::drag_top(float delta)
{ {
float previous_top = get_top(); float new_location = top() + delta;
set_top(get_top() + delta); if (new_location > bottom())
set_h(get_h() + previous_top - get_top()); {
top(bottom());
height(new_location - top());
}
else
{
height(bottom() - new_location);
top(new_location);
}
} }
void Box::set_right(float right, bool drag) /* Set the x coordinate of the right side of the box. If drag is set, the other sides of the box will remain in the
* same position, and the right will be moved, altering the size of the box. Otherwise, the box will remain the
* same size, and the left location will change, moving the box but preserving the size. */
void Box::right(float right, bool drag)
{ {
float delta = right - get_right(); float delta = right - this->right();
if (!drag) if (!drag)
{ {
move({delta, 0}); move({delta, 0});
@ -141,17 +153,24 @@ void Box::set_right(float right, bool drag)
} }
} }
/* Drag the right side delta amount, leaving the left in the same position and altering the size of the box. The right
* side can be dragged past the left, in which case the current left will become the new right value. */
void Box::drag_right(float delta) void Box::drag_right(float delta)
{ {
float previous_right = get_right(); float new_location = right() + delta;
float new_right = get_right() + delta; width(std::abs(left() - new_location));
set_w(get_w() + new_right - previous_right); if (new_location < left())
set_right(new_right); {
left(new_location);
}
} }
void Box::set_bottom(float bottom, bool drag) /* Set the y coordinate of the bottom of the box. If drag is set, the other sides of the box will remain in the
* same position, and the bottom will be moved, altering the size of the box. Otherwise, the box will remain the
* same size, and the top location will change, moving the box but preserving the size. */
void Box::bottom(float bottom, bool drag)
{ {
float delta = bottom - get_bottom(); float delta = bottom - this->bottom();
if (!drag) if (!drag)
{ {
move({0, delta}); move({0, delta});
@ -162,180 +181,230 @@ void Box::set_bottom(float bottom, bool drag)
} }
} }
/* Drag the bottom delta amount, leaving the top in the same position and altering the size of the box. The bottom
* can be dragged past the top, in which case the current top will become the new bottom value. */
void Box::drag_bottom(float delta) void Box::drag_bottom(float delta)
{ {
float previous_bottom = get_bottom(); float new_location = bottom() + delta;
float new_bottom = get_bottom() + delta; height(std::abs(top() - new_location));
set_h(get_h() + new_bottom - previous_bottom); if (new_location < top())
set_bottom(new_bottom); {
top(new_location);
}
} }
void Box::set_left(float left, bool drag) /* Set the x coordinate of the left side of the box. If drag is set, the other sides of the box will remain in the
* same position, and the left will be moved, altering the size of the box. Otherwise, the box will remain the
* same size, and the right location will change, moving the box but preserving the size. */
void Box::left(float left, bool drag)
{ {
if (!drag) if (!drag)
{ {
set_x(left); x = left;
} }
else else
{ {
drag_left(left - get_left()); drag_left(left - this->left());
} }
} }
/* Drag the left side delta amount, leaving the right side in the same position and altering the size of the box.
* The left side can be dragged past the right, in which case the current right will become the new left value. */
void Box::drag_left(float delta) void Box::drag_left(float delta)
{ {
float previous_left = get_left(); float new_location = left() + delta;
set_left(get_left() + delta); if (new_location > right())
set_w(get_w() + previous_left - get_left());
}
void Box::set_center_x(float x)
{
move({x - get_center_x(), 0});
}
void Box::set_center_y(float y)
{
move({0, y - get_center_y()});
}
glm::vec2 Box::get_nw() const
{
return {get_x(), get_y()};
}
glm::vec2 Box::get_north() const
{
return glm::vec2(get_x() + get_w() / 2, get_y());
}
glm::vec2 Box::get_ne() const
{
return glm::vec2(get_right(), get_y());
}
glm::vec2 Box::get_east() const
{
return glm::vec2(get_right(), get_top() + get_h() / 2);
}
glm::vec2 Box::get_se() const
{
return glm::vec2(get_right(), get_bottom());
}
glm::vec2 Box::get_south() const
{
return glm::vec2(get_left() + get_w() / 2, get_bottom());
}
glm::vec2 Box::get_sw() const
{
return glm::vec2(get_left(), get_bottom());
}
glm::vec2 Box::get_west() const
{
return glm::vec2(get_x(), get_y() + get_h() / 2);
}
glm::vec2 Box::get_center() const
{
return glm::vec2(get_x() + get_w() / 2, get_y() + get_h() / 2);
}
void Box::set_nw(const glm::vec2& nw)
{
move(nw - get_nw());
}
void Box::set_north(const glm::vec2& n)
{
move(n - get_north());
}
void Box::set_ne(const glm::vec2& ne)
{
move(ne - get_ne());
}
void Box::set_east(const glm::vec2& e)
{
move(e - get_east());
}
void Box::set_se(const glm::vec2& se)
{
move(se - get_se());
}
void Box::set_south(const glm::vec2& s)
{
move(s - get_south());
}
void Box::set_sw(const glm::vec2& sw)
{
move(sw - get_sw());
}
void Box::set_west(const glm::vec2& w)
{
move(w - get_west());
}
void Box::set_center(const glm::vec2& center)
{
move(center - get_center());
}
Box::operator SDL_Rect() const
{
return {static_cast<int>(get_x()), static_cast<int>(get_y()), static_cast<int>(get_w()), static_cast<int>(get_h())};
}
void Box::clear()
{
set_nw(glm::vec2(0, 0));
set_size(glm::vec2(0, 0));
}
void Box::scale(glm::vec2 delta, bool preserve_center)
{
glm::vec2 center = get_center();
set_size(get_size() * delta);
if (preserve_center)
{ {
set_center(center); left(right());
width(new_location - left());
}
else
{
width(right() - new_location);
left(new_location);
} }
} }
/* Set the center x component */
void Box::cx(float x)
{
move({x - cx(), 0.0f});
}
/* Set the center y component */
void Box::cy(float y)
{
move({0.0f, y - cy()});
}
/* Return the coordinates of the top left corner */
glm::vec2 Box::nw() const
{
return {left(), top()};
}
/* Return the coordinates of the center of the top edge */
glm::vec2 Box::north() const
{
return glm::vec2(left() + width() / 2.0f, top());
}
/* Return the coordinates of the top right corner */
glm::vec2 Box::ne() const
{
return glm::vec2(right(), top());
}
/* Return the coordinates of the center of the right edge */
glm::vec2 Box::east() const
{
return glm::vec2(right(), top() + height() / 2.0f);
}
/* Return the coordinates of the bottom right corner */
glm::vec2 Box::se() const
{
return glm::vec2(right(), bottom());
}
/* Return the coordinates of the center of the bottom edge */
glm::vec2 Box::south() const
{
return glm::vec2(left() + width() / 2, bottom());
}
/* Return the coordinates of the bottom left edge */
glm::vec2 Box::sw() const
{
return glm::vec2(left(), bottom());
}
/* Return the coordinates of the center of the left edge */
glm::vec2 Box::west() const
{
return glm::vec2(left(), top() + height() / 2);
}
/* Return the center coordinates */
glm::vec2 Box::center() const
{
return glm::vec2(left() + width() / 2, top() + height() / 2);
}
/* Move the box by specifying the top left corner coordinates */
void Box::nw(const glm::vec2& nw)
{
move(nw - this->nw());
}
/* Move the box by specifying the center of the top edge */
void Box::north(const glm::vec2& north)
{
move(north - this->north());
}
/* Move the box by specifying the top right corner coordinates */
void Box::ne(const glm::vec2& ne)
{
move(ne - this->ne());
}
/* Move the box by specifying the center of the right edge */
void Box::east(const glm::vec2& east)
{
move(east - this->east());
}
/* Move the box by specifying the bottom right corner coordinates */
void Box::se(const glm::vec2& se)
{
move(se - this->se());
}
/* Move the box by specifying the center of the bottom edge */
void Box::south(const glm::vec2& south)
{
move(south - this->south());
}
/* Move the box by specifying the bottom left corner coordinates */
void Box::sw(const glm::vec2& sw)
{
move(sw - this->sw());
}
/* Move the box by specifying the center of the left edge */
void Box::west(const glm::vec2& west)
{
move(west - this->west());
}
/* Move the box by specifying the center coordinates */
void Box::center(const glm::vec2& center)
{
move(center - this->center());
}
/* Called when a Box instance is converted into an SDL_Rect. Allows passing Box to SDL functions that
* expect an SDL_Rect instead of an SDL_FRect */
Box::operator SDL_Rect() const
{
return {static_cast<int>(left()), static_cast<int>(top()), static_cast<int>(width()), static_cast<int>(height())};
}
/* Zero out the values of the box coordinates and size */
void Box::clear()
{
nw(glm::vec2(0, 0));
size(glm::vec2(0, 0));
}
/* Scale the box by multiplying size by {delta.x, delta.y}. If preserve center is set, the box will be scaled
* around the center, otherwise the top left corner will remain in place. */
void Box::scale(glm::vec2 delta, bool preserve_center)
{
glm::vec2 center = this->center();
size(this->size() * delta);
if (preserve_center)
{
this->center(center);
}
}
/* Scale the box by multiplying both width and height by delta. If preserve center is set, the box will be scaled
* around the center, otherwise the top left corner will remain in place. */
void Box::scale(float delta, bool preserve_center) void Box::scale(float delta, bool preserve_center)
{ {
scale({delta, delta}, preserve_center); scale({delta, delta}, preserve_center);
} }
/* Expand (or shrink by passing negative values) the box size by adding delta to the current size. If preserve center
* is set, the box will expand around the center, otherwise the top left corner will remain in place. */
void Box::expand(glm::vec2 delta, bool preserve_center) void Box::expand(glm::vec2 delta, bool preserve_center)
{ {
glm::vec2 center = get_center(); glm::vec2 center = this->center();
set_size(get_size() + delta); size(size() + delta);
if (preserve_center) if (preserve_center)
{ {
set_center(center); this->center(center);
} }
} }
/* Expand (or shrink by passing negative values) the box size by adding delta to both width and height. If preserve
* center is set, the box will expand around the center, otherwise the top left corner will remain in place. */
void Box::expand(float delta, bool preserve_center) void Box::expand(float delta, bool preserve_center)
{ {
expand({delta, delta}, preserve_center); expand({delta, delta}, preserve_center);
} }
/* Move the box in the x and y plane by delta amount */
void Box::move(const glm::vec2& delta) void Box::move(const glm::vec2& delta)
{ {
set_x(get_x() + delta.x); left(left() + delta.x);
set_y(get_y() + delta.y); top(top() + delta.y);
} }
/* Return a copy of the original box, moved by delta amount in the x and y plane */
Box Box::stamp(const glm::vec2& delta) const Box Box::stamp(const glm::vec2& delta) const
{ {
Box clone = *this; Box clone = *this;
@ -343,45 +412,69 @@ Box Box::stamp(const glm::vec2& delta) const
return clone; return clone;
} }
/* Returns true if box fits completely inside container, false otherwise. Includes the sides
* of the box, so if the sides are equal, it is considered inside. */
bool Box::fits(const Box& container) const bool Box::fits(const Box& container) const
{ {
return !(get_top() < container.get_top() || get_right() > container.get_right() || return !(top() < container.top() || right() > container.right() ||
get_bottom() > container.get_bottom() || get_left() < container.get_left()); bottom() > container.bottom() || left() < container.left());
} }
/* Removes any part of the box that is not inside the passed crop area box */
void Box::crop(const Box& area) void Box::crop(const Box& area)
{ {
if (get_top() < area.get_top()) if (top() < area.top())
{ {
set_top(area.get_top(), true); top(area.top(), true);
} }
if (get_right() > area.get_right()) if (right() > area.right())
{ {
set_right(area.get_right(), true); right(area.right(), true);
} }
if (get_bottom() > area.get_bottom()) if (bottom() > area.bottom())
{ {
set_bottom(area.get_bottom(), true); bottom(area.bottom(), true);
} }
if (get_left() < area.get_left()) if (left() < area.left())
{ {
set_left(area.get_left(), true); left(area.left(), true);
} }
} }
/* Returns true if point is inside the box, false otherwise. Includes the edges, so points equal to the edges
* will return true. */
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 >= left() && point.x <= right() && point.y >= top() && point.y <= bottom();
} }
/* Returns true if the line segment intersects the box, false otherwise. If intersection is passed and there is a
* collision, intersection will be filled with the coordinates of the first intersection found unless the segment
* is fully within the box not touching any edges. */
bool Box::collide(const Segment& segment, glm::vec2* intersection) const bool Box::collide(const Segment& segment, glm::vec2* intersection) const
{ {
if (collide(segment.get_box())) /* do the faster check of whether the square represented by the segment diagonal collides to determine
* if we should look more closely */
if (collide(segment.box()))
{ {
return segment.intersect({get_nw(), get_ne()}, intersection) || /* check if segment intersects any edges, storing the intersection point if so */
segment.intersect({get_ne(), get_se()}, intersection) || if (segment.intersect({nw(), ne()}, intersection) ||
segment.intersect({get_sw(), get_se()}, intersection) || segment.intersect({ne(), se()}, intersection) ||
segment.intersect({get_nw(), get_sw()}, intersection); segment.intersect({sw(), se()}, intersection) ||
segment.intersect({nw(), sw()}, intersection))
{
return true;
}
/* check if segment is fully inside the box */
else if (collide(segment.start()) && collide(segment.end()))
{
return true;
}
/* otherwise, segment must be outside the box even though its box has collided */
else
{
return false;
}
} }
else else
{ {
@ -389,42 +482,58 @@ bool Box::collide(const Segment& segment, glm::vec2* intersection) const
} }
} }
/* Do segment collision with intersection specified by reference rather than pointer */
bool Box::collide(const Segment& segment, glm::vec2& intersection) const bool Box::collide(const Segment& segment, glm::vec2& intersection) const
{ {
return collide(segment, &intersection); return collide(segment, &intersection);
} }
/* Return true if box collides with the passed box, false otherwise. If overlap is passed, it is set to
* the box representing the area where the two boxes overlap. */
bool Box::collide(const Box& box, Box* overlap) const bool Box::collide(const Box& box, Box* overlap) const
{ {
float top = std::max(get_top(), box.get_top()); float top = std::max(this->top(), box.top());
float right = std::min(get_right(), box.get_right()); float right = std::min(this->right(), box.right());
float bottom = std::min(get_bottom(), box.get_bottom()); float bottom = std::min(this->bottom(), box.bottom());
float left = std::max(get_left(), box.get_left()); float left = std::max(this->left(), box.left());
float w = right - left; float w = right - left;
float h = bottom - top; float h = bottom - top;
bool collide = w > 0 && h > 0; bool collide = w > 0 && h > 0;
if (collide && overlap != NULL) if (collide && overlap != nullptr)
{ {
overlap->set_x(left); overlap->left(left);
overlap->set_y(top); overlap->top(top);
overlap->set_w(w); overlap->width(w);
overlap->set_h(h); overlap->height(h);
} }
return collide; return collide;
} }
/* Do a box to box collision test with overlap passed by reference instead of pointer */
bool Box::collide(const Box& box, Box& overlap) const bool Box::collide(const Box& box, Box& overlap) const
{ {
return collide(box, &overlap); return collide(box, &overlap);
} }
std::ostream& Box::to_string (std::ostream& out) const /* Map any point in the bounds of a square with x and y between [-, radius] to a circle with specified radius. If
* center is specified, both the square and circle are centered at specified point. The default radius is 1, and the
* default center is (0, 0). Formula taken from http://squircular.blogspot.com/2015/09/mapping-circle-to-square.html */
glm::vec2 Box::map_point_to_circle(const glm::vec2& point, float radius, const glm::vec2& center) const
{ {
out << "{(" << get_x() << ", " << get_y() << "), (" << get_w() << ", " << get_h() << ")}";
return out;
} }
/* Return the string representation of a Box "{left, top, width, height}" */
std::string Box::string() const
{
std::stringstream output;
output << "{(" << left() << ", " << top() << "), (" << width() << ", " << height() << ")}";
return output.str();
}
/* Feed a string representation of the box to the passed ostream */
std::ostream& operator<< (std::ostream& out, const Box& box) std::ostream& operator<< (std::ostream& out, const Box& box)
{ {
return box.to_string(out); out << box.string();
return out;
} }

View File

@ -3,6 +3,7 @@
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
#include <stdexcept>
#include "SDL.h" #include "SDL.h"
@ -19,52 +20,48 @@ public:
Box(const glm::vec2& = {0, 0}, const glm::vec2& = {0, 0}); Box(const glm::vec2& = {0, 0}, const glm::vec2& = {0, 0});
Box(const SDL_Rect&); Box(const SDL_Rect&);
float get_x() const; float width() const;
float get_y() const; void width(float);
float get_w() const; float height() const;
float get_h() const; void height(float);
void set_x(float); glm::vec2 size() const;
void set_y(float); void size(const glm::vec2&, bool = false);
void set_w(float);
void set_h(float);
glm::vec2 get_size() const;
void set_size(const glm::vec2&, bool = false);
float aspect() const; float aspect() const;
float get_area() const; float area() const;
float get_top() const; float top() const;
float get_right() const; float right() const;
float get_bottom() const; float bottom() const;
float get_left() const; float left() const;
float get_center_x() const; float cx() const;
float get_center_y() const; float cy() const;
void set_top(float, bool=false); void top(float, bool = false);
void drag_top(float); void drag_top(float);
void set_right(float, bool=false); void right(float, bool = false);
void drag_right(float); void drag_right(float);
void set_bottom(float, bool=false); void bottom(float, bool = false);
void drag_bottom(float); void drag_bottom(float);
void set_left(float, bool=false); void left(float, bool = false);
void drag_left(float); void drag_left(float);
void set_center_x(float); void cx(float);
void set_center_y(float); void cy(float);
glm::vec2 get_nw() const; glm::vec2 nw() const;
glm::vec2 get_north() const; glm::vec2 north() const;
glm::vec2 get_ne() const; glm::vec2 ne() const;
glm::vec2 get_east() const; glm::vec2 east() const;
glm::vec2 get_se() const; glm::vec2 se() const;
glm::vec2 get_south() const; glm::vec2 south() const;
glm::vec2 get_sw() const; glm::vec2 sw() const;
glm::vec2 get_west() const; glm::vec2 west() const;
glm::vec2 get_center() const; glm::vec2 center() const;
void set_nw(const glm::vec2&); void nw(const glm::vec2&);
void set_north(const glm::vec2&); void north(const glm::vec2&);
void set_ne(const glm::vec2&); void ne(const glm::vec2&);
void set_east(const glm::vec2&); void east(const glm::vec2&);
void set_se(const glm::vec2&); void se(const glm::vec2&);
void set_south(const glm::vec2&); void south(const glm::vec2&);
void set_sw(const glm::vec2&); void sw(const glm::vec2&);
void set_west(const glm::vec2&); void west(const glm::vec2&);
void set_center(const glm::vec2&); void center(const glm::vec2&);
operator SDL_Rect() const; operator SDL_Rect() const;
void clear(); void clear();
void scale(glm::vec2, bool = false); void scale(glm::vec2, bool = false);
@ -80,8 +77,9 @@ public:
bool collide(const Segment&, glm::vec2&) const; bool collide(const Segment&, glm::vec2&) const;
bool collide(const Box&, Box* = nullptr) const; bool collide(const Box&, Box* = nullptr) const;
bool collide(const Box&, Box&) const; bool collide(const Box&, Box&) const;
virtual std::string get_class_name() const { return "Box"; } glm::vec2 map_point_to_circle(const glm::vec2&, float, const glm::vec2&) const;
std::ostream& to_string (std::ostream&) const; virtual std::string class_name() const { return "Box"; }
std::string string() const;
}; };

View File

@ -20,7 +20,7 @@ struct Configuration : Node
void merge(); void merge();
void write(); void write();
void write(fs::path path); void write(fs::path path);
virtual std::string get_class_name() const { return "Configuration"; } virtual std::string class_name() const { return "Configuration"; }
}; };

View File

@ -8,7 +8,7 @@ Display::Display(Node* parent) : Node(parent)
} }
/* Return the (x, y) size in pixels of the window as an integer vector */ /* Return the (x, y) size in pixels of the window as an integer vector */
glm::ivec2 Display::get_window_size() const glm::ivec2 Display::window_size() const
{ {
glm::ivec2 size; glm::ivec2 size;
SDL_GetWindowSize(const_cast<SDL_Window*>(get_window()), &size.x, &size.y); SDL_GetWindowSize(const_cast<SDL_Window*>(get_window()), &size.x, &size.y);
@ -16,13 +16,13 @@ glm::ivec2 Display::get_window_size() const
} }
/* Return the window dimensions as a Box object */ /* Return the window dimensions as a Box object */
Box Display::get_window_box() const Box Display::window_box() const
{ {
return Box(glm::vec2(0, 0), get_window_size()); return Box(glm::vec2(0, 0), window_size());
} }
/* Get the pixel format of display at specified index (defaults to index 0) */ /* Get the pixel format of display at specified index (defaults to index 0) */
Uint32 Display::get_pixel_format(int display_index) const Uint32 Display::pixel_format(int display_index) const
{ {
SDL_DisplayMode display_mode; SDL_DisplayMode display_mode;
if (SDL_GetCurrentDisplayMode(display_index, &display_mode) != 0) if (SDL_GetCurrentDisplayMode(display_index, &display_mode) != 0)
@ -38,7 +38,7 @@ Uint32 Display::get_pixel_format(int display_index) const
/* Fill the supplied, pre-allocated buffer with 32-bit pixels (8 bits per component) from the GL /* Fill the supplied, pre-allocated buffer with 32-bit pixels (8 bits per component) from the GL
* read buffer if in GL context or from the SDL renderer if in SDL context */ * read buffer if in GL context or from the SDL renderer if in SDL context */
void Display::get_screen_pixels(unsigned char* pixels, int w, int h, int x, int y) const void Display::screen_pixels(unsigned char* pixels, int w, int h, int x, int y) const
{ {
if (get_root()->is_gl_context) if (get_root()->is_gl_context)
{ {
@ -65,19 +65,19 @@ void Display::get_screen_pixels(unsigned char* pixels, int w, int h, int x, int
} }
} }
SDL_Surface* Display::get_screen_surface() const SDL_Surface* Display::screen_surface() const
{ {
glm::ivec2 size = get_window_size(); glm::ivec2 size = window_size();
unsigned char* pixels = new unsigned char[bpp / 8 * size.x * size.y]; unsigned char* pixels = new unsigned char[bpp / 8 * size.x * size.y];
get_screen_pixels(pixels, size.x, size.y); screen_pixels(pixels, size.x, size.y);
SDL_Surface* surface = get_screen_surface_from_pixels(pixels, get_root()->is_gl_context); SDL_Surface* surface = screen_surface_from_pixels(pixels, get_root()->is_gl_context);
delete[] pixels; delete[] pixels;
return surface; return surface;
} }
SDL_Surface* Display::get_screen_surface_from_pixels(unsigned char* pixels, bool flip) const SDL_Surface* Display::screen_surface_from_pixels(unsigned char* pixels, bool flip) const
{ {
glm::ivec2 size = get_window_size(); glm::ivec2 size = window_size();
SDL_Surface* surface; SDL_Surface* surface;
Uint32 rmask, gmask, bmask, amask; Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN #if SDL_BYTEORDER == SDL_BIG_ENDIAN

View File

@ -13,18 +13,20 @@
#include "Node.hpp" #include "Node.hpp"
#include "Box.hpp" #include "Box.hpp"
struct Display : Node class Display : public Node
{ {
public:
const static int bpp = 32; const static int bpp = 32;
Display(Node*); Display(Node*);
glm::ivec2 get_window_size() const; glm::ivec2 window_size() const;
Uint32 get_pixel_format(int = 0) const; Uint32 pixel_format(int = 0) const;
Box get_window_box() const; Box window_box() const;
void get_screen_pixels(unsigned char*, int, int, int = 0, int = 0) const; void screen_pixels(unsigned char*, int, int, int = 0, int = 0) const;
SDL_Surface* get_screen_surface() const; SDL_Surface* screen_surface() const;
SDL_Surface* get_screen_surface_from_pixels(unsigned char*, bool) const; SDL_Surface* screen_surface_from_pixels(unsigned char*, bool) const;
void respond(SDL_Event&); void respond(SDL_Event&);
void toggle_fullscreen() const; void toggle_fullscreen() const;

View File

@ -35,7 +35,7 @@ void FramerateIndicator::refresh()
SDL_Texture* texture = SDL_CreateTextureFromSurface(get_root()->get_renderer(), surface); SDL_Texture* texture = SDL_CreateTextureFromSurface(get_root()->get_renderer(), surface);
add_frames(texture); add_frames(texture);
SDL_FreeSurface(surface); SDL_FreeSurface(surface);
set_ne(get_display().get_window_box().get_ne()); set_ne(get_display().window_box().ne());
} }
} }

View File

@ -112,7 +112,7 @@ public:
float get_frame_length() const; float get_frame_length() const;
void handle_quit_event(SDL_Event&); void handle_quit_event(SDL_Event&);
void quit(); void quit();
virtual std::string get_class_name() const { return "Game"; } virtual std::string class_name() const { return "Game"; }
~Game(); ~Game();
/* Applies delta timing to a value: returns the value as weighted by the amount of time passed since the /* Applies delta timing to a value: returns the value as weighted by the amount of time passed since the

View File

@ -60,7 +60,7 @@ struct Input : Node
void suppress(); void suppress();
void unsuppress(); void unsuppress();
bool is_suppressed(); bool is_suppressed();
virtual std::string get_class_name() const { return "Input"; } virtual std::string class_name() const { return "Input"; }
}; };

View File

@ -99,9 +99,9 @@ const Game* Node::get_root() const
return dynamic_cast<const Game*>(r); return dynamic_cast<const Game*>(r);
} }
Box Node::get_window_box() Box Node::window_box()
{ {
return get_display().get_window_box(); return get_display().window_box();
} }
void Node::suppress_input() void Node::suppress_input()
@ -140,7 +140,7 @@ const std::string Node::get_branch_as_string() const
std::stringstream branch; std::stringstream branch;
while (current != nullptr) while (current != nullptr)
{ {
branch << current->get_class_name() << " @ " << current; branch << current->class_name() << " @ " << current;
if (current->parent != nullptr) if (current->parent != nullptr)
{ {
branch << " -> "; branch << " -> ";

View File

@ -12,7 +12,7 @@
class Game; class Game;
struct Delegate; struct Delegate;
struct Display; class Display;
struct Input; struct Input;
class Box; class Box;
struct Audio; struct Audio;
@ -43,14 +43,14 @@ public:
Input& get_input(); Input& get_input();
Audio& get_audio(); Audio& get_audio();
const Game* get_root() const; const Game* get_root() const;
Box get_window_box(); Box window_box();
void suppress_input(); void suppress_input();
void suppress_input_temporarily(int = 0); void suppress_input_temporarily(int = 0);
void unsuppress_input(); void unsuppress_input();
void log(const std::string&) const; void log(const std::string&) const;
void debug(const std::string&) const; void debug(const std::string&) const;
const std::string get_branch_as_string() const; const std::string get_branch_as_string() const;
virtual std::string get_class_name() const { return "Node"; }; virtual std::string class_name() const { return "Node"; };
virtual ~Node(); virtual ~Node();
template<typename T = Game> template<typename T = Game>

View File

@ -63,7 +63,7 @@ void Recorder::respond(SDL_Event& event)
void Recorder::capture_screen() void Recorder::capture_screen()
{ {
nlohmann::json config = get_configuration(); nlohmann::json config = get_configuration();
SDL_Surface* surface = get_display().get_screen_surface(); SDL_Surface* surface = get_display().screen_surface();
fs::path directory = config["recording"]["screenshot-directory"]; fs::path directory = config["recording"]["screenshot-directory"];
fs::create_directories(directory); fs::create_directories(directory);
std::string prefix = config["recording"]["screenshot-prefix"].get<std::string>(); std::string prefix = config["recording"]["screenshot-prefix"].get<std::string>();
@ -147,10 +147,10 @@ void Recorder::open_audio_file()
void Recorder::add_frame() void Recorder::add_frame()
{ {
glm::ivec2 size = get_display().get_window_size(); glm::ivec2 size = get_display().window_size();
int bytes = Display::bpp / 8 * size.x * size.y; int bytes = Display::bpp / 8 * size.x * size.y;
unsigned char* pixels = new unsigned char[bytes]; unsigned char* pixels = new unsigned char[bytes];
get_display().get_screen_pixels(pixels, size.x, size.y); get_display().screen_pixels(pixels, size.x, size.y);
int max_length = get_configuration()["recording"]["max-stash-length"]; int max_length = get_configuration()["recording"]["max-stash-length"];
float length = frame_length() * current_stash.pixel_buffers.size(); float length = frame_length() * current_stash.pixel_buffers.size();
if (length > max_length) if (length > max_length)
@ -177,7 +177,7 @@ void Recorder::add_frame()
// std::vector<bool> flipped = video_stashes.back().flipped; // std::vector<bool> flipped = video_stashes.back().flipped;
// for (int ii = frame_offset; ii < pixel_buffers.size() + frame_offset; ii++) // for (int ii = frame_offset; ii < pixel_buffers.size() + frame_offset; ii++)
// { // {
// SDL_Surface* frame = get_display().get_screen_surface_from_pixels( // SDL_Surface* frame = get_display().screen_surface_from_pixels(
// pixel_buffers[ii - frame_offset], flipped[ii - frame_offset]); // pixel_buffers[ii - frame_offset], flipped[ii - frame_offset]);
// std::stringstream name; // std::stringstream name;
// name << sfw::pad(ii, 5) << ".png"; // name << sfw::pad(ii, 5) << ".png";
@ -199,7 +199,7 @@ void Recorder::add_frame()
int Recorder::get_memory_size() int Recorder::get_memory_size()
{ {
glm::ivec2 window = get_display().get_window_size(); glm::ivec2 window = get_display().window_size();
int bytes_per_frame = Display::bpp / 8 * window.x * window.y, int bytes_per_frame = Display::bpp / 8 * window.x * window.y,
size_in_bytes = 0; size_in_bytes = 0;
for (Stash& stash : in_game_stashes) for (Stash& stash : in_game_stashes)
@ -248,7 +248,7 @@ void Recorder::write_stash_frames(Stash* stash)
float elapsed = 0, last_gif_write = 0, gif_write_overflow = 0; float elapsed = 0, last_gif_write = 0, gif_write_overflow = 0;
for (int ii = stash->frame_offset; not stash->pixel_buffers.empty(); ii++) for (int ii = stash->frame_offset; not stash->pixel_buffers.empty(); ii++)
{ {
frame = get_display().get_screen_surface_from_pixels( frame = get_display().screen_surface_from_pixels(
stash->pixel_buffers.front(), stash->flipped.front()); stash->pixel_buffers.front(), stash->flipped.front());
std::stringstream name; std::stringstream name;
name << sfw::pad(ii, 5) << ".png"; name << sfw::pad(ii, 5) << ".png";
@ -339,7 +339,7 @@ void Recorder::finish_writing_video()
* This requires ffmpeg to be installed on the user's system. Might only work on Linux (?) */ * This requires ffmpeg to be installed on the user's system. Might only work on Linux (?) */
void Recorder::write_mp4() void Recorder::write_mp4()
{ {
glm::ivec2 size = get_display().get_window_size(); glm::ivec2 size = get_display().window_size();
std::ostringstream mp4_command; std::ostringstream mp4_command;
std::string pixel_format = get_configuration()["recording"]["mp4-pixel-format"].get<std::string>(); std::string pixel_format = get_configuration()["recording"]["mp4-pixel-format"].get<std::string>();
fs::path images_match = current_video_directory / "%05d.png"; fs::path images_match = current_video_directory / "%05d.png";

View File

@ -68,7 +68,7 @@ public:
void write_mp4(); void write_mp4();
void write_audio(Uint8*, int); void write_audio(Uint8*, int);
void update(); void update();
virtual std::string get_class_name() const { return "Recorder"; } virtual std::string class_name() const { return "Recorder"; }
}; };

View File

@ -3,39 +3,43 @@
#include "Box.hpp" #include "Box.hpp"
#include "Segment.hpp" #include "Segment.hpp"
Segment::Segment(const glm::vec2& start, const glm::vec2& end) : start(start), end(end) {}; Segment::Segment(const glm::vec2& start, const glm::vec2& end)
{
this->start(start);
this->end(end);
}
Segment::Segment() : Segment({0, 0}, {0, 0}) {}; Segment::Segment() : Segment({0, 0}, {0, 0}) {};
Segment::Segment(const glm::vec2& location) : Segment(location, location) {}; Segment::Segment(const glm::vec2& location) : Segment(location, location) {};
Segment::Segment(const Box& start, const Box& end) : Segment(start.get_center(), end.get_center()) {}; Segment::Segment(const Box& start, const Box& end) : Segment(start.center(), end.center()) {};
glm::vec2 Segment::get_start() const inline glm::vec2 Segment::start() const
{ {
return start; return start_;
} }
void Segment::set_start(const glm::vec2& s) void Segment::start(const glm::vec2& start)
{ {
start = s; start_ = start;
} }
glm::vec2 Segment::get_end() const glm::vec2 Segment::end() const
{ {
return end; return end_;
} }
void Segment::set_end(const glm::vec2& e) void Segment::end(const glm::vec2& end)
{ {
end = e; end_ = end;
} }
// taken from http://www.realtimerendering.com/resources/GraphicsGems/gemsii/xlines.c // taken from http://www.realtimerendering.com/resources/GraphicsGems/gemsii/xlines.c
bool Segment::intersect(const Segment& segment, glm::vec2* intersection) const bool Segment::intersect(const Segment& segment, glm::vec2* intersection) const
{ {
float x1 = start.x, y1 = start.y, x2 = end.x, y2 = end.y, x3 = segment.start.x, 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; y3 = segment.start_.y, x4 = segment.end_.x, y4 = segment.end_.y;
float a1, a2, b1, b2, c1, c2; // Coefficients of line eqns. float a1, a2, b1, b2, c1, c2; // Coefficients of line eqns.
float r1, r2, r3, r4; // 'Sign' values float r1, r2, r3, r4; // 'Sign' values
@ -99,58 +103,58 @@ bool Segment::intersect(const Segment& segment, glm::vec2& intersection) const
return intersect(segment, &intersection); return intersect(segment, &intersection);
} }
float Segment::get_dx() const float Segment::dx() const
{ {
return end.x - start.x; return end_.x - start_.x;
} }
float Segment::get_dy() const float Segment::dy() const
{ {
return end.y - start.y; return end_.y - start_.y;
} }
float Segment::get_length() const float Segment::length() const
{ {
return glm::distance(start, end); return glm::distance(start_, end_);
} }
Box Segment::get_box() const Box Segment::box() const
{ {
float x = std::min(start.x, end.x); float x = std::min(start_.x, end_.x);
float y = std::min(start.y, end.y); float y = std::min(start_.y, end_.y);
float w = std::abs(get_dx()); float w = std::abs(dx());
float h = std::abs(get_dy()); float h = std::abs(dy());
return Box({x, y}, {w, h}); return Box({x, y}, {w, h});
} }
void Segment::move(const glm::vec2& delta) void Segment::move(const glm::vec2& delta)
{ {
start += delta; start_ += delta;
end += delta; end_ += delta;
} }
glm::vec2 Segment::get_center() const glm::vec2 Segment::center() const
{ {
return get_subsegments(2)[0].end; return subsegments(2)[0].end_;
} }
glm::vec2 Segment::get_step(float speed) const glm::vec2 Segment::step(float speed) const
{ {
float angle = glm::atan(end.x - start.x, end.y - start.y); float angle = glm::atan(end_.x - start_.x, end_.y - start_.y);
return glm::vec2(speed * glm::sin(angle), speed * glm::cos(angle)); return glm::vec2(speed * glm::sin(angle), speed * glm::cos(angle));
} }
glm::vec2 Segment::get_step_relative(float relative_length_per_step) const glm::vec2 Segment::step_relative(float relative_length_per_step) const
{ {
return get_step(glm::distance(start, end) * relative_length_per_step); return step(glm::distance(start_, end_) * relative_length_per_step);
} }
std::vector<Segment> Segment::get_subsegments(int count) const std::vector<Segment> Segment::subsegments(int count) const
{ {
glm::vec2 step = get_step_relative(1.0f / count); glm::vec2 step = step_relative(1.0f / count);
std::vector<Segment> subsegments; std::vector<Segment> subsegments;
subsegments.reserve(count); subsegments.reserve(count);
glm::vec2 subsegment_start = start, subsegment_end; glm::vec2 subsegment_start = start_, subsegment_end;
for (int ii = 0; ii < count; ii++) for (int ii = 0; ii < count; ii++)
{ {
subsegment_end = subsegment_start + step; subsegment_end = subsegment_start + step;
@ -162,7 +166,7 @@ std::vector<Segment> Segment::get_subsegments(int count) const
std::ostream& operator<<(std::ostream& out, const Segment& segment) std::ostream& operator<<(std::ostream& out, const Segment& segment)
{ {
out << "{(" << segment.start.x << ", " << segment.start.y << "), (" << out << "{(" << segment.start().x << ", " << segment.start().y << "), (" <<
segment.end.x << ", " << segment.end.y << ")}"; segment.end().x << ", " << segment.end().y << ")}";
return out; return out;
} }

View File

@ -13,31 +13,33 @@ struct Sprite;
class Segment class Segment
{ {
private:
glm::vec2 start_, end_;
public: public:
glm::vec2 start, end;
Segment(const glm::vec2&, const glm::vec2&); Segment(const glm::vec2&, const glm::vec2&);
Segment(); Segment();
Segment(const glm::vec2&); Segment(const glm::vec2&);
Segment(const Box&, const Box&); Segment(const Box&, const Box&);
Segment(const Sprite&, const Sprite&); Segment(const Sprite&, const Sprite&);
glm::vec2 get_start() const; inline glm::vec2 start() const;
void set_start(const glm::vec2&); void start(const glm::vec2&);
glm::vec2 get_end() const; glm::vec2 end() const;
void set_end(const glm::vec2&); void end(const glm::vec2&);
bool intersect(const Segment&, glm::vec2* = nullptr) const; bool intersect(const Segment&, glm::vec2* = nullptr) const;
bool intersect(const Segment&, glm::vec2&) const; bool intersect(const Segment&, glm::vec2&) const;
float get_dx() const; float dx() const;
float get_dy() const; float dy() const;
float get_length() const; float length() const;
Box get_box() const; Box box() const;
void move(const glm::vec2&); void move(const glm::vec2&);
glm::vec2 get_center() const; glm::vec2 center() const;
glm::vec2 get_step(float) const; glm::vec2 step(float) const;
glm::vec2 get_step_relative(float) const; glm::vec2 step_relative(float) const;
std::vector<Segment> get_subsegments(int) const; std::vector<Segment> subsegments(int) const;
inline bool operator<(const Segment& segment) const { return operator<(segment.get_length()); } inline bool operator<(const Segment& segment) const { return operator<(segment.length()); }
/* /*
std::cout << (a < b) << (a > b) << (b < c) << (b <= c) << (c > b) << (c >= b) << (d < 1) << (d < 2) << std::cout << (a < b) << (a > b) << (b < c) << (b <= c) << (c > b) << (c >= b) << (d < 1) << (d < 2) <<
@ -47,10 +49,10 @@ public:
*/ */
template<typename N> template<typename N>
inline bool operator<(const N& other) const { return get_length() < other; } inline bool operator<(const N& other) const { return length() < other; }
template<typename N> template<typename N>
inline bool operator>(const N& other) const { return other < get_length(); } inline bool operator>(const N& other) const { return other < length(); }
template<typename N> template<typename N>
inline bool operator<=(const N& other) const { return !operator>(other); } inline bool operator<=(const N& other) const { return !operator>(other); }

View File

@ -197,7 +197,7 @@ void Sprite::update_size(bool preserve_center)
{ {
for (std::size_t ii = 0; ii < boxes.size(); ii++) for (std::size_t ii = 0; ii < boxes.size(); ii++)
{ {
boxes[ii].set_size(get_current_frameset().get_size(), preserve_center); boxes[ii].size(get_current_frameset().get_size(), preserve_center);
if (scale != 1) if (scale != 1)
{ {
boxes[ii].scale(scale, preserve_center); boxes[ii].scale(scale, preserve_center);
@ -307,92 +307,92 @@ const SDL_Color& Sprite::get_color_mod() const
float Sprite::get_w() const float Sprite::get_w() const
{ {
return get_box().get_w(); return get_box().width();
} }
float Sprite::get_h() const float Sprite::get_h() const
{ {
return get_box().get_h(); return get_box().height();
} }
glm::vec2 Sprite::get_size() const glm::vec2 Sprite::get_size() const
{ {
return get_box().get_size(); return get_box().size();
} }
float Sprite::get_top(int index) const float Sprite::get_top(int index) const
{ {
return get_box(index).get_top(); return get_box(index).top();
} }
float Sprite::get_right(int index) const float Sprite::get_right(int index) const
{ {
return get_box(index).get_right(); return get_box(index).right();
} }
float Sprite::get_bottom(int index) const float Sprite::get_bottom(int index) const
{ {
return get_box(index).get_bottom(); return get_box(index).bottom();
} }
float Sprite::get_left(int index) const float Sprite::get_left(int index) const
{ {
return get_box(index).get_left(); return get_box(index).left();
} }
float Sprite::get_center_x(int index) const float Sprite::get_center_x(int index) const
{ {
return get_box(index).get_center_x(); return get_box(index).cx();
} }
float Sprite::get_center_y(int index) const float Sprite::get_center_y(int index) const
{ {
return get_box(index).get_center_y(); return get_box(index).cy();
} }
glm::vec2 Sprite::get_nw(int index) const glm::vec2 Sprite::get_nw(int index) const
{ {
return get_box(index).get_nw(); return get_box(index).nw();
} }
glm::vec2 Sprite::get_north(int index) const glm::vec2 Sprite::get_north(int index) const
{ {
return get_box(index).get_north(); return get_box(index).north();
} }
glm::vec2 Sprite::get_ne(int index) const glm::vec2 Sprite::get_ne(int index) const
{ {
return get_box(index).get_ne(); return get_box(index).ne();
} }
glm::vec2 Sprite::get_east(int index) const glm::vec2 Sprite::get_east(int index) const
{ {
return get_box(index).get_east(); return get_box(index).east();
} }
glm::vec2 Sprite::get_se(int index) const glm::vec2 Sprite::get_se(int index) const
{ {
return get_box(index).get_se(); return get_box(index).se();
} }
glm::vec2 Sprite::get_south(int index) const glm::vec2 Sprite::get_south(int index) const
{ {
return get_box(index).get_south(); return get_box(index).south();
} }
glm::vec2 Sprite::get_sw(int index) const glm::vec2 Sprite::get_sw(int index) const
{ {
return get_box(index).get_sw(); return get_box(index).sw();
} }
glm::vec2 Sprite::get_west(int index) const glm::vec2 Sprite::get_west(int index) const
{ {
return get_box(index).get_west(); return get_box(index).west();
} }
glm::vec2 Sprite::get_center(int index) const glm::vec2 Sprite::get_center(int index) const
{ {
return get_box(index).get_center(); return get_box(index).center();
} }
void Sprite::set_top(float top) void Sprite::set_top(float top)
@ -467,7 +467,7 @@ void Sprite::set_center(const glm::vec2& center)
void Sprite::add_wrap(bool x, bool y) void Sprite::add_wrap(bool x, bool y)
{ {
add_wrap(x, y, get_display().get_window_box()); add_wrap(x, y, get_display().window_box());
} }
void Sprite::add_wrap(bool x, bool y, Box frame) void Sprite::add_wrap(bool x, bool y, Box frame)
@ -478,15 +478,15 @@ void Sprite::add_wrap(bool x, bool y, Box frame)
{ {
if (x) if (x)
{ {
add_box({frame.get_w(), 0}); add_box({frame.width(), 0});
} }
if (y) if (y)
{ {
add_box({0, frame.get_h()}); add_box({0, frame.height()});
} }
if (x && y) if (x && y)
{ {
add_box({frame.get_w(), frame.get_h()}); add_box({frame.width(), frame.height()});
} }
} }
wrap_frame = frame; wrap_frame = frame;
@ -510,24 +510,24 @@ glm::vec2 Sprite::move(const glm::vec2& delta)
} }
if (wrap.x) if (wrap.x)
{ {
if (get_right() > wrap_frame.get_right()) if (get_right() > wrap_frame.right())
{ {
move({-wrap_frame.get_w(), 0}); move({-wrap_frame.width(), 0});
} }
else if (get_right() < wrap_frame.get_left()) else if (get_right() < wrap_frame.left())
{ {
move({wrap_frame.get_w(), 0}); move({wrap_frame.width(), 0});
} }
} }
if (wrap.y) if (wrap.y)
{ {
if (get_bottom() > wrap_frame.get_bottom()) if (get_bottom() > wrap_frame.bottom())
{ {
move({0, -wrap_frame.get_h()}); move({0, -wrap_frame.height()});
} }
else if (get_bottom() < wrap_frame.get_top()) else if (get_bottom() < wrap_frame.top())
{ {
move({0, wrap_frame.get_h()}); move({0, wrap_frame.height()});
} }
} }
return delta; return delta;
@ -626,7 +626,7 @@ bool Sprite::collide(const Box& box, bool precise, Box* overlap, bool all, SDL_T
else else
{ {
collision_check_frame = sfw::duplicate_texture( collision_check_frame = sfw::duplicate_texture(
const_cast<SDL_Renderer*>(get_renderer()), get_current_frame(), get_box(ii).get_size()); const_cast<SDL_Renderer*>(get_renderer()), get_current_frame(), get_box(ii).size());
} }
Pixels region_pixels = Pixels( Pixels region_pixels = Pixels(
const_cast<SDL_Renderer*>(get_renderer()), collision_check_frame, overlap->stamp(-get_nw(ii))); const_cast<SDL_Renderer*>(get_renderer()), collision_check_frame, overlap->stamp(-get_nw(ii)));
@ -647,7 +647,7 @@ bool Sprite::collide(const Box& box, bool precise, Box* overlap, bool all, SDL_T
else else
{ {
Pixels other_region_pixels = Pixels( Pixels other_region_pixels = Pixels(
const_cast<SDL_Renderer*>(get_renderer()), other_texture, overlap->stamp(-box.get_nw())); const_cast<SDL_Renderer*>(get_renderer()), other_texture, overlap->stamp(-box.nw()));
for (int x = 0; x < region_pixels.rect.w && x < other_region_pixels.rect.w; x++) for (int x = 0; x < region_pixels.rect.w && x < other_region_pixels.rect.w; x++)
{ {
for (int y = 0; y < region_pixels.rect.h && y < other_region_pixels.rect.h; y++) for (int y = 0; y < region_pixels.rect.h && y < other_region_pixels.rect.h; y++)
@ -711,7 +711,7 @@ bool Sprite::collide(const Sprite& sprite, bool precise, Box* overlap, bool all,
else else
{ {
other_sprite_collision_check_texture = sfw::duplicate_texture( other_sprite_collision_check_texture = sfw::duplicate_texture(
const_cast<SDL_Renderer*>(get_renderer()), sprite.get_current_frame(), sprite.get_box(ii).get_size()); const_cast<SDL_Renderer*>(get_renderer()), sprite.get_current_frame(), sprite.get_box(ii).size());
} }
} }
if (collide(sprite.get_box(ii), precise, overlap, all, other_sprite_collision_check_texture)) if (collide(sprite.get_box(ii), precise, overlap, all, other_sprite_collision_check_texture))
@ -914,17 +914,17 @@ void Sprite::update()
void Sprite::render_subsection(SDL_Renderer* renderer, SDL_Texture* texture, const Box& subsection, const Box& box) void Sprite::render_subsection(SDL_Renderer* renderer, SDL_Texture* texture, const Box& subsection, const Box& box)
{ {
bottom_save = std::round(subsection.get_bottom()); bottom_save = std::round(subsection.bottom());
subsection_int_rect = SDL_Rect(subsection); subsection_int_rect = SDL_Rect(subsection);
subsection_int_rect.y += bottom_save - (subsection_int_rect.y + subsection_int_rect.h); subsection_int_rect.y += bottom_save - (subsection_int_rect.y + subsection_int_rect.h);
subsection_destination = subsection_int_rect; subsection_destination = subsection_int_rect;
subsection_destination.x += box.get_left(); subsection_destination.x += box.left();
subsection_destination.y += box.get_top(); subsection_destination.y += box.top();
if (get_scale() != 1) if (get_scale() != 1)
{ {
unscaled_subsection = subsection; unscaled_subsection = subsection;
unscaled_subsection.set_nw(unscaled_subsection.get_nw() / get_scale()); unscaled_subsection.nw(unscaled_subsection.nw() / get_scale());
unscaled_subsection.set_size(unscaled_subsection.get_size() / get_scale()); unscaled_subsection.size(unscaled_subsection.size() / get_scale());
subsection_int_rect = unscaled_subsection; subsection_int_rect = unscaled_subsection;
} }
SDL_RenderCopy(renderer, texture, &subsection_int_rect, &subsection_destination); SDL_RenderCopy(renderer, texture, &subsection_int_rect, &subsection_destination);

View File

@ -143,7 +143,7 @@ struct Sprite : Node
void render_subsection(SDL_Renderer*, SDL_Texture*, const Box&, const Box&); void render_subsection(SDL_Renderer*, SDL_Texture*, const Box&, const Box&);
void set_to_leave_memory_allocated(); void set_to_leave_memory_allocated();
void set_to_deallocate_memory(); void set_to_deallocate_memory();
virtual std::string get_class_name() const { return "Sprite"; } virtual std::string class_name() const { return "Sprite"; }
~Sprite() { unload(); } ~Sprite() { unload(); }
}; };

View File

@ -73,14 +73,14 @@ std::vector<std::vector<Box>> sfw::get_blinds_boxes(glm::vec2 size, float step,
float inflate_per_frame = blind_height * step; float inflate_per_frame = blind_height * step;
std::vector<std::vector<Box>> frames; std::vector<std::vector<Box>> frames;
float bottom_save; float bottom_save;
while (blinds[0].get_h() < blind_height) while (blinds[0].height() < blind_height)
{ {
frames.push_back({}); frames.push_back({});
for (Box& blind : blinds) for (Box& blind : blinds)
{ {
bottom_save = blind.get_bottom(); bottom_save = blind.bottom();
blind.expand({0, inflate_per_frame}); blind.expand({0, inflate_per_frame});
blind.set_bottom(bottom_save); blind.bottom(bottom_save);
frames.back().push_back(blind); frames.back().push_back(blind);
} }
} }
@ -114,8 +114,8 @@ void sfw::populate_pixel_2d_array(
{ {
Uint32 format = SDL_PIXELFORMAT_RGBA32; Uint32 format = SDL_PIXELFORMAT_RGBA32;
int bytes_per_pixel = SDL_BYTESPERPIXEL(format); int bytes_per_pixel = SDL_BYTESPERPIXEL(format);
int bytes_per_row = bytes_per_pixel * region.get_w(); int bytes_per_row = bytes_per_pixel * region.width();
int bytes_total = bytes_per_row * region.get_h(); int bytes_total = bytes_per_row * region.height();
Uint8* source = new Uint8[bytes_total]; Uint8* source = new Uint8[bytes_total];
SDL_Rect int_rect = region; SDL_Rect int_rect = region;
if (SDL_RenderReadPixels(renderer, &int_rect, format, source, bytes_per_row) < 0) if (SDL_RenderReadPixels(renderer, &int_rect, format, source, bytes_per_row) < 0)
@ -124,16 +124,16 @@ void sfw::populate_pixel_2d_array(
} }
else else
{ {
pixels.reserve(region.get_w()); pixels.reserve(region.width());
for (int x = 0; x < region.get_w(); x++) for (int x = 0; x < region.width(); x++)
{ {
std::vector<SDL_Color> column; std::vector<SDL_Color> column;
pixels.push_back(column); pixels.push_back(column);
pixels[x].reserve(region.get_h()); pixels[x].reserve(region.height());
} }
for (int y = 0, ii = 0; y < region.get_h(); y++) for (int y = 0, ii = 0; y < region.height(); y++)
{ {
for (int x = 0; x < region.get_w(); x++) for (int x = 0; x < region.width(); x++)
{ {
pixels[x][y] = {source[ii++], source[ii++], source[ii++], source[ii++]}; pixels[x][y] = {source[ii++], source[ii++], source[ii++], source[ii++]};
} }
@ -236,11 +236,11 @@ void sfw::fill_texture(SDL_Renderer* renderer, SDL_Texture* texture, SDL_Texture
} }
else else
{ {
for (int x = 0; x < texture_box.get_w(); x += tile_box.get_w()) for (int x = 0; x < texture_box.width(); x += tile_box.width())
{ {
for (int y = 0; y < texture_box.get_h(); y += tile_box.get_h()) for (int y = 0; y < texture_box.height(); y += tile_box.height())
{ {
draw_rect = {(float) x, (float) y, tile_box.get_w(), tile_box.get_h()}; draw_rect = {(float) x, (float) y, tile_box.width(), tile_box.height()};
SDL_RenderCopyF(renderer, tile, nullptr, &draw_rect); SDL_RenderCopyF(renderer, tile, nullptr, &draw_rect);
} }
} }
@ -328,7 +328,7 @@ SDL_Texture* sfw::get_hue_shifted_texture(SDL_Renderer* renderer, SDL_Texture* b
SDL_Texture* sfw::duplicate_texture(SDL_Renderer* renderer, SDL_Texture* base) SDL_Texture* sfw::duplicate_texture(SDL_Renderer* renderer, SDL_Texture* base)
{ {
Box box = get_texture_box(base); Box box = get_texture_box(base);
return duplicate_texture(renderer, base, box.get_size()); return duplicate_texture(renderer, base, box.size());
} }
SDL_Texture* sfw::duplicate_texture(SDL_Renderer* renderer, SDL_Texture* base, const glm::vec2& size) SDL_Texture* sfw::duplicate_texture(SDL_Renderer* renderer, SDL_Texture* base, const glm::vec2& size)
@ -424,7 +424,7 @@ SDL_Texture* sfw::get_pixel_scaled_texture(SDL_Renderer* renderer, SDL_Texture*
print_sdl_error("could not set render target to remapped texture"); print_sdl_error("could not set render target to remapped texture");
return nullptr; return nullptr;
} }
glm::ivec2 size = get_texture_box(base).get_size(); glm::ivec2 size = get_texture_box(base).size();
Uint32 format = SDL_PIXELFORMAT_RGBA32; Uint32 format = SDL_PIXELFORMAT_RGBA32;
int bytes_per_pixel, bytes_per_row, bytes_total; int bytes_per_pixel, bytes_per_row, bytes_total;
Uint32 *src, *dst, *src_begin, *dst_begin; Uint32 *src, *dst, *src_begin, *dst_begin;
@ -516,11 +516,11 @@ SDL_Texture* sfw::get_pixel_scaled_texture(SDL_Renderer* renderer, SDL_Texture*
delete[] src_begin; delete[] src_begin;
} }
SDL_Texture* scaled = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, size.x, size.y); SDL_Texture* scaled = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, size.x, size.y);
if (scaled == NULL) if (scaled == nullptr)
{ {
print_sdl_error("could not create scaled texture"); print_sdl_error("could not create scaled texture");
} }
if (SDL_UpdateTexture(scaled, NULL, dst_begin, bytes_per_row * 2) < 0) if (SDL_UpdateTexture(scaled, nullptr, dst_begin, bytes_per_row * 2) < 0)
{ {
print_sdl_error("could not copy pixels to scaled texture"); print_sdl_error("could not copy pixels to scaled texture");
} }
@ -565,8 +565,7 @@ SDL_Surface* sfw::get_surface_from_pixels(Pixels& pixels)
return nullptr; return nullptr;
} }
fs::path sfw::get_next_file_name( fs::path sfw::get_next_file_name(fs::path directory, int zfill, std::string prefix, std::string extension)
fs::path directory, int zfill, std::string prefix, std::string extension)
{ {
std::stringstream file_pattern; std::stringstream file_pattern;
file_pattern << prefix << "([0-9]+)" << extension; file_pattern << prefix << "([0-9]+)" << extension;
@ -649,11 +648,11 @@ int lineColor(SDL_Renderer* renderer, const Segment& segment, const Color& color
{ {
if (thickness == 1) if (thickness == 1)
{ {
return lineColor(renderer, segment.start.x, segment.start.y, segment.end.x, segment.end.y, color); return lineColor(renderer, segment.start().x, segment.start().y, segment.end().x, segment.end().y, color);
} }
else else
{ {
return thickLineColor(renderer, segment.start.x, segment.start.y, segment.end.x, segment.end.y, thickness, color); return thickLineColor(renderer, segment.start().x, segment.start().y, segment.end().x, segment.end().y, thickness, color);
} }
} }

View File

@ -40,6 +40,7 @@ namespace sfw
glm::vec2 point_on_circle(float, float = 1.0f); glm::vec2 point_on_circle(float, float = 1.0f);
void points_on_circle(std::vector<glm::vec2>&, int, float = 1.0f, const glm::vec2& = {0, 0}, float = 0.0f); void points_on_circle(std::vector<glm::vec2>&, int, float = 1.0f, const glm::vec2& = {0, 0}, float = 0.0f);
std::vector<glm::vec2> points_on_circle(int, float = 1.0f, const glm::vec2& = {0, 0}, float = 0.0f); std::vector<glm::vec2> points_on_circle(int, float = 1.0f, const glm::vec2& = {0, 0}, float = 0.0f);
glm::vec2 map_rectangle_xy_to_circle(const glm::vec2&, float = 1.0f, const glm::vec2& = {0, 0});
Box get_texture_box(SDL_Texture*); Box get_texture_box(SDL_Texture*);
glm::vec2 fit_and_preserve_aspect(const glm::vec2&, const glm::vec2&); glm::vec2 fit_and_preserve_aspect(const glm::vec2&, const glm::vec2&);
std::vector<std::vector<Box>> get_blinds_boxes(glm::vec2, float = 0.05f, int = 4); std::vector<std::vector<Box>> get_blinds_boxes(glm::vec2, float = 0.05f, int = 4);