#include "KCircle.h" #include #include #include "KRect.h" #include "Utils.h" namespace KapitanGame { bool KCircle::IsCollision(const KCircle* other) const { return (GetParent()->GetPosition() - other->GetParent()->GetPosition()).Length() < Radius + other->Radius; } bool KCircle::IsCollision(const KCollider* other) const { if (const auto circle = dynamic_cast(other); circle != nullptr) return IsCollision(circle); if (const auto rect = dynamic_cast(other); rect != nullptr) return IsCollision(rect); throw std::runtime_error("unsupported shape"); } KVector2D KCircle::GetSeparationVector(const KCollider* other) const { if (const auto circle = dynamic_cast(other); circle != nullptr) return GetSeparationVector(circle); if (const auto rect = dynamic_cast(other); rect != nullptr) return GetSeparationVector(rect); throw std::runtime_error("unsupported shape"); } bool KCircle::IsCollision(const KRect* other) const { const auto f = KVector2D(Utils::Clamp(GetParent()->GetPosition().X, other->GetParent()->GetPosition().X - other->GetWidth() / 2, other->GetParent()->GetPosition().X + other->GetWidth() / 2), Utils::Clamp(GetParent()->GetPosition().Y, other->GetParent()->GetPosition().Y - other->GetHeight() / 2, other->GetParent()->GetPosition().Y + other->GetHeight() / 2)); return (GetParent()->GetPosition() - f).Length() < Radius; } KVector2D KCircle::GetSeparationVector(const KCircle* other) const { const KVector2D centerDiff = GetParent()->GetPosition() - other->GetParent()->GetPosition(); const float centerDiffLength = centerDiff.Length(); return centerDiff / centerDiffLength * (Radius + other->Radius - centerDiffLength); } KVector2D KCircle::GetSeparationVector(const KRect* other) const { const float l = other->GetParent()->GetPosition().X - other->GetWidth() / 2; const float r = other->GetParent()->GetPosition().X + other->GetWidth() / 2; const float t = other->GetParent()->GetPosition().Y - other->GetHeight() / 2; const float b = other->GetParent()->GetPosition().Y + other->GetHeight() / 2; const auto f = KVector2D(Utils::Clamp(GetParent()->GetPosition().X, l, r), Utils::Clamp(GetParent()->GetPosition().Y, t, b)); if (GetParent()->GetPosition() == f) { const auto left = GetParent()->GetPosition().X - l + Radius; const auto right = r - GetParent()->GetPosition().X + Radius; const auto top = GetParent()->GetPosition().Y - t + Radius; const auto bottom = b - GetParent()->GetPosition().Y + Radius; return KRect::GetSeparationVector(left, right, top, bottom); } return (GetParent()->GetPosition() - f) / (GetParent()->GetPosition() - f).Length() * (Radius - (GetParent()->GetPosition() - f).Length()); } KVector2D KCircle::GetSeparationVector(const SDL_FRect& map) const { KVector2D separationVector{ 0.f,0.f }; if (GetParent()->GetPosition().X - map.x - Radius < 0) { separationVector.X += -(GetParent()->GetPosition().X - map.x - Radius); } if (GetParent()->GetPosition().X + Radius - (map.x + map.w) > 0) { separationVector.X += -(GetParent()->GetPosition().X - (map.x+map.w) + Radius); } if (GetParent()->GetPosition().Y - Radius - map.y < 0) { separationVector.Y += -(GetParent()->GetPosition().Y - map.y - Radius); } if (GetParent()->GetPosition().Y + Radius - (map.y + map.h) > 0) { separationVector.Y += -(GetParent()->GetPosition().Y - (map.y + map.h) + Radius); } return separationVector; } float KCircle::GetWidth() const { return Radius * 2; } float KCircle::GetHeight() const { return Radius * 2; } KCircle::KCircle(KSolid* parent, const float radius): KCollider(parent), Radius(radius) { } float KCircle::GetRadius() const { return Radius; } }