충돌 여부를 판정할 수 있는 함수를 구현했는데,
실제 충돌 후 발생하는 동작은 오브젝트마다
다를 수 있습니다.
즉 충돌이 발생한 경우 오브젝트마다
다 다르게, 충돌 이벤트를 구현해야 하는 것이죠.
예를 들어 플레이어가 몬스터가 발사하는
미사일에 맞았을 때 10의 데미지를 받고,
플레이어가 몬스터와 직접 닿았을 때는
30의 데미지를 받으며 밀려나는 동작을
수행하고 싶습니다.
첫 상황은 플레이어의 Collider와
몬스터 미사일의 Collider와의 충돌이고,
두 번째 상황은 플레이어의 Collider와
몬스터의 Collider와의 충돌이죠.
그렇다고 이것을 구현하기 위해 Collider 클래스를 파생시켜
플레이어 타입의 Collider 자식 클래스를,
몬스터 타입의 Collider 자식 클래스,
미사일 타입의 Collider 자식 클래스를 만들어
어떤 Collider끼리의 충돌인지에 따라
다르게 동작할 수 있도록 구현한다고 하면
번거로운 작업이 되겠죠.
게다가 새로운 오브젝트 타입이 추가될 때마다
Collider 클래스를 상속하는 새로운 자식 클래스까지
같이 만들어야 하죠.
이러한 점을 해결하기 위해
C++의 다형성을 적극 활용하는 겁니다.
Collider는 멤버 m_pOwner를 통해 자신이
어떤 오브젝트의 Collider인지 알고 있습니다.
이걸 이용해서 위 코드처럼
Collider를 통해 충돌 관련 함수가 호출되면
Collider가 붙어 있는 오브젝트에도
같은 함수를 호출해 주는 겁니다.
물론 Collider는 멤버 m_pOwner는
오브젝트의 주소만 알고 있고
가리키는 오브젝트가 어떤 타입인지 모릅니다.
그러나 해당 오브젝트에 접근하기만 한다면
충돌 관련 함수들은 모두 virtual로 선언되었기 때문에
어떤 종류의 오브젝트인지 몰라도 호출하기만 한다면
알아서 상속 받은 클래스의 함수가 호출되어 동작하겠죠.
CMonster 클래스의 헤더 파일을 보시면
부모 클래스인 CObject 클래스가 갖고 있는,
상속받은 OnCollisionEnter 가상 함수를
자식 클래스에서 재정의하기 위해
다시 선언해 주는 모습입니다.
virtual과 override 키워드를 붙여
부모 클래스로부터 상속받은
가상 함수임을 명시하고 있죠.
CMonster 클래스에서 OnCollisionEnter 함수를
재정의한다면 위와 같이 구현할 수 있겠죠.
Collider는 자신이 붙어 있는 오브젝트의 주솟값을
포인터를 통해 저장하고 있죠? 그 포인터를 반환하는
GetOwnerObj 함수를 호출하고 지역 변수에 저장합니다.
그리고 지역 변수를 통해 해당 오브젝트에 접근하여
오브젝트의 이름을 반환하는 GetName 함수를 호출하여
해당 함수가 반환한 이름이 Missile과 같다면
몬스터가 데미지를 입거나 또는 제거되는
동작을 구현하면 되겠죠.
( CObject 클래스에는 wstring형 멤버 ObjName를 두어
CObject 클래스로부터 파생된 자식 클래스로 만든 객체가
어떤 클래스를 통해 만들어진 객체인지 나타내고 있습니다. )
하지만 오브젝트를 그냥 제거하는 것은 문제가 있습니다.
예를 들어 플레이어가 유도 미사일을 발사했습니다.
해당 유도 미사일은 몬스터 3을 향해 가고 있었죠.
유도 미사일은 몬스터 3의 좌푯값을 토대로
움직이며 좌푯값을 지속적으로 업데이트하여
몬스터 3이 움직여도 계속 따라가게 구현되었을 겁니다.
근데 유도 미사일이 몬스터 3에게 닿기 전에
몬스터 3가 씬에서 제거되었습니다.
그러면 유도 미사일은 몬스터 3의 좌푯값을 받고
있다가 사라진 좌푯값을 받게 되며 이상한 위치로 이동하게 되겠죠.
오브젝트의 제거 상황뿐만 아니라 씬이 바뀌는 상황이나
오브젝트가 생성되는 상황에서도 문제가 발생할 수 있습니다.
플레이어 1과 플레이어 2, 몬스터 1이 생성된 상태에서
갑자기 몬스터 1이 제거되고 플레이어 3이 생성되면
플레이어 1과 플레이어 2는 몬스터 1이 제거된 것을
인식할 수 없고, 플레이어 3만이 몬스터 1이 제거된 것을
인식할 수 있는 것이죠.
이러한 문제 상황을 방지하기 위해
이벤트 매니저를 추가할 겁니다.
다양한 이벤트 상황을 상황이 발생하자마자
실행시키지 않고 이벤트 매니저를 통해
발생할 이벤트를 갖고만 있다가
다음 프레임에 일괄적으로 실행하는 것이죠.
tEvent형 객체를 저장하고 있는 가변 배열( vector )형
멤버 m_vecEvent를 두어 각종 이벤트를 vector에
저장합니다. vector에 저장된 이벤트를 다음 프레임에
실행시키면 되겠죠.
이벤트를 나타내는 자료형( 구조체 ) tEvent는
어떤 이벤트인지 나타내는 eEvent와,
오브젝트가 생성되는 이벤트인 경우
생성된 오브젝트를 어느 그룹에 넣을 것인지에 대한 정보,
생성된 오브젝트의 주솟값 등 해당 이벤트에 필요한
정보를 저장하기 위한 lParam과 wParam으로 구성되어 있습니다.
이벤트 타입은
enum class를 통해 표현해 주었습니다.
오브젝트가 생성되는 이벤트와
오브젝트가 제거되는 이벤트,
씬이 교체되는 이벤트를 표현해 주었죠.
강의 출처 : https://www.youtube.com/watch?v=daTCS2xEAwM&list=PL4SIC1d_ab-ZLg4TvAO5R4nqlJTyJXsPK&index=31
'Win32 API > 기초' 카테고리의 다른 글
Win32 API 기초 : Event Manager (3) (0) | 2024.08.16 |
---|---|
Win32 API 기초 : Event Manager (2) (0) | 2024.08.15 |
Win32 API 기초 : Collider (6) (0) | 2024.08.10 |
Win32 API 기초 : Collider (5) (0) | 2024.08.05 |
Win32 API 기초 : Collider (4) (0) | 2024.08.04 |