- Collision Manager 설계.
// CCollisionMgr.h
#pragma once
class CCollisionMgr
{
SINGLETON(CCollisionMgr);
private:
UINT m_arrCheck[(UINT)GROUP_TYPE::END];
private:
void CollisionGroupUpdate(GROUP_TYPE eType1, GROUP_TYPE eType2);
public:
void init();
void late_update();
public:
void CheckGroup(GROUP_TYPE eType1, GROUP_TYPE eType2);
inline void Reset() { memset(m_arrCheck, 0, sizeof(UINT) * (UINT)GROUP_TYPE::END); }
};
m_arrCheck 는 충돌 매트릭스임. UINT 값(4바이트)

충돌 매트릭스는 이렇게 row 값이 col 값 이하인 부분만 씀.
그래서 그림으로 나타냈을 때 이차원 배열이지만(column 은 비트 값 역순으로 나열), 배열의 절반은 안써야 함.
// CCollisionMgr.cpp
void CCollisionMgr::CheckGroup(GROUP_TYPE eType1, GROUP_TYPE eType2)
{
// 더 작은 그룹 번호가 eType1이 되도록 보장.
if (eType1 > eType2)
std::swap(eType1, eType2);
m_arrCheck[(UINT)eType1] ^= (1 << (UINT)eType2);
}
CheckGroup 함수에서 입력된 두 그룹의 충돌 유무를 on / off 한다. XOR 연산자로 기존의 값을 반전시킬 수 있음.
// CCollisionMgr.cpp
void CCollisionMgr::late_update()
{
for(UINT i = 0; i < (UINT)GROUP_TYPE::END; ++i)
{
for(UINT j = i; j < (UINT)GROUP_TYPE::END; ++j)
{
if(m_arrCheck[i] & (1 << j))
{
CollisionGroupUpdate((GROUP_TYPE)i, (GROUP_TYPE)j);
}
}
}
}
매 프레임마다 두 그룹 간 충돌 체크를 한다. late_update 로 해줬는데,
이는 충돌체 위치의 최종 계산이 오브젝트에서 update 로 로직 계산이 끝난 이후
late_update 에서 이루어지기 때문.
// CCore.cpp
void CCore::progress()
{
update();
late_update();
render();
}
void CCore::update()
{
// Manager Update
CTimeMgr::GetInstance()->update();
CKeyMgr::GetInstance()->update();
CSceneMgr::GetInstance()->update();
}
void CCore::late_update()
{
// Scene late_update -> Object late_update
CSceneMgr::GetInstance()->late_update();
CCollisionMgr::GetInstance()->late_update();
}
Core 에서 호출 순서도 조금 손봤다.
// CCollisionMgr.cpp
void CCollisionMgr::CollisionGroupUpdate(GROUP_TYPE eType1, GROUP_TYPE eType2)
{
CScene* pCurScene = CSceneMgr::GetInstance()->GetCurScene();
if (pCurScene == nullptr)
return;
const vector<CObject*>& arrObj1 = pCurScene->GetObjByGroup(eType1);
const vector<CObject*>& arrObj2 = pCurScene->GetObjByGroup(eType2);
for(CObject* pObj1 : arrObj1)
{
if (pObj1 == nullptr || pObj1->GetCollider() == nullptr)
continue;
for(CObject* pObj2 : arrObj2)
{
if (pObj2 == nullptr || pObj2->GetCollider() == nullptr)
continue;
// 같은 오브젝트끼리 충돌 검사하지 않도록.
if (pObj1 == pObj2)
continue;
// 충돌 검사.
if (pObj1->GetCollider()->Collision(pObj2->GetCollider()))
{
// 충돌 처리 로직 구현.
// 예: 이벤트 발생, 상태 변경 등.
int a = 0;
}
}
}
}
코드는 길지만 단순히 2중 for 문을 돌면서 두 그룹 간 충돌한 Collider 를 찾아내는 과정임. Collider::Collision 함수는
// CCollider.cpp
bool CCollider::Collision(CCollider* pOther)
{
if (pOther == nullptr)
return false;
// AABB 충돌 검사
float leftA = m_vFinalPos.x - m_vSize.x * 0.5f;
float rightA = m_vFinalPos.x + m_vSize.x * 0.5f;
float topA = m_vFinalPos.y - m_vSize.y * 0.5f;
float bottomA = m_vFinalPos.y + m_vSize.y * 0.5f;
float leftB = pOther->m_vFinalPos.x - pOther->m_vSize.x * 0.5f;
float rightB = pOther->m_vFinalPos.x + pOther->m_vSize.x * 0.5f;
float topB = pOther->m_vFinalPos.y - pOther->m_vSize.y * 0.5f;
float bottomB = pOther->m_vFinalPos.y + pOther->m_vSize.y * 0.5f;
// 사각형 A와 B가 겹치는지 확인
if (leftA >= rightB || rightA <= leftB ||
topA >= bottomB || bottomA <= topB)
{
// 겹치지 않음
return false;
}
return true;
}
일단 사각형 충돌만 구현해둠.
'Win32 api' 카테고리의 다른 글
| Win32 api 강의 31 - 33화. (0) | 2025.09.19 |
|---|---|
| Win32 api 강의 29 - 30화. (0) | 2025.09.18 |
| Win32 api 강의 25 - 26화. (0) | 2025.09.17 |
| Win32 api 강의 24화. (0) | 2025.09.17 |
| Win32 api 강의 23화. (0) | 2025.09.16 |