Erweitern des Spielbeispiels

Hinweis

Dieses Thema ist Teil der Tutorialreihe Erstellen eines einfachen Universelle Windows-Plattform -Spiels (UWP) mit DirectX. Das Thema unter diesem Link legt den Kontext für die Reihe fest.

Informationen zum Herunterladen der Version dieses Spiels, die XAML für das Overlay verwendet, finden Sie unter DirectX- und XAML-Spielbeispiel. Lesen Sie unbedingt die Infodatei dort, um Details zum Erstellen des Beispiels zu erhalten.

An diesem Punkt haben wir die wichtigsten Komponenten eines UWP-DirectX-3D-Spiels (Basic Universelle Windows-Plattform) behandelt. Sie können das Framework für ein Spiel einrichten, einschließlich des Ansichtsanbieters und der Renderingpipeline, und eine einfache Spielschleife implementieren. Sie können auch eine einfache Benutzeroberflächenüberlagerung erstellen, Sounds integrieren und Steuerelemente implementieren. Sie sind auf dem Weg, ein eigenes Spiel zu erstellen, aber wenn Sie weitere Hilfe und Informationen benötigen, schauen Sie sich diese Ressourcen an.

Verwenden von XAML für die Überlagerung

Eine Alternative, die wir nicht ausführlich behandelt haben, ist die Verwendung von XAML anstelle von Direct2D für das Overlay. XAML bietet viele Vorteile gegenüber Direct2D für das Zeichnen von Benutzeroberflächenelementen. Der wichtigste Vorteil ist, dass die Einbindung der Windows 10 Look and Feel in Ihr DirectX-Spiel bequemer wird. Viele der allgemeinen Elemente, Stile und Verhalten, die eine UWP-App ausmachen, sind eng in das XAML-Modell integriert und ersparen einem Spieleentwickler eine Menge Arbeit bei der Implementierung. Falls Ihr eigenes Spieldesign eine komplizierte Benutzeroberfläche hat, empfiehlt sich unter Umständen die Verwendung von XAML anstelle von Direct2D.

Mit XAML können wir eine Spieloberfläche erstellen, die der zuvor erstellten Direct2D-Schnittstelle ähnelt.

XAML

XAML-Überlagerung

Direct2D

D2D-Überlagerung

Obwohl sie ähnliche Endergebnisse aufweisen, gibt es eine Reihe von Unterschieden zwischen der Implementierung von Direct2D- und XAML-Schnittstellen.

Funktion XAML Direct2D
Definieren der Überlagerung Definiert in einer XAML-Datei, \*.xaml. Nach dem Verständnis von XAML wird das Erstellen und Konfigurieren komplizierterer Überlagerungen im Vergleich zu Direct2D vereinfacht. Definiert als Sammlung von Direct2D-Grundtypen und DirectWrite Zeichenfolgen, die manuell platziert und in einen Direct2D-Zielpuffer geschrieben werden.
Benutzeroberflächenelemente XAML-Benutzeroberflächenelemente stammen aus standardisierten Elementen, die Teil der Windows-Runtime XAML-APIs sind, einschließlich Windows::UI::Xaml und Windows::UI::Xaml::Controls. Der Code zum Behandeln des Verhaltens der XAML-UI-Elemente ist in der CodeBehind-Datei „Main.xaml.cpp“ definiert. Einfache Formen können wie Rechtecke und Auslassungspunkte gezeichnet werden.
Ändern der Fenstergröße Natürlich behandelt Größenänderungs- und Anzeigezustandsänderungsereignisse und transformiert die Überlagerung entsprechend. Sie müssen manuell angeben, wie die Komponenten des Overlays neu gezeichnet werden sollen.

Ein weiterer großer Unterschied ist die Swapchain. Sie müssen die Swapchain nicht an ein Windows::UI::Core::CoreWindow-Objekt anfügen. Stattdessen ordnet eine DirectX-App, die XAML enthält, eine Swapchain zu, wenn ein neues SwapChainPanel-Objekt erstellt wird.

Der folgende Codeausschnitt zeigt, wie XAML für swapChainPanel in der Datei DirectXPage.xaml deklariert wird.

<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>

Das SwapChainPanel-Objekt wird als Content-Eigenschaft des aktuellen Fensterobjekts festgelegt, das beim Starten vom App-Singleton erstellt wurde.

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

Um die konfigurierte Swapchain an die swapChainPanel-instance anzufügen, die von Ihrem XAML definiert wird, müssen Sie einen Zeiger auf die zugrunde liegende native ISwapChainPanelNative-Schnittstellenimplementierung abrufen und ISwapChainPanelNative::SetSwapChain darauf aufrufen und die konfigurierte Swapchain übergeben.

Der folgende Codeausschnitt aus DX::D eviceResources::CreateWindowSizeDependentResources beschreibt dies für DirectX/XAML-Interop:

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

Weitere Informationen zu diesem Prozess finden Sie unter Interoperabilität von DirectX und XAML.

Beispiel

Informationen zum Herunterladen der Version dieses Spiels, die XAML für das Overlay verwendet, finden Sie unter DirectX- und XAML-Spielbeispiel. Lesen Sie unbedingt die Infodatei dort, um Details zum Erstellen des Beispiels zu erhalten.

Im Gegensatz zur Version des Beispielspiels, die in den restlichen Themen erläutert wird, definiert die XAML-Version das Framework in den Dateien App.xaml.cpp und DirectXPage.xaml.cpp anstelle von App.cpp bzw. GameInfoOverlay.cpp.