본문 바로가기
Win32 API/기초

Win32 API 기초 : Event Manager (2)

글: 시플마 2024. 8. 15.

이벤트 매니저를 통한

오브젝트의 생성과 제거를 구현하겠습니다.

 

CEventMgr 클래스의 헤더 파일을 보시면

 

vector형 멤버 m_vecDeadObj가 추가되었습니다.

 

해당 멤버는 제거될 예정인 오브젝트를 저장하는 vector이죠.

 

생성되는 오브젝트와 다르게, 제거할 오브젝트는 따로 보관하고 있죠.

 

이유는 만약 현재 프레임이 58 프레임이고

오브젝트 1이 제거되었다고 합시다.

 

그래서 58 프레임 마지막 순간에 오브젝트 1을 제거하고

이를 다음 프레임인 59 프레임에 적용시키려고 합니다.

 

이때 문제가 될 수 있는 점은 오브젝트 1과 관련된

다른 오브젝트들은 오브젝트 1이 제거된 사실을 

59 프레임 때 모른다는 것이죠.

 

그래서 관련된 오브젝트들이 오브젝트 1에 접근하려고

하면 실제로는 제거가 되었으므로 문제가 발생할 것입니다.

 

 

이를 해결하려면 58 프레임에서

오브젝트 1을 바로 제거하지 않고

제거될 예정인 상태로만 만들고,

59 프레임에서 오브젝트 1과 관련된

오브젝트들은 제거 예정인 오브젝트 1과의

관계를 끊습니다. 그러고 나서 제거합니다.

 

그럼 60 프레임에서는 오브젝트 1이 

제거된 상태로 렌더링이 되겠죠.

 

정리하면 58 프레임에서 제거하고

59 프레임에 이를 적용하는 것이 아닌,

58 프레임에서 제거될 예정이라고만 설정하고

59 프레임에서 관련된 오브젝트와의 참조를 끊습니다.

그리고 59 프레임에서 오브젝트 1을 제거하면

60 프레임에서 오브젝트 1은 제거된 상태일 겁니다.

 

 

다시 헤더 파일로 돌아와서

 

기존에 있던 update 함수가 보이고,

AddEvent 함수와 Excute 함수가

추가된 것을 확인할 수 있습니다.

 

 

먼저 update 함수의 정의부터 살펴보죠.

 

코어 매니저에서 다른 매니저의 update가 다 실행되고 난 후에

이벤트 매니저의 update 함수가 실행될 겁니다.

 

제거될 예정인 오브젝트가 들어있는 vector를

하나씩 순회하면서 delete 시켜 줍니다.

 

그리고 해당 vector를 clear 시키죠.

 

 

다음에는 실행해야 하는 이벤트가 모인 

vector인 m_vecEvent를 하나씩 순회하면서

Excute 함수를 호출한 후 m_vecEvent를 clear 시킵니다.

 

clear 시키지 않으면 m_vecEvent에 

실행해야 할 이벤트 목록이 계속 남아있어

실행이 된 이벤트임에도 프레임마다 

또 실행되며 문제가 생기겠죠.

 

 

Excute 함수는 

 

해당 vector 인덱스에 들어있는 이벤트가

어떤 이벤트인지 파악하여 switch 문을 통해

적절한 이벤트를 실행하는 함수입니다.

 

인자로 받은 tEvent형 _event의 멤버

eEvent에는 어떤 이벤트인지에 대한 정보가 들었죠.

 

여기에 있는 값을 통해 switch 문에 접근하는 것이죠.

 

이벤트 타입이 CREATE_OBJECT라면

_event의 멤버 lParam에 들어있는 주솟값을

CObject형 포인터 NewObj를 통해 가리킵니다.

 

_event의 멤버 wParam에 들어있는

생성될 오브젝트의 그룹 타입 정보를

groupType에 저장하고, 씬 매니저를 통해

현재 씬에 접근하여 AddObject 함수의

인자로 NewObj와 groupType를 넘깁니다.

 

그러면 현재 씬에는 NewObj가 가리키는 

주솟값에 있는 오브젝트가 생성되겠죠.

 

이때 생성된 오브젝트는 groupType에

저장된 그룹에 속하겠죠.

 

 

evenType에 저장된 이벤트 타입이 

DELETE_OBJECT라면 오브젝트 제거

이벤트라는 의미겠죠.

 

_event의 멤버 lParam에 저장된 주솟값에

접근하면 제거할 오브젝트가 존재할텐데

이를 CObject형 포인터 deadObj가 가리키게 하고

해당 오브젝트에 접근하여 SetDead 함수를 호출합니다.

 

오브젝트마다

 

m_bAlive라는 멤버를 갖고 있습니다. 

 

오브젝트가 살아있으면 true를,

제거된 상태라면 false를 저장하죠.

 

오브젝트가 죽었는지 알려주는

 

IsDead 함수와 해당 오브젝트가

제거될 오브젝트로 설정해 주는 SetDead 함수가 있죠.

 

SetDead 함수를 통해 

 

deadObj가 가리키는 오브젝트를

제거될 예정임을 나타내는 것이죠.

 

그리고 그 오브젝트를 

m_vecDeadObj에 삽입해 줍니다.

 

 

이렇게 하면

 

다음 프레임에 update 함수가 실행되면

m_vecDeadObj에 삽입된 오브젝트가

22번째 줄에 있는 코드에 의해 제거가 되겠죠.

 

 

 


 

 

 

 

위에서 작성한 코드가 잘 작동하는지

확인하기 위해 플레이어의 발사체

오브젝트를 생성하는 부분에 

 

CreateObject 함수를 호출하였습니다. 

 

인자로 발사체를 가리키는 포인터와

발사체가 속한 그룹 정보를 넘겨주고 있네요.

 

 

CreateObject 함수는

 

오브젝트를 생성하기 위한 코드를 

매번 작성하기 힘드니 함수로 따로 만든 것이죠.

( 이렇게 자주 사용될 것 같은 함수를 func.h 파일에 선언하고, func.cpp에

정의했습니다. 이렇게 하면 마치 전역 함수처럼 사용할 수 있게 되는 것이죠.

미리 컴파일된 헤더 파일이 존재하는 경우, 반드시 미리 컴파일된 헤더 파일에

func.h 파일을 include해야 하고, func.cpp 파일에는 미리 컴파일된 헤더 파일을

include해야 에러가 발생하지 않습니다. ) 

 

tEvent형 변수 even를 만들어

어떤 이벤트인지 나타내는 멤버 eEvent에는 

CREATE_OBJECT 값을 저장하고,

lParam에는 생성시킬 오브젝트의 주솟값을,

wParam에는 해당 오브젝트의 그룹을 저장합니다.

 

 

여기서 DWORD_PTR 형변환해 주고 있는데,

64Bit 환경에서는 8Byte로, 32Bit 환경에서는

4Byte로 설정되어 사용되는 자료형이죠.

 

현재 64Bit 환경이므로 멤버 lParam과

wParam은 8Byte의 크기를 갖겠네요.

 

 

이렇게 멤버들의 값이 설정된 even을

이벤트 매니저의 AddEvent 함수의 인자로

넘깁니다.

 

AddEvent 함수는

 

실행해야 할 이벤트가 저장된

이벤트 매니저의 멤버 m_vecEvent에

인자로 받은 이벤트를 저장하는 함수입니다.

 

 

이렇게 m_vecEvent에 저장된 이벤트들을

프레임마다 실행되는 update 함수를 통해

실행하게 될 겁니다.

 

 


강의 출처 : https://www.youtube.com/watch?v=Hccu_MI3th0