你可能對實際地編寫游戲代碼期待已久了。由於DirectX SDK 2004年夏季更新包含了一個牢固的示例框架組件,並且它被設計成能在你自己的代碼中直接使用,同時還為你處理了很多事務,所以你只要簡單的使用它,就可以節省大量的時間和精力。
本文中的例子使用的就是這個示例框架組件,在本文中,你將學習到的內容有:
· 如何建立自己的項目
· 如何使用示例框架組件來列舉設備
建立項目
在本文中,我假定你的所有開發工作都將使用Visual Studio .NET 2003來完成。如果你不希望使用這個環境,可以使用命令行編譯代碼,它允許你使用任意的文本編輯器或集成開發環境(IDE)。
啟動Visual Studio .NET 2003並點擊起始頁面中的"新建項目"按鈕。如果你沒有使用起始頁面,可以點擊"文件"菜單下的"新建"子菜單中的"項目"菜單項,或者使用Ctrl+Shift+N。選擇"Visual C#項目"區域中的"Windows項目"數據項。把這個項目命名為Blockers,這是游戲的名稱。
在你查看自動生成的代碼之前,首先把示例框架組件添加到你的項目中。一般情況下,我會在"解決方案浏覽器"中建立一個新文件夾,並把這些文件放入一個這個獨立的文件夾中(把這個文件夾的名字取為Framework)。右鍵點擊這個新建的文件夾,從"添加"菜單中選擇"添加已有的項"。導航到DirectX SDK文件夾,你會發現該示例框架文件位於SamplesManagedCommon文件夾中,選擇每個文件並添加到你的項目中。
在示例框架組件被添加到項目中以後,你就可以去掉自動生成的代碼了。這些代碼中的大部分都是用於建立別致的Windows窗體應用程序的,因此,它與我們編寫游戲的代碼是無關的。用列表1中的代碼替換已有的代碼和類(Form1)。
列表1:空的框架組件
using System;
using System.Configuration;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.Samples.DirectX.UtilityToolkit;
public class GameEngine : IDeviceCreation
{
///程序入口。初始化所有部分並進入一個消息處理循環。用空閒時間顯示場景
static int Main()
{
using(Framework sampleFramework = new Framework())
{
return sampleFramework.ExitCode;
}
}
}
這段新代碼中有三個地方比較突出。首先,你可能注意到了除了靜態的main方法之外,刪除了所有東西,而且main方法也被修改過。剩余的代碼是Windows窗體設計器的支撐代碼。由於這個應用程序不需要使用該設計器,因此這些代碼就沒有用了,可以被刪除。其次,這段代碼不能編譯,因為游戲引擎希望實現的兩個接口還未實現。再次,這段代碼實際上沒有做任何事務。
在你開始解決後面兩個問題之前,你必須添加一些引用。由於你准備在這個項目中顯示奇特的3D圖像,你就必須給項目添加能執行這樣的顯示操作的組件的引用。本文采用受控DirectX來執行這種操作,因此你需要在"項目"菜單中選擇"添加引用"。圖1顯示了彈出的對話框。
圖1:添加引用對話框
如果你安裝了DirectX 9 SDK 2004年夏季更新,你會發現有多個版本的受控DirectX組件可供使用。請選擇最新的版本(1.0.2902.0版本)。對於這個項目來說,你需要添加三個不同的組件引用:
· Microsoft.DirectX
· Microsoft.DirectX.Direct3D
· Microsoft.DirectX.Direct3DX
DirectX根(root)組件包含了輔助顯示計算的數學結構。其它兩個組件相應地包含了Direct3D和D3DX的功能。添加這些引用之後,你可以簡單地查看一下列表1中添加的using語句,以確保名字空間被正確地引用了。這個步驟可以確保你不需要完整地限定類型。例如,如果不添加using語句,那麼聲明一個Direct3D設備變量,就必須使用下面的語句:
Microsoft.DirectX.Direct3D.Device device = null;
Using語句可以減少很多輸入內容(沒有人希望在聲明一個變量時輸入全部的內容)。由於你已經增加了using語句,就可以使用如下所示的聲明語句了:
private Device device = null;
你可以看到,用這種方式聲明變量簡單多了,節省了大量的輸入。在了解這些信息之後,你可以開始修補應用程序編譯過程中的錯誤了,並准備好編寫第一個3D游戲了。你現在必須實現的唯一一個接口是IDeviceCreation,它控制著設備的列舉和建立。
你可能會想"列舉設備做什麼?我只有一個監視器"!盡管一般情況下是這樣的,但是現在的顯卡實際上是支持多個監視器的,即使你只有一個設備,你仍然擁有多個可選擇的模式。顯示器的格式可能不同(你可以在Windows桌面設置中看到這些種類,例如16位色和32位色)。全屏幕模式下的高度和寬度也可能有不同的值,你甚至於還可以控制屏幕的刷新率。總而言之,還是有些事情需要解決。
列表2中的代碼修補的應用程序中的編譯錯誤。
列表2:實現接口
/// 設備初始化的時候調用。這段代碼檢查設備最小的性能,
/// 如果沒有通過檢查,就返回false
public bool IsDeviceAcceptable(Caps caps, Format adapterFormat,
Format backBufferFormat, bool windowed)
{
if (!Manager.CheckDeviceFormat(caps.AdapterOrdinal, caps.DeviceType,
adapterFormat, Usage.QueryPostPixelShaderBlending,
ResourceType.Textures, backBufferFormat))
return false;
if (caps.MaxActiveLights == 0)
return false;
return true;
}
/// 在建立某個設備之前,這個回調函數會被立即調用,以允許應用程序修改設備的
/// 設置信息。它提供的設置參數包含了框架組件為新設備挑選的設置, 並且應用程序
/// 可以直接對這個結構進行任何需要的修改。請注意,示例框架沒有糾正無效的
/// 設備設置信息,因此必須小心地返回有效的設備設置,否則建立設備就會失敗。
public void ModifyDeviceSettings(DeviceSettings settings, Caps caps)
{
// 這個應用程序沒有使用任何get方法,它被設計成在一個純設備上工作。
// 因此如果受到支持並且使用HWVP,就建立一個純設備。
if ( (caps.DeviceCaps.SupportsPureDevice) && ((settings.BehaviorFlags & CreateFlags.HardwareVertexProcessing) != 0 ) )
settings.BehaviorFlags |= CreateFlags.PureDevice;
}
請你查看一下聲明的IsDeviceAcceptable方法。在示例框架忙著枚舉系統中的設備的時候,它會在每個找到的組合上調用該方法。注意到該方法返回一個布爾型值嗎?這使得你有權利告訴示例框架你認為某個設備是否符合需求。但是,在你仔細查看第一個方法中的代碼的時候,請先看一下聲明的第二個方法(ModifyDeviceSettings)。某個設備被建立之前,示例框架會立即調用這個方法,允許你加入任何希望的選項。但是你要小心地使用參數選項,因為它可能導致設備建立失敗。
現在我們回到第一個方法:我們先看一下它的參數。首先,它帶有一個Caps類型的參數,它是設備性能的簡單結構體。該結構體包含了具體設備的巨量信息,可以幫助你決定某個類型是不是你正在使用的設備類型。其後的兩個參數都是特定設備的格式參數:一個是後台的緩沖區格式,另一個是設備的格式。
請注意
後台緩沖區是實際要顯示的數據(象素)在發送給顯卡處理並輸出到屏幕之前所存儲的地方。後台緩沖區的格式決定了可以顯示多少種色彩。大多數格式遵循特定的命名習慣--每個字符跟著一個數字,例如A8R8G8B8。字符所指定的構成部分擁有與其後面的數字相同數量的位(bit)。在A8R8G8B8中,該格式可以包含32位色彩信息,alpha、red、green和blue各用8位。最常見的構成是:
A Alpha
R Red
G Green
B Blue
X Unused
你可以查看DirectX SDK文檔得到更多關於格式的信息。由於我們還需要知道該設備時候可以顯示在窗體中,所以這個方法還有一個參數(最後一個)。盡管大多數游戲都運行在全屏模式下,但是編寫和調試在全屏模式下運行的游戲卻很困難。在調試過程中,這個應用程序在窗體模式而不是全屏模式下顯示。
請注意
窗體模式是我們運行的大多數應用程序的顯示方式。其中大多數應用程序帶有邊框和控制菜單,右上角帶有最小化、最大化和關閉按鈕。在全屏模式下,應用程序覆蓋了整個屏幕,並且在大多數情況下沒有邊框。如果全屏模式使用了另外的屏幕大小(你當前使用的桌面),你可以改變桌面的分辨率。
你可能注意到了默認行為是接受