第十二章键盘与鼠标输入_第1页
第十二章键盘与鼠标输入_第2页
第十二章键盘与鼠标输入_第3页
第十二章键盘与鼠标输入_第4页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、DirectX TutorialsBy Andy Pike第十二章:键盘与鼠标输入Introduction (序)这一章我们将会创建一个简单的、可以被用户控制的地球模型。用户将可以通过鼠标来控制它的位置,通过键盘控制它的尺寸和旋转。DirectInput 我们一直在用Direct3D来绘制3D对象,现在,我们想给程序增加一些与用户交互的功能,这得靠DirectInput。DirectInput允许我们从任何输入设备读取数据,鼠标、键盘或是游戏操纵杆,我们能用这些数据来改变场景中的元素。在此教程中,我们只会接触到键盘与鼠标,我们会在将来的教程中接触游戏操纵杆。在我们的程序中,要增加与用户交互的功

2、能我们需要完成以下步骤:o 初始化DirectInput o 设置键盘o 设置鼠标o 在每一帧,得到键盘与鼠标的当前状态并借以修改场景o 程序结束时清理DirectInputInclude and Library files (头文件与库文件)首先我们必须要做的,就是在项目中增加一些头文件与库文件,这很简单,不是吗?o dinput.h o dinput8.lib o dxguid.lib The Controls (控制方案)此章例子的控制方案如下:o 上键:地球放大o 下键:地球缩小o 左键:增加地球的向左旋转o 右键:增加地球的向右旋转o 鼠标移动:改变地球的位置o 鼠标左键:停止地球旋

3、转o 鼠标右键:默认的旋转方式 Initialising DirectInput (初始化DirectInput)首先我们得初始化DirectInput,为此我们增加了一个新的函数InitialiseDirectInput,它会在CGame: Initialise中被调用。下面这一小段代码用于创建DirectInput对象以待用:/Create the DirectInput objectif(FAILED(DirectInput8Create(hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void*)&m_pDirectInput, NULL

4、) LogError(Unable to create DirectInput interface.); return false;else LogInfo(DirectInput interface created OK); 第一个参数是我们从WinMain函数获得的应用程序实例句柄;第二个参数是DirectInput的版本,用DIRECTINPUT_VERSION代表当前的版本(输入其它版本导致Dinput模拟那个版本);第三个是想要的接口,我们这里就用IID_IDirectInput8;第四个是最重要的,它会返回DInput对象的接口指针已待用;第五个我们不用理它,输入NULL就对了。m

5、_pDirectInput是CGame的一个LPDIRECTINPUT8型的成员变量,当然是DInput对象的接口指针了。Setting up the keyboard (设置键盘)创建好DirectInput对象之后我们就可以设置键盘了。下面是设置键盘的代码,我会在后面逐渐地解释它们。/KEYBOARD =/Create the keyboard device objectif(FAILED(m_pDirectInput-CreateDevice(GUID_SysKeyboard, &m_pKeyboard, NULL) CleanUpDirectInput(); LogError(Unab

6、le to create DirectInput keyboard device interface.); return false; else LogInfo(DirectInput keyboard device interface created OK.);/Set the data format for the keyboardif(FAILED(m_pKeyboard-SetDataFormat(&c_dfDIKeyboard) CleanUpDirectInput(); LogError(Unable to set the keyboard data format.); retur

7、n false; else LogInfo(Set the keyboard data format OK.);/Set the cooperative level for the keyboardif(FAILED(m_pKeyboard-SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE) CleanUpDirectInput(); LogError(Unable to set the keyboard cooperative level.); return false;else LogInfo(Set the k

8、eyboard cooperative level OK.);/Acquire the keyboardif(m_pKeyboard) m_pKeyboard-Acquire(); 首先,我们需要调用CreateDevice函数来创建一个键盘设备。第一个参数是一个GUID(全局唯一标识),这里我们输入GUID_SysKeyboard这个预定义的标识即可;第二个参数用于返回设备的指针,我们把它定义为CGame的成员变量了;最后一个参数我们还是不用理它,输入NULL就行了。然后要做的是设置键盘设备的数据格式,这需要调用SetDataFormat函数,并输入预定义的c_dfDIKeyboard。然后

9、,我们还需要设置协作等级。这需要调用SetCooperativeLevel函数,它的第二个参数由两部分构成,第一部分用于指定是前台访问还是后台访问(DISCL_FOREGROUND或DISCL_BACKGROUND),第二部分用于指定是独占还是非独占模式(DISCL_EXCLUSIVE或DISCL_NONEXCLUSIVE)。下面是这四个标识所代表的意义:DISCL_FOREGROUND:输入设备处于前台(有焦点)时可访问,处于后台时失去设备获取。DISCL_BACKGROUND:输入设备处于前台、后台时均可访问。DISCL_EXCLUSIVE:独占模式,一旦得到准许,在获取设备时其它程序便不

10、能独占此设备。DISCL_NONEXCLUSIVE:非独占模式,这时对该设备的访问将不会因其它应用程序对该设备的使用而受到干扰。 最后要做的是获取设备,通过设备的Acquire函数,这意味着我们有权读取设备的数据了。Setting up the mouse (设置鼠标)同样的,在使用鼠标之前我们也得设置它。下面是设置鼠标的源代码,你会发现它们跟设置键盘的代码差不多:/MOUSE =/Create the mouse device objectif(FAILED(m_pDirectInput-CreateDevice(GUID_SysMouse, &m_pMouse, NULL) CleanUp

11、DirectInput(); LogError(Unable to create DirectInput mouse device interface.); return false; else LogInfo(DirectInput mouse device interface created OK.);/Set the data format for the mouseif(FAILED(m_pMouse-SetDataFormat(&c_dfDIMouse) CleanUpDirectInput(); LogError(Unable to set the mouse data forma

12、t.); return false; else LogInfo(Set the mouse data format OK.);/Set the cooperative level for the mouseif(FAILED(m_pMouse-SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE) CleanUpDirectInput(); LogError(Unable to set the mouse cooperative level.); return false;else LogInfo(Set the mou

13、se cooperative level OK.);/Acquire the mouseif(m_pMouse) m_pMouse-Acquire(); 其实跟设置键盘差不多,有一点不同是我们这回输入给CreateDevice的GUID是系统预定的GUID_SysMouse了,这样就会返回一个鼠标设备的接口指针。另一点不同是设备数据格式,我们用了c_dfDIMouse(而不是原来的c_dfDIKeyboard),这是标准的鼠标数据格式。最后,我们设置了同样的协作等级并获取了鼠标设备。Buffered and Immediate Data (缓冲数据与即时数据)现在我们已经设置好鼠标和键盘了,我

14、们可以读取它们的数据了。我们可以读取两种类型的数据:缓冲数据和即时数据。顾名思义,缓冲数据就是在专用的缓冲区中存储的输入设备的数据,而即时数据就是指设备当前的状态,例如鼠标左键是被按下还是弹起。这两种数据都是有效的,而且经常被应用程序同时使用。例如,用缓冲数据来控测鼠标的移动,用即时数据来检测按键的操作。在此教程中我们只接触一下即时数据类型。Getting keyboard data (读取键盘数据)我们又有了一个新的函数ProcessKeyboard,它会在Render函数中被调用,这意味着在每一帧它都会被调用一次。下面是它的代码:void CGame:ProcessKeyboard() c

15、har KeyboardState256; if(FAILED(m_pKeyboard-GetDeviceState(sizeof(KeyboardState), (LPVOID)&KeyboardState) return; if(KEYDOWN(KeyboardState, DIK_ESCAPE) /Escape key pressed. Quit game. m_fQuit = true; /Rotate Earth if(KEYDOWN(KeyboardState, DIK_RIGHT) m_rRotate -= 0.5f; else if(KEYDOWN(KeyboardState,

16、 DIK_LEFT) m_rRotate += 0.5f; /Set an upper and lower limit for the rotation factor if(m_rRotate 20.0f) m_rRotate = 20.0f; /Scale Earth if(KEYDOWN(KeyboardState, DIK_UP) m_rScale += 0.5f; else if (KEYDOWN(KeyboardState, DIK_DOWN) m_rScale -= 0.5f; /Set an upper and lower limit for the scale factor i

17、f(m_rScale 20.0f) m_rScale = 20.0f; 这个函数真是简单明了。首先,我们调用了GetDeviceState函数并把当前的键盘状态填充到了一个字符数组中。然后,我们用了一个简单的宏KEYDOWN来检测我们感兴趣的按键是否费按下了。所以,就基于这几个按键,我们就能控制一些成员变量了(进而控制程序的运行)。#define KEYDOWN(name, key) (namekey & 0x80) Getting mouse data (读取鼠标数据)同样地,我们又有了一个函数ProcessMouse,也是在Render中被调用,下面是它的代码:void CGame:Pro

18、cessMouse() DIMOUSESTATE MouseState; if(FAILED(m_pMouse-GetDeviceState(sizeof(MouseState),(LPVOID)&MouseState) return; /Is the left mouse button down? if(MOUSEBUTTONDOWN(MouseState.rgbButtonsMOUSEBUTTON_LEFT) m_nMouseLeft = 1; else m_nMouseLeft = 0; /Is the right mouse button down? if(MOUSEBUTTONDOW

19、N(MouseState.rgbButtonsMOUSEBUTTON_RIGHT) m_nMouseRight = 1; else m_nMouseRight = 0; m_nMouseX += MouseState.lX; m_nMouseY += MouseState.lY;我们首先也是调用了GetDeviceState,用鼠标数据填充了一个DIMOUSESTATE型数据结构,它有四个成员:lX:此次与上次调用GetDeviceState的这段期间,x轴移动的距离。lY:此次与上次调用GetDeviceState的这段期间,y轴移动的距离。lZ:此次与上次调用GetDeviceState的

20、这段期间,轮移动的距离。rgbButtons:鼠标按键状态的数组。lX,lY和lZ返回此次与上次调用GetDeviceState的这段期间内所移动的设备单位距离(非像素距离)。如果你想得到鼠标在屏幕上的当前位置,可以调用GetCursorPos这个Win32 API函数。我们用MOUSEBUTTONDOWN这个宏来检测感兴趣的鼠标按键是否被按下。下面是我们定义的宏:#define MOUSEBUTTONDOWN(key) (key & 0x80)#define MOUSEBUTTON_LEFT 0#define MOUSEBUTTON_RIGHT 1#define MOUSEBUTTON_MI

21、DDLE 2Using the data (使用数据)在我们的Render3D函数中,我们用刚刚得到的键盘鼠标数据来变更场景。下面是Render3D的代码:void CGame:Render3D() /Render our 3D objects D3DXMATRIX matEarth, matScale, matRotate, matEarthRoll, matEarthMove; float rMouseSpeed = 20.0f; /If left mouse button is down, stop the earth from rotating if(m_nMouseLeft = 1)

22、 m_rRotate = 0.0f; /If right mouse button is down, start the earth rotating at default speed if(m_nMouseRight = 1) m_rRotate = 2.0f; m_rAngle += m_rRotate; /Create the transformation matrices D3DXMatrixRotationY(&matRotate, D3DXToRadian(m_rAngle); D3DXMatrixScaling(&matScale, m_rScale, m_rScale, m_r

23、Scale); D3DXMatrixRotationYawPitchRoll(&matEarthRoll, 0.0f, 0.0f, D3DXToRadian(23.44f); D3DXMatrixTranslation(&matEarthMove, (m_nMouseX / rMouseSpeed), -(m_nMouseY / rMouseSpeed), 0.0f); D3DXMatrixMultiply(&matEarth, &matScale, &matRotate); D3DXMatrixMultiply(&matEarth, &matEarth, &matEarthRoll); D3DXMatrixMultiply(&matEarth, &matEarth, &matEarthMove); /Render our obj

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论