135 lines
4.1 KiB
C++
135 lines
4.1 KiB
C++
#include "KRect.h"
|
|
|
|
#include "KCircle.h"
|
|
#include "Utils.h"
|
|
|
|
namespace KapitanGame {
|
|
|
|
float KRect::GetWidth() const {
|
|
return Width;
|
|
}
|
|
|
|
float KRect::GetHeight() const {
|
|
return Height;
|
|
}
|
|
|
|
KVector2D KRect::GetSeparationVector(const float left, const float right, const float top, const float bottom) {
|
|
const auto x = left < right ? -left : right;
|
|
const auto y = top < bottom ? -top : bottom;
|
|
auto vX = x;
|
|
auto vY = y;
|
|
if (fabs(x) < fabs(y))
|
|
vY = 0;
|
|
if (fabs(x) > fabs(y))
|
|
vX = 0;
|
|
return { vX, vY };
|
|
}
|
|
|
|
KVector2D KRect::GetSeparationVector(const KCircle* other) const {
|
|
const float l = GetLeft();
|
|
const float r = GetRight();
|
|
const float t = GetTop();
|
|
const float b = GetBottom();
|
|
const auto f = KVector2D(Utils::Clamp(other->GetParent()->GetPosition().X, l, r),
|
|
Utils::Clamp(other->GetParent()->GetPosition().Y, t, b));
|
|
|
|
if (other->GetParent()->GetPosition() == f) {
|
|
const auto left = other->GetParent()->GetPosition().X - l + other->GetRadius();
|
|
const auto right = r - other->GetParent()->GetPosition().X + other->GetRadius();
|
|
const auto top = other->GetParent()->GetPosition().Y - t + other->GetRadius();
|
|
const auto bottom = b - other->GetParent()->GetPosition().Y + other->GetRadius();
|
|
return GetSeparationVector(left, right, top, bottom) * -1.f;
|
|
}
|
|
return (other->GetParent()->GetPosition() - f) / (other->GetParent()->GetPosition() - f).Length() * (other->GetRadius() - (other->GetParent()->GetPosition() - f).Length()) * 1.f;
|
|
}
|
|
|
|
KVector2D KRect::GetSeparationVector(const KRect* other) const {
|
|
const auto left = GetRight() - other->GetLeft();
|
|
const auto right = other->GetRight() - GetLeft();
|
|
const auto top = GetBottom() - other->GetTop();
|
|
const auto bottom = other->GetBottom() - GetTop();
|
|
|
|
return GetSeparationVector(left, right, top, bottom);
|
|
}
|
|
|
|
bool KRect::IsCollision(const KCircle* other) const {
|
|
const auto f = KVector2D(Utils::Clamp(other->GetParent()->GetPosition().X, GetLeft(), GetRight()),
|
|
Utils::Clamp(other->GetParent()->GetPosition().Y, GetTop(), GetBottom()));
|
|
|
|
return (other->GetParent()->GetPosition() - f).Length() < other->GetRadius();
|
|
}
|
|
|
|
float KRect::GetLeft() const
|
|
{
|
|
return GetParent()->GetPosition().X - Width / 2;
|
|
}
|
|
|
|
float KRect::GetRight() const
|
|
{
|
|
return GetParent()->GetPosition().X + Width / 2;
|
|
}
|
|
|
|
float KRect::GetBottom() const
|
|
{
|
|
return GetParent()->GetPosition().Y + Height / 2;
|
|
}
|
|
|
|
float KRect::GetTop() const
|
|
{
|
|
return GetParent()->GetPosition().Y - Height / 2;
|
|
}
|
|
|
|
bool KRect::IsCollision(const KRect* other) const {
|
|
return GetRight() >= other->GetLeft()
|
|
&& other->GetRight() >= GetLeft()
|
|
&& GetBottom() >= other->GetTop()
|
|
&& other->GetBottom() >= GetTop();
|
|
}
|
|
|
|
bool KRect::IsCollision(const KCollider* other) const
|
|
{
|
|
const auto circle = dynamic_cast<const KCircle*>(other);
|
|
if (circle != nullptr)
|
|
return IsCollision(circle);
|
|
|
|
const auto rect = dynamic_cast<const KRect*>(other);
|
|
if (rect != nullptr)
|
|
return IsCollision(rect);
|
|
|
|
throw std::runtime_error("unsupported shape");
|
|
}
|
|
|
|
KVector2D KRect::GetSeparationVector(const KCollider* other) const
|
|
{
|
|
const auto circle = dynamic_cast<const KCircle*>(other);
|
|
if (circle != nullptr)
|
|
return GetSeparationVector(circle);
|
|
|
|
const auto rect = dynamic_cast<const KRect*>(other);
|
|
if (rect != nullptr)
|
|
return GetSeparationVector(rect);
|
|
|
|
throw std::runtime_error("unsupported shape");
|
|
}
|
|
|
|
KVector2D KRect::GetSeparationVector(const SDL_FRect& map) const
|
|
{
|
|
KVector2D separationVector{ 0.f,0.f };
|
|
if (GetParent()->GetPosition().X - map.x - GetWidth() / 2 < 0)
|
|
{
|
|
separationVector.X += -(GetParent()->GetPosition().X - map.x - GetWidth() / 2);
|
|
}
|
|
if (GetParent()->GetPosition().X + GetWidth() / 2 - (map.x + map.w) > 0)
|
|
{
|
|
separationVector.X += -(GetParent()->GetPosition().X - (map.x + map.w) + GetWidth() / 2);
|
|
}
|
|
if (GetParent()->GetPosition().Y - GetHeight() / 2 - map.y < 0) {
|
|
separationVector.Y += -(GetParent()->GetPosition().Y - map.y - GetHeight() / 2);
|
|
}
|
|
if (GetParent()->GetPosition().Y + GetHeight() / 2 - (map.y + map.h) > 0) {
|
|
separationVector.Y += -(GetParent()->GetPosition().Y - (map.y + map.h) + GetHeight() / 2);
|
|
}
|
|
return separationVector;
|
|
}
|
|
}
|