DirectX5.0最新遊戲程式設計指南 DirectDraw篇 一、DirectDraw的基本圖象概念 (轉)

worldblog發表於2007-12-04
DirectX5.0最新遊戲程式設計指南 DirectDraw篇 一、DirectDraw的基本圖象概念 (轉)[@more@]

 

5.0最新遊戲指南
 DirectDraw篇

  DirectDraw是DirectX SDK的主要部分之一,它允許你直接對顯示操作,支援位塊傳輸、硬體覆蓋、表面翻轉,並且保持同目前的基於的應用和程式相容。
  DirectDraw是一種介面,它除了能直接對顯示裝置存取外,還保持同Windows圖形裝置介面GDI(Graphics Device Interface)相容。對於圖形來說,它並不是一種高階應用程式介面。DirectDraw提供了一種裝置無關性的方法,使得基於Windows的應用軟體和遊戲(例如三維圖形軟體包和數字影片遊戲)能直接獲取顯示裝置的特性。
  DirectDraw能工作於各種各樣的顯示裝置,從簡單的SVGA顯示器到能夠提供剪下、拉伸和非RGB格式支援的高階顯示裝置。DirectDraw介面使得你的應用程式能模擬基本硬體的並使用硬體加速特性;硬體不提供的特性將由DirectX來模擬。DirectDraw提供的對顯示記憶體的裝置無關性的訪問能使你很容易地管理顯示記憶體。你的應用程式只需要識別一些基本的裝置屬性,它們都是標準的硬體應用,例如RGB和YUV格式的顏色。你不需要特殊的過程來使用位塊傳輸或操縱調色盤暫存器。使用DirectDraw,你可以很容易地操作顯示記憶體,充
分利用不同型別顯示裝置的位塊傳輸和顏色解壓功能,而不需要依賴於特定的硬體。DirectDraw可以執行在Windows95/NT4.0和以後的版本中。
  DirectDraw的硬體抽象層HAL(Hardware Abstraction Layer)提供了統一的介面,透過該介面,程式可以直接在顯示記憶體或影片記憶體中工作,獲取硬體的最佳效能。
  DirectDraw對影片硬體的效能進行估計,只要可能就會使用硬體提供的特定效能。例如,如果影片卡支援位塊傳輸,DirectDraw就會把位塊傳輸委託給影片卡,不參與位塊傳輸的處理,這就大大提高了程式執行的效能。另外,DirectDraw提供了硬體模擬層HEL(Hardware Emulation Layer ),使得在某些硬體不存在時可以用軟體模擬來支援本應該由這些硬體提供的特性。
  DirectDraw執行在Windows 95上,能夠利用32位記憶體的優越性和操作提供的“平坦”記憶體模型。DirectDraw將系統記憶體和影片記憶體作為大塊而不是一小段一小段地使用。另外,DirectDraw還為 Windows圖形程式設計師帶來了許多強大的功能:
  .DirectDraw使得在全屏下的應用多個後臺緩衝區的頁翻轉變得容易
  .支援視窗模式和全屏模式下的剪下功能
  .支援三維 Z緩衝區
  .支援Z方向的硬體輔助覆蓋
  .提供對圖象拉伸的硬體的存取
  .同時訪問標準的和增強的顯示裝置記憶體區域
  .動態調色盤、獨佔式的硬體訪問、解析度切換等
將這些特性結合在一起,你就可以較容易地編制出效能超過基於GDI的標準Windows遊戲甚至是MS-DOS下的遊戲。

一、DirectDraw的基本圖象概念
  DirectDraw提供了一組不同於GDI的圖形術語,因此,要用好DirectDraw,首先應該瞭解其中的有關概念。下面就對DirectDraw中重要的概念作一介紹。
1.1裝置無關性點陣圖DIB(Device-Independent Bitmap)
  DirectX使用裝置無關性點陣圖DIB作為主要的圖形格式。一個DIB檔案主要保護瞭如下資訊:圖象的維數、使用的顏色數、描述顏色的值及描述每一個畫素的資料。DIB檔案還保護了較少用到的引數,象有關檔案的資訊和圖象的物理維數。DIB檔案的副檔名一般是“.BMP”,有時也可能是“.DIB”。
  因為DIB在Windows程式設計中的應用極其廣泛,DirectX SDK已經包含了許多相關的。例如,DirectX SDK提供的ddutil.cpp檔案中有一個函式,它將和DirectX函式結合在一起,概念是把一個DIB檔案裝入DirectX表面,程式碼如下:
extern "C" IDirectDrawSurface * DDLoaitmap(IDirectDraw *pdd,
  LPCSTR szBitmap, int dx, int dy)
{
  HBITMAP  hbm;
  BITMAP  bm;
  DDSURFACEDESC  ddsd;
  IDirectDrawSurface *pdds;
  //  This is the Win32 part.
  //  Try to load the bitmap as a re, if that fails, try it as a file.
  hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), szBitmap, IMAGE_BITMAP, dx, dy, LR_CREATEDIBSECTION);
  if (hbm == NULL)
  hbm = (HBITMAP)LoadImage(NULL, szBitmap, IMAGE_BITMAP, dx, dy, LR_LOADFROMFILE|LR_CREATEDIBSECTION);
  if (hbm == NULL)
  return NULL;
  // Get the size of the bitmap.
  Get(hbm, sizeof(bm), &bm);
  // Now, return to DirectX function calls.
  // Create a DirectDrawSurface for this bitmap.
  ZeroMemory(&ddsd, sizeof(ddsd));
  ddsd.dwSize = sizeof(ddsd);
  ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
  ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  ddsd.dwWidth = bm.bmWidth;
  ddsd.dwHeight = bm.bmHeight;
  if (pdd->CreateSurface(&ddsd, &pdds, NULL) != DD_OK)
  return NULL;
  DDCopyBitmap(pdds, hbm, 0, 0, 0, 0);
  DeleteObject(hbm);
  return pdds;
}

 1.2、繪圖表面(Drawing Surface)
  繪圖表面接受影片資料並將其作為圖象顯示出來。在大多數的Windows應用程式中,你可以使用Win32的函式如GetDC來訪問繪圖表
面。GetDC獲取裝置上下文DC(Device Context),獲得了裝置上下文後,就可以重畫表面了。然而,Win32的圖象函式是由GDI提供的。
GDI是系統的一部分,它提供了抽象層,使得標準的Windows程式向表面繪圖。
  GDI的缺點是它並不是為高效能的多軟體設計的,它主要用於商業軟體如字處理和電子表格軟體。GDI提供了對系統記憶體中的影片緩衝區的訪問,但不提供對影片記憶體的訪問。儘管GDI對於大多數的商業軟體非常合適,但對於多媒體應用程式和遊戲軟體則顯得太慢了。
  另一方面,DirectDraw 能提供表徵真實影片記憶體的繪圖表面,這就意味著當你使用DirectDraw 時,你能夠直接向影片記憶體寫資料,使得圖象的顯示速度足夠快。這些表面表徵為連續的記憶體塊,使得定址時更加容易。
1.3、位塊傳輸Blit
  Blit是“Bit Block Traner”的簡寫,表示位塊傳輸。它是將記憶體中一個地址的一塊資料傳送到另一個地址的一種方法。位塊傳輸經常用於精靈動畫中。你可以使用IDirectDrawSurface3::Blt 方法和IDirectDrawSurface3::BltFast方法來位塊傳輸。

1.4、頁翻轉(Page Flip)和後臺緩衝(Back Buffering)
  頁翻轉是多媒體、動畫、遊戲軟體中的關鍵。軟體頁翻轉是對卡通畫家使圖象運動的過程的模擬。例如,畫家在一張紙上畫了一個人物,然後將其置於下一幀的工作狀態,對於每一幀,只很少地改變人物圖象。當你翻轉紙片時,連續的人物圖象看起來就成了動畫。
  軟體中的頁翻轉類似於上述的過程。首先,你建立了一系列DirectDraw表面,這些設計好的表面準備“翻轉”到螢幕。第一個表面被看作是主表面(Primary Surface),在主表面後的所有表面都稱為後臺緩衝區。應用程式將資料寫向後臺緩衝區,然後翻轉主表面,於是後臺緩衝區就顯示在片面上了。當系統正在顯示圖象時,程式就可以向後臺緩衝區寫資料,這個過程一直持續到動畫的結束,它使你快速而高效地將離散的圖象變成動畫。 DirectDraw可以利用相對簡單一些的雙緩衝區(一個主表面和一個後臺緩衝區),也可以使用較複雜的技術,加入其它的後臺緩衝區。使得你能夠容易地建立頁翻轉的程式。

1.5、矩形(Rectangle)
  貫穿DirectDraw和Windows程式設計的一個最重要的概念是表面上的──有界矩形。一個有界矩形由兩個點來確定,即左上角和右下角。當以位塊傳輸的方式向螢幕寫資料時,大多數的應用程式都使用RECT結構來傳送有關有界矩形的資訊。RECT結構的定義如下:
typedef struct tagRECT {
  LONG  left;  // This is the top-left corner's X-coordinate.
  LONG  top;  // The top-left corner's Y-coordinate.
  LONG  right;  // The bottom-right corner's X-coordinate.
  LONG  bottom;  // The bottom-right corner's Y-coordinate.
} RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT;

  其中left和top成員變數是矩形左上角的X、Y座標的值,right和bottom是右下角的X、Y的座標值。

1.6、精靈(Sprite )
  許多影片遊戲都使用了精靈。從最基本的意義上來講,一個精靈就是在螢幕上移動的圖象。精靈畫在一個表面上,覆蓋在已有的背景上,合成後的圖象被送到螢幕上顯示出來。
1.6.1、透明位塊傳輸(Transparent Blitting)和Color Key
  精靈動畫中的難點在於對非標準矩形的精靈的處理。因為位塊傳輸函式是工作在矩形方式下,你的精靈也必須放在一個矩形之中,而不管它在螢幕上是否矩形。
  精靈圖象本身不是矩形的,但卻包含在矩形區域中。當用位塊傳輸將圖象移動到目的地時,矩形區域中不屬於精靈的畫素就被“透明”處理。程式設計師選擇任意一種顏色來建立精靈,這種顏色就被用來作為透明度“Color Key”。它是一種不常用的顏色,程式設計師僅僅用於表示透明度或特定的顏色範圍。
  使用IDirectDrawSurface3::SetColorKey方法,你可以為一個表面設定Color Key。設定了Color Key後,呼叫 IDirectDrawSurface3::BltFast方法來使用已設好的Color Key,而不管畫素是否同該Color Key匹配。這種型別的Color Key是源 Color Key。源Color Key禁止“透明”的畫素寫到目的地,這樣,原來的背景畫素就保留下來了,使得精靈看起來就是非矩形的了並且精靈還可以在背景上移動。
  另外,你還可以使用一個Color Key來影響目的表面(目的Color Key)。目的Color Key也是表面上的一種顏色,它用於指明畫素是否可以被精靈所覆蓋。
1.6.2、精靈和修補矩形(Sprite and Patch Rectangle)
  為了產生精靈運動的效果,你在將精靈畫到新的位置之前還必須從背景上擦除舊的位置上的精靈圖象。當然,也可以重新調入整個背景再重畫精靈,但這會大大降低動畫的質量。事實上,你可以保留精靈矩形的上一次的軌跡,僅對該位置重畫。這種方法稱為“修補”(Patching)。
為了修補精靈舊的位置,可以利用原始背景圖象(已經調入到一個屏外表面)的一個複製來重畫這一位置。在這個過程中使用的是位塊傳輸方法,在整個表面的迴圈中進行,需要耗用的處理時間很少。下面是這一過程的簡單步驟:
(1). 設定精靈上一次位置的修補矩形
(2). 使用位塊傳輸將屏外表面中的背景圖象的主複製補到該位置
(3). 精靈是目的矩形,它反映了精靈新的位置
(4). 將精靈位塊傳輸到背景上最新更新的矩形位置
(5).重複
  將DirectDraw提供的強大的圖象功能同直線式的C/C++程式結合起來,利用上面的步驟,馬上就可以建立一個簡單的精靈動畫。
1.6.3、邊界檢查和碰撞檢測(Bounds Checking and Hit Detection)
  在精靈動畫中,邊界檢查和碰撞檢測是兩個非常車間而又相當重要的任務。邊界是限制精靈活動的範圍,邊界檢查就是透過RECT結構來檢查精靈的位置,判斷精靈是否超出了限定的範圍。
碰撞檢測就是檢查多個精靈是否佔用了同一個位置。大部分的碰撞檢測是檢查各個精靈的矩形之間是否有所覆蓋。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-987853/,如需轉載,請註明出處,否則將追究法律責任。

相關文章