Compartilhar via


Estender o exemplo de jogo

Observação

Este tópico faz parte da série de tutoriais Criar um jogo simples da Plataforma Universal do Windows (UWP) com DirectX. O tópico nesse link define o contexto da série.

Para baixar a versão deste jogo que usa XAML para a sobreposição, consulte Exemplo de jogo DirectX e XAML. Certifique-se de ler o arquivo readme para obter detalhes sobre como criar o exemplo.

Neste ponto, abordamos os principais componentes de um jogo básico em DirectX 3D da Plataforma Universal do Windows (UWP). Você pode configurar a estrutura de um jogo, incluindo o provedor de exibição e o pipeline de renderização, e implementar um loop de jogo básico. Você também pode criar uma sobreposição de interface de usuário básica, incorporar sons e implementar controles. Você está no caminho certo para criar seu próprio jogo, mas se precisar de mais ajuda e informações, confira estes recursos.

Usando XAML para a sobreposição

Uma alternativa que não discutimos em profundidade é o uso de XAML em vez de Direct2D para a sobreposição. O XAML tem muitos benefícios em relação ao Direct2D para desenhar elementos da interface do usuário. O benefício mais importante é que ele torna a incorporação da aparência do Windows 10 em seu jogo DirectX mais conveniente. Muitos dos elementos, estilos e comportamentos comuns que definem um aplicativo UWP são totalmente integrados ao modelo XAML, tornando muito menos trabalhoso para um desenvolvedor de jogos implementar. Se o design do seu próprio jogo tiver uma interface do usuário complicada, considere usar XAML em vez de Direct2D.

Com o XAML, podemos criar uma interface de jogo semelhante à do Direct2D feita anteriormente.

XAML

Sobreposição XAML

Direct2D

Sobreposição D2D

Embora tenham resultados finais semelhantes, há várias diferenças entre a implementação de interfaces Direct2D e XAML.

Recurso XAML Direct2D
Definindo sobreposição Definido em um arquivo XAML, \*.xaml. Depois de entender o XAML, a criação e a configuração de sobreposições mais complicadas são simplificadas quando comparadas ao Direct2D. Definido como uma coleção de primitivos Direct2D e cadeias de caracteres DirectWrite colocadas manualmente e gravadas em um buffer de destino Direct2D.
Elementos da interface do usuário Os elementos da interface do usuário XAML vêm de elementos padronizados que fazem parte das APIs XAML do Tempo de Execução do Windows, incluindo Windows::UI::Xaml e Windows::UI::Xaml::Controls. O código que manipula o comportamento dos elementos da interface do usuário XAML é definido em um arquivo codebehind, Main.xaml.cpp. Formas simples podem ser desenhadas como retângulos e elipses.
Redimensionamento de janela Lida naturalmente com eventos de alteração de estado de redimensionamento e exibição, transformando a sobreposição de acordo É necessário especificar manualmente como redesenhar os componentes da sobreposição.

Outra grande diferença envolve a cadeia de troca. Você não precisa anexar a cadeia de troca a um objeto Windows::UI::Core::CoreWindow . Em vez disso, um aplicativo DirectX que incorpora XAML associa uma cadeia de troca quando um novo objeto SwapChainPanel é construído.

O snippet a seguir mostra como declarar XAML para o SwapChainPanel no arquivo DirectXPage.xaml .

<Page
    x:Class="Simple3DGameXaml.DirectXPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Simple3DGameXaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <SwapChainPanel x:Name="DXSwapChainPanel">

    <!-- ... XAML user controls and elements -->

    </SwapChainPanel>
</Page>

O objeto SwapChainPanel é definido como a propriedade Content do objeto de janela atual criado na inicialização pelo singleton do aplicativo.

void App::OnLaunched(_In_ LaunchActivatedEventArgs^ /* args */)
{
    m_mainPage = ref new DirectXPage();

    Window::Current->Content = m_mainPage;
    // Bring the application to the foreground so that it's visible
    Window::Current->Activate();
}

Para anexar a cadeia de troca configurada à instância SwapChainPanel definida pelo XAML, você deve obter um ponteiro para a implementação de interface ISwapChainPanelNative nativa subjacente e chamar ISwapChainPanelNative::SetSwapChain nela, passando a cadeia de troca configurada.

O seguinte trecho de DX::D eviceResources::CreateWindowSizeDependentResources detalha isso para interoperabilidade DirectX/XAML:

        ComPtr<IDXGIDevice3> dxgiDevice;
        DX::ThrowIfFailed(
            m_d3dDevice.As(&dxgiDevice)
            );

        ComPtr<IDXGIAdapter> dxgiAdapter;
        DX::ThrowIfFailed(
            dxgiDevice->GetAdapter(&dxgiAdapter)
            );

        ComPtr<IDXGIFactory2> dxgiFactory;
        DX::ThrowIfFailed(
            dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))
            );

        // When using XAML interop, the swap chain must be created for composition.
        DX::ThrowIfFailed(
            dxgiFactory->CreateSwapChainForComposition(
                m_d3dDevice.Get(),
                &swapChainDesc,
                nullptr,
                &m_swapChain
                )
            );

        // Associate swap chain with SwapChainPanel
        // UI changes will need to be dispatched back to the UI thread
        m_swapChainPanel->Dispatcher->RunAsync(CoreDispatcherPriority::High, ref new DispatchedHandler([=]()
        {
            // Get backing native interface for SwapChainPanel
            ComPtr<ISwapChainPanelNative> panelNative;
            DX::ThrowIfFailed(
                reinterpret_cast<IUnknown*>(m_swapChainPanel)->QueryInterface(IID_PPV_ARGS(&panelNative))
                );
            DX::ThrowIfFailed(
                panelNative->SetSwapChain(m_swapChain.Get())
                );
        }, CallbackContext::Any));

        // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
        // ensures that the application will only render after each VSync, minimizing power consumption.
        DX::ThrowIfFailed(
            dxgiDevice->SetMaximumFrameLatency(1)
            );
    }

Para obter mais informações sobre esse processo, consulte Interoperabilidade entre DirectX e XAML.

Amostra

Para baixar a versão deste jogo que usa XAML para a sobreposição, consulte Exemplo de jogo DirectX e XAML. Certifique-se de ler o arquivo readme para obter detalhes sobre como criar o exemplo.

Ao contrário da versão do jogo de exemplo discutida no restante desses tópicos, a versão XAML define sua estrutura nos arquivos App.xaml.cpp e DirectXPage.xaml.cpp , em vez de App.cpp e GameInfoOverlay.cpp, respectivamente.