diff --git a/include/misc/Shapes.h b/include/misc/Shapes.h new file mode 100644 index 0000000..ff209f6 --- /dev/null +++ b/include/misc/Shapes.h @@ -0,0 +1,68 @@ +#pragma once + +#include + +namespace td { +namespace utils { +namespace shape { + +class Point { +private: + float m_X, m_Y; +public: + Point() : m_X(0), m_Y(0) {} + Point(float x, float y) : m_X(x), m_Y(y) {} + + float getX() const { return m_X; } + float getY() const { return m_Y; } + + void setX(float x) { m_X = x; } + void setY(float y) { m_Y = y; } + + float distance(const Point& point) const; + float distanceSquared(const Point& point) const; +}; + +class Circle; + +class Rectangle { +private: + Point m_Center; + float m_Width, m_Height; +public: + Rectangle() {} + + const Point& getCenter() const { return m_Center; } + float getWidth() const { return m_Width; } + float getHeight() const { return m_Height; } + + Point getTopLeft() const { return { m_Center.getX() - (m_Width / 2.0f), m_Center.getY() - (m_Height / 2.0f) }; } + Point getBottomRight() const { return { m_Center.getX() + (m_Width / 2.0f), m_Center.getY() + (m_Height / 2.0f) }; } + + void setCenter(const Point& center) { m_Center = center; } + void setWidth(float width) { m_Width = width; } + void setHeight(float height) { m_Height = height; } + + bool collidesWith(const Point& point) const; + bool collidesWith(const Rectangle& rect) const; + bool collidesWith(const Circle& circle) const; +}; + +class Circle { +private: + Point m_Center; + float m_Radius; +public: + Circle() : m_Radius(0) {} + + const Point& getCenter() const { return m_Center; } + float getRadius() const { return m_Radius; } + + bool collidesWith(const Point& point) const; + bool collidesWith(const Rectangle& rect) const; + bool collidesWith(const Circle& circle) const; +}; + +} // namespace shape +} // namespace utils +} // namespace td diff --git a/src/misc/Shapes.cpp b/src/misc/Shapes.cpp new file mode 100644 index 0000000..b1801ae --- /dev/null +++ b/src/misc/Shapes.cpp @@ -0,0 +1,68 @@ +#include "misc/Shapes.h" + +#include +#include + +namespace td { +namespace utils { +namespace shape { + +float Point::distance(const Point& point) const { + return std::sqrt(distanceSquared(point)); +} + +float Point::distanceSquared(const Point& point) const { + return (m_X - point.getX()) * (m_X - point.getX()) + (m_Y - point.getY()) * (m_Y - point.getY()); +} + + +bool Rectangle::collidesWith(const Point& point) const { + return point.getX() > getTopLeft().getX() && point.getX() < getBottomRight().getX() && + point.getY() > getTopLeft().getY() && point.getY() < getBottomRight().getY(); +} + +bool Rectangle::collidesWith(const Rectangle& rect) const { + Point point1{ rect.getTopLeft().getX(), rect.getTopLeft().getY() }; + Point point2{ rect.getTopLeft().getX(), rect.getBottomRight().getY() }; + Point point3{ rect.getBottomRight().getX(), rect.getTopLeft().getY() }; + Point point4{ rect.getBottomRight().getX(), rect.getBottomRight().getY() }; + + if (collidesWith(point1)) return true; + if (collidesWith(point2)) return true; + if (collidesWith(point3)) return true; + if (collidesWith(point4)) return true; + + return false; +} + +bool Rectangle::collidesWith(const Circle& circle) const { + return circle.collidesWith(*this); +} + + + + + +bool Circle::collidesWith(const Point& point) const { + return m_Radius * m_Radius > m_Center.distanceSquared(point); +} + +bool Circle::collidesWith(const Rectangle& rect) const { + float closestX = std::clamp(m_Center.getX(), rect.getTopLeft().getX(), rect.getBottomRight().getX()); + float closestY = std::clamp(m_Center.getY(), rect.getTopLeft().getY(), rect.getBottomRight().getY()); + + float distanceX = m_Center.getX() - closestX; + float distanceY = m_Center.getY() - closestY; + + float distanceSquared = (distanceX * distanceX) + (distanceY * distanceY); + + return distanceSquared < m_Radius * m_Radius; +} + +bool Circle::collidesWith(const Circle& circle) const { + return m_Radius + circle.getRadius() > m_Center.distanceSquared(circle.getCenter()); +} + +} // namespace shape +} // namespace utils +} // namespace td