본문 바로가기
Win32 API/기초

Win32 API 기초 : Collider (3)

글: 시플마 2024. 7. 28.

CPlayer 클래스의 생성자가 호출되면,

 

즉 플레이어가 생성될 때 Collider를 만들죠.

 

Collider의 크기는 설정해 주었으니 

22번째 줄에 있는 SetColliderOffset 함수를 통해

오브젝트 위치로부터 얼마만큼 떨어진 위치에

Collider를 위치시킬 것인지 설정해 줍니다.

 

 


 

 

 

몬스터가 생성될 때에도

 

몬스터에 Collider를 붙여줍시다.

 

마찬가지로 Collider의 Offset을 설정해 주고,

23번째 줄에 있는 SetColliderSize 함수를 통해

크기를 설정해 줍니다.

 

 

그리고 몬스터의 render 함수에도

 

component_render 함수를 호출하여

몬스터 오브젝트에 Collider가 있다면

Collider도 윈도우 창에 그릴 수 있도록 해야겠죠.

 

 

몬스터( 분홍 상자 )와 플레이어( 하늘색 상자 ) 안에 있는

 

빨간 테두리가 바로 Collider의 범위를 나타내는 겁니다.

 

 

 


 

 

 

Collider 값을 설정해 주었으니,

실제 Collider가 충돌을 인식할 수 있도록 해야겠죠.

 

게임 시작 시의 출력되는 화면을 세팅하는

CScene_Start의 Enter 함수를 봅시다.

 

24번째 줄에서 플레이어 오브젝트의 그룹을 PLAYER로, 

45번째 줄에서 몬스터 오브젝트의 그룹을 MONSTER로 설정합니다.

 

 

49번째 줄에서 CCollisionMgr의 CheckGroup 함수를 호출하고 있습니다.

플레이어와 몬스터 그룹 타입을 인자로 넣고 있습니다.

 

CheckGroup 함수는 인자로 넣은 두 그룹을

충돌 가능한 그룹으로 설정해 주는 함수입니다.

 

이렇게 충돌 그룹을 따로 지정해 주는 이유가 있습니다.

 

만약 Start 씬에 100개의 오브젝트가 있다고 합시다.

 

그럼 오브젝트1이 나머지 99개의 오브젝트와

충돌을 하고 있는지 하고 있지 않은지 체크해야 합니다.

 

이후 오브젝트2도 나머지 99개의 오브젝트와

충돌 체크를 진행해야 하죠.

 

이렇게 하면 너무 많은 연산을 진행하게 되기 때문에

충돌을 진행할 두 그룹을 지정해 주고

그 두 그룹에 속한 오브젝트만 충돌을 하고 있는지

하고 있지 않은지 체크하는 것이죠.

 

 

이러한 그룹 간의 충돌 설정은

CCollisionMgr 클래스로 만든 싱글톤 객체가 관리합니다.

 

UINT형 멤버 m_arrCheck를 갖고 있습니다.

 

해당 멤버는 배열이며, 그룹 타입의 개수만큼 

인덱스를 보유하고 있습니다.

 

멤버 m_arrCheck의 인덱스 하나하나에는

한 그룹과 나머지 그룹 간의 충돌 설정이 저장되는 것이죠.

 

이때 비트 연산을 통해서 충돌 설정을 인식할 것입니다.

 

enum class GROUP_TYPE의 END 값은

32이므로 32개의 그룹이 존재합니다.

 

위 그림처럼 멤버 m_arrCheck의 0번 인덱스의

1번 자리와 3번 자리 비트가 1이라면

0번 그룹은 1번 그룹과 3번 그룹과 충돌할 수 있다는

의미겠죠.

 

멤버 m_arrCheck의 2번 인덱스의

2번 자리 비트가 1이라면 2번 그룹은

2번 그룹과 충돌할 수 있다는 의미이죠.

( 같은 그룹끼리 충돌하는 상황은 몬스터와 몬스터의

동선이 겹칠 때 오브젝트가 서로 겹치지 않고 밀어내는

상황 등이 있겠죠. )

 

 

근데 여기서 아래 그림과 같은 상황이라면

 

어떨까요?

 

0번 인덱스에 1번 그룹이 충돌할 수 있다고 지정이 되어 있는데,

1번 인덱스에서도 0번 그룹과 충돌할 수 있다고 지정이 되어 있습니다.

 

이 둘은 사실 같은 의미죠?

 

그래서 위 그림에서 보이는 것처럼

빨간 삼각형 범위에 속하는 부분만 생각하면 되는 거죠.

 

 

또한 비트 연산을 통해

체크를 할 것이기 때문에 아래 그림처럼

 

가장 오른쪽 비트를 0번 그룹으로 보고 

가장 왼쪽 비트를 31번 그룹으로 보는 게 생각하기 편하겠죠?

 

0번 인덱스의 가장 왼쪽 비트가 1이면

0번 그룹과 31번 그룹은 충돌할 수 있는 상태인 것이죠.

 

그럼 최종적으로 위 그림에서

빨간 삼각형 범위 내의 비트만 신경써 주면 되는 겁니다.

 

32개의 인덱스가 존재하고 각 인덱스는

32개의 Bit( 4Byte )를 가지므로 멤버 m_arrCheck는

UINT( Unsigned Int )로 선언된 것입니다.

 

 

두 그룹이 충돌할 수 있는 그룹임을

체크하기 위한 함수인 CheckGroup 함수의

 

인자로 0번 그룹과 3번 그룹을 받으면

멤버 m_arrCheck의 0번 인덱스의 3번 비트를

1로 설정하겠죠.

 

이때 생각해야 하는 것은

두 개의 그룹값 중 작은 값을 행으로,

큰 값을 열로 봐야 한다는 것이죠.

 

만약 0번 그룹과 31번 그룹을 인자로 받으면

0번 인덱스의 31번 비트를 1로 설정하면 되지만,

 

31번 그룹과 0번 그룹순으로 인자를 받게 되면

31번 인덱스의 0번 비트를 1로 설정하는 것이 아니라,

0번 인덱스의 31번 비트를 1로 설정해야 하는 것입니다.

( 빨간 삼각형 내부의 범위가 그렇습니다. 결과적으로

0번 인덱스는 0 ~ 31번 비트까지 모두 체크할 수 있지만,

31번 인덱스는 31번 비트만을 체크할 수 있죠. )

 

 

 


 

 

 

Start 씬이 시작되면서 서로 충돌 가능하게 할 그룹을

지정하여 해당 그룹에 속한 오브젝트들이

서로 충돌할 수 있도록 하였습니다.

 

그럼 Start 씬이 종료될 때에는 충돌 가능하도록

지정했던 그룹을 모두 해제해 주어야겠죠? 

 

그래서 Start 씬이 종료될 때 호출되는 Exit 함수에서

충돌 매니저가 갖고 있는 충돌 가능 그룹들을 모두

모두 해제해 주는 Reset 함수를 호출합니다.

 

 

Reset 함수가 호출되면

 

memset 함수가 호출됩니다.

 

첫 번째 인자는 값을 설정할 공간의 주솟값, 

두 번쨰 인자는 그 공간에 넣을 값 ( Byte 단위 ),

세 번째 인자는 그 채우고자 하는 공간의 크기입니다.

 

그래서 배열의 이름은 곧 배열의 주솟값이기 때문에 첫 번째 인자로

배열의 이름을 넣고, 모든 인덱스를 0으로 리셋해 줘야 하므로 

두 번째 인자로 0을 넣습니다.

 

배열의 인덱스가 32개이고, 한 인덱스의 크기는 UINT ( 4Byte )이므로

이 둘을 곱한 값이 m_arrCheck 배열의 전체 크기가 되겠네요.

이 값을 세 번째 인자로 넘깁니다.

 

그럼 m_arrCheck의 인덱스가 모두 0이 되어 

충돌 가능한 그룹이 없는 상태가 되는 것이죠.

 

 


 

 

 

 

정리하면 Start 씬이 시작되면서

충돌 가능한 그룹을 지정하면

Start 씬에서는 그 그룹에 속한

오브젝트는 서로 충돌이 발생할 수 있게 되죠.

 

그리고 CCore 클래스의 멤버 함수 progress에서

CCollisionMgr의 update 함수를 호출해 줍니다.

 

그러면 이제 매 프레임마다

충돌 가능한 오브젝트가 충돌이 발생하는지

하지 않는지 계속 체하며 충돌 관련하여

업데이트가 발생하겠죠.

 

 

이후 Start 씬이 종료되면 

모든 그룹들은 충돌될 수 있는 상태에서 

해제가 되어 충돌 불가능한 상태가 되는 것이죠.

 

 


강의 출처 : https://www.youtube.com/watch?v=V6cC0nf3FVw&list=PL4SIC1d_ab-ZLg4TvAO5R4nqlJTyJXsPK&index=27


'Win32 API > 기초' 카테고리의 다른 글

Win32 API 기초 : Collider (5)  (0) 2024.08.05
Win32 API 기초 : Collider (4)  (0) 2024.08.04
Win32 API 기초 : Collider (2)  (0) 2024.07.27
Win32 API 기초 : Collider (1)  (4) 2024.07.20
Win32 API 기초 : Resource Manager  (0) 2024.07.19