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

天行健 君子當自強而不息

【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>
            欧美一区二区国产| 欧美激情亚洲另类| 免费观看一区| 欧美a级在线| 国产在线欧美日韩| 久久久噜久噜久久综合| 亚洲综合色视频| 久久久久久久网站| 亚洲国产精品久久人人爱蜜臀| 国产一区二区三区四区老人| 国产精品综合不卡av| 久久国产精品99国产| 亚洲国产一区在线| 一区二区三区在线不卡| 黑人巨大精品欧美一区二区小视频| 欧美成人午夜视频| 亚洲美女av网站| 乱中年女人伦av一区二区| 国产伦精品一区二区三区高清| 国产精品一区=区| 欧美精品网站| 免费亚洲电影在线观看| 99视频国产精品免费观看| 亚洲二区在线观看| 亚洲天堂男人| 一区二区三区四区蜜桃| 欧美片第一页| 亚洲国产欧美不卡在线观看| 欧美成人激情在线| 久久久夜精品| 欧美一区二区三区婷婷月色| 亚洲午夜极品| 欧美一区亚洲| 欧美在线播放视频| 欧美在线免费观看| 99热在线精品观看| 亚洲香蕉网站| 欧美日韩一区二| 欧美影院成人| 欧美肉体xxxx裸体137大胆| 国产精品久久久久高潮| 欧美成人性网| 亚洲一级黄色片| 一区二区三区精品国产| 亚洲伦伦在线| 日韩亚洲精品在线| 在线午夜精品自拍| 亚洲一区二区伦理| 亚洲尤物在线| 国产午夜精品理论片a级大结局 | 极品尤物一区二区三区| 国产三区精品| 久久综合免费视频影院| 欧美第一黄网免费网站| 欧美精品在线观看| 国产精品网站一区| 亚洲国产精品欧美一二99| 国产日韩在线视频| 99视频精品全部免费在线| 亚洲亚洲精品三区日韩精品在线视频 | 亚洲国产三级在线| 国产精品99久久久久久久久久久久| 国产伦一区二区三区色一情| 国产精品免费一区二区三区在线观看| 国产精品va在线播放| 国产欧美成人| 亚洲国产精品久久| 国产精品色在线| 精品成人国产在线观看男人呻吟| 在线观看亚洲| 亚洲一区自拍| 久久精品一区四区| 国产精品久久一区二区三区| 伊人久久大香线| 亚洲性色视频| 在线免费观看一区二区三区| 欧美成人69av| 亚洲韩国青草视频| 在线播放日韩专区| 久久性天堂网| 99re热精品| 欧美日韩在线播放一区二区| 亚洲综合视频1区| 亚洲视频免费看| 亚洲图片欧洲图片av| 国产精品黄视频| 久久国产综合精品| 亚洲国产精品一区二区尤物区| 欧美 日韩 国产一区二区在线视频 | 午夜精品亚洲一区二区三区嫩草| 欧美成人小视频| 欧美国产丝袜视频| 99pao成人国产永久免费视频| 正在播放欧美视频| 尤物yw午夜国产精品视频明星| 欧美美女bbbb| 欧美在线观看网站| 美女成人午夜| 欧美在线视频一区| 欧美大片免费观看| 久久精品人人做人人爽| 农村妇女精品| 99精品国产福利在线观看免费| 美女视频黄免费的久久| 日韩香蕉视频| 亚洲欧美一区在线| 亚洲日本精品国产第一区| 久久国产直播| 国产在线不卡| 亚洲精选一区二区| 国产婷婷一区二区| 亚洲人成精品久久久久| 亚洲午夜电影在线观看| 亚洲国产精品欧美一二99| 亚洲欧美精品| 日韩视频在线免费| 久久亚洲午夜电影| 欧美在线免费播放| 亚洲国产精品综合| 久久精品二区亚洲w码| 亚洲免费视频在线观看| 欧美好骚综合网| 久久久久一区二区三区四区| 欧美三日本三级少妇三2023 | 亚洲精品一区二区三区婷婷月| 性高湖久久久久久久久| 一区二区三区久久网| 麻豆精品在线观看| 美日韩精品免费观看视频| 国产日韩亚洲| 久久狠狠久久综合桃花| 久久黄色小说| 国产美女诱惑一区二区| 亚洲免费视频成人| 免费看的黄色欧美网站| 狼狼综合久久久久综合网| 国产亚洲欧美另类一区二区三区| 亚洲一级黄色av| 久久大香伊蕉在人线观看热2| 国产精品久久久久av| 亚洲一区二区免费看| 午夜久久tv| 国产日韩一区在线| 久久九九国产精品| 欧美国产亚洲精品久久久8v| 最近看过的日韩成人| 欧美激情一区二区三区蜜桃视频| 亚洲国产精品悠悠久久琪琪| 亚洲精品视频在线| 欧美视频一区二区三区…| 国产精品99久久久久久白浆小说| 亚洲一区二区伦理| 国产午夜精品久久久久久久| 久久精品成人| 亚洲精品黄网在线观看| 亚洲一区二区三区色| 国产欧美日韩亚州综合| 久久精品2019中文字幕| 欧美大香线蕉线伊人久久国产精品| 在线成人欧美| 欧美日韩一级视频| 久久av一区二区三区漫画| 美女精品在线观看| 一本色道久久综合亚洲精品按摩| 国产精品电影网站| 欧美影院在线| 亚洲国产精品一区二区三区| 久久av一区二区| 夜色激情一区二区| 国产精品国产三级国产普通话99 | 一本色道久久88亚洲综合88| 亚洲精品欧美日韩| 国产精品黄页免费高清在线观看| 欧美在线日韩在线| 日韩午夜中文字幕| 久久久久综合一区二区三区| 在线播放不卡| 欧美视频一区二区三区在线观看| 亚洲午夜av电影| 欧美激情一区二区三区四区| 一区二区三区视频免费在线观看| 国产精品视频免费观看www| 久久综合久久综合这里只有精品 | 久久久xxx| 中文有码久久| 欧美肥婆在线| 亚洲欧美日韩在线高清直播| 亚洲福利视频一区二区| 国外成人在线视频| 欧美日韩一区在线| 久久婷婷国产综合国色天香| 亚洲剧情一区二区| 久久一区二区三区四区| 欧美专区18| 欧美高清影院| 久久在线免费视频| 亚洲欧美一区二区视频| 最新日韩av| 亚洲国产1区| 影音先锋中文字幕一区|