設定遊戲專案
注意
本主題屬於<使用 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 類別以瞭解 IFrameworkViewSource 和 IFrameworkView
在 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 類別需要實作該介面。
本主題接下來兩節會說明 IFrameworkViewSource 和 IFrameworkView 介面。 這些介面 (以及 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 方法的實作。
- Initialize
- SetWindow
- 載入
- CoreApplicationView::Activated 事件引發。 因此,若您已註冊處理該事件 (選擇性),則系統此時會呼叫 OnActivated 處理常式。
- 執行
- Uninitialize
以下是 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 類別進行下列變更。
- 刪除其資料成員。
- 刪除 OnPointerPressed、OnPointerMoved 和 AddVisual
- 從 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 檔案,啟動資訊清單設計工具。
如需有關 package.appxmanifest 檔案和封裝的詳細資訊,請參閱<資訊清單設計工具>。 現在,請查看 [功能] 索引標籤提供的選項。
如果您未選取遊戲所用的功能 (例如存取網際網路查看全球高分榜),就無法存取對應的資源和功能。 建立新遊戲時,請務必選取遊戲呼叫 API 需要的所有功能。
接著,我們來看看 Simple3DGameDX 範例遊戲隨附的其餘檔案。
檢閱其他重要的程式庫和原始程式碼檔案
若您想建立自己的遊戲專案範本,當成日後專案的起點重複使用,請從下載的 Simple3DGameDX 專案複製 GameMain.h
和 GameMain.cpp
,並將複製項目新增至新的 Core 應用程式專案。 研讀這些檔案並瞭解其用途,然後移除與 Simple3DGameDX 相關的內容。 此外,請在您尚未複製的程式碼部分,標出任何相依項目。 舉例來說,GameMain.h
相依於 GameRenderer.h
, 當您一邊從 Simple3DGameDX 複製更多檔案,就可一邊取消標註。
如果您要自行建立範本,可參閱下表,其中簡要整理了 Simple3DGameDX 中的一些檔案,很適合納入範本使用。 無論如何,瞭解 Simple3DGameDX 本身的運作方式也很重要。
來源檔案 | 檔案資料夾 | 描述 |
---|---|---|
DeviceResources.h/.cpp | 公用程式 | 定義 DeviceResources 類別,用於控制所有 DirectX 裝置資源。 也會定義 IDeviceNotify 介面,用於通知應用程式圖形介面卡裝置已遺失或重新建立。 |
DirectXSample.h | 公用程式 | 實作協助程式函式,例如:ConvertDipsToPixels。 ConvertDipsToPixels 將裝置獨立畫素 (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 的運作方式。