DirectX編程技術 — 想學遊戲編程嗎?必讀

來源:互聯網
上載者:User

 大家對DirectX一定不陌生吧,因為在微軟剛剛推出WINDOWS視窗作業系統時,由於顯示介面採用統一的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能正確的編譯、連結你的程式,你必須先在Microsoft Developer Studio中進行如下設定,以使得編譯器能夠找到需要的連結庫和包含檔案。
    首先,開啟一個新的project workspace,在File菜單中,選擇New建立一個新的Win32 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,然後在Object/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->SetCooperativeLevel( 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_FLIP | 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; file://翻轉完成,退出迴圈
            }
            file://如果表面丟失了   
  if( ddrval == DDERR_SURFACELOST ) 
   {
   ddral = LpDDSPrimary->Restore(); file://恢複表面
   if( ddral != DD_OK )
    {
       break;//恢複成功,退出迴圈
    }
               }
            file://如果前一次表面翻轉還未發生
            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編程的技巧,你還須付出艱辛的努力。我的建議是多上機,多看書,多讀讀別人的程式,只有這樣才能快速提高自己的水平。
    好了,今天我們就先聊到這裡,希望這能對你有所協助,

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.