• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            牽著老婆滿街逛

            嚴以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            DirectDraw 與 DirectInput 的游戲編程體驗

            原文地址:http://www.gameres.com/Articles/Program/Abstract/DirectDraw%E4%B8%8EDirectInput%E7%9A%84%E6%B8%B8%E6%88%8F%E7%BC%96%E7%A8%8B%E4%BD%93%E9%AA%8C.htm

              我想關于這個主題的文章,不算少,但也不算太多。但大多是分別介紹 DirectDraw 與 DirectInput,而并沒有將其結合起來,也許你會問:“分開與合并起來并沒有本質區別啊!”。其實的確沒有本質區別,但那樣使那些最初對游戲編程報有極大熱情的愛好者感到非常失望,因為這其中的一個并不能完全滿足他們的要求,并且使其感到巨大的阻力,從而失去信心。所以本文將 DirectDraw 與 DirectInput結合起來去講一個主題就是“游戲編程”,請注意是“游戲編程”,當然這只是一個簡單的桌面游戲,但這已經與先前有很大的不同了,這已不是簡單的 DirectDraw或 DirectInput編程。我想你現在應該能夠體會出其中的區別了。

              聲明:在這之前需要你具有一定的 WIN32 API 函數的知識,并且可以熟練使用。和 DirectDraw的知識,關于DirectDraw可以參見 www.frontfree.net 中的 <<動畫程序編寫——DirectDraw之旅>> 1-3),或其它文章。最后是 c++ 語言,當然也要包括面向對象的那部分。在 Visual C++ .NET 編譯環境下進行開發的。

              首先 ,我們還是先簡要復習一下DirectDraw的概念吧!
            DirectDraw本質上是顯存管理程序。它最重要的性能是允許程序員直接在顯存里存儲和操縱位圖。它使你能夠利用視頻硬件bliter(位塊傳輸器)在顯存內部進行位圖的blit(位塊傳輸)。用視頻硬件的blitter從顯存向顯存進行blit比從內存向顯存更快。這在64位顯卡向顯存提供64位數據路徑的今天顯得尤其重要,硬件獨立于促CPU進行位塊傳輸操作,使得CPU得以繼續工作。另外DirectDraw支持顯卡的其他硬件加速特性,例如對精靈和z -buffering的硬件支持。

            DirectDraw的工作原理

            我們這里還是用圖表方式展現給大家吧!

              細心的朋友可以很明顯地注意到圖示中的右上角的圖解中說明,表面對象有兩個寬度,一個是WIDTH,一個是PITCH。WIDTH就是創建表面時所給出的那個寬度,而PITCH是表面的實際寬度,是按字節算的。在許多顯卡上,PITCH和WIDTH是相等的,比如在640x480的高彩模式下,PITCH為1280。而在某些顯卡上,PITCH比WIDTH要大。比如在640x480的256色模式下,當WIDTH是640時,PITCH為1024而不是640,這些顯卡這樣做是為了更好地進行數據對齊來提高性能或達到其它目的。所以,我們在實際編程時,為了保證程序的兼容性,必須按PITCH處理。 但這些硬件的底層問題,我們不用太關心,只要稍有了解就可以了。

            下面我們再簡要敘述一下,如何使用 DirectX 9.0 中提供的 DirectDraw 類庫來創建對象并使用操作對象。

            宏定義在先,定義刪除指針和釋放對象的宏

            #defineSAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
            #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }

            先創建一個 CDisplay 的全局對象
            CDisplay就是ddutil.h中定義的類,用于處理表面之間的拷貝翻頁等操作的類,再次定義一個全局變量,用于以后對指向的表面之間進行操作

            CDisplay* g_pDisplay = NULL;

            然后創建表面,當然可以創建很多的表面,這些表面都是離屏表面,在更新畫面時,都可以用 CDisplay 類的對象中的方法,將其拷貝到后備緩沖區表面上。只要創建離屏表面,就要用到 CSurface 類。CSurface也是ddutil.h頭文件中定義的類,用于對表面本身進行操作,如設置色彩鍵碼,在此定義的圖畫指針。
             

            CSurface* g_pBackSurface = NULL;

            DirectX 中就一共用這兩個類封裝了 DirectDraw 對象的大部分操作,如果你覺得這還不能滿足要求,那么你也可以在程序中用 DirectDraw API 函數編寫程序,不過在本文中不再介紹。

            這之后,我們會用到 InitDirectDraw 函數。這個函數是我們自己創建的。在此函數中作所有的 DirectDraw 的對象初始化工作。

            HRESULT InitDirectDraw( HWND hWnd )
            {
            ?????HRESULT hr;
            //接受返回值,其實是long型變量
            ?????LPDIRECTDRAWPALETTE pDDPal = NULL; //定義程序中的調色板
            ?????int iSprite;//定義與sprite個數有關的計數器
            ?????g_pDisplay = newCDisplay();//動態開辟一個CDisplay類
            ?????if( FAILED( hr = g_pDisplay->CreateFullScreenDisplay( hWnd, SCREEN_WIDTH,
            ???????????SCREEN_HEIGHT, SCREEN_BPP ) ) )
            /*設置程序為全屏,并且 g_pDisplay 就是動態開辟一個CDisplay類的指針,而在這個類的域中,有一個DirectDraw主表面指針,和一個后備緩沖區表面的指針。在從我建議你可以先去閱讀一下 ddutil.h 和 ddutil.cpp 文件。*/
            ?????{
            ???????????MessageBox( hWnd, TEXT("This display card does not support 1024x768x8. "),
            ?????????????????TEXT("DirectDraw Sample"), MB_ICONERROR | MB_OK );

            ???????????return hr;
            ?????}

            ?????if( FAILED( hr = g_pDisplay->CreatePaletteFromBitmap( &pDDPal, MAKEINTRESOURCE( IDB_DIRECTX ) ) ) )//顧名思義,就是從bmp圖片中獲得調色板值,并賦值在pDDPal結構指針所指向的結構體中。
            ???????????returnhr;
            ?????if( FAILED( hr = g_pDisplay->SetPalette( pDDPal ) ) )//用剛才從IDB_DIRECTX中獲得的調色板制來設置程序調色板
            ???????????returnhr;
            ?????SAFE_RELEASE( pDDPal );
            //釋放指針,在用過后,一定要釋放,這是良好的編程習慣
            ??????// 用IDB_WINXP圖片創建一個表面,并用g_pBackSurface指向這個表面
            ?????if( FAILED( hr = g_pDisplay->CreateSurfaceFromBitmap( ??????&g_pBackSurface, MAKEINTRESOURCE( IDB_WINXP ),
            ??????SCREEN_WIDTH, SCREEN_HEIGHT ) ) )

            ???????????return hr;//設置色彩鍵碼為黑色,0代表黑色,這樣在表面的拷貝過程中黑色像素的點將不會被拷貝,這樣可以產生鏤空效果。當然你可以任意設置關鍵顏色,而顏色的表示法可以用 RGB 宏定義。例如 紅色:RGB( 255,0,0 ), 黑色 RGB( 255,255,255 )
            ??????if( FAILED( hr = g_pBackSurface->SetColorKey( RGB( 255,255,255 ) ) ) )
            ???????????returnhr;
            ?????returnS_OK;
            }

            下面的函數是用于更新畫面的。
             

            HRESULT DisplayFrame()
            {
            ?????HRESULT hr;
            ?????g_pDisplay->Clear( 0 );
            //清空后備緩沖區表面
            ?????//將g_pBackSurface所指向的圖片拷貝到后備緩沖區表面
            ??????g_pDisplay->Blt( 0, 0, g_pBackSurface, NULL );//最關鍵的地方在這里,請看下面的語句,只要我們一執行翻頁操作,就可以將改動了的圖像了顯示在屏幕上了
            ?????if( FAILED( hr = g_pDisplay->Present()/*翻頁操作*/) )
            ???????????returnhr;
            ?????returnS_OK;
            }

            下面的函數是用于在程序失去焦點時調用的。

            HRESULT RestoreSurfaces()
            {
            ?????HRESULT hr;
            ?????LPDIRECTDRAWPALETTE pDDPal = NULL;
            /*當程序失去焦點,要保存當前的畫面,請注意這里,g_pDisplay->GetDirectDraw()函數返回的才是真正的 DirectDraw 對象 */
            ?????if( FAILED( hr = g_pDisplay->GetDirectDraw()->RestoreAllSurfaces() ) )
            ???????????returnhr;//在此我們還要重新創建調色板
            ?????if( FAILED( hr = g_pDisplay->CreatePaletteFromBitmap( &pDDPal, MAKEINTRESOURCE( IDB_DIRECTX ) ) ) )
            ???????????returnhr;//重新設置調色板
            ?????if( FAILED( hr = g_pDisplay->SetPalette( pDDPal ) ) )
            ???????????returnhr;
            ?????SAFE_RELEASE( pDDPal );//重新畫出圖畫
            ?????if( FAILED( hr = g_pLogoSurface->DrawBitmap( MAKEINTRESOURCE( IDB_WINXP ),
            SPRITE_DIAMETER, SPRITE_DIAMETER ) ) )

            ???????????returnhr;
            ?????returnS_OK;
            }

            下面這個函數是釋放表面指針所用的。

            VOID FreeDirectDraw()
            {
            ??????SAFE_DELETE( g_pBackSurface );
            ??????SAFE_DELETE( g_pDisplay );
            }

            我們的回顧到此結束,下面我們開始本文要介紹的一個關鍵技術,DirectInput 的使用。
            游戲編程可不僅僅是圖形程序的開發工作,實際上包含了許多方面,本文所要講述的就是關于如何使用 DirectInput 來對鍵盤編程的問題。
            而我們為什么要選擇用 DirectInput 來處理游戲中的輸入問題呢?其實用 Win32 API 函數也完全可以處理這些工作,例如其中,有一個

            GetAsyncKeyState() 的函數可以返回一個指定鍵的當前狀態是按下還是松開。這個函數還能返回該指定鍵在上次調用 GetAsyncKeyState() 函數以后,是否被按下過。雖然這個函數聽上去很不錯,但需要我們自己輪換查詢每個鍵盤的狀態。而在 DirectInput 中我們已經可以脫離這些煩瑣的工作,只因它的功能更強大。

            由于本文重點在二者的結合,故在此只介紹 DirectInput 中比較簡單的,而且最容易上手的立即模式的工作方式。
            而這里我們要用到 DirectInput 的 API 函數。有人會問,為什么在 DirectDraw 中用 DirectX 提供的類庫編程,而對于 DirectInput 卻直接使用要用其 API 函數呢,是因為沒有提供 DirectInput 的類庫嗎?不是!而是因為使用類庫并不很方便而且不靈活。

            OK,讓我們開始我們游戲編程的第二部——DirectInput編程。

            前面講 DirectDraw 時,并沒有提到,微軟是按 COM 來設計DirectX的,所以就有了一個 DIRECTINPUT 對象來表示輸入設備,而某個具體的設備由 DIRECTINPUTDEVICE 對象來表示。也許會感到很無奈,怎么游戲編程需要這么多的知識啊,其實您也無需煩惱,只要知道一下就可以了,其實這并不;影響您的設計,而且就算您不知道,也同樣可以駕馭DIRECTINPUT。

            實際的建立過程是先創建一個 DIRECTINPUT 對象,然后在通過此對象的 CreateDevice 方法來創建 DIRECTINPUTDEVICE 對象。

            #include <dinput.h>
            #defineDINPUT_BUFFERSIZE 16
            LPDIRECTINPUT lpDirectInput;
            // DirectInput 對象實際上是一個com對象
            LPDIRECTINPUTDEVICE lpKeyboard; // DirectInput 設備
            BOOL InitDInput(HWND hWnd)
            {
            ??????HRESULT hr;
            // 創建一個 DIRECTINPUT 對象
            ?????if( FAILED( hr = DirectInputCreate(hInstanceCopy, DIRECTINPUT_VERSION, &lpDirectInput, NULL)))
            ?????{
            // 失敗提示或處理
            ???????returnhr;
            ??????}
            // 創建一個 DIRECTINPUTDEVICE 界面
            //參數 GUID_SysKeyboard 指明了建立的是鍵盤對象

            ??????if( FAILED( hr = lpDirectInput->CreateDevice(GUID_SysKeyboard, &lpKeyboard, NULL)))
            ??????{

            ????????????// 失敗提示或處理
            ????????????returnhr;
            ???????}
            // 設定為通過一個 256 字節的數組返回查詢狀態值
            ??????if( FAILED(hr = lpKeyboard->SetDataFormat(&c_dfDIKeyboard)))
            ??????{

            ??????// 失敗提示或處理
            ????????????return hr;
            ??????}// 設定協作模式為獨占模式和前臺模式,獨占模式表面本程序在運行中占有所有鍵盤資源,而前臺模式指出當程序具有焦點時才可以占有鍵盤資源
            ??????if( FAILED( hr = lpKeyboard->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND)))
            ??????{

            ??????// 失敗提示或處理
            ????????????returnhr;
            ??????}

            ??????// 設定緩沖區大小
            ??????// 如果不設定,緩沖區大小默認值為 0,程序就只能按立即模式工作
            ??????// 如果要用緩沖模式工作,必須使緩沖區大小超過 0
            ??????// 在此,我們沒有必要設定,因為我們就用立即模式工作(還有一種緩沖模式),所有我們將其注調了

            ??????/* DIPROPDWORD property;

            ??????property.diph.dwSize = sizeof(DIPROPDWORD);
            ??????property.diph.dwHeaderSize = sizeof(DIPROPHEADER);
            ??????property.diph.dwObj = 0;
            ??????property.diph.dwHow = DIPH_DEVICE;
            ??????property.dwData = DINPUT_BUFFERSIZE;

            ??????if( FAILED(hr = lpKeyboard->SetProperty(DIPROP_BUFFERSIZE, &property.diph)))
            ??????{
            ??????// 失敗
            ????????????return FALSE;
            ??????}
            ??????*/

            ??????//此處是關鍵,我們要通過這個函數來鎖定鍵盤,記住,所有的DirectInput資源在使用前都要鎖定,在此即獲得鍵盤資源,在知識我們剛才設定的鍵盤模式才能起作用
            ??????hr = lpKeyboard->Acquire();
            ??????if FAILED(hr)
            ??????{

            ????????????// 失敗
            ????????????return FALSE;
            ??????}
            ??????returnTRUE;
            ??????}

            在這段代碼中,我們首先定義了 lpDirectInput 和 lpKeyboard 兩個指針,前者指向 DIRECTINPUT 對象,后者指向一個

            DIRECTINPUTDEVICE 界面。其順序就是這樣的。這和其它COM對象的使用方法都一樣,即先創建 COM 對象,然后創建界面,然后再獲得
            硬件資源,然后使用資源,然后釋放。

            通過 DirectInputCreate(), 我們為 lpDirectInput 創建了一個 DIRECTINPUT 對象。然后我們調用 CreateDevice 來建立一個DIRECTINPUTDEVICE 界面。
              
            完成這些工作以后,我們便調用 DIRECTINPUTDEVICE 對象的 Acquire 方法來激活對設備的訪問權限。在此要特別說明一點,任何一個

            DIRECTINPUT 設備,如果未經 Acquire,是無法進行訪問的。還有,當系統切換到別的進程時,必須用 Unacquire 方法來釋放訪問權限,在系統切換回本進程時再調用 Acquire 來重新獲得訪問權限。

            立即模式的數據查詢

            HRESULT ReadImmediateData( HWND hWnd )
            {
            ??????HRESULT hr;
            ??????BYTE diks[256];
            // 創建鍵盤狀態數據緩沖區存取鍵盤信息
            ??????inti; // 計數器
            ??????if( NULL == g_pKeyboard )
            ????????????returnS_OK;// 鍵盤狀態數據緩沖區清0
            ??????ZeroMemory( &diks, sizeof(diks) );// 獲得鍵盤所有鍵的信息,這只是檢查一次
            ??????hr = g_pKeyboard->GetDeviceState( sizeof(diks), &diks );
            ??????if( FAILED(hr) )
            ??????{

            ????????????// 如果鍵盤資源丟失,我們要重新獲得
            ????????????hr = g_pKeyboard->Acquire();
            ????????????while( hr == DIERR_INPUTLOST )
            ????????????hr = g_pKeyboard->Acquire();

            ????????????returnS_OK;
            ??????}
            // 進行一下輪循,處理鍵盤信息。
            ??????for( i = 0; i < 256; i++ )
            ??????{

            ????????????if( diks[i] & 0x80 ) //記錄此鍵的狀態,低字節最高位是 1 表示按下,0 表示松開,一般用 diks[i]&0x80 來測試
            ????????????{
            ??????????????????switch(i)
            ??????????????????{

            ??????????????????????????????//我們可以通過測試計數器i,來判斷是哪個鍵被按下了。
            ??????????????????????????????//我們提供幾個數據 UP:200 down:208 left:203 right:205 enter:28 space:57
            ??????????????????????????????//其實你可以用DirectX中的Samples\C++\DirectInput\Bin\Keyboard.exe程序來測試,只不過那是用
            ??????????????????????????????//16進制顯示的。
            ????????????????????????case200:
            ??????????????????????????????break;
            ????????????????????????case0xc8:
            ??????????????????????????????break;
            ??????????????????}
            ????????????}
            ??????}

            ??????returnS_OK;
            }

            請注意,上面的這段代碼只是一個示例,重在使你明白其原理,但并不能滿足游戲的需求,因為這其中只查詢了一次鍵盤的全部信息,做了一次輪循,而在游戲中要周期性地查詢,并輪循,這就需要你自己用Win32 API函數 SetTimer和 KillTimer 設置初始化 DirectInput 對象函數中在相應的地方設置計計時器,讓windows定時向程序發送 WM_TIMER消息,你要通過此消息進行周期性地鍵盤查詢,并在相應的地方解除計時器。

            最后一個函數是用于釋放指針或DirectInput對象的

            void ReleaseDInput(void)
            {

            ??????if(lpDirectInput)
            ??????{

            ????????????if(lpKeyboard)
            ????????????{

            ??????????????????// Always unacquire the device before calling Release().
            ??????????????????lpKeyboard->Unacquire();
            ??????????????????lpKeyboard->Release();
            ??????????????????lpKeyboard = NULL;
            ????????????}
            ????????????lpDirectInput->Release();
            ????????????lpDirectInput = NULL;
            ??????}
            }

            在這些函數中的注釋很明確,關鍵在于理解其原理,而怎樣將他們融入到 Win32 API 程序的基本框架中的,在<<動畫程序編寫——DirectDraw之旅>> 1-3中的示例代碼中已經解釋得很明確了,在此不再贅述。不過我們提供其中的代碼示例下載。同時你也可以去仔細閱讀DirectX 8.0 SDK 包中的 samples\ multimedia\ directdraw\ fullscreenmode\ samples\ multimedia\ directdraw\ windowedmode 這兩個工程中的文件,因為為了我們的示例也是照這兩個工程改編過來的,讀者可以通過仔細閱讀代碼和對比我們的更改,而更加了解 DirectDraw的運行運行原理。(請注意:是 DirectX 8.0 SDK 包中的示例,而在 9.0 中 DirectX SDK 已經不提供 DirectDraw的示例代碼了)

            我們就用這七個函數就已經可以創造出一個小游戲了。

            我們下面就要利用<<動畫程序編寫——DirectDraw之旅>> 1-3 中所用的代碼進行進一部的游戲開發。
            我們先展示一下 DirectX中\ samples\ multimedia\ directdraw\ windowedmode 工程中的截圖
            在這個動畫中有黑色背景,并有很多 DirectX 精靈在漂浮。



            這是一個全屏的動畫程序,而我們在<<動畫程序編寫——DirectDraw之旅>> 1-3其中做的改動就是為其加了一個背景,改屏幕分辨率 640×480 為 1024×768.注意,因為我們應用的是全屏模式,即可以獨占顯存資源,所以我們可以更改屏幕的分辨率。這只是做的小小的改動,而我們的目的只在于讓大家更加深入了解。且看下面的這副截圖:

            而我們還要繼續深入編程,我們的思路是,先將程序由先前的全屏程序改編成一個windows的窗口程序,然后將其所有的界面翻新,并改編 DirectX精靈為許多小蘑菇在漂浮,還要加入DirectInput 的組建,用鍵盤控制一個小娃娃。可以上下左右,并可以斜向飛行。
            我們先將此動畫的截圖展現給大家

            怎么樣,你有什么想法,是想說:“唉,這還不好辦,就是又多加了一個!”,但不要光看截圖,不要忘記,我們一定讓她動起來,并且是可以控制的,這就不是那么簡單的事了!
            什么?若有人看到這里感到有些迷茫和泄氣,不禁想問:“你說了這么多,那么源代碼在那里呢!,光給我們幾個函數,又能做什么呢?”,如果你這么想,你也不要太急迫。我們還是先分析一下程序框架吧。

            不過,還有一件重要的事情,我還是要重申一邊。一定要將 DirectX 的頭文件價,和lib文件夾加入到 Visual C++.NET 的默認目錄中去,這樣編譯器就可以正確地找到它們了。
            如果你不會加入,就請通過工具欄上的 Tool -> Option… 打開Option 對話框,設置如圖:



            好了,這樣我們的準備工作就算已經做好了。

            來看看我們的工程文件結構吧,還有工程中的資源。

            在工程資源中我們的 ID 號是都用的字符串表示的,筆者認為這樣更加方便。
            我想對于工程文件中的 ddutil.cpp 和 dxutil.cpp 文件,讀者如果了解有些 DirectDraw編程是不會感到陌生的,我們只是將其引入到我們的工程中了。而我們自己實際編程的文件是
            outfly.cpp 文件。

            我們的程序敘述如下:
            首先進行宏定義,結構設置,和全局變量的聲明。
            后在 WinMain (windows程序的入口點)中首先初始化一切需要初始化的物件(有windows窗口,DirectDraw對象,和 DirectInput對象),在此我們就調用前文講過的函數,但要有寫改動,讀者在會在后面看到的。然后進入消息循環,在其中沒有消息時,程序會自動更新畫面,在有消息時處理消息。
            當遇到 WM_QUIT 消息后,結束整個程序。

            我們在一些地方有一些小小的改動,我們來看看吧。

            1 我們在 HRESULT InitDirectInput( HWND hWnd )
            函數中的開始加入了

            KillTimer( hWnd, 0 );
            FreeDirectInput();

            關掉上一次使用的計時器,并釋放 DirectInput 設備。
            而在最后加入了

            SetTimer( hWnd, 0, 1000 / 100, NULL );

            用來重新設置計時器。

            2 我們在主窗口的消息處理函數中加入了

            case WM_ACTIVATE: //當程序先失去焦點,而現在有重新得到焦點時,要重新鎖定鍵盤資源
            ??????if( WA_INACTIVE != wParam && g_pKeyboard )
            ??????{

            ????????????// Make sure the device is acquired, if we are gaining focus.
            ????????????g_pKeyboard->Acquire();
            ??????}

            ??????break;
            caseWM_TIMER: //因為設置了計時器所以要處理此消息
            ??????if( FAILED( ReadImmediateData( hWnd ) ) )
            ??????{
            ????????????KillTimer( hWnd, 0 );
            ????????????MessageBox( NULL, _T("Error reading input state. ")
            ????????????_T("The sample will now exit."),
            ????????????_T("Keyboard"), MB_ICONERROR | MB_OK );
            ??????}

            ??????break;
            caseWM_DESTROY:// Cleanup and close the app
            ??????FreeDirectDraw();
            ??????FreeDirectInput();
            // 釋放資源
            ??????PostQuitMessage( 0 );
            ??????return 0L;

            3 在HRESULT ReadImmediateData( HWND hWnd ) 函數中進行了這樣的處理,來時時改變小娃娃的坐標。

            for( i = 0; i < 256; i++ )
            {

            ??????if( diks[i] & 0x80 )
            ??????{

            ????????????switch(i)
            ????????????{

            ??????????????????case200: //上鍵
            ????????????????????????if( g_me.fPosY > g_me.fVelY)
            ??????????????????????????????g_me.fPosY -= g_me.fVelY;

            ????????????????????????else
            ??????????????????????????????g_me.fPosY = 0;
            ????????????????????????break;
            ??????????????????case208: //下鍵
            ????????????????????????if( g_me.fPosY <= WINDOW_HEIGHT - SPRITE_DIAMETER - g_me.fVelY)
            ??????????????????????????????g_me.fPosY += g_me.fVelY;

            ????????????????????????else
            ??????????????????????????????g_me.fPosY = WINDOW_HEIGHT- SPRITE_DIAMETER;
            ????????????????????????break;
            ??????????????????case203://左鍵
            ????????????????????????if( g_me.fPosX > g_me.fVelX)
            ??????????????????????????????g_me.fPosX -= g_me.fVelX;

            ????????????????????????else
            ??????????????????????????????g_me.fPosX = 0;
            ????????????????????????break;
            ??????????????????case205://右鍵
            ????????????????????????if( g_me.fPosX <= WINDOW_WIDTH - SPRITE_DIAMETER - g_me.fVelX)
            ??????????????????????????????g_me.fPosX += g_me.fVelX;

            ????????????????????????else
            ??????????????????????????????g_me.fPosX = WINDOW_WIDTH- SPRITE_DIAMETER;
            ????????????????????????break;
            ????????????}
            ??????}
            }

            這些只是其中一些比較重要的改動,還有許多改動,讀者會在實際的程序中看到的。如果你覺得:“啊!到這里就結束了,可是我還是感到似乎莫不到頭緒,就這樣草草收尾了?”,其實文章并沒有結束,重頭戲還在后面呢,那就不是我的工作了,而是看你有沒有耐心去仔細閱讀代碼了,因為想要把握程序的整體,與其讓我將代碼放在文章中,還不如讀者自己在編譯器中自己運行實踐一下好,其實我們已經在第二個工程代碼中有過詳細的解釋。但記住一定要按照順序閱讀 工程1,工程2 ,工程3。工程1就是 DirectX中提供的原代碼,工程2就是我們改了一個背景的工程,而3就是我們討論的工程。

             

            放飛技術網?

            posted on 2006-06-20 15:26 楊粼波 閱讀(302) 評論(0)  編輯 收藏 引用 所屬分類: 文章收藏

            久久久国产亚洲精品| 国产成人精品综合久久久| 婷婷伊人久久大香线蕉AV| 亚洲伊人久久成综合人影院| 精品久久久久久国产三级| 美女写真久久影院| 久久成人影院精品777| 国内精品久久久久影院免费| 久久久久久国产精品免费无码| 中文字幕日本人妻久久久免费| 亚洲香蕉网久久综合影视| 日产精品久久久久久久性色| 亚洲AV无码久久精品蜜桃| 久久久久亚洲av无码专区| 国内精品久久久久影院优| 国产精品久久网| 国产精品xxxx国产喷水亚洲国产精品无码久久一区 | 欧美久久一级内射wwwwww.| 久久精品国产亚洲av瑜伽| 亚洲国产香蕉人人爽成AV片久久| 亚洲精品WWW久久久久久| 国内精品综合久久久40p| 国产Av激情久久无码天堂| 久久精品嫩草影院| 久久综合九色综合久99| 国内精品久久久久久久久电影网| 亚洲精品无码久久千人斩| 久久精品国产精品青草| 久久人妻少妇嫩草AV蜜桃| 97久久国产露脸精品国产| 久久99国产精品久久| 性做久久久久久久久老女人 | 久久最新免费视频| 亚洲国产精品无码久久一线| 久久亚洲高清观看| 久久天天躁夜夜躁狠狠| 久久最新精品国产| 无码人妻久久一区二区三区 | 精品久久久久久成人AV| 久久免费视频一区| 丁香五月网久久综合|