DirectDraw──也許大多數人聞所未聞,但當提到 DirectX 恐怕每一個 遊戲愛好者都再熟悉不過了,但是只知道那是一個很多遊戲都要求的必須安裝的程序,再多就無從所知了,那麼它到底能為我們的遊戲幹什麼呢,其實它又叫 Game SDK,它最大的特點是直接對硬件的抽象層(HAL)進行操作,利用 此特點可制作出高性能的Windows遊戲。 http://www. microsoft.com/directx/default.asp。
DirectDraw就是DirectX5的6個組件之一。DirectX5的其它5個組件分別是:
| Direct3D |
提供了3D硬件接口。 |
| DirectSound |
立體聲和3D聲音效果,同時管理聲卡的內存。 |
| DirectPlay |
支持開發多人網絡遊戲,並能處理遊戲中網絡之間的通信問題。 |
| DirectInput |
為大量的設備提供輸入支持。 |
| DirectSetup |
自動安裝DirectX驅動程序。 |
而DirectDraw則是DirectX的基礎,DirectX的其它組件都是建立在它的基礎之上的。DirectDraw使用頁面切換的方法實現動畫,它不僅可以訪問系統內存,還可以訪問顯示內存,這是以往的Windows程序員所不能的。(例如:如果你是用MFC中的CDC類進行繪圖,那麼它是絕對不會讓您直接訪問顯存的。) 另外,我們利用DirectDraw還可以生成、移動、剪切、轉換、合成圖像數據,從而編寫出各種“炫麗多彩”圖形的應用程序。
您先不要急,我們會在後面附上本文介紹的動畫程序原代碼,只要將其用vc打開,進行工程的編譯創建後,您就會立刻看到效果。並且我們在工程文件中有詳細的中文注釋,力求將理論與實踐緊密聯系在一起。
首先,讓我們先了解一下DirectDraw的三個重要概念──表面、Bltting、色彩鍵碼
1.表面
在用DirectDraw編寫程序時,我們先要創建若幹個圖形數據緩衝區,並把這些圖形數據裝入其中,再進行轉換、拉伸、挎貝等操作,並且還可以顯示這些緩衝區中的圖形數據,這些緩衝區就稱為表面。
表面可以分為幾類。
主表面(primary surface)是用戶在屏幕上可以看到的,它是顯示內存的一部分。所有DirectDraw程序都有主表面,而且只有一個。它在DirectDraw表面對象之前就已經存在了,因此不能改變它的尺寸、格式和位置。
主表面有一個很重要的特性──翻頁(flip)。頁面翻頁用于程序中,可以產生相當平滑、不閃爍的動畫。一個可以翻頁的主表面實際上是兩個表面,一個是可見的,一個是不可見的。不可見的表面稱為後備緩衝區。當發生表面翻頁時,後備緩衝區就成為可見的,而以前的可見主表面則成為後備緩衝區。 下面我們用圖示來向您解釋上面的概念:

當翻頁後,將原後備緩衝區頁中的內容copy入可見主表面頁,而同時將原可見主表面頁的內容copy入後備緩衝區頁。
顯示器屏幕雖然每秒中刷新很多次,在此我們假定為85次,但每次都是一遍一遍地讀取可見主表面中存儲的顯示頁信息,而你對後備緩衝區的改動不會顯示出來,並且也不會影響可見主表面的顯示,而只有當施行翻頁操作後,兩頁的內容互換,而你已經完成了的在原後備緩衝區的改動才會顯示在屏幕上,而這個互相拷貝的過程幾乎是瞬間完成的,這個時間比起每次刷新所用的時間少得多得多,兩者幾乎差了幾乎幾十萬個數量級。而人眼是根本察覺不到的,所以用這種方法可以不閃爍,平滑,優質的動畫效果
還有一種表面叫離屏表面(off_screen surface),它是不能直接見到的。離屏表面作為存儲緩衝區,有助于表面之間的互相切換,它的大小是可以改變的。
主表面和離屏表面都分為有調色板的和無調色板的這兩類。像素深度為8位(256色)的表面稱為有調色板的表面;而像素深度為16位(64K色)、24位(16M色)的像素表面稱為無調色板的表面,它們存儲實際的色彩值(RGB值)。
在本文下面的程序中,我們先使用256位表面即有調色板的表面。
2. Bltting
Bltting是用于復制圖形的語言,可以將圖像從一處拷貝到另一處。例如大家所熟悉的CDC類(設備描述表類)的BitBlt()就是具有這樣功能的函數。
在DirectDraw中,典型的blt操作是將離屏表面的內容拷貝到一個後備緩衝區,而一般的blt操作調用一個源表面和一個目標表面,把源表面的內容拷貝到目標表面中,不僅可以整體拷貝源表面,而且還可以拷貝源表面內的任何矩形區域到目標表面的任何位置。blt還支持透明拷貝,就是指表面中的某一像素在blt過程中可以不予以拷貝,而這個像素值是由色彩鍵碼(DDCOLOR KEY )決定的。如圖:

DirectDraw中有三個支持blt的函數,它們是
Blt( )用得最多,BltFast()的速度比Blt()要快,但功能卻很有限,例如不支持拉伸、剪切等操作。
還有一個函數BltSurface(),它是DirectWin類的一個成員函數,Blt()、BltFast()更具有適應性,並且使用起來更加簡單。例如,當我們把源表面拷貝到目標表面外時需要裁剪,而BltFast()不支持裁剪。這時我們使用BltSurface()函數,它在內部使用Blt()和 BltSurface()函數,並根據情況自動執行裁剪。
在此,有人會問,這種頁面切換的方法到底好在那裡?它到底與用一般的繪圖方法的區別在什麼地方?而其它的繪圖方法為什麼會使屏幕閃動呢?下面我們舉二個例子:(我們仍然用圖示的方法給您一個直觀的解釋)
(1) 在一些繪圖程序中您會發現其用到了清屏函數,這種方式是使屏幕效果最差的,這種方法使得沒有直接從第一個畫面切換到第二個畫面,而是先用黑色將圖形數據緩衝區清空,並且還顯示在屏幕上,但這個時間很短。如果反復清屏,則會產生嚴重的屏幕閃爍。如下圖:

(2)在一些程序中用異或的方式進行繪圖,即先在屏幕上畫出第一個圖像,然後在畫第二個圖像之前,再在屏幕上畫一遍第一個圖像,這樣起到清除第一個圖像的效果。如果您仔細看,會發現這樣就會比上一個方法的畫面效果好得多,但這並不是很完美,因為如果反復使用,雖然不會產生全屏幕的閃動,但在所清除圖像處會產生閃爍。究其根本原因還是因其沒能直接從第一個畫面切換到第二個畫面。如下圖:

我想現在您應明白DirectDraw繪圖的優勢了吧,其實這就是對上述方法中缺點的很好的解決方法。
3.色彩鍵碼
DirectDraw 可以把某種顏色或某個範圍的顏色指定為一個顏色值,這個顏色值是由DDCOLORKEY結構即色彩鍵碼說明的,DDCORLORKEY結構說明如下:
typedef struct _DDCOLORKEY { DWORD dwColorSpaceLowValue; //顏色範圍的低端 DWORD dwColorSpaceHighValue; //顏色範圍的高端 } DDCOLORKEY; |
當我們對表面進行拷貝操作時,表面中哪些像素不被拷貝是由色彩鍵碼決定的。例如當DDCOLORKEY結構的兩個分量都為零時,表面內所有置為零的像素都不能被拷貝。又例如,當表面是24位RGB模式時,若想指定RGB=(120,120,120)像素不被拷貝,則應該:
DDCOLORKEY ddck; ddck.dwColorSpaceLowValue=RGB(120,120,120); ddck.dwColorSpaceHighValue=RGB(120,120,120); surf→SetColorKey(DDCKEY_SRCBLT,&ddck); |
其中SetColorKey()函數是把色彩鍵碼賦給表面surf。這樣,在對表面surf的 blt操作期間RGB值為(120,120,120)的像素不能被拷貝。
OK,我們現在已經具備基本的DirectDraw的知識,下面我們就來進行實戰演練(未完待續......) |