?? 2d.txt
字號:
上一次我寫了一個史上最簡單的Windows程序。很不幸,在計算機的世界里最簡單的也是最愚蠢的東西。如果一個程序什么也不做的話那它就沒有臉面再存活在這世界上,所以為了讓我的作品能夠有更多生存的空間我必須加入一些有意思的東西。DirectDraw雖然只是一段很短的代碼但卻能徹底地改變人們對這個愚蠢作品的看法。
可能并不是每個人都明白什么是DirectDraw,其實它是DirectX的一部分。一看它的名字也大概猜到它是用來畫圖之類的。不管用來干嘛,先看看著名的John De Goes 在他的名著《3D GAME PROGRAMMING WITH C++》里對DirectX的定義。
DirectX is a software development kit (SDK) specifically to promote hardware assisted, high performance games for Windows, consists of many components...
The components of DirectX are divided into two groups: DirectX Foundation contains low level components that supply basic functionality; DirectX Media contains high level components that perform many complex operations.
這是他的原文,為了讓一些英文不太好的朋友不必浪費時間去翻詞典我將其翻譯一下,這沒有任何商業目的,所以請別告我侵權。
DirectX是一個開發軟件特別用于提高硬件協助能力以支持高質量的Windows游戲。
DirectX有兩組組件:DirectX基本庫,包含低級組件用于基本功能;DirectX媒體,包括高級組件用于完成許多復雜的操作。
以上文字好象有點隱晦難懂。其實我對上面的英文的理解也就相當于上面這段中文的水平。雖然John De Goes的這本書被公認為3D游戲的教材,而且我的偶像Andre LaMothe還特地為這本書寫了序但我在看這本800頁的英文書時常常被許多類似于上面的文字搞的頭昏腦脹。
講了這么多你可能還是沒明白我到底要說些什么,不要著急,所謂心急吃不了熱豆腐,特別是美女的豆腐。再看看下面的文字。
DirectX Foundation consists of the following components: DirectDraw, DirectSound, DirectMusic, Direct3D Immediate Mode (IM), DirectInput, DirectSetup, and AutoPlay.
DirectDraw provides a way for software developers to access the display's attributes - including the size of the desktop and how many colors can be displayed at once - and the display's features, such as playing back video, displaying images and bitmaps, and so on. DirectDraw is not graphics library, in that it cannot draw lines, polygons, or text, but it is still nonetheless for today's 3D games.
這段比較好理解,我也照著翻譯:
DirectX 基本庫包括:DirectDraw, DirectSound, DirectMusic......(參見英文)
DirectDraw 提供了一個方法給軟件開發人員進入顯示的屬性——包括桌面的大小和能被顯示的顏色數——顯示特征,列如播放后臺視頻,顯示圖象和位圖,等等。DirectDraw不是圖形函數庫,也就是說它不能畫線,多邊形,或文字,但是它并非對今天的3D游戲毫無用處。
天啊!為什么譯成中文后反而看不太明白了!看來我還是不適合當翻譯。所以大家將就點,反正就是那個意思,用一句教我軟件工程的老師Mr. Christopher常掛在嘴上的話“你明白就是明白,不明白就是不明白”
哈,如果真不明白的話,就忘掉上面所有的廢話(forget these bullshit)。這完全沒有關系,我保證如果你看完本文后能從地獄爬回來而且能解釋的比我更好的話,你就可以毫不客氣地揍我一頓。
從程序員的角度來說,DirectDraw是一個很復雜的類。不必管它到底是什么,反正你如果要使用DirectDraw, 首先必須創建一個DirectDraw的對象(object)。也就是說聲明一個DirectDraw變量。用下面的代碼:
LPDIRECTDRAW lpDD; //LPDIRECTDRAW 就是微軟寫的DirectDraw類的指針類型。
有了這個變量后就可以對DirectDraw進行初始化:
HRESULT Result;
Result = DirectDrawCreate( NULL, &lpDD, NULL);
DirectDrawCreate函數用來初始化DirectDraw的對象(object),這個函數有三個參數,它的原型如下:
HRESULT WINAPI DirectDrawCreate(
GUID FAR *lpGUID,
LPDIRECTDRAW FAR *lplpDD,
IUnknown FAR *pUnkOuter);
lpGUID:一個指向GUID(Globally Unique Identifier)的地址變量,它描述了一個用于在其上面創建DirectDraw的驅動器。如果這個變量為NULL那么就是說使用當前的顯示驅動程序。
lplpDD:就是上面的lpDD的指針。
pUnkOuter:微軟說這是用于將來對COM的兼容而設定的參數,但微軟又說如果這個變量不為NULL的話,將返回一個錯誤。所以如果你不是反微軟聯盟的成員的話就給它NULL吧。
如果初始化成功的話函數返回的值為DD_OK。
初始化成功后就可以設定Cooperative Level(應該是合作層之類的意思吧,反正就是指定游戲是運行于窗口模式還是令人激動的全屏模式)。
調用SetCooperativeLevel函數:
Result = lpDD->SetCooperativeLevel(
GetActiveWindow(),
DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT);
此函數的原型為:
HRESULT SetCooperativeLevel(
HWND hwnd,
DWORD dwFlags);
參數說明:
hwnd:要設定窗口的句柄。
dwFlags:這包括很多莫名其妙卻非常有用的標志。最常用的當然是DDSCL_FULLSCREEN和DDSCL_NORMAL分別指定全屏模式或普通窗口模式。DDSCL_EXCLUSIVE表示該窗口獨占所有操作。DDSCL_ALLOWREBOOT當然就是指可以讓你重啟電腦,就是不將Ctrl+Alt+Del給屏蔽掉。至于其他標志可參考MSDN,當然如果你有的話。
同樣,函數成功將返回一個DD_OK。
如果將窗口模式設為全屏的話,可以設定顯示模式:
Result = lpDD->SetDisplayMode(800, 600, 32);
if(Result == DD_OK)
{/*Display mode was set*/}
else
{/*Display mode was not set*/}
很顯然可以通過一個SetDisplayMode的函數來設定顯示模式,大家一眼就能明白上面的代碼將顯示模式設成800*600顏色數為32位。還是在看看該函數的原型:
HRESULT SetDisplayMode(
DWORD dwWidth,
DWORD dwHeight,
DWORD dwBPP,
參數說明:
dwWidth:屏幕寬度。
dwHeight:屏幕高度。
dwBPP:顏色的位數。
好了,請注意,下面我要說的是DirectDraw的精華,創建一個主頁面。聽起來好象沒什么了不起,但我們玩游戲所看到的圖象正是畫在這個主頁面上的。它其實是一段顯卡上的內存。DirectX允許我們直接向這段內存里寫數據。這意味著顯示速度將會大大的提高,如果你開發一個射擊游戲,那么玩家就不必在發出子彈后要一邊泡咖啡,一邊等待子彈命中目標了。看下面的代碼:
LPDIRECTDRAWSURFACE lpDDPS; //聲明一個DirectDrawSurface的對象的指針。
DDSURFACEDESC ddsd;//創建一個DDSURFACEDESC對象。
ddsd.dwSize = sizeof(ddsd); //指定該結構所占的內存字節數。
ddsd.dwFlag = DDSD_CAPS; //使ddsCaps成員有效。
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; //指定為主頁面。
Result = lpDD->CreateSurface(&ddsd, &lpDDPS, NULL); //創建這個頁面
我敢肯定這是本文里最讓人迷惑的代碼。但不必擔心,我會使出吃奶的力氣來將其解釋清楚,雖然我并不喜歡喝牛奶。
首先大家要明白一個概念,什么是DirectDraw頁面?這其實就是一個頁面,類似于一張白紙,你可以在上面畫任何東西。在做游戲時所有的圖象都是畫在不同的頁面上,將某一個頁面復制到主頁面去就能立即在屏幕上看到這些圖象。
我們來看看那個似乎比長城還長的類型名LPDIRECTDRAWSURFACE,它的意思是lp(long point)-DirectDraw-Surface,就是一個指向DirectDraw頁面的長指針。這里聲明了一個變量lpDDPS我用該變量來代表我要創建的主頁面。記住這最好是個全局變量。
然后我還要聲明一個ddsd的變量,它的數據類型是DDSURFACEDESC。DDSURFACEDESC其實是DirectDraw Surface Description的縮寫。意即DirectDraw頁面描述。這是一個用于描述頁面的結構。我們定義了這個結構的對象ddsd后就可以對其進行填充,比如指定它為一個主頁面。
ddsd.dwSize就是ddsd所占的字節數,記住在你使用DDSURFACEDESC之前一定要填充這個數。不過這是我所見過的最滑稽的賦值運算。好比在說“我的身高等于用尺子量我的身高所得到的長度”!
ddsd.dwFlag是控制標志,這里讓它等于DDSD_CAPS意思是讓ddsd結構里的ddsCaps成員有效。而ddsCaps是DDSCAPS結構,它包含著一些頁面性能的描述。
ddsd.ddsCaps.dwCaps里有許多高級和復雜的設定,比如是否為3D頁面,是否具備Alpha特性等等。但現在我們只需要指定該頁面為主頁面。
最后用CreateSurface函數來創建這個頁面。
函數原型:
HRESULT CreateSurface(
LPDDSURFACEDESC lpDDSurfaceDesc,
LPDIRECTDRAWSURFACE7 FAR *lplpDDSurface,
IUnknown FAR *pUnkOuter);
參數說明:
lpDDSurfaceDesc:當然是DDSURFACEDESC的指針變量。
lplpDDSurface:一個指針變量指向那個頁面指針變量。
pUnkOuter:不用說又是微軟的陷阱,如果不想掉進去摔個粉身粹骨就放NULL吧。
好了終于完成了,現在你可以在屏幕上寫字了,或者調入一幅bmp的位圖。記得前面尊敬的John De Goes 說過DrectDraw并不能用來畫點或畫線,但實際上可以做到。我無意冒犯Geos先生,只不過電腦實際上是個傻瓜而已,無論它多么鐵面無私不講人情只要一點點技巧往往就能瞞天過海。不過這不是我今天要透露的秘密。還是先寫兩個字上去吧。
HDC hDC;
if(lpDDSP->GetDC(&hDC) != DD_OK)
return FALSE;
SetBkColor( hDC, RGB( 0, 0, 255 ) );
SetTextColor( hDC, RGB( 255, 255, 0 ));
TextOut( hDC, 220, 200, "Yes, I did it!",14);
LPSTR lpMesg;
lpMesag = "Press Esc to exit";
TextOut( hDC, 280, 240, lpMesg, lstrlen(lpMesg));
lpDDSP->ReleaseDC(hDC);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -