109 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			109 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "KCircle.h"
 | |
| 
 | |
| #include <SDL_rect.h>
 | |
| #include <stdexcept>
 | |
| 
 | |
| #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<const KCircle*>(other); circle != nullptr)
 | |
| 			return IsCollision(circle);
 | |
| 
 | |
| 
 | |
| 		if (const auto rect = dynamic_cast<const KRect*>(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<const KCircle*>(other); circle != nullptr)
 | |
| 			return GetSeparationVector(circle);
 | |
| 
 | |
| 		if (const auto rect = dynamic_cast<const KRect*>(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;
 | |
| 	}
 | |
| 
 | |
| }
 | |
| 
 |