DircetDraw c/c++ 使用指導(三) (轉)

worldblog發表於2008-01-05
DircetDraw c/c++ 使用指導(三) (轉)[@more@]

DircetDraw c/c++ 使用指導



310cdt 譯


這幾篇指導的例程我放到網上了


    tutorial3:從一個離屏表面(off-screen surface)的塊移動(blt)


在ddex2中,把一張點陣圖放到了後臺快取中,然後在快取與主平面間翻啊翻...其實這不是顯示點陣圖的一般行為.在這一篇中(例子是ddex3)將要透過包含兩個離屏表面來擴充套件ddex2的能力.兩個點陣圖-一個是第偶數次顯示的,一個是奇數次顯示-存放在這兩個離屏表面.例子中,用IDirectDrawSurface7::BltFast方法把離屏表面的內容複製到後臺快取中去,然後翻轉,然後再把下一個離屏表面拷到快取...
(譯者注:這一篇只是演示離屏表面和blit的方法,實際上,離屏表面使用的時候大部分是用來存放精靈,實現動畫的.存放的都是小的圖片,是一個特殊的平面)
ddex3新的以下面3個步驟演示:
step1:建立離屏表面
step2:載入點陣圖到離屏表面
step3:塊移動(blit)離屏表面到後臺緩衝



step1:建立離屏表面
下面的程式碼是加入到doInit函式中建立兩個離屏表面.
// Create an off-screen bitmap.
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwHeight = 480;
ddsd.dwWidth = 640;
ddrval = lpDD->CreateSurface(&ddsd, &lpDDSOne, NULL);
if(ddrval != DD_OK)
{
  return initFail(hwnd);
}
 
// Create another off-screen bitmap.
ddrval = lpDD->CreateSurface(&ddsd, &lpDDSTwo, NULL);
if(ddrval != DD_OK)
{
  return initFail(hwnd);
}
dwFlags成員定義了將使用DDSCAPS結構,並且將要設定離屏表面的高和寬.這個表面因為標示了DDSCAPS_OFFSCREEN在DDSCAPS結構中,所以將會是一個完全的離屏的快取.高和寬分別設為480 和640.隨後,表面經過IDirectDraw7::CreateSurface方法建立.
因為兩個離屏表面大小相同,就又不同的指標了IDirectDraw7::CreateSurface又一次,建立了另一個.
你可以透過在DDSCAPS結構中定義DDSCAPS_SYSTEMMEMORY或DDSCAPS_VOMEMORY來決定將離屏表面放在還是視訊記憶體中.放在視訊記憶體中,你可以加快離屏表面到後臺快取的移動速度.將用到點陣圖的動畫的時候,這將十分的重要.但是,如果你使用DDSCAPS_VIDEOMEMORY並且沒有足夠的視訊記憶體區存放那個點陣圖了,當你試圖建立這個表面的時候,將會返回一個DDERR_OUTOFVIDEOMEMORY錯誤.


 


step2:載入點陣圖到離屏表面
當兩個離屏表面建立好後,DDEx3用InitSurface函式將frntback.bmp的點陣圖裝入到表面中.InitSurface函式用到了ddutil.cpp檔案中的DDCopyBitmap函式去裝載點陣圖.如下:
// Load the bitmap re.
hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), szBitmap,
  IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
 
if (hbm == NULL)
  return FALSE;
 
DDCopyBitmap(lpDDSOne, hbm, 0, 0,  640, 480);
DDCopyBitmap(lpDDSTwo, hbm, 0, 480, 640, 480);
Delete(hbm);
 
return TRUE;
如果你用看圖或畫圖的看過frntback.bmp檔案了,你就知道,這個檔案包括兩個圖,一個在另一個的上面.DDCopyBitmap函式把這個點陣圖從分界的地方分成兩部分.一個裝入到第一個離屏表面(lpDDSOne),另一個在第二個離屏表面(lpDDSTwo).



step3:塊移動(blit)離屏表面到後臺緩衝
WM_TIMER訊息觸發的程式碼包括寫入表面和翻轉表面.在DDEx3中,他包含了下面的程式碼去選擇適當的離屏表面,然後把他塊移動(blit)到後臺快取.
rcRect.left = 0;
rcRect.top = 0;
rcRect.right = 640;
rcRect.bottom = 480;
if(phase)
{
  pdds = lpDDSTwo;
  phase = 0;
}
else
{
  pdds = lpDDSOne;
  phase = 1;
}
while(1)
{
  ddrval = lpDDSBack->BltFast(0, 0, pdds, &rcRect, FALSE);
  if(ddrval == DD_OK)
  {
  break;
  }
}
phase變數決定了到底是哪一個離屏表面將被移動到後臺快取.IDirectDrawSurface7::BltFast方法的呼叫是用來把所選的離屏表面塊移動到後臺快取的.在(0,0)處開始,左上角.reRect引數指向一個RECT結構,他定義了移動出來的離屏表面的左上和右下角.最後的一個引數設為FALSE(0),標示沒有使用特殊的傳輸標示符.
根據你的程式的需要,你可以使用IDirectDrawSurface7::Blt 或者IDirectDrawSurface7::BltFast 方法實現塊移動.如果你的離屏表面在視訊記憶體中,你最好使用IDirectDrawSurface7::BltFast 方法.這樣做,如果你使用的是塊移動支援的系統,你不會獲得更快的速度,但是,如果使用的硬體模仿的塊移動,你將會少用10%的時間.所以,你應該使用IDirectDrawSurface7::BltFast方法去做所有的在視訊記憶體中的塊移動.如果你從系統記憶體中移動,或者需要特別的硬體標誌,那就只好使用IDirectDrawSurface7::Blt了.
當完成的從離屏表面到後臺快取的塊移動,後臺快取就和主平面之間像前面幾篇一樣不停的翻啊翻....


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

相關文章