• <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ū) 里等待下一次處理,這樣對于一些應用軟件是非常重要的,但是對游戲來說(特別是一些動作游戲,包括體育游戲)就顯得有蛇足之嫌了。舉個例子,在足球游戲 里,你去搶截對手的球——搶球和射門、鏟斷和長傳(大腳)總是設成同一個鍵,這好像是個公認的標準了——但這時剛好對手的球脫腳了,球直接就到了你的腳 下,這時你本來想帶球繞過他的,可是你的搶球鍵已經按過了,由于這個該死的緩沖機制,先要處理一下這個搶球鍵(也就是射門鍵),于是你的動作就變成了一次 盲目的后場遠射(等同于大腳解圍)了。控制不了自己的動作,做球員做到這個份兒上真是夠失敗的了。這里就是緩沖機制不適用的地方了。

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

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

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

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


            現(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里寫數據呀,不用我說了吧
            ………………
            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);
                }
            }

              好了,現(xiàn)在算是完了。但是我個人覺得有一點小小的缺憾,大家如果試一下就會發(fā)現(xiàn),鼠標移動的總比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結構中還有一個時間標記,用這個可以 判斷鼠標的雙擊,現(xiàn)在我們的鼠標模擬已經初具雛形。自己接管鼠標后,就可以定義方便自己的消息比如什么拖動啦(在Windows下判斷拖動就是煩,自己定 義一個)、三擊啦什么的,好處是不言而喻的,當然也帶來了壞處——就是編寫的代碼就多了,不過這就是游戲程序員的職責呀。

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

            公告

            導航

            統(tǒng)計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            日本欧美久久久久免费播放网 | 久久一区二区三区免费| 伊人久久综在合线亚洲2019| 91精品国产91热久久久久福利| 久久精品国产99久久久香蕉| 精品无码久久久久国产动漫3d | 亚洲欧洲久久久精品| 久久久久久久精品妇女99| 国产91色综合久久免费| 亚洲国产婷婷香蕉久久久久久| 亚洲国产精品无码久久久不卡 | 久久精品国产欧美日韩| 精品久久久无码21p发布| 狠狠久久亚洲欧美专区| 一本色道久久综合| 久久免费视频观看| 无码人妻久久一区二区三区免费丨| 久久福利青草精品资源站| 99久久国产亚洲综合精品| 91久久香蕉国产熟女线看| 亚洲级αV无码毛片久久精品 | 久久婷婷五月综合97色一本一本 | 精品国产福利久久久| 婷婷国产天堂久久综合五月| 欧美一区二区精品久久| 久久综合给久久狠狠97色| 久久综合成人网| 久久久久九国产精品| 国内精品伊人久久久久| 久久久一本精品99久久精品66| 中文字幕无码久久久| 久久亚洲精品无码播放| 久久久久99精品成人片| 亚洲国产天堂久久综合网站| 久久人人爽人人爽人人AV东京热| 性做久久久久久久久浪潮| 欧美性猛交xxxx免费看久久久| 丰满少妇人妻久久久久久4| 大美女久久久久久j久久| 久久久久久久国产免费看| 欧美午夜精品久久久久久浪潮|