設定遊戲專案

注意

本主題屬於<使用 DirectX 建立簡單的通用 Windows 平台 (UWP) 遊戲>教學課程系列的一部分。 該連結主題是提供這系列教學的基本背景介紹。

開發遊戲的第一步是在 Microsoft Visual Studio 中建立專案。 特別為遊戲開發工作設定一個專案,之後該專案便可當成範本重複使用。

目標

  • 使用專案範本在 Visual Studio 中建立新專案。
  • 透過檢視 App 類別的來源檔案,瞭解遊戲的進入點和初始化。
  • 查看遊戲迴圈。
  • 檢閱專案的 package.appxmanifest 檔案。

在 Visual Studio 中建立新專案

注意

如需安裝和為 C++/WinRT 開發設定 Visual Studio 的相關資訊,包括如何安裝和使用 C++/WinRT Visual Studio 延伸模組 (VSIX) 與 NuGet 套件 (一起提供專案範本和建置支援),請參閱 C++/WinRT 的 Visual Studio 支援

首先安裝 (或更新至) 最新版本的 C++/WinRT Visual Studio 延伸模組 (VSIX);請參閱上方注意事項。 接著在 Visual Studio 中,根據 Core App (C++/WinRT) 專案範本建立新的專案。 以 Windows SDK 最新的正式推出版本 (即非預覽版本) 為目標。

檢閱 App 類別以瞭解 IFrameworkViewSourceIFrameworkView

在 Core App 專案中,開啟原始程式碼檔案 App.cpp。 其中的 App 類別實作代表應用程式及其生命週期。 我們知道在此案例中,應用程式就是指遊戲。 不過,我們還是會將遊戲稱為「應用程式」,以便更廣泛地討論通用 Windows 平台 (UWP) 應用程式初始化的方式。

wWinMain 函式

wWinMain 函式是應用程式的進入點。 wWinMain 看起來如下 (來自 App.cpp)。

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

我們會建立 App 類別的執行個體 (這也是已建立的 App 中唯一的執行個體),接著將其傳遞至靜態的 CoreApplication.Run 方法。 請注意,CoreApplication.Run 預期使用 IFrameworkViewSource 介面。 因此 App 類別需要實作該介面。

本主題接下來兩節會說明 IFrameworkViewSourceIFrameworkView 介面。 這些介面 (以及 CoreApplication.Run) ) 代表應用程式會向 Windows 提供 view-provider。 Windows 會使用該 view-provider 將應用程式與 Windows 殼層連線,以便您處理應用程式生命週期事件。

IFrameworkViewSource 介面

App 類別確實實作 IFrameworkViewSource,如下方清單所示。

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

實作 IFrameworkViewSource 的物件是 view-provider factory 物件。 該物件的工作是製造並傳回 view-provider 物件。

IFrameworkViewSource 具有單一方法 IFrameworkViewSource::CreateView。 Windows 會對您傳遞至 CoreApplication.Run 的物件呼叫該函式。 如上所述,該方法的 App::CreateView 實作會傳回 *this。 換句話說,App 物件會傳回本身。 由於 IFrameworkViewSource::CreateView 具有 IFrameworkView 類型的傳回值,因此 App 類別也需要跟著實作「該」介面。 從上方清單可看出確實有這項實作。

IFrameworkView 介面

實作 IFrameworkView 的物件是 view-provider 物件。 我們現在已向 Windows 提供該 view-provider。 這與我們在 wWinMain中建立的 App 物件相同。 因此 App 類別是 view-provider factory,也是 view-provider

現在 Windows 可呼叫 App 類別的 IFrameworkView 方法實作。 在這些方法的實作中,應用程式有機會執行各種工作如:初始化工作、開始載入所需資源、連結適當的事件處理常式,以及接收 CoreWindow

系統會依下方清單順序呼叫 IFrameworkView 方法的實作。

以下是 App 類別 (位於 App.cpp) 的基本架構,顯示這些方法的簽章。

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() { ... }
    ...
}

這些只是 IFrameworkView 簡介。 我們會在<定義遊戲的 UWP 應用程式架構>一文中,介紹更多有關這些方法的詳細資料及實作方式。

整理專案

根據專案範本建立的 Core 應用程式專案包含現在應整理的功能。 之後,我們可使用該專案重新建立射擊場景遊戲 (Simple3DGameDX)。 對 App.cpp 中的 App 類別進行下列變更。

  • 刪除其資料成員。
  • 刪除 OnPointerPressedOnPointerMovedAddVisual
  • SetWindow 刪除程式碼。

專案將會建置並執行,但在工作區中只顯示純色。

遊戲迴圈

若想知道遊戲迴圈看起來的樣子,請查看您下載的 Simple3DGameDX 範例遊戲原始程式碼。

App 類別有資料成員,稱為 m_main (屬於 GameMain 類型)。 該成員將用於 App::Run,如下所示。

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

您可在 GameMain.cpp 中找到 GameMain::Run。 這是遊戲的主要迴圈,以下非常概略地展示其中最重要的功能。

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

我們簡短描述一下此主要遊戲迴圈的工作。

如果遊戲的視窗未關閉,則分派所有事件、更新計時器,然後轉譯並呈現圖形管線的結果。 這方面的作業還有許多注意事項,我們會在<定義遊戲的 UWP 應用程式架構>、<轉譯架構 I:轉譯簡介,>及<轉譯架構 II:遊戲轉譯>這些主題進一步說明。 現在這裡是 UWP DirectX 遊戲的基本程式碼結構。

檢閱並更新 package.appxmanifest 檔案

Package.appxmanifest 檔案包含與 UWP 專案相關的中繼資料。 這些中繼資料用於封裝及啟動遊戲,以及提交至 Microsoft Store。 此外,檔案也包含玩家系統需要的重要資訊,以用來提供執行遊戲所需的系統資源存取權。

按兩下 Solution Explorer 中的 Package.appxmanifest 檔案,啟動資訊清單設計工具

screenshot of the package.appx manifest editor.

如需有關 package.appxmanifest 檔案和封裝的詳細資訊,請參閱<資訊清單設計工具>。 現在,請查看 [功能] 索引標籤提供的選項。

screenshot with the default capabilities of a direct3d app.

如果您未選取遊戲所用的功能 (例如存取網際網路查看全球高分榜),就無法存取對應的資源和功能。 建立新遊戲時,請務必選取遊戲呼叫 API 需要的所有功能。

接著,我們來看看 Simple3DGameDX 範例遊戲隨附的其餘檔案。

檢閱其他重要的程式庫和原始程式碼檔案

若您想建立自己的遊戲專案範本,當成日後專案的起點重複使用,請從下載的 Simple3DGameDX 專案複製 GameMain.hGameMain.cpp,並將複製項目新增至新的 Core 應用程式專案。 研讀這些檔案並瞭解其用途,然後移除與 Simple3DGameDX 相關的內容。 此外,請在您尚未複製的程式碼部分,標出任何相依項目。 舉例來說,GameMain.h 相依於 GameRenderer.h, 當您一邊從 Simple3DGameDX 複製更多檔案,就可一邊取消標註。

如果您要自行建立範本,可參閱下表,其中簡要整理了 Simple3DGameDX 中的一些檔案,很適合納入範本使用。 無論如何,瞭解 Simple3DGameDX 本身的運作方式也很重要。

來源檔案 檔案資料夾 描述
DeviceResources.h/.cpp 公用程式 定義 DeviceResources 類別,用於控制所有 DirectX 裝置資源。 也會定義 IDeviceNotify 介面,用於通知應用程式圖形介面卡裝置已遺失或重新建立。
DirectXSample.h 公用程式 實作協助程式函式,例如:ConvertDipsToPixelsConvertDipsToPixels 將裝置獨立畫素 (DIP) 的長度轉換成實體像素長度。
GameTimer.h/.cpp 公用程式 定義適用於遊戲或互動式轉譯應用程式的高解析度計時器。
GameRenderer.h/.cpp 轉譯 定義 GameRenderer 類別,實作基本的轉譯管線。
GameHud.h/.cpp 轉譯 定義類別,以使用 Direct2D 和 DirectWrite 轉譯遊戲的平視顯示 (HUD)。
VertexShader.hlsl 和 VertexShaderFlat.hlsl 著色器 包含基本頂點著色器的高階著色器語言 (HLSL) 程式碼。
PixelShader.hlsl 和 PixelShaderFlat.hlsl 著色器 包含基本像素著色器的高階著色器語言 (HLSL) 程式碼。
ConstantBuffers.hlsli 著色器 包含常數緩衝區和著色器結構的資料結構定義,用於將 model-view-projection (MVP) 矩陣和每頂點資料傳遞至頂點著色器。
pch.h/.cpp N/A 包含常見的 C++/WinRT、Windows 和 DirectX includes。

下一步

到目前為止,我們已示範如何為 DirectX 遊戲建立新的 UWP 專案、查看其中的程式碼,並開始構思如何將該專案轉換成可重複使用的遊戲範本。 另外也介紹了 Simple3DGameDX 範例遊戲的一些重要元素。

下一節是<定義遊戲的 UWP 應用程式架構>。 我們會進一步說明 Simple3DGameDX 的運作方式。