青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當自強而不息

【ZT】DirectInput里的鍵盤鼠標的應用

設計一個PC游戲,鍵盤鼠標的輸入是絕不能少。Windows也提供了諸如 WM_LBUTTONDOWN、WM_RBUTTONUP等鼠標消息以及WM_KEYDOWN、WM_KEYUP等鍵盤輸入消息。但是 DirectInput中仍然提供了對鼠標鍵盤的支持,其原因就是DirectInput提供一個更直接更快捷的對輸入設備的訪問方法。就象我們在DOS 下直接接管鍵盤中斷,而不是去用什么討厭的INT16來處理鍵盤輸入一樣(用INT16來處理鍵盤輸入其弊端在《金庸群俠傳》中顯得尤為明顯,人物在走路 之前總要頓那么一下,就是這一下讓我覺得非常之不爽!其原因我想我也不用羅嗦了)。

  當然Windows的鍵盤消息比之INT16當然有了長足的進步(因為它提供了一 個WM_KEYUP消息),但是在某些方面仍顯不足。因為Windows的消息機制是一個緩沖(buffer)機制,未被處理的鍵盤鼠標消息都放在緩沖區 里等待下一次處理,這樣對于一些應用軟件是非常重要的,但是對游戲來說(特別是一些動作游戲,包括體育游戲)就顯得有蛇足之嫌了。舉個例子,在足球游戲 里,你去搶截對手的球——搶球和射門、鏟斷和長傳(大腳)總是設成同一個鍵,這好像是個公認的標準了——但這時剛好對手的球脫腳了,球直接就到了你的腳 下,這時你本來想帶球繞過他的,可是你的搶球鍵已經按過了,由于這個該死的緩沖機制,先要處理一下這個搶球鍵(也就是射門鍵),于是你的動作就變成了一次 盲目的后場遠射(等同于大腳解圍)了。控制不了自己的動作,做球員做到這個份兒上真是夠失敗的了。這里就是緩沖機制不適用的地方了。

  而DirectInput提供了緩沖和立即兩種訪問輸入設備的方式,對于立即方 式,正好就是解決上面弊病的方法。DirectInput里關于鍵盤的初始化部分,已經在很早以前的一篇文章里給出來了。雖是針對于DirectX7的, 但關于DirectInput部分在DX8和DX7里差別不大,把LPDIRECTINPUT7換成LPDIRECTINPUT8、 LPDIRECTINPUTDEVICE7換成LPDIRECTINPUTDEVICE8就OK了,此外還有一點點需要改動的就是DirectInput 對象的創建,DX8里用的是下面這個函數:

DirectInput8Create(hInst, DIRECTINPUT_VERSION, IID_IDirectInput8,(LPVOID *)&lpDI, NULL);

  里面具體的參數大家看也看得出來,我就不多說了。

  下面說一下鼠標,鼠標的緩沖機制還是滿重要的,鼠標的移動就建立在滾動計數累積的 基礎上的。鼠標是每隔8ms采樣一次(反正USB鼠標是這樣,我估計一般鼠標也是一樣),要是只獲取當前狀態的話,那這個鼠標移動起來就太慢了(應該不會 有人在應用程序里每隔8ms就調用一次鼠標的狀態獲取函數吧)。之所以采用DirectInput,不是因為緩沖這個原因,而是因為一個我個人的喜好因 素。一般的游戲在卷屏時是判斷鼠標的位置是否在屏幕邊緣,如果是就向這一方向卷屏。我個人不是很喜歡這種做法,可能因為我手比較笨,玩游戲是經常莫名其妙 地畫面就移走了,這讓我覺得很成問題,為什么光標指到屏幕邊上就要卷屏?所以我希望鼠標的移動才是卷屏的依據,這在Windows的消息機制里就做不到 了。因為在Windows的消息機制里,當鼠標一到屏幕邊上時再向外移動,應用程序是收不到WM_MOUSEMOVE消息的。但在DirectInput 里就可以由我自己來實現,DirectInput接收到的只是鼠標的滾動計數,它可沒有什么光標位置的限制。

  下面就給出DirectInput鼠標對象的初始化代碼,只能這么一步步的來,沒什么好說的。


//=================================
LPDIRECTINPUT8  pDI;
LPDIRECTINPUTDEVICE8  lpMouse;

// 存放鼠標光標的Surface
LPDIRECT3DSURFACE8  lpDSCursor;
HANDLE  hMouseEvent;

//是有符號型,所以可以判斷光標是否移出屏幕來決定是否卷屏
short  MouseX = FULLSCREEN_WIDTH/2,MouseY =FULLSCREEN_HEIGHT/2;

bool InitInput()
{
    HRESULT   hres;
    hres 
= DirectInput8Create(hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID *)&lpDI, NULL);
    
if(FAILED(hres))
        
return FALSE;

    hres 
= lpDI->CreateDevice(GUID_SysMouse, &lpMouse,NULL);
    
if(FAILED(hres))
        
return FALSE;

    hres 
= lpMouse->SetDataFormat(&c_dfDIMouse);
    
if(FAILED(hres))
        
return FALSE;

    hres 
= lpMouse->SetCooperativeLevel(hMainWnd,DISCL_EXCLUSIVE | DISCL_FOREGROUND);
    
if(FAILED(hres))
        
return FALSE;

    hMouseEvent 
= CreateEvent(NULL, FALSE, FALSE, NULL);
    
if(!hMouseEvent)
        
return FALSE;

    hres 
= lpMouse->SetEventNotification(hMouseEvent);
    
if(FAILED(hres))
        
return FALSE;

    DIPROPDWORD dipdw;
    dipdw.diph.dwSize 
= sizeof(DIPROPDWORD);
    dipdw.diph.dwHeaderSize 
= sizeof(DIPROPHEADER);
    dipdw.diph.dwObj 
= 0;
    dipdw.diph.dwHow 
= DIPH_DEVICE;
    dipdw.dwData 
= MOUSE_SAMPLEBUFFER;  // 預定義為16
    hres = lpMouse->SetProperty(DIPROP_BUFFERSIZE,&dipdw.diph);
    
if(FAILED(hres))
        
return FALSE;

    lpMouse
->Acquire();

    
return TRUE;
}


現在是我們完全接管了鼠標,那么無可非議的,鼠標光標的顯示任務也落到了我們頭上,不過在D3D8入門里我提到了,光標的顯示可以由D3D8支持。下面我們就來創建一個光標:

D3DLOCKED_RECT  dlr;
//光標的Surface只能是A8R8G8B8格式的,占了一個alpha字節又不支持半透明,真是shit 

hres 
= lpDevice->CreateImageSurface(3232, D3DFMT_A8R8G8B8,&lpDSCursor);
if(FAILED(hres))
    
return FALSE;

hres 
= lpDSCursor->LockRect(&dlr, NULL, 0);
if(FAILED(hres))
    
return FALSE;

// 往Surface里寫數據呀,不用我說了吧
………………
hres 
= lpDSCursor->UnlockRect();
hres 
= lpDevice->SetCursorProperties(00, lpDSCursor);
if(FAILED(hres))
    
return FALSE;

lpDevice
->ShowCursor(TRUE);

接下來就是鼠標數據的存取了,這里我只處理了鼠標的移動。

void MouseEvent()
{
    DIDEVICEOBJECTDATA od;
    HRESULT  hres;
    DWORD   count;
    
short   x = 0, y = 0;
    
while(1)
    {
        count 
= 1;
        hres 
=lpMouse->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &od,&count, 0);
        
if(hres == DIERR_INPUTLOST)
        {
            lpMouse
->Acquire();
            
return;
        }

        
if(FAILED(hres) || !count)
            
break;

        
switch(od.dwOfs)
        {
        
case DIMOFS_X:
            x 
+= (short)od.dwData;
            
break;
        
case DIMOFS_Y:
            y 
+= (short)od.dwData;
            
break;
        
//物理設備上左鍵或右鍵按下/釋放,如有左右鍵交換可是要自己判斷的
        case DIMOFS_BUTTON0:
        
case DIMOFS_BUTTON1:
            
if(od.dwData & 0x80)
            
// 鍵按下
            …………
        
else
            
// 鍵釋放
            …………    
        }
    }

    
if(x || y)
    {
        MouseX 
+= x;
        MouseY 
+= y;
        
// 決定光標的位置以及是否卷屏等等
        …………
        lpDevice
->SetCursorPosition(MouseX, MouseY,D3DCURSOR_IMMEDIATE_UPDATE);
    }
}

  好了,現在算是完了。但是我個人覺得有一點小小的缺憾,大家如果試一下就會發現,鼠標移動的總比Windows下慢一些,這是為什么?我在Windows的鼠標設置里看到一個加速選項,覺得可能是由于這個原因。那就模擬一下了。(以下只列出上面函數的改動部分)

short  xaccel,yaccel;
xaccel 
= yaccel = 1;

while(1)
{
    …………
    
switch(od.dwOfs)
    {
    
case DIMOFS_X:
        x 
+= (short)od.dwData*xaccel;
        xaccel
++;
        
break;
    
case DIMOFS_Y:
        y 
+= (short)od.dwData*yaccel;
        yaccel
++;
        
break;
        …………
    }
    ………
}

      經過這樣改動后,鼠標再移動起來果然順暢了很多。

  此外,DIDEVICEOBJECTDATA結構中還有一個時間標記,用這個可以 判斷鼠標的雙擊,現在我們的鼠標模擬已經初具雛形。自己接管鼠標后,就可以定義方便自己的消息比如什么拖動啦(在Windows下判斷拖動就是煩,自己定 義一個)、三擊啦什么的,好處是不言而喻的,當然也帶來了壞處——就是編寫的代碼就多了,不過這就是游戲程序員的職責呀。

posted on 2007-05-06 17:17 lovedday 閱讀(646) 評論(0)  編輯 收藏 引用 所屬分類: ■ DirectX 9 Program

公告

導航

統計

常用鏈接

隨筆分類(178)

3D游戲編程相關鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲黄色av| 久久国产精品毛片| 性色av一区二区三区红粉影视| 亚洲精品久久久一区二区三区| 在线电影欧美日韩一区二区私密| 国产综合欧美| 亚洲精品1234| 在线视频中文亚洲| 性感少妇一区| 久久综合综合久久综合| 亚洲国产99精品国自产| a4yy欧美一区二区三区| 中文在线资源观看网站视频免费不卡 | 亚洲免费一级电影| 久久av资源网站| 蜜臀va亚洲va欧美va天堂 | 久久噜噜亚洲综合| 欧美国产精品va在线观看| 欧美日韩一区二区视频在线| 国产欧美日本在线| 亚洲激情不卡| 性欧美xxxx视频在线观看| 老司机凹凸av亚洲导航| 99热免费精品在线观看| 欧美在线一二三四区| 欧美激情偷拍| 国产亚洲人成a一在线v站| 99精品99| 久久久久久黄| 一区二区三区免费网站| 麻豆国产精品一区二区三区 | 国产精品综合网站| 亚洲人成艺术| 久久久久久久国产| 中国成人黄色视屏| 欧美风情在线| 韩国成人理伦片免费播放| 亚洲视频自拍偷拍| 亚洲国产精品电影| 亚洲欧美日韩综合国产aⅴ| 欧美国产精品日韩| 红桃视频一区| 久久国产夜色精品鲁鲁99| 亚洲免费观看在线视频| 免费成人在线观看视频| 一区在线观看视频| 久久亚洲综合色一区二区三区| 亚洲一区二区三区精品在线| 欧美性一二三区| 亚洲一区二区毛片| 亚洲最快最全在线视频| 欧美日韩国产91| 夜夜嗨av一区二区三区中文字幕| 欧美国产欧美亚州国产日韩mv天天看完整| 欧美一区二区三区男人的天堂| 国产精品一区二区在线观看网站 | 欧美夜福利tv在线| 亚洲高清在线视频| 久久成年人视频| 日韩视频二区| 欧美日韩国产免费| 99视频日韩| 亚洲精品久久久久久下一站| 夜夜爽99久久国产综合精品女不卡| 久久精品国产77777蜜臀| 亚洲免费不卡| 欧美日韩国内自拍| 亚洲国产精品久久久久婷婷884| 欧美亚洲尤物久久| 一本一本久久a久久精品综合麻豆| 久久综合久久综合久久| 毛片一区二区三区| 亚洲经典在线看| 久久久夜精品| 欧美中文字幕在线播放| 国产欧美日韩亚洲精品| 午夜免费在线观看精品视频| 亚洲裸体视频| 欧美日韩日本国产亚洲在线 | 午夜一区在线| 国产农村妇女精品| 性娇小13――14欧美| 亚洲一区二区三| 欧美日本国产精品| 一本色道久久综合狠狠躁篇怎么玩| 亚洲国产成人精品女人久久久| 久久久久国产精品人| 黄色小说综合网站| 欧美jizz19hd性欧美| 久久久久久夜| 激情一区二区三区| 欧美成人一区二区| 欧美精品免费播放| 亚洲天堂成人在线观看| 在线视频亚洲欧美| 国产亚洲成精品久久| 久久一区二区视频| 欧美专区18| 国产字幕视频一区二区| 欧美电影在线观看| 欧美日韩国产一区精品一区| 欧美色偷偷大香| 亚洲欧美日韩综合| 99国产麻豆精品| 久久视频国产精品免费视频在线| 亚洲免费视频成人| 国产精品美女久久久久av超清| 一区二区在线视频播放| 免费永久网站黄欧美| 欧美成人高清| 国内精品国语自产拍在线观看| 亚洲国产精品黑人久久久| 欧美日韩蜜桃| 久久精品一区二区三区中文字幕| 香蕉免费一区二区三区在线观看 | 欧美激情第10页| 国产精品视频网| 美女尤物久久精品| 欧美日精品一区视频| 久久精品欧美日韩| 久久国产福利| 亚洲制服少妇| 性刺激综合网| 亚洲第一搞黄网站| 一区二区三区免费在线观看| 激情欧美一区二区| 亚洲私人影院在线观看| 亚洲第一精品影视| 性欧美长视频| 亚洲久色影视| 99视频在线观看一区三区| 国产一区二区三区高清| 亚洲美女免费精品视频在线观看| 精品成人国产| 性色av一区二区三区在线观看| 久久亚洲精品网站| 一区二区三区视频在线播放| 国产精品久久激情| 欧美激情国产高清| 国产亚洲在线观看| 一区二区av在线| 亚洲精品乱码久久久久久蜜桃麻豆 | 国产自产2019最新不卡| 一区二区三区国产| 亚洲国产乱码最新视频| 欧美在线中文字幕| 久久久久久9| 国产一区二区久久精品| 欧美亚洲一区二区在线观看| 香蕉国产精品偷在线观看不卡| 欧美日韩三级| 一本久道久久综合婷婷鲸鱼| 99精品视频免费全部在线| 欧美国产综合| 999亚洲国产精| 亚洲乱码一区二区| 欧美精品日韩综合在线| 欧美黄色aa电影| 亚洲欧洲在线观看| 欧美激情精品久久久久久黑人| 亚洲国产裸拍裸体视频在线观看乱了中文 | 国产又爽又黄的激情精品视频| 一本久久a久久精品亚洲| 亚洲天堂av在线免费观看| 欧美日韩第一页| 在线视频欧美日韩| 久久久美女艺术照精彩视频福利播放| 国产精品久久久久久五月尺| 亚洲麻豆av| 亚洲国产影院| 欧美日韩国产一区二区三区| 免费看的黄色欧美网站| 日韩天堂在线观看| 欧美日韩亚洲一区在线观看| 9l国产精品久久久久麻豆| 亚洲先锋成人| 久久久福利视频| 女仆av观看一区| 伊人久久大香线| 欧美激情a∨在线视频播放| 欧美日韩在线一区二区三区| 亚洲精品网址在线观看| 亚洲与欧洲av电影| 国产精品午夜久久| 免播放器亚洲一区| 一区二区三区视频在线播放| 欧美成人免费在线视频| 国产在线精品一区二区夜色| 欧美激情综合五月色丁香小说| 欧美黄色aa电影| 亚洲日本一区二区| 欧美日韩一视频区二区| 欧美一区二区三区在线看| 欧美国产国产综合| 亚洲一区二区在线| 亚洲国产精品电影| 国产精品一区二区久久久久| 久久国产精品久久国产精品| 亚洲精品久久久久| 久久视频这里只有精品|