Compartir a través de


Extender el juego de ejemplo

Nota:

Este tema forma parte de la serie de tutoriales Crear un juego sencillo para la Plataforma universal de Windows (UWP) con DirectX. El tema de ese vínculo establece el contexto de la serie.

Para descargar la versión de este juego que usa XAML para la superposición, consulta Ejemplo de juego DirectX y XAML. Asegúrese de leer el archivo Léame allí para obtener más información sobre cómo compilar el ejemplo.

En este punto hemos tratado los componentes clave de un juego directX 3D de Plataforma universal de Windows básico (UWP). Puedes configurar el marco para un juego, incluido el proveedor de vistas y la canalización de representación, e implementar un bucle de juego básico. También puede crear una superposición de interfaz de usuario básica, incorporar sonidos e implementar controles. Estás en tu camino para crear un juego propio, pero si necesitas más ayuda e información, echa un vistazo a estos recursos.

Uso de XAML para la superposición

Una alternativa que no analizamos en profundidad es el uso de XAML en lugar de Direct2D para la superposición. XAML tiene muchas ventajas sobre Direct2D para dibujar elementos de la interfaz de usuario. La ventaja más importante es que hace que la incorporación del aspecto de Windows 10 a tu juego directX sea más conveniente. Muchos de los elementos, estilos y comportamientos comunes que definen una aplicación para UWP están estrechamente integrados en el modelo XAML, lo que hace que sea mucho menos trabajo para que un desarrollador de juegos implemente. Si tu propio diseño de juego tiene una interfaz de usuario complicada, considera la posibilidad de usar XAML en lugar de Direct2D.

Con XAML, podemos crear una interfaz de juego similar a la direct2D que se hizo anteriormente.

XAML

Superposición xaml

Direct2D

Superposición D2D

Aunque tienen resultados finales similares, hay varias diferencias entre implementar interfaces Direct2D y XAML.

Característica XAML Direct2D
Definición de la superposición Definido en un archivo XAML, \*.xaml. Una vez que comprenda XAML, la creación y configuración de superposiciones más complicadas se simplifica en comparación con Direct2D. Se define como una colección de primitivas de Direct2D y cadenas de DirectWrite colocadas y escritas manualmente en un búfer de destino de Direct2D.
Elementos de la interfaz de usuario Los elementos de la interfaz de usuario XAML proceden de elementos estandarizados que forman parte de las API XAML de Windows Runtime, como Windows::UI::Xaml y Windows::UI::Xaml::Controls. El código que controla el comportamiento de los elementos de la interfaz de usuario XAML se define en un archivo codebehind, Main.xaml.cpp. Las formas simples se pueden dibujar como rectángulos y elipses.
Cambio de tamaño de ventana Controla de forma natural los eventos de cambio de estado de cambio de tamaño y visualización, lo que transforma la superposición en consecuencia. Debe especificar manualmente cómo volver a dibujar los componentes de la superposición.

Otra gran diferencia implica la cadena de intercambio. No es necesario asociar la cadena de intercambio a un objeto Windows::UI::Core::Core::CoreWindow. En su lugar, una aplicación DirectX que incorpora XAML asocia una cadena de intercambio cuando se construye un nuevo objeto SwapChainPanel.

El fragmento de código siguiente muestra cómo declarar XAML para SwapChainPanel en el archivo 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>

El objeto SwapChainPanel se establece como la propiedad Content del objeto de ventana actual creado al iniciar el singleton de la aplicación.

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 adjuntar la cadena de intercambio configurada a la instancia swapChainPanel definida por el XAML, debes obtener un puntero a la implementación de la interfaz ISwapChainPanelNative subyacente y llamar a ISwapChainPanelNative::SetSwapChain en ella, pasando la cadena de intercambio configurada.

El siguiente fragmento de código de DX::D eviceResources::CreateWindowSizeDependentResources detalla esto para la interoperabilidad de 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 obtener más información sobre este proceso, consulta Interoperabilidad xaml y DirectX.

Ejemplo

Para descargar la versión de este juego que usa XAML para la superposición, consulta Ejemplo de juego DirectX y XAML. Asegúrese de leer el archivo Léame allí para obtener más información sobre cómo compilar el ejemplo.

A diferencia de la versión del juego de ejemplo que se describe en el resto de estos temas, la versión XAML define su marco en los archivos App.xaml.cpp y DirectXPage.xaml.cpp , en lugar de App.cpp y GameInfoOverlay.cpp, respectivamente.