Scene
Scene의 필요성
게임은 여러가지 오브젝트가 생성되고 렌더링 된다. 그렇다면 이것들은 어떻게 구분 짓고 관리를 해야될까?일반적으로 게임은 실행과 동시에 플레이가 시작되기 보다는 시작화면이나 로비같은 곳에서 시작하여 플레이가 시작되는 경우가 많다. 이런것으로 미루어 보아 게임안에 모든 오브젝트와 기능들을 넣어두고 관리하는것은 옳지 않다고 볼수 있을것이다. 언리얼엔진의 경우 Level이라는 Scene에서 여러가지 오브젝트와 컴포넌트를 관리한다.
Scene생성
Scene의 역활은 화면을 렌더링할때 화면에 있는 오브젝트나 로직을 관리하는 역할을 수행한다. 이번 프로젝트에서는 Scene과 Scene자체를 관리하는 SceneManager을 이용하여 Scene에 대해 알아보려고 한다. SceneManager와 Scene을 구분하는 이유는 Scene에 따라 오브젝트나 로직 및 라이팅이 달라질수 있기 때문에 모든것을 한곳에 넣고 관리하게 되면 복잡해질수 있기 때문에 나누어 관리한다.
게임에서 Scene은 여러종류가 존재할수 있기에 SceneType또한 정의해준다.
//Eunm.h
enum class SceneType
{
None,
DevScene,
GameScene,
EditScene
};
SceneManager 생성
그리고 SceneManager를 생성해준다.
//SceneManager.h
#pragma once
class SceneManager
{
DECLARE_SINGLE(SceneManager)
public:
void Init();
void Update();
void Render(HDC hdc);
void Clear();
public:
void ChangeScene(SceneType sceneType);
private:
class Scene* _scene;
SceneType _sceneType = SceneType::None;
};
SceneManager이 완성되었다면 Scene을 생성해준다.
//Scene.h
class Scene
{
public:
Scene();
virtual ~Scene();
virtual void Init()abstract;
virtual void Update()abstract;
virtual void Render(HDC hdc)abstract;
};
현재 정의한 DevScene/GameScene/EditScene은 Scene을 상속받아서 만들어주면 된다.
//"원하는"Scene.h
#include "Scene.h"
class "원하는"Scene :public Scene
{
public:
"원하는"Scene();
virtual ~"원하는"Scene();
virtual void Init()override;
virtual void Update()override;
virtual void Render(HDC hdc)override;
};
원하는 Scene을 정의했다면 SceneManager에서 장면 전환을 생성한다. 먼저 중복을 체크하고 Scene이 중복되지 않는다면 Scene에 덮어씌운다. 덮어 씌우기 전에 Scene이 존재할 경우 초기화 해준다.업데이트시 해당 Scene을 업데이트 해주고, 렌더링시 해당Scene을 렌더링해주는 것이 SceneManager의 주 된 역할이다.
//SceneManager.cpp
void SceneManager::Update()
{
if (_scene)
_scene->Update();
}
void SceneManager::Render(HDC hdc)
{
if (_scene)
_scene->Render(hdc);
}
void SceneManager::ChangeScene(SceneType sceneType)
{
if (_sceneType == sceneType)//중복체크
return;
Scene* newScene = nullptr;
switch (sceneType)
{
case SceneType::DevScene:
newScene = new DevScene();
break;
case SceneType::GameScene:
newScene = new GameScene();
break;
case SceneType::EditScene:
newScene = new EditScene();
break;
}
if (_scene) //기존에 Scene이 존재했다면 삭제
{
delete _scene;
_scene = nullptr;
}
_scene = newScene;
_sceneType = sceneType;
newScene->Init();
}
Game 적용
SceneManager가 완성되었다면 Game에도 적용시킨다.
//Game.cpp
void Game::Init(HWND hwnd)
{
GET_SINGLE(SceneManager)->Init();
GET_SINGLE(SceneManager)->ChangeScene(SceneType::"원하는"Scene);
}
void Game::Update()
{
GET_SINGLE(SceneManager)->Update();
}
void Game::Render()
{
GET_SINGLE(SceneManager)->Render(_hdc);
}
테스트하기
지금까지 생성해왔던 Scene과 SceneManager가 잘 작동하는지 테스트를 해볼 필요가 있다. Scene에서 사각형을 하나 만들고 InputManager를 이용하여 특정버튼을 누르면 x,y축으로 이동이 가능하도록 설정하였다. 이때 주의사항은 증가하는 x,y값은 DeltaTime에 비례해야되는것이다. 그렇지 않으면 각 컴퓨터마다 속도가 달라질수 있기 때문이다.
문제점
테스트를 해보면 위와 같이 검정색의 잔상이 남아 있게 된다. 이 검정색 잔상은 하나의 도화지에 모든것을 그리고 있기 때문에 생기는 현상이다. 그렇다면 두개의 도화지에 번갈아 그린다면 이 현상은 해결될 것인가?
다음 포스팅에서는 두가지 도화지를 이용하여 랜더링하는 것에 대해 알아보고자 한다.
'게임엔진 > 윈도우API' 카테고리의 다른 글
윈도우API)8. 벡터 (0) | 2022.12.18 |
---|---|
윈도우API)7. 삼각함수 (0) | 2022.12.18 |
윈도우API)5. 오브젝트 설계 (0) | 2022.12.17 |
윈도우API)2. 프레임워크 제작 (0) | 2022.12.15 |
윈도우API)1. 기본템플릿 분석 (0) | 2022.12.10 |
댓글