• <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>

            天行健 君子當自強而不息

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

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

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

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

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

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

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

              下面就給出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;
            }


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

            D3DLOCKED_RECT  dlr;
            //光標的Surface只能是A8R8G8B8格式的,占了一個alpha字節(jié)又不支持半透明,真是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里寫數(shù)據(jù)呀,不用我說了吧
            ………………
            hres 
            = lpDSCursor->UnlockRect();
            hres 
            = lpDevice->SetCursorProperties(00, lpDSCursor);
            if(FAILED(hres))
                
            return FALSE;

            lpDevice
            ->ShowCursor(TRUE);

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

            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);
                }
            }

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

            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;
                    …………
                }
                ………
            }

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

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

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

            公告

            導航

            統(tǒng)計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            久久99这里只有精品国产| 久久96国产精品久久久| 久久久久亚洲国产| 狠狠色丁香久久婷婷综合蜜芽五月 | 久久久久久av无码免费看大片| 久久国产免费| 亚洲午夜久久久影院伊人| 久久夜色精品国产噜噜噜亚洲AV| 国产亚洲色婷婷久久99精品| 久久九色综合九色99伊人| 亚洲精品高清国产一线久久| 99久久婷婷免费国产综合精品| 久久精品成人免费观看97| 亚洲人成无码www久久久| 国产成人久久精品区一区二区| 久久精品亚洲欧美日韩久久| 亚洲国产精品无码久久一线| 国产精品免费久久| 国内精品久久久久影院优| 色婷婷久久综合中文久久一本| 99精品国产在热久久| 无码8090精品久久一区| 99久久久久| 久久久久久a亚洲欧洲aⅴ| 精品久久亚洲中文无码| 日韩电影久久久被窝网| 国产成人久久激情91| 无码人妻精品一区二区三区久久久 | 国产精品欧美久久久久无广告| 久久精品一区二区三区AV| 精品久久综合1区2区3区激情| 国产精品视频久久| 久久免费视频观看| 91精品国产综合久久婷婷| av色综合久久天堂av色综合在 | 武侠古典久久婷婷狼人伊人| 亚洲午夜久久久精品影院| 国产精品视频久久久| …久久精品99久久香蕉国产| 精品久久久无码人妻中文字幕豆芽| 97久久国产露脸精品国产|