#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(other); if (circle != nullptr) return IsCollision(circle); const auto rect = dynamic_cast(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(other); if (circle != nullptr) return GetSeparationVector(circle); const auto rect = dynamic_cast(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; } }