사용자 인터페이스 추가Add a user interface

이제 게임에 3D 시각적 개체, 게임 플레이어에 게 게임 상태에 대 한 피드백을 제공할 수 있도록 몇 가지 2D 요소를 추가 하는 방법에 집중할 수 있는 시간입니다.Now that our game has its 3D visuals in place, it's time to focus on adding some 2D elements so that the game can provide feedback about game state to the player. 이 간단한 메뉴 옵션을 추가 하 여 수행할 수 있습니다 및 3 차원 그래픽 위에 (heads-up display) 구성 요소 출력을 파이프라인 합니다.This can be accomplished by adding simple menu options and heads-up display components on top of the 3-D graphics pipeline output.

참고

이 샘플의 최신 게임 코드를 다운로드하지 않은 경우 Direct3D 게임 샘플로 이동합니다.If you haven't downloaded the latest game code for this sample, go to Direct3D game sample. 이 샘플은 UWP 기능 샘플의 큰 컬렉션의 일부입니다.This sample is part of a large collection of UWP feature samples. 샘플을 다운로드하는 방법에 대한 지침은 GitHub에서 UWP 샘플 가져오기를 참조하세요.For instructions on how to download the sample, see Get the UWP samples from GitHub.

목표Objective

Direct2D를 사용 하 여 포함 하는 UWP DirectX 게임에 다양 한 사용자 인터페이스 그래픽 및 동작을 추가 합니다.Using Direct2D, add a number of user interface graphics and behaviors to our UWP DirectX game including:

사용자 인터페이스 오버레이The user interface overlay

여러 가지 방법을 사용 하 여 DirectX 게임에서 텍스트 및 사용자 인터페이스 요소를 표시할 수 있습니다, 있지만 하겠습니다 포커스를 사용 하 여 Direct2D합니다.While there are many ways to display text and user interface elements in a DirectX game, we're going to focus on using Direct2D. 또한 사용할 것 DirectWrite 텍스트 요소에 대 한 합니다.We'll also be using DirectWrite for the text elements.

Direct2D 픽셀 기반 기본 형식 및 효과 그리는 데 사용 되는 2D 그리기 Api 집합입니다.Direct2D is a set of 2D drawing APIs used to draw pixel-based primitives and effects. Direct2D를 사용 하 여 시작을 하는 경우 간단 하 게 유지 하는 것이 좋습니다.When starting out with Direct2D, it's best to keep things simple. 복잡한 레이아웃 및 인터페이스 동작에는 시간과 계획이 필요합니다.Complex layouts and interface behaviors need time and planning. 게임 시뮬레이션 및 전략 게임에서 복잡 한 사용자 인터페이스를 요구 하는 경우에 대신 XAML을 사용 하는 것이 좋습니다.If your game requires a complex user interface, like those found in simulation and strategy games, consider using XAML instead.

참고

UWP DirectX 게임에서 XAML 사용 하 여 사용자 인터페이스를 개발 하는 방법에 대 한 정보를 참조 하세요 게임 샘플 확장합니다.For info about developing a user interface with XAML in a UWP DirectX game, see Extending the game sample.

Direct2D는 사용자 인터페이스 또는 HTML 및 XAML와 같은 레이아웃에 대 한 설계 되지 않습니다.Direct2D isn't specifically designed for user interfaces or layouts like HTML and XAML. 목록 상자, 단추와 같은 사용자 인터페이스 구성 요소가 제공 하지 않습니다.It doesn't provide user interface components like lists, boxes, or buttons. 또한 div, 테이블 또는 그리드와 같은 구성 요소 레이아웃도 제공 하지 않습니다.It also doesn't provide layout components like divs, tables, or grids.

이 게임 샘플에 대 한 두 가지 주요 UI 구성 요소가 있습니다.For this game sample we have two major UI components.

  1. 점수 및 게임 내 컨트롤의 헤드업 디스플레이입니다.A heads-up display for the score and in-game controls.
  2. 오버레이 게임 상태 텍스트 및 일시 중지 정보 등의 옵션을 표시 하 고 수준 옵션을 시작 합니다.An overlay used to display game state text and options such as pause info and level start options.

주의 표시에 Direct2D 사용Using Direct2D for a heads-up display

다음 이미지에서는 샘플 게임 헤드업 디스플레이 보여 줍니다.The following image shows the in-game heads-up display for the sample. 것이 간단 하 고 깔끔해야 플레이어 3D 세계를 탐색 하 고 대상 해결에 집중할 수 있도록 합니다.It's simple and uncluttered, allowing the player to focus on navigating the 3D world and shooting targets. 적절 한 인터페이스 또는 헤 즈 업 디스플레이의 플레이어를 처리 하 고 게임의 이벤트에 대응할 수 복잡 해질 되지 해야 합니다.A good interface or heads-up display must never complicate the ability of the player to process and react to the events in the game.

게임 오버레이의 스크린샷

오버레이 다음 기본 기본 형식으로 구성 됩니다.The overlay consists of the following basic primitives.

  • DirectWrite 의 플레이어에 게 알려 주는 오른쪽 위 모서리에 있는 텍스트DirectWrite text in the upper-right corner that informs the player of
    • 성공적인 적중 횟수Successful hits
    • 플레이어 했습니다 샷 수Number of shots the player has made
    • 수준에 남은 시간Time remaining in the level
    • 현재 수준 수Current level number
  • 십자선을 형성 하는 데 사용 되는 선 세그먼트를 교차 두Two intersecting line segments used to form a cross hair
  • 두 개의 사각형에 대 한 아래쪽 모서리에는 모양을 이동 컨트롤러 경계입니다.Two rectangles at the bottom corners for the move-look controller boundries.

게임에 헤 즈 업 디스플레이 상태의 오버레이 그릴지를 GameHud::Render 메서드를 GameHud 클래스.The in-game heads-up display state of the overlay is drawn in the GameHud::Render method of the GameHud class. 이 메서드 내에서 UI를 나타내는 Direct2D 오버레이 적중 횟수, 시간, 남은 및 수준 번호 수의 변경 내용을 반영 하도록 업데이트 됩니다.Within this method, the Direct2D overlay that represents our UI is updated to reflect the changes in the number of hits, time remaining, and level number.

게임 초기화 된 경우 추가 TotalHits(), TotalShots(), 및 TimeRemaining() swprintf_s 버퍼링 하 고 인쇄 형식을 지정 합니다.If the game has been initialized, we add TotalHits(), TotalShots(), and TimeRemaining() to a swprintf_s buffer and specify the print format. 사용 하 여 다음 내릴 수 있습니다 합니다 DrawText 메서드.We can then draw it using the DrawText method. 에서는 동일한 작업을 수행 현재 수준 표시기에 대 한 그리기 ➀를 같은 완료 되지 않은 수준을 표시 합니다. 빈 번호 및 특정 수준 완료 되었음을 표시할 ➊ 같은 채워진된 숫자입니다.We do the same for the current level indicator, drawing empty numbers to show uncompleted levels like ➀, and filled numbers like ➊ to show that the specific level was completed.

다음 코드는 과정을 안내 합니다 GameHud::Render 메서드의 프로세스The following code snippet walks through the GameHud::Render method's process for

void GameHud::Render(_In_ Simple3DGame^ game)
{
    auto d2dContext = m_deviceResources->GetD2DDeviceContext();
    auto windowBounds = m_deviceResources->GetLogicalSize();

    if (m_showTitle)
    {
        d2dContext->DrawBitmap(
            m_logoBitmap.Get(),
            D2D1::RectF(
                GameConstants::Margin,
                GameConstants::Margin,
                m_logoSize.width + GameConstants::Margin,
                m_logoSize.height + GameConstants::Margin
                )
            );
        d2dContext->DrawTextLayout(
            Point2F(m_logoSize.width + 2.0f * GameConstants::Margin, GameConstants::Margin),
            m_titleHeaderLayout.Get(),
            m_textBrush.Get()
            );
        d2dContext->DrawTextLayout(
            Point2F(GameConstants::Margin, m_titleBodyVerticalOffset),
            m_titleBodyLayout.Get(),
            m_textBrush.Get()
            );
    }

    // Draw text for number of hits, total shots, and time remaining
    if (game != nullptr)
    {
        // This section is only used after the game state has been initialized.
        static const int bufferLength = 256;
        static char16 wsbuffer[bufferLength];
        int length = swprintf_s(
            wsbuffer,
            bufferLength,
            L"Hits:\t%10d\nShots:\t%10d\nTime:\t%8.1f",
            game->TotalHits(),
            game->TotalShots(),
            game->TimeRemaining()
            );
        
        // Draw the upper right portion of the HUD displaying total hits, shots, and time remaining
        d2dContext->DrawText(
            wsbuffer,
            length,
            m_textFormatBody.Get(),
            D2D1::RectF(
                windowBounds.Width - GameConstants::HudRightOffset,
                GameConstants::HudTopOffset,
                windowBounds.Width,
                GameConstants::HudTopOffset + (GameConstants::HudBodyPointSize + GameConstants::Margin) * 3
                ),
            m_textBrush.Get()
            );

        // Using the unicode characters starting at 0x2780 ( ➀ ) for the consecutive levels of the game.
        // For completed levels start with 0x278A ( ➊ ) (This is 0x2780 + 10).
        uint32 levelCharacter[6];
        for (uint32 i = 0; i < 6; i++)
        {
            levelCharacter[i] = 0x2780 + i + ((static_cast<uint32>(game->LevelCompleted()) == i) ? 10 : 0);
        }
        length = swprintf_s(
            wsbuffer,
            bufferLength,
            L"%lc %lc %lc %lc %lc %lc",
            levelCharacter[0],
            levelCharacter[1],
            levelCharacter[2],
            levelCharacter[3],
            levelCharacter[4],
            levelCharacter[5]
            );
        // Create a new rectangle and draw the current level info text inside
        d2dContext->DrawText(
            wsbuffer,
            length,
            m_textFormatBodySymbol.Get(),
            D2D1::RectF(
                windowBounds.Width - GameConstants::HudRightOffset,
                GameConstants::HudTopOffset + (GameConstants::HudBodyPointSize + GameConstants::Margin) * 3 + GameConstants::Margin,
                windowBounds.Width,
                GameConstants::HudTopOffset + (GameConstants::HudBodyPointSize+ GameConstants::Margin) * 4
                ),
            m_textBrush.Get()
            );

        if (game->IsActivePlay())
        {
            // Draw the move and fire rectangles
            // Draw the crosshairs
        }
    }
}

이 부분은 더 아래로 메서드 주요 합니다 GameHud::Render 메서드 이동 하는 과정을 그리는 데 사용 하 여 사각형을 실행 합니다. ID2D1RenderTarget::DrawRectangle , 및에 대 한 두 호출을 사용 하 여 십자 ID2D1RenderTarget::DrawLine합니다.Breaking the method down further, this piece of the GameHud::Render method draws our move and fire rectangles with ID2D1RenderTarget::DrawRectangle, and crosshairs using two calls to ID2D1RenderTarget::DrawLine.

        // Check if game is playing
        if (game->IsActivePlay())
        {
            // Draw a rectangle for the touch input for the move control.
            d2dContext->DrawRectangle(
                D2D1::RectF(
                    0.0f,
                    windowBounds.Height - GameConstants::TouchRectangleSize,
                    GameConstants::TouchRectangleSize,
                    windowBounds.Height
                    ),
                m_textBrush.Get()
                );
            // Draw a rectangle for the touch input of the fire control.
            d2dContext->DrawRectangle(
                D2D1::RectF(
                    windowBounds.Width - GameConstants::TouchRectangleSize,
                    windowBounds.Height - GameConstants::TouchRectangleSize,
                    windowBounds.Width,
                    windowBounds.Height
                    ),
                m_textBrush.Get()
                );

            // Draw two lines to form crosshairs
            d2dContext->DrawLine(
                D2D1::Point2F(windowBounds.Width / 2.0f - GameConstants::CrossHairHalfSize, windowBounds.Height / 2.0f),
                D2D1::Point2F(windowBounds.Width / 2.0f + GameConstants::CrossHairHalfSize, windowBounds.Height / 2.0f),
                m_textBrush.Get(),
                3.0f
                );
            d2dContext->DrawLine(
                D2D1::Point2F(windowBounds.Width / 2.0f, windowBounds.Height / 2.0f - GameConstants::CrossHairHalfSize),
                D2D1::Point2F(windowBounds.Width / 2.0f, windowBounds.Height / 2.0f + GameConstants::CrossHairHalfSize),
                m_textBrush.Get(),
                3.0f
                );
        }

GameHud::Render 게임 창의 논리적 크기 저장 메서드는 windowBounds 변수입니다.In the GameHud::Render method we store the logical size of the game window in the windowBounds variable. 사용 하 여이 GetLogicalSize 메서드를 DeviceResources 클래스입니다.This uses the GetLogicalSize method of the DeviceResources class.

auto windowBounds = m_deviceResources->GetLogicalSize();

게임 창 크기를 가져오는 UI 프로그래밍에 대 한 필수적입니다.Obtaining the size of the game window is essential for UI programming. 창의 크기는 DIP를 1/96 인치로 정의 되어 있는 Dip (장치 독립적 픽셀) 라는 측정 단위로 제공 됩니다.The size of the window is given in a measurement called DIPs (device independent pixels), where a DIP is defined as 1/96 of an inch. Direct2D 조정 실제 픽셀 그리기 단위 그리기 경우 Windows에 대 한 인치당 dpi 설정 사용 하 여 이렇게 합니다.Direct2D scales the drawing units to actual pixels when the drawing occurs, doing so by using the Windows dots per inch (DPI) setting. 마찬가지로, 그릴 때 사용 하 여 텍스트 DirectWrite, 글꼴의 포인트 크기 보다는 Dip를 지정 합니다.Similarly, when you draw text using DirectWrite, you specify DIPs rather than points for the size of the font. DIP는 부동 소수점 수로 표현됩니다.DIPs are expressed as floating point numbers.

 

게임 상태 정보를 표시합니다.Displaying game state info

헤드업 디스플레이 외에도 게임 샘플에는 6 가지 게임 상태를 나타내는 오버레이 합니다.Besides the heads-up display, the game sample has an overlay that represents six game states. 모든 상태를 읽는 플레이어에 대 한 텍스트를 사용 하 여 큰 검은색 사각형 기본을 기능입니다.All states feature a large black rectangle primitive with text for the player to read. 컨트롤러 사각형과 십자 모양을 이동 하지 그려집니다 하지 않기 때문에 현재 이러한 상태에서.The move-look controller rectangles and crosshairs are not drawn because they are not active in these states.

오버레이 사용 하 여 만들어집니다 합니다 GameInfoOverlay 게임의 상태에 맞게 표시할 텍스트를 전환 하도록 허락해 클래스입니다.The overlay is created using the GameInfoOverlay class, allowing us to switch out what text is displayed to align with the state of the game.

상태 및 작업의 오버레이

오버레이 두 개의 섹션으로 세분화 됩니다. 상태 하 고 동작합니다.The overlay is broken up into two sections: Status and Action. 합니다 상태 섹션으로 세분화 추가 됩니다 Title 하 고 본문 사각형입니다.The Status secton is further broken down into Title and Body rectangles. 합니다 동작 섹션에는 하나의 사각형만 합니다.The Action section only has one rectangle. 각 사각형 다양 한 용도가 있습니다.Each rectangle has a different purpose.

  • titleRectangle 제목 텍스트를 포함합니다.titleRectangle contains the title text.
  • bodyRectangle 본문 텍스트를 포함합니다.bodyRectangle contains the body text.
  • actionRectangle 특정 작업을 수행 하는 플레이어에 게 알려 주는 텍스트를 포함 합니다.actionRectangle contains the text that informs the player to take a specific action.

게임에 설정할 수 있는 6 가지 상태가 있습니다.The game has six states that can be set. 사용 하 여 전달 게임의 상태를 상태 오버레이 부분입니다.The state of the game conveyed using the Status portion of the overlay. 합니다 상태 사각형 다양 한 상태를 사용 하 여 해당 메서드를 사용 하 여 업데이트 됩니다.The Status rectangles are updated using a number of methods corresponding with the following states.

  • 로드Loading
  • 초기 시작/높은 점수 통계Initial start/high score stats
  • 수준 시작Level start
  • 게임이 일시 중지Game paused
  • 게임 종료Game over
  • 게임-이득Game won

작업 부분 오버레이 사용 하 여 업데이트 되는 GameInfoOverlay::SetAction 메서드를 다음 중 하나로 설정할 동작 텍스트를 허용 합니다.The Action portion of the overlay is updated using the GameInfoOverlay::SetAction method, allowing the action text to be set to one of the following.

  • "... 다시 재생 탭""Tap to play again..."
  • "로드 수준, 잠시 기다려 주십시오.""Level loading, please wait ..."
  • "계속 하려면... 탭""Tap to continue ..."
  • 없음None

참고

두 가지이 방법에 설명 합니다에 추가 합니다 게임 상태를 나타내는 섹션입니다.Both of these methods will be discussed further in the Representing game state section.

어떤 일이 일어나는지 게임을 따라 합니다 상태 하 고 작업 섹션 텍스트 필드를 조정 하는 합니다.Depending on the what's going on in the game, the Status and Action section text fields are adjusted. 초기화 하 고 이러한 6 가지 상태에 대 한 오버레이 그리는 방법을 살펴보겠습니다.Let's look at how we initialize and draw the overlay for these six states.

오버레이 초기화 및 그리기Initializing and drawing the overlay

6 개의 상태 서로 몇 가지 공통 상태, 리소스 및 메서드 만들기와 매우 유사 해야 합니다.The six Status states have a few things in common, making the resources and methods they need very similar. - 모두 검은 사각형 화면의 가운데에서 해당 배경으로 사용합니다.They all use a black rectangle in the center of the screen as their background. - 표시 된 텍스트는 제목 하거나 본문 텍스트입니다.The displayed text is either Title or Body text. - 텍스트는 Segoe UI 글꼴을 사용 하 고 백 사각형 위에 그려집니다.The text uses the Segoe UI font and is drawn on top of the back rectangle.

샘플 게임에 오버레이 만들 때 고려해 야 하는 네 가지 메서드가 있습니다.The game sample has four methods that come into play when creating the overlay.

GameInfoOverlay::GameInfoOverlayGameInfoOverlay::GameInfoOverlay

합니다 GameInfoOverlay::GameInfoOverlay 생성자에서 플레이어에 게 정보를 표시를 사용 하는 비트맵 표면을 유지 오버레이 초기화 합니다.The GameInfoOverlay::GameInfoOverlay constructor initializes the overlay, maintaining the bitmap surface that we will use to display info to the player on. 생성자에서 팩터리를 가져옵니다 합니다 ID2D1Device 만드는 데 사용 하기에 전달 된 개체를 ID2D1DeviceContext 오버레이 개체 자체를 그릴 수 있습니다.The constructor obtains a factory from the ID2D1Device object passed to it, which it uses to create an ID2D1DeviceContext that the overlay object itself can draw to. IDWriteFactory::CreateTextFormatIDWriteFactory::CreateTextFormat

GameInfoOverlay::CreateDeviceDependentResourcesGameInfoOverlay::CreateDeviceDependentResources

GameInfoOverlay::CreateDeviceDependentResources 는 브러시를 만드는 데 사용할 텍스트를 그리는 메서드입니다.GameInfoOverlay::CreateDeviceDependentResources is our method for creating brushes that will be used to draw our text. 구한이 작업을 수행 하는 ID2D1DeviceContext2 개체를 만들 수 있으며 메시 잉크 및 그라데이션 같은 기능 및 기 하 도형 그리기 렌더링 합니다.To do this, we obtain a ID2D1DeviceContext2 object which enables the creation and drawing of geometry, plus functionality such as ink and gradient mesh rendering. 그런 다음 일련의 색이 지정 된 브러시를 사용 하 여 만듭니다 ID2D1SolidColorBrush folling UI 요소를 그립니다.We then create a series of colored brushes using ID2D1SolidColorBrush to draw the folling UI elements.

  • 사각형 배경에 대 한 검정 브러시Black brush for rectangle backgrounds
  • 흰색 브러시로 상태 텍스트White brush for status text
  • 작업 텍스트 주황색 브러시Orange brush for action text

DeviceResources::SetDpiDeviceResources::SetDpi

합니다 DeviceResources::SetDpi 메서드 창의 인치당을 설정 합니다.The DeviceResources::SetDpi method sets the dots per inch of the window. 이 메서드가 호출 되는 DPI가 변경 되 고 해야 하는 경우는 게임 창 크기를 조정할 때 발생 하는 재조정 합니다.This method gets called when the DPI is changed and needs to be readjusted which happens when the game window is resized. DPI를 업데이트 한 후이 메서드 호출DeviceResources::CreateWindowSizeDependentResources 필요한 있는지 확인 하려면 리소스 창 크기를 조정할 때마다 다시 만들어집니다.After updating the DPI, this method also callsDeviceResources::CreateWindowSizeDependentResources to make sure necessary resources are recreated every time the window is resized.

GameInfoOverlay::CreateWindowsSizeDependentResourcesGameInfoOverlay::CreateWindowsSizeDependentResources

합니다 GameInfoOverlay::CreateWindowsSizeDependentResources 메서드는 모든 그리기 이루어지는 곳입니다.The GameInfoOverlay::CreateWindowsSizeDependentResources method is where all our drawing takes place. 다음은 메서드의 단계 개요입니다.The following is an outline of the method's steps.

  • 섹션의 UI 텍스트를 해제 하기 위해 세 개의 사각형이 만들어집니다 합니다 제목, 본문, 및 작업 텍스트입니다.Three rectangles are created to section off the UI text for the Title, Body, and Action text.

    m_titleRectangle = D2D1::RectF(
        GameInfoOverlayConstant::SideMargin,
        GameInfoOverlayConstant::TopMargin,
        overlaySize.width - GameInfoOverlayConstant::SideMargin,
        GameInfoOverlayConstant::TopMargin + GameInfoOverlayConstant::TitleHeight
        );
    m_actionRectangle = D2D1::RectF(
        GameInfoOverlayConstant::SideMargin,
        overlaySize.height - (GameInfoOverlayConstant::ActionHeight + GameInfoOverlayConstant::BottomMargin),
        overlaySize.width - GameInfoOverlayConstant::SideMargin,
        overlaySize.height - GameInfoOverlayConstant::BottomMargin
        );
    m_bodyRectangle = D2D1::RectF(
        GameInfoOverlayConstant::SideMargin,
        m_titleRectangle.bottom + GameInfoOverlayConstant::Separator,
        overlaySize.width - GameInfoOverlayConstant::SideMargin,
        m_actionRectangle.top - GameInfoOverlayConstant::Separator
        );
    
  • 비트맵 라는 생성 됩니다 m_levelBitmap를 사용 하 여 계정을 현재 DPI 고려 CreateBitmap합니다.A Bitmap is created named m_levelBitmap, taking the current DPI into account using CreateBitmap.

  • m_levelBitmap 사용 하 여 2D 렌더링 대상으로 설정 됩니다 ID2D1DeviceContext::SetTarget합니다.m_levelBitmap is set as our 2D render target using ID2D1DeviceContext::SetTarget.

  • 사용 하 여 검정을 수행 하는 모든 픽셀을 사용 하 여 비트맵 지워집니다 ID2D1RenderTarget::Clear합니다.The Bitmap is cleared with every pixel made black using ID2D1RenderTarget::Clear.

  • ID2D1RenderTarget::BeginDraw 그리기를 시작 하기 위해 호출 됩니다.ID2D1RenderTarget::BeginDraw is called to initiate drawing.

  • DrawText 에 저장 된 텍스트를 그리기 위해 호출 됩니다 m_titleString, m_bodyString, 및 m_actionString 해당를 사용 하 여 approperiate 사각형에서 ID2D1SolidColorBrush합니다.DrawText is called to draw the text stored in m_titleString, m_bodyString, and m_actionString in the approperiate rectangle using the corresponding ID2D1SolidColorBrush.

  • ID2D1RenderTarget::EndDraw 에서 모든 그리기 작업을 중지 하 라고 m_levelBitmap합니다.ID2D1RenderTarget::EndDraw is called to stop all drawing operations on m_levelBitmap.

  • 사용 하 여 다른 비트 멥 만들어집니다 CreateBitmap 라는 m_tooSmallBitmap 표시 구성은 게임에 비해 너무 작은 경우에 표시에서 대체 방법으로 사용 하도록 합니다.Another Bitmap is created using CreateBitmap named m_tooSmallBitmap to use as a fallback, showing only if the display configuration is too small for the game.

  • 에 그리기 위한 프로세스를 반복 m_levelBitmap 에 대 한 m_tooSmallBitmap문자열을 그리기만 이번 Paused 본문에 있습니다.Repeat process for drawing on m_levelBitmap for m_tooSmallBitmap, this time only drawing the string Paused in the body.

이제는 6 개의 오버레이 상태 텍스트를 입력 하는 6 가지가 하기만 했습니다!Now all we need are six methods to fill the text of our six overlay states!

게임 상태를 나타내는Representing game state

각 게임의 6 오버레이 상태에 해당 되는 메서드를 GameInfoOverlay 개체입니다.Each of the six overlay states in the game has a corresponding method in the GameInfoOverlay object. 이러한 메서드는 오버레이의 변형을 그려 게임 자체에 대한 명시적 정보를 플레이어에게 전달합니다.These methods draw a variation of the overlay to communicate explicit info to the player about the game itself. 이 통신으로 표시 되는 제목 하 고 본문 문자열.This communication is represented with a Title and Body string. 샘플 초기화 될 때와 해당 리소스와이 정보에 대 한 레이아웃을 이미 구성 때문에 합니다 GameInfoOverlay::CreateDeviceDependentResources 메서드만 제공 해야 오버레이 상태 관련 문자열입니다.Because the sample already configured the resources and layout for this info when it was initialized and with the GameInfoOverlay::CreateDeviceDependentResources method, it only needs to provide the overlay state-specific strings.

합니다 상태 오버레이에 다음 메서드 중 하나를 호출 하 여 설정 됩니다.The Status portion of the overlay is set with a call to one of the following methods.

게임 상태Game state 상태 set 메서드Status set method 상태 필드Status fields
로드Loading GameInfoOverlay::SetGameLoadingGameInfoOverlay::SetGameLoading TitleTitle
리소스 로드Loading Resources
BodyBody
증분 방식으로 인쇄 "." 로드 작업을 의미 합니다.Incrementally prints "." to imply loading activity.
초기 시작/높은 점수 통계Initial start/high score stats GameInfoOverlay::SetGameStatsGameInfoOverlay::SetGameStats TitleTitle
최고 점수High Score
BodyBody
수준 # 완료Levels Completed #
Total # 요소Total Points #
Total # 장면Total Shots #
수준 시작Level start GameInfoOverlay::SetLevelStartGameInfoOverlay::SetLevelStart TitleTitle
수준 #Level #
BodyBody
수준 목표 설명입니다.Level objective description.
게임이 일시 중지Game paused GameInfoOverlay::SetPauseGameInfoOverlay::SetPause TitleTitle
게임이 일시 중지Game Paused
BodyBody
없음None
게임 종료Game over GameInfoOverlay::SetGameOverGameInfoOverlay::SetGameOver TitleTitle
게임 오버Game Over
BodyBody
수준 # 완료Levels Completed #
Total # 요소Total Points #
Total # 장면Total Shots #
수준 # 완료Levels Completed #
높은 # 점수 매기기High Score #
게임-이득Game won GameInfoOverlay::SetGameOverGameInfoOverlay::SetGameOver TitleTitle
승리 했습니다.You WON!
BodyBody
수준 # 완료Levels Completed #
Total # 요소Total Points #
Total # 장면Total Shots #
수준 # 완료Levels Completed #
높은 # 점수 매기기High Score #

사용 하 여 합니다 GameInfoOverlay::CreateWindowSizeDependentResources 메서드를 샘플 오버레이의 특정 영역에 해당 하는 세 개의 사각형 영역을 선언 합니다.With the GameInfoOverlay::CreateWindowSizeDependentResources method, the sample declared three rectangular areas that correspond to specific regions of the overlay.

이러한 영역에 주의하면서 상태 관련 메서드 중 하나인 GameInfoOverlay::SetGameStats에 대해 살펴보고 오버레이를 그리는 방법을 알아보겠습니다.With these areas in mind, let's look at one of the state-specific methods, GameInfoOverlay::SetGameStats, and see how the overlay is drawn.

void GameInfoOverlay::SetGameStats(int maxLevel, int hitCount, int shotCount)
{
    int length;

    auto d2dContext = m_deviceResources->GetD2DDeviceContext();

    d2dContext->SetTarget(m_levelBitmap.Get());
    d2dContext->BeginDraw();
    d2dContext->SetTransform(D2D1::Matrix3x2F::Identity());
    d2dContext->FillRectangle(&m_titleRectangle, m_backgroundBrush.Get());
    d2dContext->FillRectangle(&m_bodyRectangle, m_backgroundBrush.Get());
    m_titleString = "High Score";

    d2dContext->DrawText(
        m_titleString->Data(),
        m_titleString->Length(),
        m_textFormatTitle.Get(),
        m_titleRectangle,
        m_textBrush.Get()
        );
    length = swprintf_s(
        wsbuffer,
        bufferLength,
        L"Levels Completed %d\nTotal Points %d\nTotal Shots %d",
        maxLevel,
        hitCount,
        shotCount
        );
    m_bodyString = ref new Platform::String(wsbuffer, length);
    d2dContext->DrawText(
        m_bodyString->Data(),
        m_bodyString->Length(),
        m_textFormatBody.Get(),
        m_bodyRectangle,
        m_textBrush.Get()
        );

    // We ignore D2DERR_RECREATE_TARGET here. This error indicates that the device
    // is lost. It will be handled during the next call to Present.
    HRESULT hr = d2dContext->EndDraw();
    if (hr != D2DERR_RECREATE_TARGET)
    {
        // The D2DERR_RECREATE_TARGET indicates there has been a problem with the underlying
        // D3D device.  All subsequent rendering will be ignored until the device is recreated.
        // This error will be propagated and the appropriate D3D error will be returned from the
        // swapchain->Present(...) call.   At that point, the sample will recreate the device
        // and all associated resources.  As a result, the D2DERR_RECREATE_TARGET doesn't
        // need to be handled here.
        DX::ThrowIfFailed(hr);
    }
}

Direct2D 장치 컨텍스트를 사용 하는 합니다 GameInfoOverlay 초기화 하는 개체,이 메서드는 검은색 배경 브러시를 사용 하 여를 사용 하 여 제목 및 본문 사각형을 채웁니다.Using the Direct2D device context that the GameInfoOverlay object initialized, this method fills the title and body rectangles with black using the background brush. 이 메서드는 흰색 텍스트 브러시를 사용하여 "High Score" 문자열에 대한 텍스트를 제목 사각형에 그리고 게임 상태 업데이트 정보를 포함하는 문자열을 본문 사각형에 그립니다.It draws the text for the "High Score" string to the title rectangle and a string containing the updates game state information to the body rectangle using the white text brush.

작업 사각형에 대 한 후속 호출에 의해 업데이트 됩니다 GameInfoOverlay::SetAction 에서 메서드를 GameMain 필요한 게임 상태 정보를 제공 하는 개체 하 여 GameInfoOverlay::SetAction "계속 하려면 탭" 같은 플레이어에 게 적합 한 메시지를 확인 하려면.The action rectangle is updated by a subsequent call to GameInfoOverlay::SetAction from a method on the GameMain object, which provides the game state info needed by GameInfoOverlay::SetAction to determine the right message to the player, such as "Tap to continue".

지정 된 모든 상태에 대 한 오버레이 선택 합니다 GameMain::SetGameInfoOverlay 다음과 같이 메서드:The overlay for any given state is chosen in the GameMain::SetGameInfoOverlay method like this:

void GameMain::SetGameInfoOverlay(GameInfoOverlayState state)
{
    m_gameInfoOverlayState = state;
    switch (state)
    {
    case GameInfoOverlayState::Loading:
        m_uiControl->SetGameLoading();
        break;

    case GameInfoOverlayState::GameStats:
        m_uiControl->SetGameStats(
            m_game->HighScore().levelCompleted + 1,
            m_game->HighScore().totalHits,
            m_game->HighScore().totalShots
            );
        break;

    case GameInfoOverlayState::LevelStart:
        m_uiControl->SetLevelStart(
            m_game->LevelCompleted() + 1,
            m_game->CurrentLevel()->Objective(),
            m_game->CurrentLevel()->TimeLimit(),
            m_game->BonusTime()
            );
        break;

    case GameInfoOverlayState::GameOverCompleted:
        m_uiControl->SetGameOver(
            true,
            m_game->LevelCompleted() + 1,
            m_game->TotalHits(),
            m_game->TotalShots(),
            m_game->HighScore().totalHits
            );
        break;

    case GameInfoOverlayState::GameOverExpired:
        m_uiControl->SetGameOver(
            false,
            m_game->LevelCompleted(),
            m_game->TotalHits(),
            m_game->TotalShots(),
            m_game->HighScore().totalHits
            );
        break;

    case GameInfoOverlayState::Pause:
        m_uiControl->SetPause(
            m_game->LevelCompleted() + 1,
            m_game->TotalHits(),
            m_game->TotalShots(),
            m_game->TimeRemaining()
            );
        break;
    }
}

게임 플레이어 게임 상태를 기준으로 텍스트 정보를 알릴 수 있도록 설정 되었습니다 및에서는 게임 전체에 표시 되는 전환의 수입니다.Now the game has a way to communicate text info to the player based on game state, and we have a way of switching what's displayed to them throughout the game.

다음 단계Next steps

다음 항목인 컨트롤 추가에서는 플레이어가 게임 샘플과 상호 작용하는 방법 및 입력을 통해 게임 상태를 변경하는 방법에 대해 살펴봅니다.In the next topic, Adding controls, we look at how the player interacts with the game sample, and how input changes game state.