WIN32API FrameWork/한단계씩 직접 구현

43. 충돌 처리 2 - 충돌체 1

hyrule 2022. 5. 30. 00:27

http://hyrule.tistory.com/111 

 

*** 공부 방법 ***

1. 코딩을 해야 하는 부분은 첫 부분에 변수나 함수, 메소드에 대한 선언이 코드블럭으로 표시되어 있다. //ex) MakeFunction(); 2. 코드블럭 하단에는 해당 선언에 대한 구현 로직이 작성되어 있다. 처

hyrule.tistory.com

 


- 이제 실제 충돌을 확인할 객체를 만들어주어야 한다.

 

class CCollider

- 실제로 CGameObject에 붙어서 충돌을 확인할 객체 -> 외부에서의 접근을 막고 friend class로 등록해 준다.

- CRef 클래스를 상속받아 참조 카운팅을 해준다.

- 소멸자를 순수가상함수로 선언하여, 상속을 받는 객체가 있어야만 쓸 수 있도록 추상 클래스로 만들어주자.

-- 충돌체의 모양 별로 클래스를 만들어서 사용할 것이기 때문.

--- 충돌체가 원인지, 사각형인지, 점인지, 선인지 등에 따라서 충돌 여부 확인 방법이 달라진다.

 

< m_OwnerScene >

- 자신이 속해있는 씬

< GetOwnerScene() > 메소드도 추가

 

< m_OwnerObj >

- 자신이 종속된 CGameObject

< GetScene() > 메소드도 추가


flag.h

< enum class EColliderType >

- 충돌체의 모양을 저장할 열거체

- 일단 가장 기본적인 충돌체 형태인 Box와 Circle만 만들어 놓는다.

< GetColliderType() > 메소드도 추가

 


class CCollider

< EColliderType m_ColliderType >
- 자신의 모양을 저장할 변수

 

 

< Vector2 m_Offset >

- 한 CGameObject가 여러개의 충돌체를 가지고있을 수도 있다.

- 이럴 경우 여러 충돌체가 게임오브젝트의 m_Pos로부터 얼마나 떨어져있을지를 등록해서 여러 군데에 충돌체를 놓을 수 있게 만드는 용도

< void SetOffset() >

- 위의 값을 설정해주는 메소드를 추가해준다. Vector2 또는 float 변수 두개를 받아서 처리 가능하도록 오버로딩해 준다.

 

 

< CollisionProfile* m_Profile >

- 충돌 프로필 정보

< GetProfile() > 메소드도 추가. const 포인터 타입으로 리턴

< SetCollisionProfile() > 메소드도 추가. 인자로 이름을 받아서 설정

 

 

< m_CollisionBegin, m_CollisionEnd >

- 두 변수 모두 void 타입, 인자로 CCollider 포인터 두개를 받는 함수 포인터로 만들어 준다.

-- 서로 충돌된 두 물체를 인자로 넘겨주는 것이다.

- 충돌했을 때 최적화를 위해 충돌 시작 / 충돌 종료시에만 발동한다.

 

 

< std::list<CSharedPtr<CCollider>> m_CollisionList > 

- 현재 프레임에 두 물체가 충돌되고 다음 프레임에도 두 물체가 충돌이 되었다면 계속 충돌이 되고 있는 상태로 판단해야 한다.

그런데 이런 판단을 하기 위해서는 이전 프레임에서 두 물체가 서로 충돌이 되었는지에 대한 정보가 필요할 것이다.

그러므로 충돌체는 이전 프레임에 충돌되었던 충돌체를 담아둘 필요가 있다.

- 이 리스트 안에 이전 프레임에서 충돌이 일어났던 충돌체 리스트들을 넣어놓음으로써 계속 충돌이 일어나고 있는 중인지 판단할 것이다.

< AddCollisionList() >

- 이 리스트에 인자로 들어온 CCollider*를 추가

< CheckCollisionList() >

- 이 리스트에 인자로 들어온 CCollider*이 있는지 확인. bool 타입으로 리턴

< DeleteCollisionList() >

- 이 리스트에서 인자로 들어온 CCollider*을 제거

< ClearCollisionList() >

- 충돌중인 충돌체 리스트를 비운다.(List.clear())

- 이 충돌체가 제거되었거나 할 때 사용하기 위한 목적

- 이 리스트를 clear하기 전에, 여기 들어있던 충돌체 포인터에 DeleteCollisionList(this)로 자신의 주소를 전달해서 목록에서 자신의 주소를 지워달라고 요청해주어야 한다. 안 해주면 댕글링 포인터가 발생하므로 주의

 

 

 

< CCollider(const CCollider& coll) >

- 복사 생성자를 만들어 준다.

- m_Scene과 m_Owner만 복사하지 말고 nullptr로 전달

 

 

< ~CCollider() >, < ClearCollisionList() >
- 일단 여기서 동적 할당된 객체들은 RefCount를 사용 중이므로 굳이 지우지 않아도 상관 없다.

- 그런데 문제는, m_CollisionList에 들어있는, 상대방 충돌체에서 발생한다.

 

- 충돌체 A와 충돌체 B가서로 충돌 중이라고 가정하자

-- A의 m_CollisionList에 충돌체에는 B 충돌체가 목록에 들어있을 것이고

B의 m_CollisionList에는 A의 충돌체가 들어있을 것이다.

-- 근데 만약 여기서 A가 사라지게 되면, B의 m_CollisionList에는 그대로 A가 남아있을 것이고, 그대로 댕글링 포인터가 되어버린다.

- 이를 막기 위해 A가 제거될 때 m_CollisionList에 들어있는 모든 충돌체에 접근해서 자신을 목록에서 제거하도록 해 주어야 한다. 

* 아까 만든 DeleteCollisionList() 메소드를 사용하면 된다.

 

 

< bool Init() >

- m_Profile을 "Default" 프로파일로 기본 설정되도록 해준다.

 

< void Update() >

< void PostUpdate() >

< void Render() >

 


GameFrameworkStepbyStep_43_Collision2.zip
4.10MB

 

댓글수0