본문 바로가기
공부/DirectX3D

[DirectX3D] 로딩씬(씬전환)

by MY블로그 2023. 8. 21.

Loading Scene 추가

프레임워크에서 씬(Scene)를 여러개 만들고 씬전환화면으로 로딩씬을 제작하게되었습니다.

추가전

1.프로그램 실행 > 2.게임입장상호작용 > 3.실제플레이Scene > 4.엔딩Scene

추가전 후

1.프로그램 실행 > 2.게임입장상호작용 > 3. 로딩씬 > 4.실제플레이Scene > 5.엔딩Scene

로딩씬에서는 게임실행에 필요한 데이터들이 세팅되는 과정을 시각적으로 볼수있도록 하였습니다.

메인 화면에서 게임으로 진입시 실행에 필요한 데이터들을 로드(Load)하는동안 생각보다 긴 시간이 필요합니다. 때문에 멈춰있는 화면이 없는것처럼 보이도록 하기위하여 로딩씬을 추가합니다.

 

메인 화면에서 게임입장 버튼 글릭시 바로 로딩씬이 실행됩니다.

로딩씬에서는 스레드(thread)를 사용하여 로딩씬이 실행되는 동시에 다음씬 데이터의 로드를 실행합니다.

로딩씬에서 thread를 생성하고 함수를 통해서 Scene2를 추가 및 데이터 세팅(init())함수를 실행합니다.

로딩씬의 전역구간에 다음씬의 데이터 로드 현황을 시각적으로 보이게하기위한 변수들을 선언하고

다음씬의 전역구간에 extern 으로 같은 변수를 선언하여 데이터를 공유하여 로딩 게이지를 만들어줍니다.

extern 선언한 변수들은 Scene2의 init()함수에서 데이터가 세팅되는 구간마다 데이터를 갱신해주게 된다면 별도로 작동중인 스레드에서 데이터가 업데이트 되기때문에 LoadingScene 에서 해당 데이터의 업데이트된 값을 사용할 수 있습니다.

따라서 해당 변수들을 이용하여 로딩게이지나 로딩중인 데이터의 정보를 시각적으로 보는것이 가능합니다.

SceneManager 클래스 (h/cpp)

헤더 코드

#pragma once
class SceneManager :public Singleton<SceneManager>
{
private:
    map<string, Scene*> scenes;
    Scene* currentScene = nullptr;
    Scene* nextScene = nullptr;
    bool   isChanging = false;
    float  changingTime = 0.0f;
public:
    ~SceneManager();
    //씬 추가
    bool    AddScene(string key, Scene* value);
    //씬 삭제
    bool    DeleteScene(string key);
    //씬 변경
    Scene* ChangeScene(string key, float changingTime = 0.0f);
    //씬 가져오기
    Scene* GetScene(string key);
    //현재 씬 가져오기
    Scene* GetCurrentScene();

    void    Release();
    void    Update();
    void    LateUpdate();
    void    PreRender();
    void    Render();
    void    ResizeScreen();
};

CPP 코드

#include "framework.h"

SceneManager::~SceneManager()
{
    for (auto i = scenes.begin();
        i != scenes.end(); i++)
    {
        SafeDelete(i->second);
    }
    scenes.clear();
}

bool SceneManager::AddScene(string key, Scene* value)
{

    auto iter = scenes.find(key);

    if (iter != scenes.end())
    {
        delete value;
        return false;
    }
    scenes[key] = value;

    return true;
}

bool SceneManager::DeleteScene(string key)
{
    auto iter = scenes.find(key);
    if (iter == scenes.end())
    {
        return false;
    }
    SafeDelete(iter->second);
    scenes.erase(iter);

    return true;

}

Scene* SceneManager::ChangeScene(string key, float changingTime)
{
    Scene* temp = GetScene(key);
    if (temp)
    {
        nextScene = temp;
        nextScene->state = SceneState::FADEIN;
        this->changingTime = changingTime;
        if (currentScene)
        currentScene->state = SceneState::FADEOUT;
        if (changingTime <= 0.0f)
        {
            isChanging = true;
            if(currentScene)
            currentScene->Release();
            //nextScene->Init();
        }
    }
    return temp;
}

Scene* SceneManager::GetScene(string key)
{
    auto iter = scenes.find(key);
    if (iter == scenes.end())
    {
        return nullptr;
    }
    return iter->second;
}

Scene* SceneManager::GetCurrentScene()
{
    return currentScene;
}

void SceneManager::Release()
{
    if (currentScene)currentScene->Release();
}

void SceneManager::Update()
{
    if (changingTime > 0.0f)
    {
        changingTime -= DELTA;
        if (changingTime <= 0.0f)
        {
            isChanging = true;
            if (currentScene)
            {
                currentScene->Release();
            }
            //nextScene->Init();
        }
    }

    if (isChanging)
    {
        currentScene = nextScene;
        isChanging = false;
    }
    currentScene->Update();
}

void SceneManager::LateUpdate()
{
    if (isChanging)return;
    currentScene->LateUpdate();
}

void SceneManager::PreRender()
{
    if (isChanging)return;
    currentScene->PreRender();
}

void SceneManager::Render()
{
    if (isChanging)return;
    currentScene->Render();
}

void SceneManager::ResizeScreen()
{
    if (isChanging || !currentScene)return;
    currentScene->ResizeScreen();
}

 

댓글