현재 프로그램은 오브젝트를 바로 화면에 띄우고 있습니다.
이 구조를 바꾸어서 오브젝트가 포함되는 씬을 만들고
이 씬들을 관리하는 씬 매니저를 만들어서
프로그램을 관리하도록 하겠습니다.
일단 아래 코드처럼
define.h 파일에 GROUP_TYPE이라는
enum class를 만들겠습니다.
유형에 따라 기본 오브젝트인 DEFALUT,
발사체인 MISSILE, PLAYER와 MONSTER로
분류를 하겠습니다. 참고로 UI 같은 것도 모두 오브젝트입니다.
당장은 4개의 오브젝트 유형이 존재하지만 이후에
더 추가할 수도 있습니다. 32개의 유형이 존재한다고
가정하고 END를 32라고 보겠습니다.
씬들도 타입을 분류하도록 하겠습니다.
게임을 제작하기 위한 TOOL 씬,
게임 시작 장면인 START, 그리고 스테이지별로
장면을 다르게 하도록 하겠습니다.
오브젝트들이 포함되는
씬 클래스를 만들어 보도록 하죠.
Scene라는 이름의 필터를 만들고
그 안에 CScene 클래스를 만들도록 하겠습니다.
CScene.h 파일을 보시면
3번째 줄에서 CObject 클래스를 전방 선언하고 있습니다.
씬에는 오브젝트를 포함하고 있으므로
CScene 클래스에서는 CObject 자료형을 필요로 합니다.
CScene 클래스에서는 CObject를 인식하게 하는 방법으로
include 전처리 지시문을 사용하여 CObject.h 파일을 포함시킬 수도 있습니다.
하지만 이렇게 할 경우 CScene.h 파일을 컴파일할 때 CObject.h 파일을
다시 검사하게 됩니다. CObject.h 파일이 수정될 경우 CScene.h 파일에
영향을 주기 때문에 혹시 수정된 사항이 있는지 컴파일 단계에서
검사하게 되는 것이죠.
이때 CObject 클래스를 전방 선언하기만 하면
CScene.h 파일에서 CObject를 인식하게 할 수도 있으며
CObject.h 파일을 다시 검사하지도 않아 속도를 높일 수 있습니다.
대신 CObject 클래스의 구체적인 내용을
CScene.h 파일에서는 모르기 때문에
CObject 클래스를 통해 객체를 직접 만들지는 못하고
CObject 클래스를 통해 만든 객체를 가리키는
포인터만 선언해 줄 수 있습니다.
8번째 줄에서 vector를 CObject*형으로 선언하고 있습니다.
vector의 인덱스 하나하나가 오브젝트를 가리키는 포인터인 것이죠.
이러한 vector가 32개 선언되었습니다.
실제로 의미있는 vector는 4개겠죠.
각 vector는 DEFAULT 그룹의 오브젝트,
MISSILE 그룹의 오브젝트,
PLAYER 그룹의 오브젝트,
MONSTER 그룹의 오브젝트들을
가리키고 있을 겁니다.
9번째 줄에서는 wstring형
멤버 m_sceneName를 선언하였습니다.
각 씬에 이름을 저장해 주면
디버깅 과정에서 편하게 인식할 수 있을 겁니다.
12번째 줄의 SetName 함수는
인자로 받은 문자열을
멤버 m_sceneName에 대입합니다.
13번째 줄의 GetName 함수는
멤버 m_sceneName에 저장된 문자열을
반환하는 함수입니다.
17번째 줄의 있는 소멸자 앞에
virtual 키워드가 붙었습니다.
현재 CScene 클래스는 다양한 씬들이
기본적으로 갖추고 있는 틀, 즉 부모 클래스로
다양한 자식 클래스로 파생될 수 있습니다.
부모 클래스인 CScene 클래스를 상속하여
만든 자식 클래스인 CScene_Start 클래스가
있다고 해 보죠.
그리고 CScene_Start 클래스를 통해
게임 시작 장면인 객체를 만들었습니다.
이때 부모 클래스인 CScene 클래스의
소멸자의 virtual 키워드를 붙이지 않으면
게임 시작 장면인 객체가 소멸될 때
CScene 클래스인 부분만 소멸되어
자식 클래스인 부분이 그대로 남게 됩니다.
하지만 부모 클래스 소멸자에 virtual 키워드를
붙이게 되면 자식 클래스로 만든 객체가
소멸될 때 알아서 부모 클래스 부분과
자식 클래스 부분이 모두 소멸하게 되죠.
이와 같은 이유로 CObject 클래스의 소멸자에도
virtual 키워드를 붙여주어야 합니다.
씬에 대한 클래스도 만들었으니,
이제 이러한 씬들을 프로그램에서 관리할 수 있도록
CSceneMgr 클래스를 만들어 주도록 하겠습니다.
Manager 필터 안에
SceneMgr 필터를 만들고
CSceneMgr 클래스 파일을
만들었습니다.
CSceneMgr.h 파일을 봅시다.
3번째 줄에서 CScene 클래스를 전방 선언해 주었습니다.
씬 매니저를 싱글톤 객체로 할 것이기 때문에
7번째 줄에서 직접 만든 SINGLE 매크로를 통해
씬 매니저 객체를 생성해 줄 겁니다.
10번째 줄에 있는 멤버 m_arrScene는
씬들을 가리키는 포인터들을 저장하는 배열입니다.
배열의 각 칸에는 CScene 클래스로 만든 객체를 가리키는
포인터, 즉 씬 객체들을 가리키는 포인터를 저장하고 있죠.
11번째 줄에 있는 멤버 m_pCurScene는
프로그램에서 현재 진행하고 있는 씬을
가리키게 될 것입니다.
이러한 멤버들을 14번째 줄의 init 함수를 통해
초기화를 해 줄 겁니다.
CSceneMgr.cpp 파일을 살펴봅시다.
3번째 줄에서 CScene_Start.h 파일을
포함시키고 있습니다.
해당 파일은
Scene 필터 속 Scene_Start 필터 안의
만든 CScene 클래스의 자식 클래스입니다.
Ctrl + Shift + X 단축키를 통해 클래스 마법사를 실행하고
클래스 이름에는 새로 만들 자식 클래스의 이름을,
기본 클래스에는 부모 클래스의 이름을 넣으면
부모 클래스를 상속한 자식 클래스를 만들 수 있습니다.
CScene_Start.h 파일에는 아직 특별한
코드가 작성되어 있지는 않습니다.
5번째 줄에서 기본 생성자를 통해
두 멤버를 nullptr로 초기화해 주고 있습니다.
먼저 22번째 줄의 init 함수의 정의를 살펴보면
24번째 줄에서 m_arrScene의 0번 인덱스가
CScene_Start형으로 동적 할당된 공간을 가리키게 합니다.
아직 만들지는 않았지만 앞으로 다양한 씬들을 만들면
25 ~ 27번째 줄처럼 해당 인덱스의 용도에 맞는
자료형(클래스)으로 동적 할당해 주면 됩니다.
29번째 줄에서 init 함수가 호출될 시점에
출력할 씬을 m_pCurScene가 가리키게 하고 있습니다.
현재는 Start 장면밖에 없으므로 일단
m_arrScene[(UINT)SCENE_TYPE::START]가 가리키는
동적 할당된 공간을 m_pCurScene가 가리키게 합시다.
11번째 줄의 소멸자를 보시면
반복문이 SCENE_TYPE의 END값만큼
돌면서 m_arrScene가 가리키는 동적 할당된
공간들을 delete해 주고 있습니다.
근데 제대로 존재하는 건 m_arrScene의
0번 인덱스가 가리키는 Start 장면밖에 없으므로
1, 2, 3번 인덱스는 아무것도 가리키지 않고 있습니다.
이 상태에서 delete를 해 주면 문제가 있죠.
그래서 15번째 줄의 if 문을 통해 해당 인덱스가
동적 할당된 특정 공간을 가리키고 있어
nullptr가 아닌 경우에만 delete를 해 주고 있죠.
강의 출처 : https://www.youtube.com/watch?v=_IeoFRrYPiY&list=PL4SIC1d_ab-ZLg4TvAO5R4nqlJTyJXsPK&index=15
'Win32 API > 기초' 카테고리의 다른 글
Win32 API 기초 : Win32API Object (1) (0) | 2024.07.06 |
---|---|
Win32 API 기초 : Scene Manager (2) (0) | 2024.07.05 |
Win32 API 기초 : Key Manager (2) (2) | 2024.07.03 |
Win32 API 기초 : Key Manager (1) (0) | 2024.07.01 |
Win32 API 기초 : Double Buffering (0) | 2024.06.30 |