충돌 처리의 개념

충돌 처리는 객체 간의 상호작용을 감지하고, 그 결과를 처리하는 게임 개발의 중요한 요소입니다. 일반적으로 두 가지 방식으로 나뉩니다:
1. 충돌 감지 (Collision Detection): 객체들이 충돌했는지 확인하는 단계.
2. 충돌 반응 (Collision Response): 충돌 시의 반응을 처리하는 단계. 예를 들어, 객체를 튕겨내거나, 이동을 막는 등의 작업.


강의 주요 내용

  1. 충돌을 감지하기 위해 BoxCollider 클래스와 GetRect 함수를 활용.
  2. 충돌을 처리하기 위해 충돌 방향을 계산하고, 객체의 위치를 조정.
  3. 충돌 처리에서 발생 가능한 오류부들거림 현상의 원인 분석 및 해결.

코드 분석

Player 클래스

class Player : public FlipbookActor
{
	using Super = FlipbookActor;
public:

	Player();
	virtual ~Player() override;

	virtual void BeginPlay() override;
	virtual void Tick() override;
	virtual void Render(HDC hdc) override;

	virtual void OnComponentBeginOverlap(Collider* collider, Collider* other) override;
	virtual void OnComponentEndOverlap(Collider* collider, Collider* other) override;

private:
	void TickGravity();
	void AdjustCollisionPos(BoxCollider* b1, BoxCollider* b2);

public:
	Flipbook* _flipbookUp = nullptr;
	Flipbook* _flipbookDown = nullptr;
	Flipbook* _flipbookLeft = nullptr;
	Flipbook* _flipbookRight = nullptr;
};

분석:

  • Player 클래스는 FlipbookActor를 상속받아 생성된 플레이어 객체입니다.
  • 충돌 감지 및 처리를 위해 두 가지 주요 메서드가 정의되어 있습니다:
    • OnComponentBeginOverlap: 충돌 시작 시 호출.
    • OnComponentEndOverlap: 충돌 종료 시 호출.
  • AdjustCollisionPos: 충돌 발생 시 객체 위치를 조정하는 핵심 함수.
  • _flipbookUp, _flipbookDown 등은 플레이어의 방향에 따라 애니메이션을 설정하기 위한 Flipbook 객체.

Player.cpp

Player::Player()
{
	_flipbookUp = GET_SINGLE(ResourceManager)->GetFlipbook(L"FB_MoveUp");
	_flipbookDown = GET_SINGLE(ResourceManager)->GetFlipbook(L"FB_MoveDown");
	_flipbookLeft = GET_SINGLE(ResourceManager)->GetFlipbook(L"FB_MoveLeft");
	_flipbookRight = GET_SINGLE(ResourceManager)->GetFlipbook(L"FB_MoveRight");

	// 플레이어에게 카메라 넣어주기
	CameraComponent* camera = new CameraComponent();
	AddComponent(camera);
}

분석:

  • 플립북 설정: 플레이어의 움직임 방향에 따라 사용될 애니메이션(플립북)을 ResourceManager에서 불러옵니다.
  • 카메라 컴포넌트 추가: CameraComponent를 생성하여 플레이어의 위치를 중심으로 카메라가 이동하도록 설정.

void Player::Tick()
{
	Super::Tick();
	
	float deltaTime = GET_SINGLE(TimeManager)->GetDeltaTime();
	
	if (GET_SINGLE(InputManager)->GetButton(KeyType::W))
	{
		_pos.y -= 200 * deltaTime;
		SetFlipbook(_flipbookUp);
	}
	else if (GET_SINGLE(InputManager)->GetButton(KeyType::S))
	{
		_pos.y += 200 * deltaTime;
		SetFlipbook(_flipbookDown);
	}
	else if (GET_SINGLE(InputManager)->GetButton(KeyType::A))
	{
		_pos.x -= 200 * deltaTime;
		SetFlipbook(_flipbookLeft);
	}
	else if (GET_SINGLE(InputManager)->GetButton(KeyType::D))
	{
		_pos.x += 200 * deltaTime;
		SetFlipbook(_flipbookRight);
	}
}

분석:

  • 플레이어의 이동 및 애니메이션 변경을 처리하는 함수.
  • 키 입력에 따라 플레이어의 위치와 플립북을 업데이트.
    • W, S, A, D 키는 각각 위, 아래, 왼쪽, 오른쪽으로 이동.
    • 위치는 deltaTime을 곱하여 프레임 독립적인 속도로 처리.

void Player::OnComponentBeginOverlap(Collider* collider, Collider* other)
{
	BoxCollider* b1 = dynamic_cast<BoxCollider*>(collider);
	BoxCollider* b2 = dynamic_cast<BoxCollider*>(other);

	if (b1 == nullptr || b2 == nullptr)
	{
		return;
	}
	
	AdjustCollisionPos(b1, b2);
}

분석:

  • dynamic_cast: Collider 객체를 BoxCollider로 변환. 변환에 실패하면 nullptr 반환.
  • 충돌이 발생했을 경우 AdjustCollisionPos 함수로 충돌 처리.

충돌 위치 조정

void Player::AdjustCollisionPos(BoxCollider* b1, BoxCollider* b2)
{
	RECT r1 = b1->GetRect();
	RECT r2 = b2->GetRect();

	Vec2 pos = GetPos();

	RECT intersect = {};
	if (::IntersectRect(&intersect, &r1, &r2))
	{
		int32 w = intersect.right - intersect.left;
		int32 h = intersect.bottom - intersect.top;

		if (w > h)
		{
			if (intersect.top == r2.top)
			{
				pos.y -= h;
			}
			else
			{
				pos.y += h;
			}
		}
		else
		{
			if (intersect.left == r2.left)
			{
				pos.x -= w;
			}
			else
			{
				pos.y += w;
			}
		}
	}
	SetPos(pos);
}

분석:

  • RECT 객체를 통해 두 충돌 박스의 교차 영역(intersect)을 계산.
  • 교차 영역의 폭(w)과 높이(h)를 비교하여 충돌 방향을 결정:
    • 폭이 더 크면 수직 충돌로 판단하고, pos.y를 조정.
    • 높이가 더 크면 수평 충돌로 판단하고, pos.x를 조정.
  • 중요: 이 함수는 충돌 후 플레이어의 위치를 충돌 박스 밖으로 밀어내는 역할을 수행.

BoxCollider 클래스

RECT BoxCollider::GetRect()
{
	Vec2 pos = GetOwner()->GetPos();
	Vec2 size = GetSize();

	RECT rect =
	{
		(int32)(pos.x - (size.x / 2)),
		(int32)(pos.y - (size.y / 2)),
		(int32)(pos.x + (size.x / 2)),
		(int32)(pos.y + (size.y / 2))
	};
	return rect;
}

분석:

  • 객체의 중심 좌표(pos)와 크기(size)를 기반으로 충돌 박스의 RECT를 반환.
  • 좌표 계산:
    • 왼쪽: pos.x - (size.x / 2)
    • 위쪽: pos.y - (size.y / 2)
    • 오른쪽: pos.x + (size.x / 2)
    • 아래쪽: pos.y + (size.y / 2)

profile
李家네_공부방

0개의 댓글