Einrichten des Spieleprojekts

Hinweis

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

Der erste Schritt bei der Entwicklung Ihres Spiels besteht darin, ein Projekt in Microsoft Visual Studio zu erstellen. Nachdem Sie ein Projekt speziell für die Spieleentwicklung konfiguriert haben, können Sie es später als eine Art Vorlage erneut verwenden.

Ziele

  • Erstellen Sie ein neues Projekt in Visual Studio mithilfe einer Projektvorlage.
  • Verstehen des Einstiegspunkts und der Initialisierung des Spiels, indem Sie die Quelldatei für die App-Klasse untersuchen.
  • Sehen Sie sich die Spielschleife an.
  • Überprüfen Sie die Datei package.appxmanifest des Projekts.

Erstellen eines neuen Projekts in Visual Studio

Hinweis

Informationen zum Einrichten von Visual Studio für die C++/WinRT-Entwicklung – einschließlich Installieren und Verwenden der C++/WinRT Visual Studio-Erweiterung (VSIX) und des NuGet-Pakets (die zusammen die Projektvorlage und Buildunterstützung bereitstellen) – finden Sie unter Visual Studio-Unterstützung für C++/WinRT.

Installieren Sie zuerst die neueste Version der C++/WinRT Visual Studio-Erweiterung (VSIX). Siehe den Hinweis oben. Erstellen Sie dann in Visual Studio ein neues Projekt basierend auf der Projektvorlage Core App (C++/WinRT). Die neueste allgemein verfügbare Version von Windows SDK (d. h. keine Vorschauversion).

Überprüfen Sie die App-Klasse, um IFrameworkViewSource und IFrameworkView zu verstehen.

Öffnen Sie in Ihrem Core-App-Projekt die Quellcodedatei App.cpp. Darin befindet sich die Implementierung der App-Klasse , die die App und ihren Lebenszyklus darstellt. In diesem Fall wissen wir natürlich, dass die App ein Spiel ist. Sie wird jedoch als App bezeichnet, um allgemeiner darüber zu sprechen, wie eine Universelle Windows-Plattform-App (UWP) initialisiert wird.

Die wWinMain-Funktion

Die wWinMain-Funktion ist der Einstiegspunkt für die App. So sieht wWinMain aus (von App.cpp).

int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
    CoreApplication::Run(winrt::make<App>());
}

Wir erstellen eine instance der App-Klasse (dies ist die einzige instance der erstellten App), und übergeben sie an die statische CoreApplication.Run-Methode. Beachten Sie, dass CoreApplication.Run eine IFrameworkViewSource-Schnittstelle erwartet. Daher muss die App-Klasse diese Schnittstelle implementieren.

In den nächsten beiden Abschnitten in diesem Thema werden die Schnittstellen IFrameworkViewSource und IFrameworkView beschrieben. Diese Schnittstellen (sowie CoreApplication.Run) stellen eine Möglichkeit für Ihre App dar, Windows einen Ansichtsanbieter zur Verfügung zu stellen. Windows verwendet diesen Ansichtsanbieter, um Ihre App mit der Windows-Shell zu verbinden, damit Sie Lebenszyklusereignisse der Anwendung verarbeiten können.

Die IFrameworkViewSource-Schnittstelle

Die App-Klasse implementiert tatsächlich IFrameworkViewSource, wie Sie in der folgenden Auflistung sehen können.

struct App : winrt::implements<App, IFrameworkViewSource, IFrameworkView>
{
    ...
    IFrameworkView CreateView()
    {
        return *this;
    }
    ...
}

Ein Objekt, das IFrameworkViewSource implementiert, ist ein Ansichtsanbieter-Factoryobjekt . Die Aufgabe dieses Objekts besteht darin, ein Ansichtsanbieterobjekt zu erstellen und zurückzugeben.

IFrameworkViewSource verfügt über die einzelne Methode IFrameworkViewSource::CreateView. Windows ruft diese Funktion für das Objekt auf, das Sie an CoreApplication.Run übergeben. Wie Sie oben sehen können, gibt die App::CreateView-Implementierung dieser Methode zurück *this. Anders ausgedrückt: Das App-Objekt gibt sich selbst zurück. Da IFrameworkViewSource::CreateView über den Rückgabewerttyp IFrameworkView verfügt, muss die App-Klasseauch diese Schnittstelle implementieren. Und sie sehen, dass dies in der obigen Auflistung der Fall ist.

Die IFrameworkView-Schnittstelle

Ein Objekt, das IFrameworkView implementiert, ist ein Ansichtsanbieterobjekt . Und wir haben Windows jetzt mit diesem Ansichtsanbieter bereitgestellt. Es ist das gleiche App-Objekt , das wir in wWinMain erstellt haben. Daher dient die App-Klasse sowohl als Ansichtsanbieter-Factory als auch als Ansichtsanbieter.

Jetzt kann Windows die Implementierungen der Methoden von IFrameworkView der App-Klasse aufrufen. In den Implementierungen dieser Methoden hat Ihre App die Möglichkeit, Aufgaben wie die Initialisierung auszuführen, mit dem Laden der benötigten Ressourcen zu beginnen, eine Verbindung mit den entsprechenden Ereignishandlern herzustellen und den CoreWindow zu erhalten, den Ihre App zum Anzeigen der Ausgabe verwendet.

Ihre Implementierungen der Methoden von IFrameworkView werden in der unten gezeigten Reihenfolge aufgerufen.

Und hier ist das Skelett der App-Klasse (in App.cpp), die die Signaturen dieser Methoden zeigt.

struct App : winrt::implements<App, IFrameworkViewSource, IFrameworkView>
{
    ...
    void Initialize(Windows::ApplicationModel::Core::CoreApplicationView const& applicationView) { ... }
    void SetWindow(Windows::UI::Core::CoreWindow const& window) { ... }
    void Load(winrt::hstring const& entryPoint) { ... }
    void OnActivated(
        Windows::ApplicationModel::Core::CoreApplicationView const& applicationView,
        Windows::ApplicationModel::Activation::IActivatedEventArgs const& args) { ... }
    void Run() { ... }
    void Uninitialize() { ... }
    ...
}

Dies war nur eine Einführung in IFrameworkView. Unter Definieren des UWP-App-Frameworks des Spiels gehen wir viel ausführlicher auf diese Methoden und deren Implementierung ein.

Aufräumen des Projekts

Das Core-App-Projekt, das Sie aus der Projektvorlage erstellt haben, enthält Funktionen, die wir an diesem Punkt aufräumen sollten. Danach können wir das Projekt verwenden, um das Schießgaleriespiel (Simple3DGameDX) neu zu erstellen. Nehmen Sie die folgenden Änderungen an der App-Klasse in vor App.cpp.

  • Löschen Sie die zugehörigen Datenmember.
  • Löschen von OnPointerPressed, OnPointerMoved und AddVisual
  • Löschen Sie den Code aus SetWindow.

Das Projekt erstellt und wird ausgeführt, aber es wird nur eine Volltonfarbe im Clientbereich angezeigt.

Die Spielschleife

Um eine Vorstellung davon zu erhalten, wie eine Spielschleife aussieht, sehen Sie sich den Quellcode des heruntergeladenen Simple3DGameDX-Beispielspiels an.

Die App-Klasse verfügt über einen Datenmember mit dem Namen m_main vom Typ GameMain. Und dieses Element wird in App::Run wie folgt verwendet.

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

Sie finden GameMain::Run in GameMain.cpp. Es ist die Standard Schleife des Spiels, und hier ist eine sehr grobe Gliederung des Spiels mit den wichtigsten Features.

void GameMain::Run()
{
    while (!m_windowClosed)
    {
        if (m_visible)
        {
            CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
            Update();
            m_renderer->Render();
            m_deviceResources->Present();
        }
        else
        {
            CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
        }
    }
}

Und hier ist eine kurze Beschreibung, was diese Standard Spielschleife macht.

Wenn das Fenster für Ihr Spiel nicht geschlossen ist, senden Sie alle Ereignisse, aktualisieren Sie den Timer, und rendern Und präsentieren Sie die Ergebnisse der Grafikpipeline. Es gibt noch viel mehr zu diesen Bedenken zu sagen, und wir werden dies in den Themen Definieren des UWP-App-Frameworks des Spiels, Renderingframework I: Einführung in das Rendering und Renderingframework II: Spielrendering tun. Dies ist jedoch die grundlegende Codestruktur eines UWP DirectX-Spiels.

Überprüfen und Aktualisieren der Datei "package.appxmanifest"

Die Datei Package.appxmanifest enthält Metadaten zu einem UWP-Projekt. Diese Metadaten werden für das Packen und Starten Ihres Spiels sowie für die Übermittlung an den Microsoft Store verwendet. Die Datei enthält auch wichtige Informationen, die das System des Spielers verwendet, um den Zugriff auf die Systemressourcen zu ermöglichen, die das Spiel ausführen muss.

Starten Sie den Manifest-Designer, indem Sie in Projektmappen-Explorer auf die Datei Package.appxmanifest doppelklicken.

Screenshot des Manifest-Editors

Weitere Informationen zur Datei package.appxmanifest und zum Packen finden Sie unter Manifest-Designer. Sehen Sie sich zunächst die Registerkarte Funktionen an, und sehen Sie sich die bereitgestellten Optionen an.

Screenshot mit den Standardfunktionen einer direct3d-App

Wenn Sie nicht die Funktionen auswählen, die Ihr Spiel verwendet, z. B. zugriff auf das Internet für globale Highscoreboards, können Sie nicht auf die entsprechenden Ressourcen oder Features zugreifen. Wenn Sie ein neues Spiel erstellen, stellen Sie sicher, dass Sie alle Funktionen auswählen, die von APIs benötigt werden, die ihr Spiel aufruft.

Sehen wir uns nun die restlichen Dateien an, die im Simple3DGameDX-Beispielspiel enthalten sind.

Überprüfen anderer wichtiger Bibliotheken und Quellcodedateien

Wenn Sie eine Art Spielprojektvorlage für sich selbst erstellen möchten, damit Sie diese als Ausgangspunkt für zukünftige Projekte wiederverwenden können, dann sollten Sie das simple3DGameDX-Projekt, das Sie heruntergeladen haben, kopieren und GameMain.cpp aus diesem heraus kopieren GameMain.h und ihrem neuen Core-App-Projekt hinzufügen. Untersuchen Sie diese Dateien, erfahren Sie, was sie tun, und entfernen Sie alles, was für Simple3DGameDX spezifisch ist. Kommentieren Sie auch alles, was von Code abhängt, den Sie noch nicht kopiert haben. Nur als Beispiel GameMain.h hängt von ab GameRenderer.h. Sie können die Auskommentierung aufheben, während Sie weitere Dateien aus Simple3DGameDX kopieren.

Hier finden Sie eine kurze Übersicht über einige der Dateien in Simple3DGameDX , die Sie nützlich finden, um sie in Ihre Vorlage aufzunehmen, wenn Sie eine erstellen. In jedem Fall sind diese gleichermaßen wichtig, um zu verstehen, wie Simple3DGameDX selbst funktioniert.

Quelldatei Dateiordner BESCHREIBUNG
DeviceResources.h/.cpp Versorgungsunternehmen Definiert die DeviceResources-Klasse, die alle DirectX-Geräteressourcen steuert. Definiert auch die IDeviceNotify-Schnittstelle , die verwendet wird, um Ihre Anwendung zu benachrichtigen, dass das Grafikkartengerät verloren gegangen oder neu erstellt wurde.
DirectXSample.h Versorgungsunternehmen Implementiert Hilfsfunktionen wie ConvertDipsToPixels. ConvertDipsToPixels konvertiert eine Länge in geräteunabhängigen Pixeln (DIPs) in eine Länge in physische Pixel.
GameTimer.h/.cpp Versorgungsunternehmen Definiert einen Timer mit hoher Auflösung, der sich besonders für Spiele oder Apps mit interaktivem Rendering eignet.
GameRenderer.h/.cpp Darstellung Definiert die GameRenderer-Klasse , die eine grundlegende Renderingpipeline implementiert.
GameHud.h/.cpp Darstellung Definiert eine Klasse zum Rendern eines Head Up-Displays (HUD) für das Spiel mithilfe von Direct2D und DirectWrite.
VertexShader.hlsl und VertexShaderFlat.hlsl Shader Enthält den HlSL-Code (High-Level Shader Language) für grundlegende Vertex-Shader.
PixelShader.hlsl und PixelShaderFlat.hlsl Shader Enthält den HlSL-Code (High-Level Shader Language) für grundlegende Pixel-Shader.
ConstantBuffers.hlsli Shader Enthält Datenstrukturdefinitionen für Konstantenpuffer und Shaderstrukturen, die verwendet werden, um MVP-Matrizen (Model-View-Projection) und Vertexdaten pro Vertex an den Vertex-Shader zu übergeben.
pch.h/.cpp Enthält allgemeine C++/WinRT-, Windows- und DirectX-Elemente.

Nächste Schritte

An diesem Punkt haben wir gezeigt, wie Sie ein neues UWP-Projekt für ein DirectX-Spiel erstellen, uns einige der Teile darin ansehen und darüber nachdenken, wie Sie dieses Projekt in eine Art wiederverwendbare Vorlage für Spiele umwandeln können. Wir haben uns auch einige der wichtigen Teile des Simple3DGameDX-Beispielspiels angesehen.

Der nächste Abschnitt ist Definieren des UWP-App-Frameworks des Spiels. Dort werden wir uns genauer ansehen, wie Simple3DGameDX funktioniert.