DirectX程式設計技術 --- 想學遊戲程式設計嗎?必讀 (轉)

gugu99發表於2008-03-02
DirectX程式設計技術 --- 想學遊戲程式設計嗎?必讀 (轉)[@more@]

技術

  大家對DirectX一定不陌生吧,因為在剛剛推出視窗操作時,由於顯示介面採用統一的GDI,禁止員直接操作,這使得在WIN 3.x系統上的遊戲程式速度奇慢,根本無法推廣。微軟為了解決這一問題,曾經又推出過WING圖形加速程式,但是由於WING缺乏廣大遊戲廠商的支援,也沒有普及開來。所以我們當時玩的大部分遊戲都是執行於DOS環境之下。
  直到1995年,伴隨著WINDOWS 95的誕生,微軟公司正式公佈了其新一代的遊戲開發系統DirectX。DirectX以其高效的,統一的程式介面,使得其一推出便受到了各大遊戲廠家的喜愛,並紛紛表示支援它,至此WINDOWS系統下的遊戲開發時代才真正開始。
  DirectX程式設計,將涉及到 WIN 95 和 C++ 的一些基本知識,所以在此之前您最好有這方面的基礎,如果您不是很熟悉他們的話也不要緊,完全可以隨著本文介紹一起學習,可謂一箭雙鵰。

  好了,閒話少說開始進入正題:
(一)DirectX由以下幾個部分組成:
  1、DirectDraw:透過直接訪問顯示和軟硬體加速技術,實現直接存取。
  2、DirectSound:提供軟硬體混合和錄音再生功能。
  3、DirectPlay :提供多人遊戲的互動功能,讓您輕鬆實現網上互連。
  4、Direct3D:互動式的三維圖形技術。
  5、DirectInput:使你的程式能夠控制輸入裝置如滑鼠,鍵盤,和遊戲杆等。
  6、DirectSetup:完成DirectX程式的。
  7、AutoPlay:只要您把光碟一放入它便會自動執行。
   最後補充一句,我們講到和用到的都是DirectX 5的東西,所以需要一套DirectX 5 SDK,你可以在時下一些光碟中找找,它是免費的。

(二)正式程式設計之前的準備工作
  要讓VC++ 5能正確的編譯、連結你的程式,你必須先在 Developer Studio中進行如下設定,以使得能夠找到需要的連結庫和包含。
  首先,開啟一個新的project workspace,在File選單中,選擇New建立一個新的 Application取名為‘MyDirectX1’,這時在workspace視窗中就會出現了一個新的資料夾。工程建立好後,在Project選單中選擇Add to Project/Files向新的工程中加入程式(這步在後面介紹)。
  然後,設定編譯時所需包含檔案的路徑。在Tools選單中,選擇Options,彈出Options對話方塊,選中Directories ,在Show Directories For列表框中選擇Include files,雙擊列表框底部的空白行,輸入C:DX5SDKSDKINC 和 C:DX5SDKSDKSAMPLESMISC;接著再在Show Directories For列表框選擇Library files,雙擊其底部的空白行,輸入C:DX5SDKSDKLIB(我們假定DirectX 5 SDK安裝在C:DX5SDK )。
  最後,設定連結時所需的庫檔案。開啟在Project選單中Settings/Link,在Category下拉框中選擇General,然後在/Library模組列表框加入Ddraw.lib和Winmm.lib即可。

(三)我們的第一個DirectX程式
  我們打算以DirectX SDK所帶的例子程式‘DDEX1’作為講解的基礎,因為這樣做起碼有以下幾個好處:(1)大家手裡都有正確的源程式,當你辛辛苦苦輸完一段程式後,但在編譯時不幸出現錯誤,你就不會不知所措了,可以對照源程式。(2)我也不用再把所有的程式碼都搬到紙上,這樣我們可以更詳細的介紹DirectX的重點內容。(3)可以培養你讀別人程式的能力,以後學習起來就會更輕鬆。
  既然如此,還等什麼呢?還記得我們已經建立了一個新的工程‘MyDirectX1’嗎?現在開啟Project/Add to Project/Files,瀏覽目錄 DXSDKSDKSAMPLESDDEX1,並選擇該目錄下的所有檔案,點選‘OK’就把它們加入到‘MyDirectX1’中了。好了,現在就開啟‘DDEX1.CPP’看看吧。

  1、在使用 DirextDraw之前,首先需要建立一個DirectDraw的實體,該物件實體代表微機的顯示介面卡。然後,才能使用介面所提供的方法來操作該物件實體,使之完成有關命令和任務。
  所以程式的開頭先宣告瞭一個DirectDraw物件:
LPDIRECTDRAW  lpDD;
  然後如下建立該物件 :
HRESULT  ddrval;
ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
 if( ddrval == DD_OK )
  {
  // DirectDraw 物件lpDD建立成功
 }
 else
 {
  // DirectDraw物件不能被建立
 }

  2、接下來設定協作層的執行方式。即DirectDraw程式的執行方式,指整屏、視窗模式、MODEX模式等。
HRESULT  ddrval;
ddrval = lpDD->SetCerativeLevel( hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
 if( ddrval == DD_OK ){
  // 全屏獨佔方式設定成功
  }
 else {
  // 設定失敗
   }
 
  3、設定顯示模式,即螢幕解析度和色彩數。
HRESULT  ddrval;
ddrval = lpDD->SetDisplayMode( 640, 480, 8 );
 if( ddrval == DD_OK ) {
 // 成功的把螢幕設定成了640X480X256色
 }
 else {
  // 顯示模式不能改變
 }

  4、建立表面。我們可以把表面看成是一塊記憶體緩衝區,所有的操作都是對緩衝區進行的,操作完成後只須把整個緩衝區翻轉成主表面(視訊記憶體)即完成了快速寫屏。利用這種技術,就可以實現平滑無閃爍的動畫效果,下面講解如何建立表面。
  建立可切換式表面(Surface)的第一步是:在DDSURFACEDESC結構中設定表面(Surface)的各項引數,請看下面的程式:

// Create the primary surface with 1 back buffer.
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
DDSCAPS_FL| DDSCAPS_COMPLEX;
ddsd,dwBackBufferCount = 1;

  在以上幾行中,DDSURFACEDESC結構的大小被賦給dwSize成員。這樣做可防止你在DirectDraw的方法時返回一個無效值,且便於今後DDSURFACEDESC結構的擴充套件。
  成員dwFlags用於標明DDSURFACEDESC結構中哪些區域填入的資訊有效,哪些區域的資訊無效。程式中,我們用dwFlags表明了你要使用結構DDSCAPS(DDSC_CAPS),以及你要建立一個後臺緩衝區(DDSD_BACKBUFFERCOUNT)。例程中成員dwCaps包含了一些用在DDSCAPS結構中的標誌。這樣一來,成員dwCaps就定義了一個主表面(Surface)(DDSCAPS_PRIMARYSURFACE),一個彈出式表面(Surface)(DDS-CPAS_PRIMARYSURFACE),和一個復表面(Surface)(DDSCAPS_COMPLEX)。所謂復表面(Surface)是指,該表面(Surface)是由若干子表面(Surface)組成的。最後,上面的例程定義了一個後臺緩衝區。這個後臺緩衝區是我們真正進行操作的記憶體區。操作完成後,再把它們從後臺緩衝區彈到主表面(Surface)上就行了。在這裡,後臺緩衝區的個數被設為1。但你可以設定任意多的後臺緩衝區,只要你的記憶體允許的話。
  填完了DDSURFACEDESC結構,就可以使用該結構和lpDD建立表面的指標了:
 ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
 if( ddrval == DD_OK ) {
  // lpDDSPrimary 指向主表面
 }
 else{
  return FALSE;
  }
  如果呼叫成功,則IDirectDraw::CreateSurface返回指向主表面的指標lpDDSPrimary 。然後呼叫 IDirectDrawSurface::GetAttachedSurface 取得後臺緩衝區的指標:
 ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
 ddrval = lpDDSPrimary->GetAttachedSurface( &ddcaps, &lpDDSBack );
 if( ddrval == DD_OK ) {
  // lpDDSBack 指向後臺緩衝區
 }
 else{
  return FALSE;
 }
  如果IDirectDrawSurface::GetAttachedSurface呼叫成功的話,lpDDSBack 就指向後臺緩衝區了。現在我們就可以對後臺緩衝區進行各種的操作,把想顯示的內容寫進去。比如遊戲,我們就先調入背景圖象,然後再調入各種角色當前應顯示的圖象,最後是‘對白’、‘文字’等。全部完成之後,把後臺緩衝區和主表面進行翻轉,就把你想要的東西顯示出來了。

  5、翻轉表面
 while( 1 ) {
  HRESULT ddrval;
  ddrval = lpDDSPrimary->Flip( NULL, 0 );
  if( ddrval == DD_OK ) 
 {
  break; 轉完成,退出迴圈
  }
  果表面丟失了 
 if( ddrval == DDERR_SURFACELOST ) 
  {
 ddral = LpDDSPrimary->Restore(); 復表面
 if( ddral != DD_OK )
  {
  break;//恢復成功,退出迴圈
  }
  }
  果前一次表面翻轉還未發生
  if( ddrval != DDERR_WASSTILLDRAWING )
  {
  break;
  }
  }
  例中,lpDDSPrimary指明瞭主表面及其後臺緩衝區。呼叫IDirectDrawSurface::Flip後,主表面和後臺緩衝區。如果呼叫成功,返回DD_OK,程式終止While迴圈;如果返回DDERR_SURFACELOST,表明可能是表面丟失,需要用IDirectDrawSurface::Restore 恢復該表面,若恢復成功,就再一次呼叫IDirectDrawSurface::Flip方法;如果失敗,程式終止While迴圈並返回一個錯誤值。另外,即使IDirectDrawSurface::Flip呼叫成功,交換也不是立即完成,它將等到系統中在此之前的表面交換都完成後才進行。如果前一次的表面翻轉還未發生,IDirectDrawSurface::Flip 就返回DDERR_WASSTILLDRAWING。IDirectDrawSurface::Flip將繼續迴圈直到返回DD_OK。

  6、結束程式之前別忘了用Release()釋放你建立的物件。
  if( lpDD != NULL ) 
  {
  if( lpDDSPrimary != NULL )  {
  lpDDSPrimary->Release();
  lpDDSPrimary = NULL;
  }
  lpDD->Release();
  lpDD = NULL;

  OK!大功告成。運用以上的手段我們就可以作出基本的DirectX程式了,不過不要高興的太早,DirectX遠比你想象的要龐大的多!我們所涉及的不過是一點皮毛而已(僅包括了DirectDraw),要想全面掌握DirectX程式設計的技巧,你還須付出艱辛的努力。我的建議是多上機,多看書,多讀讀別人的程式,只有這樣才能快速提高自己的水平。
  好了,今天我們就先聊到這裡,希望這能對你有所幫助,如果有機會的話,我想我們還會見面的。當然,你也可以寫信到這裡 to:wj77@990">wj77@990.net,大家交個朋友嘛!下次見啦!


成都電子科技大學 95080-5 汪疆 (610054)
 

 


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

相關文章