ABOUT ME

-

  • [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

    댓글