带缓冲的鼠标、键盘操作,这里的鼠标、按键事件会被各自的监听器捕获。其中OIS中定义的两个类MouseListener,KeyListener负责对事件的处理。我们需要使用这两个类的接口。
当一个键被按下时,会触发一个 KeyListener::keyPressed 事件,而当这个键被释放(不再按下)时,KeyListener::keyReleased 事件被触发给所有已注册的KeyListener 类。
鼠标键被按下/释放的函数: MouseListener::mousePressed 和MouseListener::mouseReleased. 它还包含一个 mouseMoved 函数,当鼠标移动时调用它。
第一,和上一节不一样的就是,TutorialFrameListener的父类又增加了两个,如下
class TutorialFrameListener:public ExampleFrameListener,public OIS::MouseListener ,public OIS::KeyListener { public: TutorialFrameListener(RenderWindow *win,Camera *cam,SceneManager *sceneMgr) :ExampleFrameListener(win,cam,true,true)//第三个参数指明是否使用带缓冲的键盘输入,第四个参数指明是否使用带缓冲的鼠标输入 { mCamNode = cam->getParentSceneNode(); mSceneMgr = sceneMgr; mRotate = 0.13;//滚动常量 mMove = 250;//移动常量 mContinue = true;//继续渲染 mMouse->setEventCallback(this);//注册鼠标监听
mKeyboard->setEventCallback(this);//注册键盘监听
mDirection = Vector3::ZERO;//初始化为零
}
//其他代码 }
而且我们增加了两个成员变量,用于获取指代鼠标和键盘。
第二,同样需要在每一帧渲染前捕获鼠标和键盘
1 bool frameStarted(const FrameEvent& evt) 2 { 3 if (mMouse) 4 { 5 mMouse->capture(); 6 } 7 if (mKeyboard) 8 { 9 mKeyboard->capture(); 10 } 11 //实现更光滑的移动 12 mCamNode->translate(mDirection*evt.timeSinceLastFrame,Node::TS_LOCAL);//根据从上一帧到现在的时间,对平移大小进行缩放 13 return mContinue; 14 }
第三,处理鼠标监听事件,首先实现鼠标左键开关灯,右键旋转摄像机
鼠标左键按下:
1 bool mousePressed(const OIS::MouseEvent &e,OIS::MouseButtonID id) 2 { 3 Light *light = mSceneMgr->getLight("light1"); 4 switch(id) 5 { 6 case OIS::MB_Left: 7 light->setVisible(!light->isVisible()); 8 break; 9 } 10 return true; 11 }
鼠标右键拖拽:
1 bool mouseMoved(const OIS::MouseEvent &e) 2 { 3 if (e.state.buttonDown(OIS::MB_Right)) 4 { 5 //拖动实体 6 mCamNode->yaw(Degree(-mRotate * e.state.X.rel),Node::TS_WORLD);// 7 mCamNode->pitch(Degree(-mRotate * e.state.Y.rel),Node::TS_LOCAL);// 8 } 9 return true; 10 }
看过上一章,这里就不解释了。
键盘处理:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 bool keyPressed(const OIS::KeyEvent &e) 2 { 3 switch (e.key) 4 { 5 case OIS::KC_ESCAPE://按下esc时推出 6 mContinue = false; 7 break; 8 case OIS::KC_1://数字键1 9 mCamera->getParentSceneNode()->detachObject(mCamera); 10 mCamNode = mSceneMgr->getSceneNode("CamNode1"); 11 mCamNode->attachObject(mCamera); 12 break; 13 case OIS::KC_2://数字键2 14 mCamera->getParentSceneNode()->detachObject(mCamera); 15 mCamNode = mSceneMgr->getSceneNode("CamNode2"); 16 mCamNode->attachObject(mCamera); 17 break; 18 case OIS::KC_UP://前 19 case OIS::KC_W: 20 mDirection.z -= mMove; 21 break; 22 case OIS::KC_DOWN://后 23 case OIS::KC_S: 24 mDirection.z += mMove; 25 break; 26 case OIS::KC_LEFT://左 27 case OIS::KC_A: 28 mDirection.x -= mMove; 29 break; 30 case OIS::KC_RIGHT://右 31 case OIS::KC_D: 32 mDirection.x += mMove; 33 break; 34 case OIS::KC_PGDOWN://上 35 case OIS::KC_E: 36 mDirection.y -= mMove; 37 break; 38 case OIS::KC_PGUP://下 39 case OIS::KC_Q: 40 mDirection.y += mMove; 41 break; 42 } 43 return true; 44 }
这样写起来看着很明了,比上一章的if()好多了。同样可以在bool keyReleased(const OIS::KeyEvent &e);里做相应处理。
其他的没有改动。代码参考上一章的。