Estendere il gioco di esempio

Nota

Questo argomento fa parte della serie di esercitazioni Creare un semplice gioco UWP (Universal Windows Platform) con DirectX. L'argomento in tale collegamento imposta il contesto per la serie.

Per scaricare la versione di questo gioco che utilizza XAML per la sovrimpressione, vedere Gioco di esempio DirectX e XAML. Accertarsi di leggere il file leggimi per informazioni dettagliate sulla realizzazione dell'esempio.

A questo punto sono stati illustrati i componenti chiave di un gioco UWP (Universal Windows Platform) DirectX 3D di base. È possibile configurare il framework per un gioco, incluso il provider di viste e la pipeline di rendering, e implementare un ciclo di gioco di base. È anche possibile creare una sovrimpressione dell'interfaccia utente di base, incorporare suoni e implementare controlli. Anche se si sta provando a creare un gioco da soli, nel caso fossero necessarie altre informazioni e assistenza, consultare queste risorse.

Uso di XAML per la sovrimpressione

Un'alternativa che non abbiamo discusso in dettaglio è l'uso di XAML invece di Direct2D per la sovrimpressione. XAML offre molti vantaggi rispetto a Direct2D per la creazione di elementi dell'interfaccia utente. Il vantaggio più importante è che rende più conveniente incorporare l'aspetto di Windows 10 in un gioco DirectX. Molti degli elementi, degli stili e dei comportamenti comuni che definiscono un'app UWP sono strettamente integrati nel modello XAML, obbligando a molto meno lavoro gli sviluppatori di giochi da implementare. Se la progettazione del gioco ha un'interfaccia utente complessa, prendere in considerazione l'uso di XAML invece di Direct2D.

Con XAML, è possibile creare un'interfaccia di gioco simile a quella di Direct2D creata in precedenza.

XAML

XAML overlay

Direct2D

D2D overlay

Sebbene abbiano risultati finali simili, esistono diverse differenze tra l'implementazione di interfacce Direct2D e XAML.

Funzionalità XAML Direct2D
Definizione della sovrimpressione Definita in un file XAML, \*.xaml. Una volta compreso XAML, la creazione e la configurazione di sovrimpressioni più complesse vengono rese più semplici rispetto a Direct2D. Definita come una raccolta di primitive Direct2D e stringhe DirectWrite posizionate e scritte manualmente in un buffer target Direct2D.
Elementi dell'interfaccia utente Gli elementi dell'interfaccia utente XAML provengono da elementi standardizzati che fanno parte delle API XAML di Windows Runtime, tra cui Windows::UI::Xaml e Windows::UI::Xaml::Controls. Il codice che gestisce il comportamento degli elementi dell'interfaccia utente XAML viene definito in un file code-behind, Main.xaml.cpp. È possibile disegnare forme semplici come rettangoli ed ellissi.
Ridimensionamento di finestre Gestisce naturalmente gli eventi di ridimensionamento e cambiamento di stato della visuale, trasformando di conseguenza la sovrimpressione È necessario specificare manualmente come ridisegnare i componenti della sovrimpressione.

Un'altra grande differenza riguarda la catena di scambio. Non è necessario collegare la catena di scambio a un oggetto Windows::UI::Core::CoreWindow. Al contrario, un'app DirectX che incorpora XAML associa una catena di scambio quando viene costruito un nuovo oggetto SwapChainPanel.

Il frammento di codice seguente illustra come dichiarare XAML per SwapChainPanel nel file 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>

L'oggetto SwapChainPanel è impostato come la proprietà Content dell'oggetto finestra corrente creato all'avvio dal singleton dell'app.

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();
}

Per collegare la catena di scambio configurata all'istanza SwapChainPanel definita da XAML, è necessario ottenere un puntatore all'implementazione dell'interfaccia ISwapChainPanelNative nativa sottostante e chiamare ISwapChainPanelNative::SetSwapChain su di essa, trasferendo la catena di scambio configurata.

Il frammento di codice seguente di DX::DeviceResources::CreateWindowSizeDependentResources illustra in dettaglio questa operazione per l'interoperabilità 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)
            );
    }

Per maggiori informazioni su questo processo, vedere Interoperabilità DirectX e XAML.

Esempio

Per scaricare la versione di questo gioco che utilizza XAML per la sovrimpressione, vedere Gioco di esempio DirectX e XAML. Accertarsi di leggere il file leggimi per informazioni dettagliate sulla realizzazione dell'esempio.

A differenza della versione del gioco di esempio descritta nel resto di questi argomenti, la versione XAML definisce il suo framework nei file App.xaml.cpp e DirectXPage.xaml.cpp, anziché App.cpp e GameInfoOverlay.cpp, rispettivamente.