?? dx5.txt
字號(hào):
DirectX5.0最新游戲編程指南
綜述篇
武漢 朱春喜 & 吳佳鮮
對(duì)于眾多的游戲制作者來(lái)說(shuō),Microsoft的DirectX 5的推出不啻是一個(gè)極好的消息。它包含了編制下一代計(jì)算機(jī)游戲和多媒體應(yīng)用程序
的最新技術(shù)和工具,為廣大的程序員提供了一整套的應(yīng)用程序接口API,使程序員能夠設(shè)計(jì)高性能實(shí)時(shí)的應(yīng)用程序。DirectX使運(yùn)行在Microsoft
Windows操作系統(tǒng)下的游戲比運(yùn)行在 MS-DOS操作系統(tǒng)下的游戲具有更高的性能的更好的交互性,甚至比專(zhuān)用的游戲機(jī)也不遑多讓。
Microsoft開(kāi)發(fā)DirectX的首要目的就是要提高Windows環(huán)境下游戲開(kāi)發(fā)的容易性。在此之前,個(gè)人電腦上的大部分游戲都是基于MS-DOS
的,游戲開(kāi)發(fā)人員必須針對(duì)不同的硬件接口卡編制不同的程序,盡管代碼類(lèi)似,但不可避免存在許多的重復(fù)勞動(dòng)。利用DirectX, 游戲開(kāi)發(fā)
人員就可以獲得DirectX的硬件獨(dú)立性的優(yōu)點(diǎn),同時(shí)又可以直接訪(fǎng)問(wèn)硬件。DirectX的最主要的目標(biāo)就是提供MS-DOS中直接的硬件訪(fǎng)問(wèn)特
性,同時(shí)去掉個(gè)人電腦中再添加新的硬件時(shí)所帶來(lái)的硬件識(shí)別問(wèn)題。
因?yàn)橛布纳?jí)是不可避免的,所以,DirectX實(shí)際上也提供了另一種即插即用的方法。因此,利用DirectX可以開(kāi)發(fā)出高性能實(shí)時(shí)的應(yīng)
用程序,可以直接訪(fǎng)問(wèn)計(jì)算機(jī)中的硬件和將來(lái)系統(tǒng)中回具有的硬件設(shè)備。DirectX在硬件和應(yīng)用之間提供了一致的接口以減少安裝和配置的
復(fù)雜性,并且使硬件的利用達(dá)到最優(yōu)。利用DirectX提供的接口,程序員能充分利用硬件的特性而不需要考慮其具體細(xì)節(jié)。一個(gè)優(yōu)秀的基于
Windows的高性能游戲應(yīng)該能夠利用系統(tǒng)的如下技術(shù):
.為提高性能而專(zhuān)門(mén)設(shè)計(jì)的加速卡
.即插即用PnP(Plug and Play)
.內(nèi)嵌于Windows的通信服務(wù),包括DirectPlay
DirectX 5包括七個(gè)部分,下面對(duì)各部分作以簡(jiǎn)要說(shuō)明。
(1).DirectDraw 通過(guò)支持訪(fǎng)問(wèn)屏外顯示內(nèi)存中位圖的軟硬件加速技術(shù),快速直接存取,利用硬件的位塊傳輸和緩沖區(qū)翻轉(zhuǎn)功能。
(2).DirectSound 提供軟硬件聲音混合和錄音再生功能。
(3).DirectPlay 使得游戲在調(diào)制解調(diào)器和網(wǎng)絡(luò)之間的連接更加簡(jiǎn)單方便。
(4).Direct3D 提供了高級(jí)保留模式(Retained-Mode)接口和低級(jí)即時(shí)模式(Immediate-Mode)接口。前者允許程序很容易地完成一個(gè)完
全的三維圖形系統(tǒng),后者使得程序能完全控制著色管道。
.DirectInput 提供了基于Windows游戲的輸入的API和驅(qū)動(dòng)程序,它不僅支持目前的鍵盤(pán)、鼠標(biāo)和操縱桿,也支持將來(lái)的基于Windows的
輸入設(shè)備。
.DirectSetup 提供了DirectX的一次性安裝過(guò)程。
(7).AutoPlay 它是Windows 95的特性,當(dāng)你將光盤(pán)放入光驅(qū)時(shí),它能自動(dòng)運(yùn)行安裝程序或游戲。事實(shí)上,AutoPlay也是Microsoft Win32
API的一部分,而不是僅存在于DirectX SDK中。.
通過(guò)查詢(xún)各種DirectX對(duì)象接口,你可以檢測(cè)系統(tǒng)中安裝的是DirectX的哪個(gè)版本,DirectX SDK中的范例文件GetDXVersion.cpp中的
GetDXVersion函數(shù)可以完成這一任務(wù)。該函數(shù)創(chuàng)建了一些關(guān)鍵的DirectX對(duì)象──一個(gè)DirectDraw對(duì)象、一個(gè)DirectDrawSurface對(duì)象和一
個(gè)DirectInput對(duì)象── 來(lái)檢測(cè)安裝在系統(tǒng)中的DirectX的版本。如果系統(tǒng)中安裝了老版本的DirectX SDK,必須確保不要包含它的INCLUDE
和LIB路徑,使用DirectX 5頭文件編譯后的代碼同DirectX 3的庫(kù)鏈接后將會(huì)出現(xiàn)不可預(yù)知的錯(cuò)誤。
因?yàn)镃++語(yǔ)言更能夠?qū)τ?jì)算機(jī)硬件作直接的訪(fǎng)問(wèn),所以DirectX采用了C++語(yǔ)言作為開(kāi)發(fā)的主語(yǔ)言。而DirectX又是專(zhuān)門(mén)為Visual C++
設(shè)計(jì)的,所以編寫(xiě)DirectX程序最好能在Visual C++下進(jìn)行。當(dāng)然Borland C++5.0也沒(méi)問(wèn)題,只是配置有些不同罷了,下面將會(huì)提到這一問(wèn)
題。為了降低編程的難度,一些公司也針對(duì)DirectX開(kāi)發(fā)了運(yùn)行在不同編程環(huán)境中的控件,如Arakelian Soft公司的ActiveX控件DirectStudio98
for Visual Basic5.0、Tegosoft公司的TegoSoft ActiveX for Visual Basic、還有John Pullen、Paul Bearne和Jeff Kurtz開(kāi)發(fā)的運(yùn)行在Delphi下的
Delphi Games Creator等。考慮到兼容性問(wèn)題,最好還是能使用Visual C++。
一、DirectX和部件對(duì)象模型COM
1.1、 部件對(duì)象模型COM(Component Object Model)
DirectX中的大部分API都由基于COM的對(duì)象和接口組成。COM是接口重利用的基于對(duì)象的系統(tǒng)的基礎(chǔ),是COM編程的核心模型,
它也是一種接口規(guī)范。在操作系統(tǒng)級(jí)別上,它又是一個(gè)對(duì)象模型。
許多DirectX API都創(chuàng)建為COM對(duì)象的實(shí)例。你可以將一個(gè)對(duì)象看做一個(gè)黑盒子,對(duì)象通過(guò)接口與對(duì)象通信,通過(guò)COM接口發(fā)送給對(duì)
象或從對(duì)象接收的命令稱(chēng)為方法。例如,IDirectDraw2::GetDisplayMode方法是通過(guò)IDirectDraw2接口從DirectDraw對(duì)象獲得當(dāng)前的顯示模
式。對(duì)象在運(yùn)行時(shí)可以同其他對(duì)象捆綁在一起,并且能夠使用這些對(duì)象的接口。如果你已知道某個(gè)對(duì)象是COM對(duì)象,并且知道該對(duì)象支持
的接口,你的應(yīng)用程序或其他對(duì)象就能夠確定第一個(gè)對(duì)象所能執(zhí)行的服務(wù)。所有COM對(duì)象都繼承的一個(gè)方法是Query接口方法,它讓你確
定一個(gè)對(duì)象支持的接口和創(chuàng)建這些接口的指針。
1.2、IUnknown 接口
所有的COM 接口都由一個(gè)稱(chēng)為Iunknown的接口衍生而來(lái),該接口為DirectX提供了對(duì)象生存期的控制和操作多接口發(fā)能力。Iunknown
含有三個(gè)方法:
.AddRef 當(dāng)一個(gè)接口或另一個(gè)應(yīng)用捆綁到一個(gè)對(duì)象上時(shí),就使用AddRef方法將該對(duì)象的索引值加1。
.QueryInterface 通過(guò)指向特定接口的指針查詢(xún)對(duì)象所支持的特性。
.Release 將對(duì)象的索引值減1,當(dāng)索引值變?yōu)?時(shí),該對(duì)象就從內(nèi)存中釋放。
其中AddRef和Release方法負(fù)責(zé)維護(hù)對(duì)象的索引值。例如,如果創(chuàng)建一個(gè)DirectDrawSurface對(duì)象,該對(duì)象的索引值就被設(shè)定為1,每
次當(dāng)有一個(gè)函數(shù)返回該對(duì)象的指針時(shí),該函數(shù)必須通過(guò)返回發(fā)指針調(diào)用AddRef方法將該對(duì)象的索引值加1。每一個(gè)AddRef的調(diào)用都必須有
一個(gè)Release的調(diào)用與其對(duì)應(yīng)。當(dāng)對(duì)象的索引值達(dá)到0時(shí),該對(duì)象就被撤消,該對(duì)象的所有接口都不可再用。
QueryInterface方法測(cè)定一個(gè)對(duì)象是否支持指定的接口,如果支持,QueryInterface就返回指向該接口的指針。然后你可以使用該接口包
含的方法同對(duì)象通信。如果QueryInterface成功地返回接口的指針,它會(huì)自動(dòng)調(diào)用AddRef方法增加對(duì)象的索引值。在撤消接口指針之前必須
調(diào)用Release來(lái)減少對(duì)象的索引值。
1.3、 DirectX COM 接口
DirectX中的接口是用相當(dāng)基本的COM編程創(chuàng)建的。表征了設(shè)備的對(duì)象的每個(gè)接口都由IUnknown COM接口派生而來(lái),如IDirectDraw2、
IDirectSound和IDirectPlay都是這樣。基本對(duì)象的創(chuàng)建工作由動(dòng)態(tài)鏈接庫(kù)DLL中的特殊函數(shù)來(lái)處理。
典型的情況是,DirectX對(duì)象模型為每個(gè)設(shè)備提供了一個(gè)主對(duì)象。其它支持服務(wù)的對(duì)象由主對(duì)象派生而來(lái)。例如,DirectDraw對(duì)象就表
征了顯示適配器。你可以利用DirectDraw來(lái)創(chuàng)建表征顯示內(nèi)存的DirectDrawSurface對(duì)象和表征硬件調(diào)色板的DirectDrawPalette對(duì)象。同樣
道理,DirectSound對(duì)象表征了音頻卡,利用它可創(chuàng)建表征音源的DirectSoundBuffer對(duì)象。
除了能夠產(chǎn)生子對(duì)象外,設(shè)備的主對(duì)象還能測(cè)定它所表征的設(shè)備的性能,如屏幕的大小和顏色數(shù)、聲卡是否支持波表合成等。
1.4、 C++和COM 接口
對(duì)C++程序員來(lái)說(shuō),COM接口就象一個(gè)抽象的基類(lèi)。在C++的基類(lèi)中,所有的方法都定義為純虛的,這就意味著沒(méi)有任何代碼同方法
關(guān)聯(lián)在一起。純虛的C++函數(shù)和COM接口都使用一種稱(chēng)為虛表(vtable)的設(shè)備。一個(gè)虛表包含了應(yīng)用于所給接口的所有函數(shù)的聲明。如果
你想讓程序或?qū)ο笫褂眠@些函數(shù),可以先用QueryInterface方法檢查對(duì)象存在的接口,獲取該接口的指針,調(diào)用QueryInterface后,應(yīng)用或?qū)?象實(shí)際上就從對(duì)象中接收到了虛表的指針,通過(guò)該指針就可以調(diào)用應(yīng)用于該對(duì)象的所有接口方法。
COM對(duì)象和C++的另一個(gè)相似之處是方法的第一個(gè)參數(shù)就是接口或類(lèi)的名字,C++中稱(chēng)為this參數(shù)。因?yàn)镃OM對(duì)象和C++對(duì)象是完全
二進(jìn)兼容的,編譯器就將COM接口同C++抽象類(lèi)同樣處理,并且具有相同的語(yǔ)法,這會(huì)使得代碼簡(jiǎn)單一些。
1.5、 獲取新的接口
部件對(duì)象模型不是通過(guò)改變存在的接口中的方法而是通過(guò)擴(kuò)展包含有新特性的新接口來(lái)更新對(duì)象的功能。在保留已有的接口狀態(tài)的情況
下,COM對(duì)象能夠自由擴(kuò)展服務(wù)并維持同舊的應(yīng)用兼容。DirectX部件遵循這一原則,例如,DirectDraw部件支持IDirectDrawSurface 接口
的三個(gè)版本: IDirectDrawSurface、IDirectDrawSurface2和IDirectDrawSurface3。要想利用新接口提供的特性,你必須調(diào)用對(duì)象的
IUnknown::QueryInterface方法,指定欲獲取的接口的全局統(tǒng)一標(biāo)識(shí)GUID(globally unique identifier)。接口的GUID在相關(guān)的頭文件中聲明。
下面的例子說(shuō)明了如何查詢(xún)一個(gè)新的接口:
LPDIRECTDRAW lpDD1;
LPDIRECTDRAW2 lpDD2;
ddrval = DirectDrawCreate( NULL, &lpDD1, NULL );
if( FAILED(ddrval))
goto ERROROUT;
// Query for the IDirectDraw2 Interface
ddrval = lpDD1->Query接口(IID_IDirectDraw2, (void **)&lpDD2);
if( FAILED(ddrval))
goto ERROROUT;
// Now that we have an IDirectDraw2, release the original Interface
lpDD1->Release();
新的接口不支持以前版本接口所提供的方法的情況極少,IDirect3DDevice2接口剛好是這樣的一個(gè)接口。如果你的應(yīng)用需要早期版本的
接口提供的特性,你可以利用老的接口的GUID,使用上述例程來(lái)查詢(xún)?cè)摻涌凇?1.6、 用C存取COM對(duì)象
使用C語(yǔ)言也可以調(diào)用任何COM接口方法。用C語(yǔ)言調(diào)用一個(gè)接口方法需要主要兩件事:
.方法的第一個(gè)參數(shù)始終是已經(jīng)創(chuàng)建的調(diào)用該方法的對(duì)象(即this)
.接口中的每個(gè)方法都通過(guò)對(duì)象虛表的指針來(lái)引用
下面的例子使用C語(yǔ)言調(diào)用IDirectDraw2::CreateSurface方法創(chuàng)建一個(gè)同一個(gè)DirectDraw對(duì)象關(guān)聯(lián)的表面:
ret = lpDD->lpVtbl->CreateSurface (lpDD, &ddsd, &lpDDS,
NULL);
其中 lpDD參數(shù)是同新表面關(guān)聯(lián)的DirectDraw對(duì)象,同時(shí),該方法填充一個(gè)描述表面(Surface)的結(jié)構(gòu)&ddsd,返回指向新接口&lpDDS
的指針。調(diào)用 IDirectDraw2::CreateSurface方法,首先要指向該DirectDraw對(duì)象的虛表,然后獲取虛表中的方法。方法中提供的第一個(gè)參數(shù)
是已經(jīng)創(chuàng)建的DirectDraw 對(duì)象的索引。下面的代碼說(shuō)明了C和C++對(duì)COM對(duì)象方法調(diào)用的不同之處:
ret = lpDD->CreateSurface(&ddsd, &lpDDS, NULL)
二、DirectX 5中的新內(nèi)容
大家知道, DirectX 5是DirectX的最新版本,在此之前,Microsoft曾發(fā)布過(guò)DirectX、DirectX2、DirectX3(沒(méi)有DirectX4)。顯然,DirectX
5比DirectX3提供了更多的功能和服務(wù),不過(guò),利用DirectX3 API寫(xiě)的程序不需要修改就可以成功地編譯和運(yùn)行。下面是DirectX5和DirectX3
的主要不同之處:
2.1、DirectDraw
DirectDraw擴(kuò)展了新的視頻端口能力,允許應(yīng)用程序控制從硬件視頻端口傳送到顯示內(nèi)存中的DirectDraw表面的數(shù)據(jù)流。另外,DirectDraw
硬件仿真層HEL(Hardware Emulate Layer)能夠利用Pentium MMX處理器提供的加速性能。DirectDraw在你第一次創(chuàng)建一個(gè)表面時(shí)會(huì)檢測(cè)
處理器是否MMX處理器,在非奔騰處理器的計(jì)算機(jī)上,該測(cè)試會(huì)導(dǎo)致調(diào)試器報(bào)告出一個(gè)事件,該事件不會(huì)影響程序的性能和穩(wěn)定性。
DirectDraw支持比主表面(Primary Surface)更寬的屏外表面(Off-screen Surface),只要硬件允許,你可以創(chuàng)建足夠?qū)挼谋砻妗? DirectDraw支持高級(jí)圖形端口AGP(Advanced Graphics Port)特性。在一個(gè)AGP設(shè)備系統(tǒng),你可以在非本地顯示內(nèi)存創(chuàng)建表面。DDSCAPS
結(jié)構(gòu)支持標(biāo)準(zhǔn)(本地)顯示內(nèi)存和AGP(非本地)顯示內(nèi)存之間不同的標(biāo)志。DirectDraw 可以向非本地顯示內(nèi)存位塊傳輸DDCAPS結(jié)構(gòu)包
含的成員信息。
2.2、DirectPlay
DirectPlay包含了一個(gè)新的接口IDirectPlay3,除了新的方法之外,其它同IDirectPlay2完全相同。同樣地,IDirectPlayLobby2也是
IdirectPlayLobby的升級(jí)版本。DirectPlay的新功能包括通過(guò)創(chuàng)建連接快捷方式來(lái)隱藏服務(wù)提供者(Service Provider)對(duì)話(huà)的能力,還可以保
持可用會(huì)話(huà)的更新列表,應(yīng)用SetSessionDesc方法更好地支持口令保護(hù)會(huì)話(huà),支持保密服務(wù)連接及使用CoCreateInstance直接創(chuàng)建多個(gè)
DirectPlay對(duì)象。
2.3、DirectSound
DirectSound 包含了一個(gè)新的接口IksPropertySet,使得支持由聲卡和相關(guān)驅(qū)動(dòng)程序提供的擴(kuò)展服務(wù)。基于COM的函數(shù)DirectSoundCapture
也是新的,它可以直接訪(fǎng)問(wèn)驅(qū)動(dòng)程序。
2.4、Direct3D
Direct3D即時(shí)模式(Immediate Mode)現(xiàn)在支持Drawing Primitive,而不必直接在緩沖區(qū)中工作。Direct3D保留模式(Retained Mode)
支持插值使你能夠調(diào)和顏色,平滑地移動(dòng)物體,變形網(wǎng)格,并且執(zhí)行許多其他的變換。保留模式也支持漸進(jìn)網(wǎng)格,即允許你先開(kāi)始于一個(gè)粗
糙的網(wǎng)格,然后再細(xì)化它。
5、DirectInput
DirectInput提供了操縱桿的COM接口,同時(shí)還提供了鍵盤(pán)和鼠標(biāo)等力反饋裝置的COM接口。
6、DirectSetup
DirectSetup現(xiàn)在包含了更多的用戶(hù)接口定制能力,而這是由一個(gè)回調(diào)函數(shù)提供的。該回調(diào)函數(shù)將當(dāng)前的安裝狀態(tài)傳遞給安裝程序,你可
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -