2025. 4. 9. 00:05ㆍ원티드_언리얼RPG 2기/WinApi
여태까지 적이 등장하는 화면 , 플레이어 이동 , 배경을 모두 backbuffer를 생성하고 backbuffechdc 를 받아서 처리했다.
렌더링한 것들이 화면에 겹쳐 나오게 할 수 밖에 없었는데, 어떻게 하면 씬을 만들어서 관리를 할 수 있을까?
정답은 씬 매니저다. 씬 매니저를 만들어보자.
씬 매니저란?
씬 매니저는 게임의 다양한 화면(씬)을 관리하고 전환하는 핵심 컴포넌트입니다. 씬 간의 전환을 부드럽게 처리하고, 게임 상태를 효율적으로 관리합니다.
주요 기능
- 씬 등록: 게임에서 사용할 다양한 씬을 등록
- 씬 전환: 현재 씬에서 다른 씬으로 전환
- 씬 업데이트: 현재 활성화된 씬의 업데이트 처리
- 씬 렌더링: 현재 활성화된 씬의 화면 출력
구현 구조
- 싱글톤 패턴: 전역적인 접근을 위한 싱글톤 디자인 패턴 적용
- 맵 컨테이너: 씬 이름(키)으로 빠르게 씬에 접근할 수 있는 맵 구조 사용
- GameObject 상속: 모든 씬은 GameObject를 상속하여 일관된 인터페이스 제공
#pragma once
#include "GameObject.h"
class Image;
class EnemyManager;
class BattleScene : public GameObject
{
private:
Image* backGround;
EnemyManager* enemyManager;
public:
virtual HRESULT Init() override;
virtual void Release() override;
virtual void Update() override;
virtual void Render(HDC hdc) override;
BattleScene() {};
virtual ~BattleScene() {};
};
#include "BattleScene.h"
#include "Image.h"
#include "EnemyManager.h"
#include "CommonFunction.h"
HRESULT BattleScene::Init()
{
SetClientRect(g_hWnd, WINSIZE_X, WINSIZE_Y);
backGround = new Image();
if (FAILED(backGround->Init(TEXT("Image/BackGround.bmp"), WINSIZE_X, WINSIZE_Y)))
{
MessageBox(g_hWnd,
TEXT("Image/backGround.bmp 생성 실패"), TEXT("경고"), MB_OK);
return E_FAIL;
}
enemyManager = new EnemyManager();
enemyManager->Init();
return S_OK;
}
void BattleScene::Release()
{
if (enemyManager)
{
enemyManager->Release();
delete enemyManager;
enemyManager = nullptr;
}
if (backGround)
{
backGround->Release();
delete backGround;
backGround = nullptr;
}
}
void BattleScene::Update()
{
enemyManager->Update();
}
void BattleScene::Render(HDC hdc)
{
backGround->Render(hdc);
enemyManager->Render(hdc);
}
기존코드들(적, 배경생성) 을 battlescene.cpp와 헤더파일에 옮겼다.
씬 매니저 클래스를 만들어보자.
#pragma once
#include "Singleton.h"
#include "config.h"
class GameObject;
class SceneManager : public Singleton<SceneManager>
{
private:
map<string, GameObject*> mapScenes;
public:
static GameObject* currentScene;
static GameObject* loadingScene;
static GameObject* nextScene;
void Init();
void Release();
void Update();
void Render(HDC hdc);
HRESULT ChangeScene(string key);
GameObject* AddScene(string key, GameObject* scene);
};
#include "SceneManager.h"
#include "GameObject.h"
GameObject* SceneManager::currentScene = nullptr;
GameObject* SceneManager::loadingScene = nullptr;
GameObject* SceneManager::nextScene = nullptr;
void SceneManager::Init()
{
}
void SceneManager::Release()
{
map<string, GameObject*>::iterator iter;
for (iter = mapScenes.begin(); iter != mapScenes.end(); iter++)
{
if (iter->second)
{
iter->second->Release();
delete iter->second;
iter->second = nullptr;
}
}
mapScenes.clear();
ReleaseInstance();
}
void SceneManager::Update()
{
if (currentScene)
{
currentScene->Update();
}
}
void SceneManager::Render(HDC hdc)
{
if (currentScene)
{
currentScene->Render(hdc);
}
}
HRESULT SceneManager::ChangeScene(string key)
{
auto iter = mapScenes.find(key); // nextScene
if (iter == mapScenes.end())
{
return E_FAIL;
}
if (iter->second == currentScene)
{
return S_OK;
}
if (SUCCEEDED(iter->second->Init()))
{
if (currentScene)
{
currentScene->Release();
}
currentScene = iter->second;
return S_OK;
}
return E_FAIL;
}
GameObject* SceneManager::AddScene(string key, GameObject* scene)
{
if (scene == nullptr)
{
return nullptr;
}
auto iter = mapScenes.find(key);
if (iter != mapScenes.end())
{
return iter->second;
}
mapScenes.insert(make_pair(key, scene));
return scene;
}
씬을 (씬의 이름, 장면)을 키와 값으로 입력받는 map에 저장한다. 씬 전환을 위한 changeScene과 씬 추가를 위한 AddScene을 만들었다.
맵을 활용한 씬 관리
씬 매니저에서는 각 씬을 (씬의 이름, 장면)을 키와 값으로 입력받는 map 컨테이너에 저장합니다. 이 방식의 장점은 문자열 키를 통해 원하는 씬에 빠르게 접근할 수 있다는 점입니다.
HRESULT 반환 타입과 예외 처리
HRESULT는 Windows API에서 함수의 성공 또는 실패를 나타내는 데 사용되는 32비트 정수 타입입니다. 성공 또는 실패를 표현할 때 주로 다음 값을 사용합니다:
- S_OK: 함수가 성공적으로 실행됨 (0 값)
- E_FAIL: 일반적인 실패 상태 (0x80004005 값)
이런 방식의 예외 처리는 C++의 try-catch 방식보다 가볍고, Windows API와의 일관성을 유지할 수 있어 게임 프로그래밍에서 자주 사용됩니다.
A키와 D키입력으로 씬이 전환되고 윈도우 창사이즈까지 바뀐다.
'원티드_언리얼RPG 2기 > WinApi' 카테고리의 다른 글
Winapi 최종 프로젝트 회고록 (0) | 2025.05.07 |
---|---|
맵 에디터 만들기 (0) | 2025.04.29 |
타일맵 툴 만들기 / 타일맵 파일 저장,로드기능 만들기 (0) | 2025.04.08 |
탱크 만들기 (0) | 2025.03.10 |
0305 화면에 도형 그리기/ 마우스,키보드로 입출력받아 움직이기 (0) | 2025.03.06 |