게임의 UWP 앱 프레임워크 정의Define the game's UWP app framework

참고

이 항목은 DirectX 자습서 시리즈 를 사용 하 여 단순 유니버설 Windows 플랫폼 (UWP) 게임 만들기 의 일부입니다.This topic is part of the Create a simple Universal Windows Platform (UWP) game with DirectX tutorial series. 해당 링크의 항목은 계열의 컨텍스트를 설정 합니다.The topic at that link sets the context for the series.

UWP (유니버설 Windows 플랫폼) 게임을 코딩 하는 첫 번째 단계는 응용 프로그램 개체가 Windows와 상호 작용할 수 있도록 하는 프레임 워크를 빌드하는 것입니다 .이 프레임 워크는 일시 중단 다시 시작 이벤트 처리, 창 포커스의 변경, 맞추기 등의 Windows 런타임 기능을 포함 합니다.The first step in coding a Universal Windows Platform (UWP) game is building the framework that lets the app object interact with Windows, including Windows Runtime features such as suspend-resume event handling, changes in window focus, and snapping.

목표Objectives

  • UWP (유니버설 Windows 플랫폼) DirectX 게임의 프레임 워크를 설정 하 고 전체 게임 흐름을 정의 하는 상태 시스템을 구현 합니다.Set up the framework for a Universal Windows Platform (UWP) DirectX game, and implement the state machine that defines the overall game flow.

참고

이 항목의 작업을 수행 하려면 다운로드 한 Simple3DGameDX 샘플 게임의 소스 코드를 확인 합니다.To follow along with this topic, look in the source code for the Simple3DGameDX sample game that you downloaded.

소개Introduction

게임 프로젝트 설정 항목에서 IFrameworkViewSourceIFrameworkView 인터페이스 뿐만 아니라 wwinmain 함수를 도입 했습니다.In the Set up the game project topic, we introduced the wWinMain function as well as the IFrameworkViewSource and IFrameworkView interfaces. Simple3DGameDX 프로젝트의 소스 코드 파일에 정의 된 것 처럼 볼 수 있는 App 클래스는 App.cpp 뷰 공급자 팩터리뷰 공급자로사용 됩니다. Simple3DGameDXWe learned that the App class (which you can see defined in the App.cpp source code file in the Simple3DGameDX project) serves as both view-provider factory and view-provider.

이 항목에서 선택 하 고 게임의 클래스에서 IFrameworkView의 메서드를 구현 하는 방법에 대 한 자세한 정보를 살펴보겠습니다.This topic picks up from there, and goes into much more detail about how the App class in a game should implement the methods of IFrameworkView.

App:: Initialize 메서드The App::Initialize method

응용 프로그램을 시작할 때 Windows에서 호출 하는 첫 번째 메서드는 IFrameworkView:: Initialize의 구현입니다.Upon application launch, the first method that Windows calls is our implementation of IFrameworkView::Initialize.

구현은 해당 이벤트를 구독 하 여 일시 중단 (및 가능한 이후 다시 시작) 이벤트를 처리할 수 있도록 하는 것과 같이 UWP 게임의 가장 기본적인 동작을 처리 해야 합니다.Your implementation should handle the most fundamental behaviors of a UWP game, such as making sure that the game can handle a suspend (and a possible later resume) event by subscribing to those events. 여기에서 디스플레이 어댑터 장치에 액세스할 수도 있으므로 장치에 종속 된 그래픽 리소스를 만들 수 있습니다.We also have access to the display adapter device here, so we can create graphics resources that depend on the device.

void Initialize(CoreApplicationView const& applicationView)
{
    applicationView.Activated({ this, &App::OnActivated });

    CoreApplication::Suspending({ this, &App::OnSuspending });

    CoreApplication::Resuming({ this, &App::OnResuming });

    // At this point we have access to the device. 
    // We can create the device-dependent resources.
    m_deviceResources = std::make_shared<DX::DeviceResources>();
}

가능 하면 원시 포인터를 사용 하지 않는 것이 좋습니다 (항상 가능한 경우).Avoid raw pointers whenever possible (and it's nearly always possible).

  • Windows 런타임 형식의 경우 포인터를 완전히 방지 하 고 스택에 값을 생성할 수 있습니다.For Windows Runtime types, you can very often avoid pointers altogether and just construct a value on the stack. 포인터가 필요한 경우 winrt:: com_ptr 을 사용 합니다 (곧 예제가 표시 됨).If you do need a pointer, then use winrt::com_ptr (we'll see an example of that soon).
  • 고유 포인터의 경우 std:: unique_ptrstd:: make_unique를 사용 합니다.For unique pointers, use std::unique_ptr and std::make_unique.
  • 공유 포인터의 경우 std:: shared_ptrstd:: make_shared를 사용 합니다.For shared pointers, use std::shared_ptr and std::make_shared.

App:: SetWindow 메서드The App::SetWindow method

초기화후 Windows에서는 IFrameworkView:: setwindow의 구현을 호출 하 여 게임의 주 창을 나타내는 CoreWindow 개체를 전달 합니다.After Initialize, Windows calls our implementation of IFrameworkView::SetWindow, passing a CoreWindow object representing the game's main window.

앱:: SetWindow에서 창 관련 이벤트를 구독 하 고 일부 창과 표시 동작을 구성 합니다.In App::SetWindow, we subscribe to window-related events, and configure some window and display behaviors. 예를 들어 마우스 포인터는 마우스 및 터치 컨트롤에서 사용할 수 있는 CoreCursor 클래스를 통해 생성 됩니다.For example, we construct a mouse pointer (via the CoreCursor class), which can be used by both mouse and touch controls. 또한 window 개체를 장치 종속 리소스 개체에 전달 합니다.We also pass the window object to our device-dependent resources object.

게임 흐름 관리 항목에서 이벤트 처리에 대해 자세히 설명 합니다.We'll talk more about handling events in the Game flow management topic.

void SetWindow(CoreWindow const& window)
{
    //CoreWindow window = CoreWindow::GetForCurrentThread();
    window.Activate();

    window.PointerCursor(CoreCursor(CoreCursorType::Arrow, 0));

    PointerVisualizationSettings visualizationSettings{ PointerVisualizationSettings::GetForCurrentView() };
    visualizationSettings.IsContactFeedbackEnabled(false);
    visualizationSettings.IsBarrelButtonFeedbackEnabled(false);

    m_deviceResources->SetWindow(window);

    window.Activated({ this, &App::OnWindowActivationChanged });

    window.SizeChanged({ this, &App::OnWindowSizeChanged });

    window.Closed({ this, &App::OnWindowClosed });

    window.VisibilityChanged({ this, &App::OnVisibilityChanged });

    DisplayInformation currentDisplayInformation{ DisplayInformation::GetForCurrentView() };

    currentDisplayInformation.DpiChanged({ this, &App::OnDpiChanged });

    currentDisplayInformation.OrientationChanged({ this, &App::OnOrientationChanged });

    currentDisplayInformation.StereoEnabledChanged({ this, &App::OnStereoEnabledChanged });

    DisplayInformation::DisplayContentsInvalidated({ this, &App::OnDisplayContentsInvalidated });
}

App:: Load 메서드The App::Load method

이제 주 창이 설정 되었으므로 IFrameworkView:: Load 구현이 호출 됩니다.Now that the main window is set, our implementation of IFrameworkView::Load is called. 로드초기화setwindow보다 게임 데이터 또는 자산을 미리 인출 하는 더 좋은 장소입니다.Load is a better place to pre-fetch game data or assets than Initialize and SetWindow.

void Load(winrt::hstring const& /* entryPoint */)
{
    if (!m_main)
    {
        m_main = winrt::make_self<GameMain>(m_deviceResources);
    }
}

여기에서 볼 수 있듯이 실제 작업은 여기에서 만든 GameMain 개체의 생성자에 게 위임 됩니다.As you can see, the actual work is delegated to the constructor of the GameMain object that we make here. GameMain 클래스는 및에 정의 GameMain.h 되어 GameMain.cpp 있습니다.The GameMain class is defined in GameMain.h and GameMain.cpp.

GameMain:: GameMain 생성자The GameMain::GameMain constructor

GameMain 생성자와이 생성자가 호출 하는 다른 멤버 함수는 게임 개체를 만들고 그래픽 리소스를 로드 하 고 게임의 상태 시스템을 초기화 하는 일련의 비동기 로드 작업을 시작 합니다.The GameMain constructor (and the other member functions that it calls) begins a set of asynchronous loading operations to create the game objects, load graphics resources, and initialize the game's state machine. 또한 시작 상태 또는 전역 값을 설정 하는 것과 같이 게임을 시작 하기 전에 필요한 준비 작업을 수행 합니다.We also do any necessary preparations before the game begins, such as setting any starting states or global values.

Windows에서는 게임에서 입력 처리를 시작 하기 전에 수행할 수 있는 시간을 제한 합니다.Windows imposes a limit on the time your game can take before it begins processing input. 따라서 여기서와 같이 asyc를 사용 하면 시작 하는 작업이 백그라운드에서 계속 진행 되는 동안 부하가 빠르게 반환 될 수 있음을 의미 합니다.So using asyc, as we do here, means that Load can return quickly while the work that it has begun continues in the background. 로드 시간이 오래 걸리거나 많은 리소스가 있는 경우 사용자에 게 자주 업데이트 되는 진행률 표시줄을 제공 하는 것이 좋습니다.If loading takes a long time, or if there are lots of resources, then providing your users with a frequently updated progress bar is a good idea.

비동기 프로그래밍을 처음 접하는 경우에는 c + +/WinRT를 사용한 동시성 및 비동기 작업을 참조 하세요.If you're new to asynchronous programming, then see Concurrency and asynchronous operations with C++/WinRT.

GameMain::GameMain(std::shared_ptr<DX::DeviceResources> const& deviceResources) :
    m_deviceResources(deviceResources),
    m_windowClosed(false),
    m_haveFocus(false),
    m_gameInfoOverlayCommand(GameInfoOverlayCommand::None),
    m_visible(true),
    m_loadingCount(0),
    m_updateState(UpdateEngineState::WaitingForResources)
{
    m_deviceResources->RegisterDeviceNotify(this);

    m_renderer = std::make_shared<GameRenderer>(m_deviceResources);
    m_game = std::make_shared<Simple3DGame>();

    m_uiControl = m_renderer->GameUIControl();

    m_controller = std::make_shared<MoveLookController>(CoreWindow::GetForCurrentThread());

    auto bounds = m_deviceResources->GetLogicalSize();

    m_controller->SetMoveRect(
        XMFLOAT2(0.0f, bounds.Height - GameUIConstants::TouchRectangleSize),
        XMFLOAT2(GameUIConstants::TouchRectangleSize, bounds.Height)
        );
    m_controller->SetFireRect(
        XMFLOAT2(bounds.Width - GameUIConstants::TouchRectangleSize, bounds.Height - GameUIConstants::TouchRectangleSize),
        XMFLOAT2(bounds.Width, bounds.Height)
        );

    SetGameInfoOverlay(GameInfoOverlayState::Loading);
    m_uiControl->SetAction(GameInfoOverlayCommand::None);
    m_uiControl->ShowGameInfoOverlay();

    // Asynchronously initialize the game class and load the renderer device resources.
    // By doing all this asynchronously, the game gets to its main loop more quickly
    // and in parallel all the necessary resources are loaded on other threads.
    ConstructInBackground();
}

winrt::fire_and_forget GameMain::ConstructInBackground()
{
    auto lifetime = get_strong();

    m_game->Initialize(m_controller, m_renderer);

    co_await m_renderer->CreateGameDeviceResourcesAsync(m_game);

    // The finalize code needs to run in the same thread context
    // as the m_renderer object was created because the D3D device context
    // can ONLY be accessed on a single thread.
    // co_await of an IAsyncAction resumes in the same thread context.
    m_renderer->FinalizeCreateGameDeviceResources();

    InitializeGameState();

    if (m_updateState == UpdateEngineState::WaitingForResources)
    {
        // In the middle of a game so spin up the async task to load the level.
        co_await m_game->LoadLevelAsync();

        // The m_game object may need to deal with D3D device context work so
        // again the finalize code needs to run in the same thread
        // context as the m_renderer object was created because the D3D
        // device context can ONLY be accessed on a single thread.
        m_game->FinalizeLoadLevel();
        m_game->SetCurrentLevelToSavedState();
        m_updateState = UpdateEngineState::ResourcesLoaded;
    }
    else
    {
        // The game is not in the middle of a level so there aren't any level
        // resources to load.
    }

    // Since Game loading is an async task, the app visual state
    // may be too small or not have focus. Put the state machine
    // into the correct state to reflect these cases.

    if (m_deviceResources->GetLogicalSize().Width < GameUIConstants::MinPlayableWidth)
    {
        m_updateStateNext = m_updateState;
        m_updateState = UpdateEngineState::TooSmall;
        m_controller->Active(false);
        m_uiControl->HideGameInfoOverlay();
        m_uiControl->ShowTooSmall();
        m_renderNeeded = true;
    }
    else if (!m_haveFocus)
    {
        m_updateStateNext = m_updateState;
        m_updateState = UpdateEngineState::Deactivated;
        m_controller->Active(false);
        m_uiControl->SetAction(GameInfoOverlayCommand::None);
        m_renderNeeded = true;
    }
}

void GameMain::InitializeGameState()
{
    // Set up the initial state machine for handling Game playing state.
    ...
}

생성자에 의해 시작 되는 작업 시퀀스에 대 한 개요는 다음과 같습니다.Here's an outline of the sequence of work that's kicked off by the constructor.

  • GameRenderer형식의 개체를 만들고 초기화 합니다.Create and initialize an object of type GameRenderer. 자세한 내용은 렌더링 프레임 워크 I: 렌더링 소개를 참조 하세요.For more information, see Rendering framework I: Intro to rendering.
  • Simple3DGame형식의 개체를 만들고 초기화 합니다.Create and initialize an object of type Simple3DGame. 자세한 내용은 기본 게임 개체 정의를 참조 하세요.For more information, see Define the main game object.
  • 게임 UI 컨트롤 개체를 만들고 게임 정보 오버레이를 표시 하 여 리소스 파일이 로드 될 때 진행률 표시줄을 표시 합니다.Create the game UI control object, and display game info overlay to show a progress bar as the resource files load. 자세한 내용은 사용자 인터페이스 추가를 참조 하세요.For more information, see Adding a user interface.
  • 컨트롤러 개체를 만들어 컨트롤러 (터치, 마우스 또는 Xbox 무선 컨트롤러)에서 입력을 읽습니다.Create a controller object to read input from the controller (touch, mouse, or Xbox wireless controller). 자세한 내용은 컨트롤 추가를 참조 하세요.For more information, see Adding controls.
  • 각각 이동 및 카메라 터치 컨트롤에 대 한 화면의 왼쪽 아래와 오른쪽 아래 모퉁이에 두 개의 사각형 영역을 정의 합니다.Define two rectangular areas in the lower-left and lower-right corners of the screen for the move and camera touch controls, respectively. 플레이어는 카메라를 앞뒤로 이동 하는 데 사용 되는 가상 제어 패드로 왼쪽 아래 사각형 ( SetMoveRect호출에 정의 됨)을 사용 합니다.The player uses the lower-left rectangle (defined in the call to SetMoveRect) as a virtual control pad for moving the camera forward and backward, and side to side. 오른쪽 아래 사각형 ( SetFireRect 메서드로 정의 됨)은 탄약을 발사 하는 가상 단추로 사용 됩니다.The lower-right rectangle (defined by the SetFireRect method) is used as a virtual button to fire the ammo.
  • 코 루틴를 사용 하 여 리소스 로드를 별도의 단계로 나눌 수 있습니다.Use coroutines to break resource loading into separate stages. Direct3D 장치 컨텍스트에 대 한 액세스는 장치 컨텍스트가 만들어진 스레드로 제한 됩니다. 개체를 만들기 위해 Direct3D 장치에 액세스 하는 것은 무료 스레드입니다.Access to the Direct3D device context is restricted to the thread on which the device context was created; while access to the Direct3D device for object creation is free-threaded. 따라서 GameRenderer:: CreateGameDeviceResourcesAsync 코 루틴는 원래 스레드에서 실행 되는 완료 작업 (GameRenderer:: FinalizeCreateGameDeviceResources)에서 별도의 스레드에서 실행 될 수 있습니다.Consequently, the GameRenderer::CreateGameDeviceResourcesAsync coroutine can run on a separate thread from the completion task (GameRenderer::FinalizeCreateGameDeviceResources), which runs on the original thread.
  • Simple3DGame:: LoadLevelAsyncSimple3DGame:: FinalizeLoadLevel를 사용 하 여 수준 리소스를 로드 하는 데 비슷한 패턴을 사용 합니다.We use a similar pattern for loading level resources with Simple3DGame::LoadLevelAsync and Simple3DGame::FinalizeLoadLevel.

다음 항목 (게임 흐름 관리)에서 GameMain:: InitializeGameState 에 대 한 추가 정보를 볼 수 있습니다.We'll see more of GameMain::InitializeGameState in the next topic (Game flow management).

App:: OnActivated 된 메서드The App::OnActivated method

그런 다음 CoreApplicationView:: 활성화 된 이벤트가 발생 합니다.Next, the CoreApplicationView::Activated event is raised. 따라서 사용자가 보유 하 고 있는 Onactivated 된 이벤트 처리기 (예: App:: onactivated 된 메서드)가 호출 됩니다.So any OnActivated event handler that you have (such as our App::OnActivated method) is called.

void OnActivated(CoreApplicationView const& /* applicationView */, IActivatedEventArgs const& /* args */)
{
    CoreWindow window = CoreWindow::GetForCurrentThread();
    window.Activate();
}

여기서 수행 하는 유일한 작업은 주 CoreWindow을 활성화 하는 것입니다.The only work we do here is to activate the main CoreWindow. 또는 앱:: SetWindow에서 수행 하도록 선택할 수 있습니다.Alternatively, you can choose to do that in App::SetWindow.

App:: Run 메서드The App::Run method

Initialize, SetwindowLoad 에서 단계를 설정 했습니다.Initialize, SetWindow, and Load have set the stage. 이제 게임이 실행 되 고 있으므로 IFrameworkView:: Run 구현이 호출 됩니다.Now that the game is up and running, our implementation of IFrameworkView::Run is called.

void Run()
{
    m_main->Run();
}

다시 GameMain에 게 작업을 위임 합니다.Again, work is delegated to GameMain.

GameMain:: Run 메서드The GameMain::Run method

GameMain:: Run 은 게임의 주 루프입니다. 에서 찾을 수 있습니다 GameMain.cpp .GameMain::Run is the main loop of the game; you can find it in GameMain.cpp. 기본 논리는 게임 창이 열려 있는 상태에서 모든 이벤트를 디스패치 하 고 타이머를 업데이트 한 다음 그래픽 파이프라인의 결과를 렌더링 하 고 표시 하는 것입니다.The basic logic is that while the window for your game remains open, dispatch all events, update the timer, and then render and present the results of the graphics pipeline. 또한 여기에서 게임 상태를 전환 하는 데 사용 되는 이벤트를 발송 하 고 처리 합니다.Also here, the events used to transition between game states are dispatched and processed.

여기에서 코드는 게임 엔진 상태 시스템의 두 가지 상태에도 관심이 있습니다.The code here is also concerned with two of the states in the game engine state machine.

  • UpdateEngineState::D eactivated되었습니다.UpdateEngineState::Deactivated. 이는 게임 창이 비활성화 되거나 (포커스가 손실 됨) 또는 스냅 됨을 나타냅니다.This specifies that the game window is deactivated (has lost focus) or is snapped.
  • UpdateEngineState:: TooSmall.UpdateEngineState::TooSmall. 이는 클라이언트 영역이 너무 작아 게임을 렌더링할 수 없음을 나타냅니다.This specifies that the client area is too small to render the game in.

이러한 상태 중 하나에서 게임은 이벤트 처리를 일시 중단 하 고 창이 포커스를 unsnap 하거나 크기를 조정할 때까지 대기 합니다.In either of these states, the game suspends event processing, and waits for the window to focus, to unsnap, or to be resized.

게임에 포커스가 있는 경우 메시지 큐가 도착할 때 메시지 큐의 모든 이벤트를 처리 해야 하므로 ProcessAllIfPresent 옵션을 사용 하 여 CoreWindowDispatch 를 호출 해야 합니다.When your game has focus, you must handle every event in the message queue as it arrives, and so you must call CoreWindowDispatch.ProcessEvents with the ProcessAllIfPresent option. 다른 옵션을 사용 하면 메시지 이벤트 처리에 지연이 발생 하 여 게임이 응답 하지 않거나 속도가 저하 되는 터치 동작이 발생할 수 있습니다.Other options can cause delays in processing message events, which can make your game feel unresponsive, or result in touch behaviors that feel sluggish.

게임을 볼 수 없거나, 일시 중단 되거나, 스냅 되지 않은 경우 도착 하지 않는 메시지를 발송 하는 모든 리소스를 사용 하는 것을 원치 않습니다.When the game is not visible, suspended, nor snapped, you don't want it to consume any resources cycling to dispatch messages that will never arrive. 이 경우 게임에서 Processoneandallpending 옵션을 사용 해야 합니다.In this case, your game must use the ProcessOneAndAllPending option. 이 옵션은 이벤트를 받을 때까지 차단 된 다음 해당 이벤트를 처리 하 고 첫 번째를 처리 하는 동안 프로세스 큐에 도착 하는 다른 이벤트를 처리 합니다.That option blocks until it gets an event, and then processes that event (as well as any others that arrive in the process queue during the processing of the first). 그러면 큐가 처리 된 후에 CoreWindowDispatch 가 즉시 반환 됩니다.CoreWindowDispatch.ProcessEvents then immediately returns after the queue has been processed.

void GameMain::Run()
{
    while (!m_windowClosed)
    {
        if (m_visible)
        {
            switch (m_updateState)
            {
            case UpdateEngineState::Deactivated:
            case UpdateEngineState::TooSmall:
                if (m_updateStateNext == UpdateEngineState::WaitingForResources)
                {
                    WaitingForResourceLoading();
                    m_renderNeeded = true;
                }
                else if (m_updateStateNext == UpdateEngineState::ResourcesLoaded)
                {
                    // In the device lost case, we transition to the final waiting state
                    // and make sure the display is updated.
                    switch (m_pressResult)
                    {
                    case PressResultState::LoadGame:
                        SetGameInfoOverlay(GameInfoOverlayState::GameStats);
                        break;

                    case PressResultState::PlayLevel:
                        SetGameInfoOverlay(GameInfoOverlayState::LevelStart);
                        break;

                    case PressResultState::ContinueLevel:
                        SetGameInfoOverlay(GameInfoOverlayState::Pause);
                        break;
                    }
                    m_updateStateNext = UpdateEngineState::WaitingForPress;
                    m_uiControl->ShowGameInfoOverlay();
                    m_renderNeeded = true;
                }

                if (!m_renderNeeded)
                {
                    // The App is not currently the active window and not in a transient state so just wait for events.
                    CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
                    break;
                }
                // otherwise fall through and do normal processing to get the rendering handled.
            default:
                CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
                Update();
                m_renderer->Render();
                m_deviceResources->Present();
                m_renderNeeded = false;
            }
        }
        else
        {
            CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
        }
    }
    m_game->OnSuspending();  // Exiting due to window close, so save state.
}

App:: 초기화 취소 메서드The App::Uninitialize method

게임이 종료 되 면 IFrameworkView:: 의 구현이 호출 됩니다.When the game ends, our implementation of IFrameworkView::Uninitialize is called. 이는 정리를 수행할 수 있는 기회입니다.This is our opportunity to perform cleanup. 앱 창을 닫으면 앱 프로세스가 종료 되지 않습니다. 대신 응용 프로그램 singleton의 상태를 메모리에 기록 합니다.Closing the app window doesn't kill the app's process; but instead it writes the state of the app singleton to memory. 시스템에서 리소스의 특별 한 정리를 포함 하 여이 메모리를 회수할 때 특별 한 작업이 발생 해야 하는 경우 해당 정리에 대 한 코드를 초기화하지 않도록 합니다.If anything special must happen when the system reclaims this memory, including any special cleanup of resources, then put the code for that cleanup in Uninitialize.

이 경우 App:: 초기화 는 작동 하지 않습니다.In our case, App::Uninitialize is a no-op.

void Uninitialize()
{
}

Tips

자신의 게임을 개발할 때이 항목에서 설명 하는 방법에 따라 시작 코드를 디자인 합니다.When developing your own game, design your startup code around the methods described in this topic. 다음은 각 방법에 대 한 간단한 기본 제안 목록입니다.Here's a simple list of basic suggestions for each method.

  • Initialize 를 사용 하 여 기본 클래스를 할당 하 고 기본 이벤트 처리기를 연결 합니다.Use Initialize to allocate your main classes, and connect up the basic event handlers.
  • Setwindow 를 사용 하 여 창 특정 이벤트를 구독 하 고, 주 창을 장치 종속 리소스 개체에 전달 하 여 스왑 체인을 만들 때 해당 창을 사용할 수 있도록 합니다.Use SetWindow to subscribe to any window-specific events, and to pass your main window to your device-dependent resources object so that it can use that window when creating a swap chain.
  • 로드 를 사용 하 여 나머지 설정을 처리 하 고 비동기 개체 생성과 리소스 로드를 시작 합니다.Use Load to handle any remaining setup, and to initiate the asynchronous creation of objects, and loading of resources. Procedurally 생성 된 자산과 같은 임시 파일이 나 데이터를 만들어야 하는 경우 여기에서 작업을 수행 해야 합니다.If you need to create any temporary files or data, such as procedurally generated assets, then do that here, too.

다음 단계Next steps

이 항목에서는 DirectX를 사용 하는 UWP 게임의 기본 구조 중 일부에 대해 설명 했습니다.This topic has covered some of the basic structure of a UWP game that uses DirectX. 이후 항목에서 일부를 다시 참조할 예정 이기 때문에 이러한 메서드를 염두에 두는 것이 좋습니다.It's a good idea to keep these methods in mind, because we'll be referring back to some of them in later topics.

다음 항목 — 게임 흐름 관리에서 게임 — 상태와 이벤트 처리를 관리 하는 방법에 대해 자세히 살펴보고 게임을 계속 진행 합니다.In the next topic—Game flow management—we'll take an in-depth look at how to manage game states and event handling in order to keep the game flowing.