• <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游戲編程相關鏈接

            搜索

            最新評論

            中文无码久久精品| 久久久久久久久久免免费精品| 国产成人久久精品麻豆一区| 香蕉久久一区二区不卡无毒影院| 激情久久久久久久久久| 久久精品aⅴ无码中文字字幕不卡| 精品一区二区久久| 久久久国产精品| 日韩AV无码久久一区二区| 亚洲Av无码国产情品久久| 色综合色天天久久婷婷基地| 久久香蕉国产线看观看精品yw| 青青草国产精品久久| 亚洲人成无码网站久久99热国产 | 久久久无码精品午夜| 久久狠狠一本精品综合网| 一本一本久久aa综合精品| 国产精品免费久久| 97久久精品无码一区二区| 成人国内精品久久久久一区| 亚洲欧美日韩中文久久| 久久亚洲中文字幕精品有坂深雪| 久久精品国产一区二区 | 无码任你躁久久久久久久| 久久精品国产99久久久| 99精品国产99久久久久久97| 色偷偷91久久综合噜噜噜噜| 久久av免费天堂小草播放| 国产国产成人久久精品| 久久久久亚洲av无码专区导航| 少妇人妻综合久久中文字幕| 久久亚洲精品国产亚洲老地址 | 99精品久久精品| 久久国产免费直播| 久久99精品国产麻豆| 97久久久久人妻精品专区| 国内精品九九久久久精品| 好久久免费视频高清| 1000部精品久久久久久久久| 色欲久久久天天天综合网| 久久天天躁狠狠躁夜夜96流白浆|