-
[007] 씬 전환Programming/Dev 2023. 3. 18. 11:52
DevLog 이번 게시글에서는 씬 전환을 구현하려고 한다.
일단은 '로고 씬' → '로그인 씬' 으로의 전환을 구현한다.
SceneManager::SceneManager() : m_scene{} { LogoScene::Instantiate(); if (LogoScene::IsInstanced()) { LogoScene::GetInstance()->OnCreate(); SetScene(LogoScene::GetInstance()); } }
현재, 씬 매니저 클래스가 생성될 때
로고 씬으로 시작되게 되어있다.
enum class FadeType { NONE, FADEIN, FADEOUT }; struct FadeInfo { FadeType type{ FadeType::NONE }; std::chrono::time_point<std::chrono::high_resolution_clock> startTime; std::chrono::time_point<std::chrono::high_resolution_clock> endTime; std::function<void()> callback{}; FLOAT alpha{ 1.0f }; };
씬을 전환할 때 페이드 인/아웃 효과를 주면서 전환하기 위해 위와 같은 구조체를 선언했다.
콜백 함수를 멤버 변수로 추가해서 페이드 인/아웃이 끝날 때 콜백 함수를 호출하려고 한다.
void SceneManager::SetFadeOut(FLOAT second, const std::function<void()>& callback) { m_fadeInfo.type = FadeType::FADEOUT; m_fadeInfo.startTime = std::chrono::high_resolution_clock::now(); m_fadeInfo.endTime = m_fadeInfo.startTime + std::chrono::milliseconds{ static_cast<UINT>(second * 1000) }; m_fadeInfo.callback = callback; m_fadeInfo.alpha = 1.0f; }
void LogoScene::Update(FLOAT deltaTime) { static BOOL isFirstUpdate{ TRUE }; if (isFirstUpdate) { SceneManager::GetInstance()->SetFadeOut(3.0f, []() { LoginScene::Instantiate(); auto sm{ SceneManager::GetInstance() }; sm->SetScene(LoginScene::GetInstance()); sm->SetFadeIn(3.0f); LogoScene::Destroy(); } ); isFirstUpdate = FALSE; } }
로고 씬의 첫번째 업데이트 때 로그인 씬으로 넘어가도록 했다.
페이드 아웃은 3초 동안 진행되며 끝나면 로그인 씬으로 넘어가고 3초 동안 페이드 인 되게 했다.
void SceneManager::UpdateFadeEffect() { using namespace std::chrono; using clock = high_resolution_clock; if (m_fadeInfo.type == FadeType::NONE) return; auto curr{ clock::now() }; milliseconds fadeDuration{ duration_cast<milliseconds>(m_fadeInfo.endTime - m_fadeInfo.startTime) }; // 페이드가 진행되는 총 시간 milliseconds timePassed{ duration_cast<milliseconds>(curr - m_fadeInfo.startTime) }; // 페이드 시작 후 지금까지 흐른 시간 if (m_fadeInfo.type == FadeType::FADEIN) m_fadeInfo.alpha = 1.0f - static_cast<float>(timePassed.count()) / static_cast<float>(fadeDuration.count()); else if (m_fadeInfo.type == FadeType::FADEOUT) m_fadeInfo.alpha = static_cast<float>(timePassed.count()) / static_cast<float>(fadeDuration.count()); if (curr > m_fadeInfo.endTime) { // 콜백에서 m_fadeInfo를 변경할 수 있기 때문에 초기화 후 콜백 함수를 호출한다. auto callback{ m_fadeInfo.callback }; m_fadeInfo = {}; callback(); } }
SetFadeOut, SetFadeIn 함수를 호출하면 위의 업데이트 코드가 작동한다.
페이드 시작, 끝 시간을 이용해서 현재의 알파값을 계산하고 페이드가 끝났다면 콜백 함수를 호출한다.
void SceneManager::RenderFadeEffect(const ComPtr<ID2D1DeviceContext2>& d2dContext) const { if (m_fadeInfo.type == FadeType::NONE) return; auto brush{ BrushPool::GetInstance()->GetBrush(BrushPool::BLACK) }; brush->SetOpacity(m_fadeInfo.alpha); d2dContext->SetTransform(MATRIX::Identity()); d2dContext->FillRectangle(RECTF{ 0.0f, 0.0f, 1920.0f, 1080.0f }, brush); brush->SetOpacity(1.0f); }
페이드 인/아웃 효과는 D2D를 이용하여 화면을 가득 채우는 사각형을 그리는 방법으로 구현했다.
굳이 최종 렌더링 결과를 D3D12 리소스로 복사하고 컴퓨터 셰이더를 이용하는 방법보단
이 방법이 훨씬 간편하고 성능 상 차이도 없을 것 같아서 이렇게 했다.
로고 -> 로그인 잘 작동한다.
이제 잠깐 진행이 멈춰있던 UI들을 구현해보려고 한다.
'Programming > Dev' 카테고리의 다른 글
[009] 플레이어 컨트롤 (0) 2023.06.06 [008] 에디트 컨트롤 (0) 2023.03.25 [006] 게임오브젝트 렌더링 (0) 2023.03.05 [005] Direct2D → DirectX12로 변경 (0) 2023.02.19 [004] 이미지 로딩 및 렌더링 (0) 2023.02.02