Definieren des UWP-App-Frameworks für das SpielDefine the game's UWP app framework

Hinweis

Dieses Thema ist Teil der Tutorial-Reihe zum Erstellen eines einfachen universelle Windows-Plattform (UWP) mit DirectX .This topic is part of the Create a simple Universal Windows Platform (UWP) game with DirectX tutorial series. Das Thema unter diesem Link legt den Kontext für die Reihe fest.The topic at that link sets the context for the series.

Der erste Schritt beim Programmieren eines universelle Windows-Plattform-Spiels (UWP) ist das Entwickeln des Frameworks, mit dem das App-Objekt mit Windows interagieren kann, einschließlich Windows-Runtime Features wie Suspend-Resume-Ereignis Behandlung, Änderungen im Fenster Fokus und ausrichten.The first step in coding a Universal Windows Platform (UWP) game is building the framework that lets the app object interact with Windows, including Windows Runtime features such as suspend-resume event handling, changes in window focus, and snapping.

ZieleObjectives

  • Richten Sie das Framework für ein DirectX-Spiel von universelle Windows-Plattform (UWP) ein, und implementieren Sie den Zustands Automat, der den gesamten Spielfluss definiert.Set up the framework for a Universal Windows Platform (UWP) DirectX game, and implement the state machine that defines the overall game flow.

Hinweis

Um dieses Thema zu befolgen, sehen Sie sich den Quellcode für das Simple3DGameDX -Beispiel Spiel an, das Sie heruntergeladen haben.To follow along with this topic, look in the source code for the Simple3DGameDX sample game that you downloaded.

EinführungIntroduction

Im Thema Einrichten des Spiel Projekts haben wir die wWinMain -Funktion sowie die Schnittstellen iframeworkviewsource und iframeworkview eingeführt.In the Set up the game project topic, we introduced the wWinMain function as well as the IFrameworkViewSource and IFrameworkView interfaces. Wir haben gelernt, dass die App -Klasse (die Sie sehen können, die in der App.cpp Quell Code Datei im Simple3DGameDX -Projekt definiert ist) sowohl als Ansichts Anbieterfactory als auch als Ansichts Anbieterfungiert.We learned that the App class (which you can see defined in the App.cpp source code file in the Simple3DGameDX project) serves as both view-provider factory and view-provider.

Dieses Thema wird von dort aus übernommen und geht ausführlicher darauf ein, wie die App -Klasse in einem Spiel die Methoden von iframeworkviewimplementieren sollte.This topic picks up from there, and goes into much more detail about how the App class in a game should implement the methods of IFrameworkView.

Die APP:: Initialize-MethodeThe App::Initialize method

Beim Anwendungsstart ist die erste Methode, die Windows aufruft, die Implementierung von iframeworkview:: Initialize.Upon application launch, the first method that Windows calls is our implementation of IFrameworkView::Initialize.

Ihre Implementierung sollte das grundlegendste Verhalten eines UWP-Spiels behandeln, z. b. sicherstellen, dass das Spiel eine Suspend (und ein mögliches späteres fortsetzen)-Ereignis behandeln kann, indem diese Ereignisse abonniert werden.Your implementation should handle the most fundamental behaviors of a UWP game, such as making sure that the game can handle a suspend (and a possible later resume) event by subscribing to those events. Wir haben auch Zugriff auf das Anzeige Adapter Gerät, damit wir Grafik Ressourcen erstellen können, die vom Gerät abhängen.We also have access to the display adapter device here, so we can create graphics resources that depend on the device.

void Initialize(CoreApplicationView const& applicationView)
{
    applicationView.Activated({ this, &App::OnActivated });

    CoreApplication::Suspending({ this, &App::OnSuspending });

    CoreApplication::Resuming({ this, &App::OnResuming });

    // At this point we have access to the device. 
    // We can create the device-dependent resources.
    m_deviceResources = std::make_shared<DX::DeviceResources>();
}

Vermeiden Sie nach Möglichkeit unformatierte Zeiger (und ist fast immer möglich).Avoid raw pointers whenever possible (and it's nearly always possible).

  • Bei Windows-Runtime Typen können Sie sehr häufig Zeiger ganz vermeiden und nur einen Wert auf dem Stapel erstellen.For Windows Runtime types, you can very often avoid pointers altogether and just construct a value on the stack. Wenn Sie einen Zeiger benötigen, verwenden Sie WinRT:: com_ptr (ein Beispiel hierfür finden Sie in Kürze).If you do need a pointer, then use winrt::com_ptr (we'll see an example of that soon).
  • Verwenden Sie für eindeutige Zeiger den Std:: unique_ptr -und den Std:: make_unique.For unique pointers, use std::unique_ptr and std::make_unique.
  • Verwenden Sie für freigegebene Zeiger Std:: shared_ptr und Std:: make_shared.For shared pointers, use std::shared_ptr and std::make_shared.

Die APP:: SetWindow-MethodeThe App::SetWindow method

Nach der Initialisierungruft Windows die Implementierung von iframeworkview:: SetWindowauf und übergibt ein corewindow -Objekt, das das Hauptfenster des Spiels darstellt.After Initialize, Windows calls our implementation of IFrameworkView::SetWindow, passing a CoreWindow object representing the game's main window.

In App:: SetWindowabonnieren wir Fenster bezogene Ereignisse und konfigurieren einige Fenster-und Anzeigeverhalten.In App::SetWindow, we subscribe to window-related events, and configure some window and display behaviors. Beispielsweise erstellen wir einen Mauszeiger (über die corecursor -Klasse), der sowohl von Maus-als auch von Touchscreen-Steuerelementen verwendet werden kann.For example, we construct a mouse pointer (via the CoreCursor class), which can be used by both mouse and touch controls. Wir übergeben auch das Window-Objekt an das Geräte abhängige Ressourcen Objekt.We also pass the window object to our device-dependent resources object.

Wir werden uns ausführlicher mit der Behandlung von Ereignissen im Thema Game Flow Management beschäftigen.We'll talk more about handling events in the Game flow management topic.

void SetWindow(CoreWindow const& window)
{
    //CoreWindow window = CoreWindow::GetForCurrentThread();
    window.Activate();

    window.PointerCursor(CoreCursor(CoreCursorType::Arrow, 0));

    PointerVisualizationSettings visualizationSettings{ PointerVisualizationSettings::GetForCurrentView() };
    visualizationSettings.IsContactFeedbackEnabled(false);
    visualizationSettings.IsBarrelButtonFeedbackEnabled(false);

    m_deviceResources->SetWindow(window);

    window.Activated({ this, &App::OnWindowActivationChanged });

    window.SizeChanged({ this, &App::OnWindowSizeChanged });

    window.Closed({ this, &App::OnWindowClosed });

    window.VisibilityChanged({ this, &App::OnVisibilityChanged });

    DisplayInformation currentDisplayInformation{ DisplayInformation::GetForCurrentView() };

    currentDisplayInformation.DpiChanged({ this, &App::OnDpiChanged });

    currentDisplayInformation.OrientationChanged({ this, &App::OnOrientationChanged });

    currentDisplayInformation.StereoEnabledChanged({ this, &App::OnStereoEnabledChanged });

    DisplayInformation::DisplayContentsInvalidated({ this, &App::OnDisplayContentsInvalidated });
}

Die APP:: Load-MethodeThe App::Load method

Nachdem das Hauptfenster festgelegt wurde, wird die Implementierung von iframeworkview:: Load aufgerufen.Now that the main window is set, our implementation of IFrameworkView::Load is called. Die Auslastung ist ein besserer Ort, um Spieldaten oder Assets vorab abzurufen, als " Initialize " und " SetWindow".Load is a better place to pre-fetch game data or assets than Initialize and SetWindow.

void Load(winrt::hstring const& /* entryPoint */)
{
    if (!m_main)
    {
        m_main = winrt::make_self<GameMain>(m_deviceResources);
    }
}

Wie Sie sehen können, wird die tatsächliche Arbeit an den Konstruktor des gamemain -Objekts delegiert, das wir hier machen.As you can see, the actual work is delegated to the constructor of the GameMain object that we make here. Die gamemain -Klasse wird in GameMain.h und definiert GameMain.cpp .The GameMain class is defined in GameMain.h and GameMain.cpp.

Der gamemain:: gamemain-KonstruktorThe GameMain::GameMain constructor

Der gamemain -Konstruktor (und die anderen Member-Funktionen, die er aufruft) startet eine Reihe von asynchronen Ladevorgängen, um die Spielobjekte zu erstellen, Grafik Ressourcen zu laden und den Zustands Automat des Spiels zu initialisieren.The GameMain constructor (and the other member functions that it calls) begins a set of asynchronous loading operations to create the game objects, load graphics resources, and initialize the game's state machine. Wir führen auch alle notwendigen Vorbereitungen aus, bevor das Spiel beginnt, z. b. das Festlegen von Start Zuständen oder globalen Werten.We also do any necessary preparations before the game begins, such as setting any starting states or global values.

Windows erzwingt eine Beschränkung für die Zeit, die das Spiel dauern kann, bevor die Verarbeitung der Eingabe beginnt.Windows imposes a limit on the time your game can take before it begins processing input. Daher bedeutet die Verwendung von asyc, wie wir hier Vorgehen, bedeutet, dass die Last schnell zurückgegeben werden kann, während die begonnene Arbeit im Hintergrund fortgesetzt wird.So using asyc, as we do here, means that Load can return quickly while the work that it has begun continues in the background. Wenn das Laden sehr lange dauert, oder wenn viele Ressourcen vorhanden sind, ist die Bereitstellung der Benutzer mit einer häufig aktualisierten Statusanzeige eine gute Idee.If loading takes a long time, or if there are lots of resources, then providing your users with a frequently updated progress bar is a good idea.

Wenn Sie mit der asynchronen Programmierung noch nicht vertraut sind, finden Sie weitere Informationen unter Parallelität und asynchrone Vorgänge mit C++/WinRT.If you're new to asynchronous programming, then see Concurrency and asynchronous operations with C++/WinRT.

GameMain::GameMain(std::shared_ptr<DX::DeviceResources> const& deviceResources) :
    m_deviceResources(deviceResources),
    m_windowClosed(false),
    m_haveFocus(false),
    m_gameInfoOverlayCommand(GameInfoOverlayCommand::None),
    m_visible(true),
    m_loadingCount(0),
    m_updateState(UpdateEngineState::WaitingForResources)
{
    m_deviceResources->RegisterDeviceNotify(this);

    m_renderer = std::make_shared<GameRenderer>(m_deviceResources);
    m_game = std::make_shared<Simple3DGame>();

    m_uiControl = m_renderer->GameUIControl();

    m_controller = std::make_shared<MoveLookController>(CoreWindow::GetForCurrentThread());

    auto bounds = m_deviceResources->GetLogicalSize();

    m_controller->SetMoveRect(
        XMFLOAT2(0.0f, bounds.Height - GameUIConstants::TouchRectangleSize),
        XMFLOAT2(GameUIConstants::TouchRectangleSize, bounds.Height)
        );
    m_controller->SetFireRect(
        XMFLOAT2(bounds.Width - GameUIConstants::TouchRectangleSize, bounds.Height - GameUIConstants::TouchRectangleSize),
        XMFLOAT2(bounds.Width, bounds.Height)
        );

    SetGameInfoOverlay(GameInfoOverlayState::Loading);
    m_uiControl->SetAction(GameInfoOverlayCommand::None);
    m_uiControl->ShowGameInfoOverlay();

    // Asynchronously initialize the game class and load the renderer device resources.
    // By doing all this asynchronously, the game gets to its main loop more quickly
    // and in parallel all the necessary resources are loaded on other threads.
    ConstructInBackground();
}

winrt::fire_and_forget GameMain::ConstructInBackground()
{
    auto lifetime = get_strong();

    m_game->Initialize(m_controller, m_renderer);

    co_await m_renderer->CreateGameDeviceResourcesAsync(m_game);

    // The finalize code needs to run in the same thread context
    // as the m_renderer object was created because the D3D device context
    // can ONLY be accessed on a single thread.
    // co_await of an IAsyncAction resumes in the same thread context.
    m_renderer->FinalizeCreateGameDeviceResources();

    InitializeGameState();

    if (m_updateState == UpdateEngineState::WaitingForResources)
    {
        // In the middle of a game so spin up the async task to load the level.
        co_await m_game->LoadLevelAsync();

        // The m_game object may need to deal with D3D device context work so
        // again the finalize code needs to run in the same thread
        // context as the m_renderer object was created because the D3D
        // device context can ONLY be accessed on a single thread.
        m_game->FinalizeLoadLevel();
        m_game->SetCurrentLevelToSavedState();
        m_updateState = UpdateEngineState::ResourcesLoaded;
    }
    else
    {
        // The game is not in the middle of a level so there aren't any level
        // resources to load.
    }

    // Since Game loading is an async task, the app visual state
    // may be too small or not have focus. Put the state machine
    // into the correct state to reflect these cases.

    if (m_deviceResources->GetLogicalSize().Width < GameUIConstants::MinPlayableWidth)
    {
        m_updateStateNext = m_updateState;
        m_updateState = UpdateEngineState::TooSmall;
        m_controller->Active(false);
        m_uiControl->HideGameInfoOverlay();
        m_uiControl->ShowTooSmall();
        m_renderNeeded = true;
    }
    else if (!m_haveFocus)
    {
        m_updateStateNext = m_updateState;
        m_updateState = UpdateEngineState::Deactivated;
        m_controller->Active(false);
        m_uiControl->SetAction(GameInfoOverlayCommand::None);
        m_renderNeeded = true;
    }
}

void GameMain::InitializeGameState()
{
    // Set up the initial state machine for handling Game playing state.
    ...
}

Im folgenden finden Sie einen Überblick über die Abfolge der Aufgaben, die vom Konstruktor gestartet werden.Here's an outline of the sequence of work that's kicked off by the constructor.

  • Erstellen und initialisieren Sie ein Objekt vom Typ " gamerenderer".Create and initialize an object of type GameRenderer. Weitere Informationen finden Sie unter Rendering Framework I: Intro to Rendering.For more information, see Rendering framework I: Intro to rendering.
  • Erstellen und initialisieren Sie ein Objekt vom Typ Simple3DGame.Create and initialize an object of type Simple3DGame. Weitere Informationen finden Sie unter Definieren des Hauptspiel Objekts.For more information, see Define the main game object.
  • Erstellen Sie das Steuerelement Objekt für die Spiel-UI, und zeigen Sie die Spiel Info Überlagerung an, um eine Statusanzeige beim Laden der Ressourcen Dateien anzuzeigenCreate the game UI control object, and display game info overlay to show a progress bar as the resource files load. Weitere Informationen finden Sie unter Hinzufügen einer Benutzeroberfläche.For more information, see Adding a user interface.
  • Erstellen Sie ein Controller Objekt, um Eingaben vom Controller zu lesen (Touchscreen, Maus oder Xbox Wireless Controller).Create a controller object to read input from the controller (touch, mouse, or Xbox wireless controller). Weitere Informationen finden Sie unter Hinzufügen von Steuerelementen.For more information, see Adding controls.
  • Definieren Sie zwei rechteckige Bereiche in der unteren linken und unteren rechten Ecke des Bildschirms für die Steuerelemente "verschieben" und "Kamera berühren".Define two rectangular areas in the lower-left and lower-right corners of the screen for the move and camera touch controls, respectively. Der Player verwendet das untere linke Rechteck (definiert im Aufrufen von setmoverect) als virtuelles Kontroll Pad, um die Kamera vorwärts und rückwärts zu bewegen, und Seite zu Seite.The player uses the lower-left rectangle (defined in the call to SetMoveRect) as a virtual control pad for moving the camera forward and backward, and side to side. Das untere rechte Rechteck (definiert durch die setfirerermethode ) wird als virtuelle Schaltfläche verwendet, um den Ammo auszulösen.The lower-right rectangle (defined by the SetFireRect method) is used as a virtual button to fire the ammo.
  • Verwenden sie Coroutinen, um das Laden von Ressourcen in separate Phasen zu unterbrechen.Use coroutines to break resource loading into separate stages. Der Zugriff auf den Direct3D-Gerätekontext ist auf den Thread beschränkt, in dem der Gerätekontext erstellt wurde. der Zugriff auf das Direct3D-Gerät für die Objekt Erstellung erfolgt zwar kostenlos.Access to the Direct3D device context is restricted to the thread on which the device context was created; while access to the Direct3D device for object creation is free-threaded. Folglich kann die " gamerenderer:: forategamedeviceresourcesasync "-Coroutine in einem separaten Thread von der Abschluss Aufgabe (gamerenderer:: finalizecreategamedeviceresources) ausgeführt werden, die im ursprünglichen Thread ausgeführt wird.Consequently, the GameRenderer::CreateGameDeviceResourcesAsync coroutine can run on a separate thread from the completion task (GameRenderer::FinalizeCreateGameDeviceResources), which runs on the original thread.
  • Wir verwenden ein ähnliches Muster für das Laden von ebenendressourcen mit Simple3DGame:: loadlevelasync und Simple3DGame:: finalizeloadlevel.We use a similar pattern for loading level resources with Simple3DGame::LoadLevelAsync and Simple3DGame::FinalizeLoadLevel.

Im nächsten Thema (Game Flow Management) wird mehr von gamemain:: initializegamestate angezeigt.We'll see more of GameMain::InitializeGameState in the next topic (Game flow management).

Die APP:: onaktivierte MethodeThe App::OnActivated method

Als nächstes wird das coreapplicationview:: aktivierte -Ereignis ausgelöst.Next, the CoreApplicationView::Activated event is raised. Daher wird jeder aktivierte aktivierte Ereignishandler (z. b. die App:: onaktivierte Methode) aufgerufen.So any OnActivated event handler that you have (such as our App::OnActivated method) is called.

void OnActivated(CoreApplicationView const& /* applicationView */, IActivatedEventArgs const& /* args */)
{
    CoreWindow window = CoreWindow::GetForCurrentThread();
    window.Activate();
}

Die einzige Arbeit, die wir hier tun, besteht darin, das Haupt- corewindowzu aktivieren.The only work we do here is to activate the main CoreWindow. Alternativ dazu können Sie auch in App:: SetWindowauswählen.Alternatively, you can choose to do that in App::SetWindow.

Die APP:: Run-MethodeThe App::Run method

Initialize, SetWindowund Load haben die Stufe festgelegt.Initialize, SetWindow, and Load have set the stage. Nachdem das Spiel eingerichtet ist und ausgeführt wird, wird die Implementierung von iframeworkview:: Run aufgerufen.Now that the game is up and running, our implementation of IFrameworkView::Run is called.

void Run()
{
    m_main->Run();
}

Auch hier wird die Arbeit an gamemaindelegiert.Again, work is delegated to GameMain.

Die gamemain:: Run-MethodeThe GameMain::Run method

Gamemain:: Run ist die Hauptschleife des Spiels. Sie finden Sie in GameMain.cpp .GameMain::Run is the main loop of the game; you can find it in GameMain.cpp. Die grundlegende Logik besteht darin, dass das Fenster für das Spiel zwar geöffnet bleibt, aber alle Ereignisse verteilt, den Timer aktualisiert und anschließend die Ergebnisse der Grafik Pipeline gerenbt und präsentiert.The basic logic is that while the window for your game remains open, dispatch all events, update the timer, and then render and present the results of the graphics pipeline. Außerdem werden die Ereignisse, die für den Übergang zwischen den Spiel Zuständen verwendet werden, verteilt und verarbeitet.Also here, the events used to transition between game states are dispatched and processed.

Der Code hier befasst sich auch mit zwei Zuständen im Status Computer der Spiel-Engine.The code here is also concerned with two of the states in the game engine state machine.

  • Updateenginestate::D eaktivierter.UpdateEngineState::Deactivated. Dadurch wird festgelegt, dass das Spielfenster deaktiviert ist (der Fokus verliert) oder am gedockt ist.This specifies that the game window is deactivated (has lost focus) or is snapped.
  • Updateenginestate::"".UpdateEngineState::TooSmall. Dies gibt an, dass der Client Bereich zu klein ist, um das Spiel zu Rendering.This specifies that the client area is too small to render the game in.

In einem dieser Zustände hält das Spiel die Ereignisverarbeitung an und wartet darauf, dass sich das Fenster auf den Fokus, auf nicht NAP oder seine Größe ändert.In either of these states, the game suspends event processing, and waits for the window to focus, to unsnap, or to be resized.

Wenn Ihr Spiel den Fokus hat, müssen Sie jedes in der Meldungswarteschlange eingehende Ereignis behandeln. Daher müssen Sie CoreWindowDispatch.ProcessEvents mit der Option ProcessAllIfPresent aufrufen.When your game has focus, you must handle every event in the message queue as it arrives, and so you must call CoreWindowDispatch.ProcessEvents with the ProcessAllIfPresent option. Andere Optionen können Verzögerungen bei der Verarbeitung von Nachrichten Ereignissen verursachen, sodass Ihr Spiel nicht mehr reagiert oder das Verhalten von Finger Eingaben zu einem langsamen Verhalten führt.Other options can cause delays in processing message events, which can make your game feel unresponsive, or result in touch behaviors that feel sluggish.

Wenn das Spiel nicht sichtbar, angehalten oder angedockt ist, ist es nicht ratsam, Ressourcen zu nutzen, um Nachrichten zu senden, die niemals eintreffen.When the game is not visible, suspended, nor snapped, you don't want it to consume any resources cycling to dispatch messages that will never arrive. In diesem Fall muss Ihr Spiel die Option processoneandallpending verwenden.In this case, your game must use the ProcessOneAndAllPending option. Diese Option wird blockiert, bis ein Ereignis abgerufen wird, und anschließend wird dieses Ereignis verarbeitet (sowie alle anderen Personen, die während der Verarbeitung der ersten in der Prozess Warteschlange eintreffen).That option blocks until it gets an event, and then processes that event (as well as any others that arrive in the process queue during the processing of the first). Corewindowdispatch. procesendvents wird dann sofort nach der Verarbeitung der Warteschlange zurückgegeben.CoreWindowDispatch.ProcessEvents then immediately returns after the queue has been processed.

void GameMain::Run()
{
    while (!m_windowClosed)
    {
        if (m_visible)
        {
            switch (m_updateState)
            {
            case UpdateEngineState::Deactivated:
            case UpdateEngineState::TooSmall:
                if (m_updateStateNext == UpdateEngineState::WaitingForResources)
                {
                    WaitingForResourceLoading();
                    m_renderNeeded = true;
                }
                else if (m_updateStateNext == UpdateEngineState::ResourcesLoaded)
                {
                    // In the device lost case, we transition to the final waiting state
                    // and make sure the display is updated.
                    switch (m_pressResult)
                    {
                    case PressResultState::LoadGame:
                        SetGameInfoOverlay(GameInfoOverlayState::GameStats);
                        break;

                    case PressResultState::PlayLevel:
                        SetGameInfoOverlay(GameInfoOverlayState::LevelStart);
                        break;

                    case PressResultState::ContinueLevel:
                        SetGameInfoOverlay(GameInfoOverlayState::Pause);
                        break;
                    }
                    m_updateStateNext = UpdateEngineState::WaitingForPress;
                    m_uiControl->ShowGameInfoOverlay();
                    m_renderNeeded = true;
                }

                if (!m_renderNeeded)
                {
                    // The App is not currently the active window and not in a transient state so just wait for events.
                    CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
                    break;
                }
                // otherwise fall through and do normal processing to get the rendering handled.
            default:
                CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
                Update();
                m_renderer->Render();
                m_deviceResources->Present();
                m_renderNeeded = false;
            }
        }
        else
        {
            CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
        }
    }
    m_game->OnSuspending();  // Exiting due to window close, so save state.
}

Die APP:: Uninitialize-MethodeThe App::Uninitialize method

Nach Beendigung des Spiels wird die Implementierung von iframeworkview:: Uninitialize aufgerufen.When the game ends, our implementation of IFrameworkView::Uninitialize is called. Das ist unsere Gelegenheit, eine Bereinigung durchzuführen.This is our opportunity to perform cleanup. Das Schließen des App-Fensters bricht den Prozess der APP nicht ab. Stattdessen wird der Zustand des App-Singleton in den Arbeitsspeicher geschrieben.Closing the app window doesn't kill the app's process; but instead it writes the state of the app singleton to memory. Wenn beim Freigeben dieses Speichers durch das System, einschließlich der besonderen Bereinigung von Ressourcen, etwas besonderes erforderlich ist, dann platzieren Sie den Code für diesen Bereinigung in der Initialisierung.If anything special must happen when the system reclaims this memory, including any special cleanup of resources, then put the code for that cleanup in Uninitialize.

In unserem Fall ist " App:: Uninitialize " kein Vorgang.In our case, App::Uninitialize is a no-op.

void Uninitialize()
{
}

TippsTips

Wenn Sie Ihr eigenes Spiel entwickeln, entwerfen Sie den Startcode um die in diesem Thema beschriebenen Methoden.When developing your own game, design your startup code around the methods described in this topic. Im folgenden finden Sie eine einfache Liste der grundlegenden Vorschläge für jede Methode.Here's a simple list of basic suggestions for each method.

  • Verwenden Sie Initialize , um die Hauptklassen zuzuordnen, und verbinden Sie die grundlegenden Ereignishandler.Use Initialize to allocate your main classes, and connect up the basic event handlers.
  • Verwenden Sie SetWindow , um beliebige Fenster spezifische Ereignisse zu abonnieren und das Hauptfenster an das Geräte abhängige Ressourcen Objekt zu übergeben, sodass dieses Fenster beim Erstellen einer Swapkette verwendet werden kann.Use SetWindow to subscribe to any window-specific events, and to pass your main window to your device-dependent resources object so that it can use that window when creating a swap chain.
  • Verwenden Sie Load , um das verbleibende Setup zu verarbeiten und die asynchrone Erstellung von Objekten und das Laden von Ressourcen zu initiieren.Use Load to handle any remaining setup, and to initiate the asynchronous creation of objects, and loading of resources. Wenn Sie temporäre Dateien oder Daten erstellen möchten, z. b. prozedurale generierte Assets, dann müssen Sie dies auch hier tun.If you need to create any temporary files or data, such as procedurally generated assets, then do that here, too.

Nächste SchritteNext steps

In diesem Thema wurde ein Teil der grundlegenden Struktur eines UWP-Spiels behandelt, das DirectX verwendet.This topic has covered some of the basic structure of a UWP game that uses DirectX. Es ist ratsam, diese Methoden zu berücksichtigen, da wir in späteren Themen auf einige davon verweisen werden.It's a good idea to keep these methods in mind, because we'll be referring back to some of them in later topics.

Im nächsten Thema — Game Flow Management — werden wir ausführlich darauf eingehen, wie Spiele Zustände und Ereignis Behandlung verwaltet werden, um das Spiel zu halten.In the next topic—Game flow management—we'll take an in-depth look at how to manage game states and event handling in order to keep the game flowing.