Collider,Collision Manager

김태훈·2024년 1월 9일
0

Win32API

목록 보기
12/24
post-custom-banner

component 기반 구조

부품기반, 멤버를 갖고는 있되
필요한 얘들은 쓰고 필요하지 않은 얘들은 쓰지 않는 구조

상속을 계속 이어 나가는 구조는 좋지 않은 구조

확장성을 늘려 나가는 구조가 설계를 해나가는 과정에서 유연한 대처를 가능케 하다

오브젝트 중에 콜라이더가 필요하면 creatcollider 를 한다
콜라이더가 오브젝트를 따라가야함,
콜라이더가 오브젝트를 알아야 함

void CObject::CreatCollider()
{
	m_pCollider = new CCollider;
	m_pCollider->m_pOwner = this;

}

final update

필요한 작업을 마무리 하는 update

모든 obj들이 final update를 한다
ex)final update에 구현되는 예
update 된 obj의 위치를 collider가 따라간다.

update->final update-> render
순으로 한 프레임이 만들어 지기 때문에
collider가 항상 obj를 따라다닌 것처럼 보인다

함수 선언+final

final update를 자식쪽에서 구현할 필요가 없음,collider가 있는 모든 obj들이 똑같이 적용 되야 함
자식쪽에서 구현을 할 수 없게 뒤에 final을 붙여 준다
virtual final update() final;

offset

어떤 기준에서 떨어지는 거리
offset+물체의 위치 = 충돌체의 finalpos
final pos를 매 final update에서 계산을 한다

물체 간의 충돌

scene enter에서 충돌하는 물체들을 지정하면
그것을 업데이트 하면서 충돌 했는지 검사 하는 식으로 동작

//충돌지정
	CCollisionMgr::GetInst()->CheckGroup(GROUP_TYPE::PALYER, GROUP_TYPE::MONSTER);
	CCollisionMgr::GetInst()->CheckGroup(GROUP_TYPE::MONSTER, GROUP_TYPE::PROJ_PLAYER);
	CCollisionMgr::GetInst()->CheckGroup(GROUP_TYPE::PALYER, GROUP_TYPE::Item);

화면을 exit할때 지정된 것들을 다 해제 시켜줘야 함

update->finalupdate->충돌 검사 ->render

순으로 진행 되어야 함
따라서 scenemgr update ->collsionmgr update 순으로 진행

Collision Manager

충돌 지정된 물체들이 충돌 했는지 검사

현재 obj 그룹이 32개,각 그룹당 가질수 있는 obj수 32개
4byte가 32 개 있는 것, 비트 연산을 활용하여 그룹 지정 가능하다

이진법을 더 쉽게 생각 할수 있게 열의 순서를 반대로 하였다

그룹간의 충돌 체크를 할때 더 작은 수의 그룹을 행으로,큰 수를 열로 해야함
이유: 아니면 쓰지 않는 곳에 체크가 되기 때문


void CCollisionMgr::CheckGroup(GROUP_TYPE _eLeft, GROUP_TYPE _eRight)
{
	UINT iRow = (UINT)_eLeft;
	UINT iCol = (UINT)_eRight;

	if (iCol < iRow)
	{
		iRow= (UINT)_eRight;
		iCol= (UINT)_eLeft;
	}
	//체크가 되어 있었다면 체크 해제
	if (m_arrCheck[iRow] & (1 << iCol))
	{
		m_arrCheck[iRow] &= ~(1 << iCol);
	}
	
	else { m_arrCheck[iRow] |= (1 << iCol);}
}

=delete

충돌체끼리 대입을 할 이유가 없다, 실수로 할 수 있기 때문에 방어 해주자

cpp
CCollider& operator=(CCollider& _Origin)= delete; //함수를 만들지 못하게 하겠다는 뜻

깊은 복사 필요

충돌체끼리 복사 생성을 할때 얕은 복사라면 ID가 동일하게 된다
이러한 것을 일어나면 되지 않기 때문에 깊은 복사로 해줘야 한다

cpp
CCollider::CCollider(const CCollider& _origin) 
:m_pOwner(nullptr)
, m_ID(g_iNextID++)
, m_iCol(0)
, m_vFinalPos{}
, m_vOffsetPos{}
{


}

이전 프레임 정보, 충돌체 ID

이전프레임의 정보를 통해
막 충돌했는지, 충돌 중인지, 충돌하다 끝났는지를 알 수 있다.
이전프레임의 정보를 저장 해야한다
저장한것을 탐색을 통해 찾아서 활용해야 한다

물체와 물체 사이의 조합의 수가 방대하다
각각의 충돌체의 ID 필요
정적변수를 만들고 후위 연산자 ++로 하여 ID가 1씩 증가하여 다 다른ID 가질 수 있다

그 충돌하는 두개의 충돌체 아이디들을 갖는
하나의 union으로 만들면 충돌조합의 키값으로 사용 할수 있다

UINT CCollider::g_iNextID = 0;

CCollider::CCollider()
	:m_pOwner(nullptr)
	,m_ID(++g_iNextID)
	,m_iCol(0)
	,m_vFinalPos{}
	,m_vOffsetPos{}
{

}

union COLLIDER_ID
{ 
  struct
  {
    UINT Left_id;
    UINT Right_id;
  };
  LONGLONG ID;
};
//두 충돌체 조합 아이디 생성	
COLLIDER_ID ID;
ID.iLeft_id = pLeftCol->GetId();
ID.iRight_id = pRightCol->GetId(); 

CCollider* pLeftCol = vecLeft[i]->GetCollider();
CCollider* pRightCol = vecRight[j]->GetCollider();	
 iter=m_mapColInfo.find(ID.ID);

map 활용

if (IsCollision(pLeftCol, pRightCol))//현재 충돌 중이다
{ 
	if (iter->second)//이전 충돌
		{   
		          pLeftCol->OnCollision(pRightCol);
	 	          pRightCol->OnCollision(pLeftCol);
		}	
		else
		{
			//이전엔 충돌 안함
			pLeftCol->OnCollisionEnter(pRightCol);
			pRightCol->OnCollisionEnter(pLeftCol);
			iter->second = true;
		}
}

else 
{   //현재 충돌 안함 
	if (iter->second)//이전 충돌
	{
		pLeftCol->OnCollisionExit(pRightCol);
		pRightCol->OnCollisionExit(pLeftCol);
		iter->second = false;			
	}
}
profile
복습을 위한 핵심 내용 및 모작
post-custom-banner

0개의 댓글