Ogre笔记八:基础教程五—缓冲输入
2011-09-15 21:35
309 查看
没太多好说的,这一章要实现的目标跟上一章一样,但是用到的方法相比较而言高级一点,我懒得解释直接复制教程里的。
缓冲输入的介绍:
在上一次课里,我们使用的是无缓冲的输入,也就是说,在每一帧里我们查询OIS::Keyboard和OIS::Mouse实例的状态,以判断它们是否被按下。而缓冲输入使用了一个listener接口,以便在事件发生时通知你的程序。比如,当一个键被按下时,会触发一个 KeyListener::keyPressed 事件,而当这个键被释放(不再按下)时,KeyListener::keyReleased
事件被触发给所有已注册的KeyListener类。这些能用在追踪按键的时间,或判断按键在上一帧中是否没有被按下。
通过OIS::JoystickListener 接口,OIS也支持无缓冲的操纵杆事件,但在本课我们不会涉及到。
关于OIS的监听系统有一点要注意的是,对于每一个Keyboard,Mouse,Joystick对象只能有一个监听器。这样是为了简单(也为了速度)。多次调用setEventCallback函数(后面会讲到)的结果是只有最后一次注册的监听器才得到事件消息。如果你有多个对象需要获得Key,Mouse,或Joystick事件,你只有自己写一个消息分发。还有,千万记得在frameStarted方法里调用Keyboard::capture和Mouse::capture。OIS不会使用线程(或其它玩意儿)来确定键盘鼠标的状态,所以你必须指明什么时候去获取输入。
键盘监听界面
OIS的KeyListener接口提供了两个纯虚函数。第一个是keyPressed函数(每次按下某个键时调用它),还一个是keyReleased(每次离开某个键时调用它)。传入这些函数的参数是一个KeyEvent,它包含被按下/释放的按键的键码。
鼠标监听界面
MouseListener接口比KeyListener接口要稍微复杂一些。它包含查看何时鼠标键被按下/释放的函数:
MouseListener::mousePressed 和 MouseListener::mouseReleased. 它还包含一个mouseMoved函数,当鼠标移动时调用它。这些函数都接收一个MouseEvent对象,在"state"变量里保存着当前鼠标的状态。需要注意的是,MouseState对象即包含了鼠标移动的相对XY坐标(即,从上一次调用MouseListener::mouseMoved开始,它所移动的距离),还包含了绝对XY坐标(即,屏幕上的准确位置)。
代码 :
缓冲输入的介绍:
在上一次课里,我们使用的是无缓冲的输入,也就是说,在每一帧里我们查询OIS::Keyboard和OIS::Mouse实例的状态,以判断它们是否被按下。而缓冲输入使用了一个listener接口,以便在事件发生时通知你的程序。比如,当一个键被按下时,会触发一个 KeyListener::keyPressed 事件,而当这个键被释放(不再按下)时,KeyListener::keyReleased
事件被触发给所有已注册的KeyListener类。这些能用在追踪按键的时间,或判断按键在上一帧中是否没有被按下。
通过OIS::JoystickListener 接口,OIS也支持无缓冲的操纵杆事件,但在本课我们不会涉及到。
关于OIS的监听系统有一点要注意的是,对于每一个Keyboard,Mouse,Joystick对象只能有一个监听器。这样是为了简单(也为了速度)。多次调用setEventCallback函数(后面会讲到)的结果是只有最后一次注册的监听器才得到事件消息。如果你有多个对象需要获得Key,Mouse,或Joystick事件,你只有自己写一个消息分发。还有,千万记得在frameStarted方法里调用Keyboard::capture和Mouse::capture。OIS不会使用线程(或其它玩意儿)来确定键盘鼠标的状态,所以你必须指明什么时候去获取输入。
键盘监听界面
OIS的KeyListener接口提供了两个纯虚函数。第一个是keyPressed函数(每次按下某个键时调用它),还一个是keyReleased(每次离开某个键时调用它)。传入这些函数的参数是一个KeyEvent,它包含被按下/释放的按键的键码。
鼠标监听界面
MouseListener接口比KeyListener接口要稍微复杂一些。它包含查看何时鼠标键被按下/释放的函数:
MouseListener::mousePressed 和 MouseListener::mouseReleased. 它还包含一个mouseMoved函数,当鼠标移动时调用它。这些函数都接收一个MouseEvent对象,在"state"变量里保存着当前鼠标的状态。需要注意的是,MouseState对象即包含了鼠标移动的相对XY坐标(即,从上一次调用MouseListener::mouseMoved开始,它所移动的距离),还包含了绝对XY坐标(即,屏幕上的准确位置)。
代码 :
#include "ExampleApplication.h" class TutorialFrameListener : public ExampleFrameListener, public OIS::MouseListener, public OIS::KeyListener { public: TutorialFrameListener(RenderWindow* win, Camera* cam, SceneManager *sceneMgr) : ExampleFrameListener(win, cam, true, true) { // Populate the camera and scene manager containers mCamNode = cam->getParentSceneNode(); mSceneMgr = sceneMgr; // 设置旋转和移动速度 mRotate = 0.13; mMove = 250; // 继续渲染 mContinue = true; mMouse->setEventCallback(this); mKeyboard->setEventCallback(this); mDirection = Vector3::ZERO; } bool frameStarted(const FrameEvent &evt) { if(mMouse) mMouse->capture(); if(mKeyboard) mKeyboard->capture(); mCamNode->translate(mDirection * evt.timeSinceLastFrame, Node::TS_LOCAL); return mContinue; } //MouseListener bool mouseMoved(const OIS::MouseEvent &e) { if (e.state.buttonDown(OIS::MB_Right)) { mCamNode->yaw(Degree(-mRotate * e.state.X.rel), Node::TS_WORLD); mCamNode->pitch(Degree(-mRotate * e.state.Y.rel), Node::TS_LOCAL); } return true; } bool mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID id) { Light *light = mSceneMgr->getLight("Light1"); switch (id) { case OIS::MB_Left: light->setVisible(! light->isVisible()); break; } return true; } bool mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID id) { return true; } // KeyListener bool keyPressed(const OIS::KeyEvent &e) { switch (e.key) { case OIS::KC_ESCAPE: mContinue = false; break; case OIS::KC_1: mCamera->getParentSceneNode()->detachObject(mCamera); mCamNode = mSceneMgr->getSceneNode("CamNode1"); mCamNode->attachObject(mCamera); break; case OIS::KC_2: mCamera->getParentSceneNode()->detachObject(mCamera); mCamNode = mSceneMgr->getSceneNode("CamNode2"); mCamNode->attachObject(mCamera); break; case OIS::KC_UP: case OIS::KC_W: mDirection.z -= mMove; break; case OIS::KC_DOWN: case OIS::KC_S: mDirection.z += mMove; break; case OIS::KC_LEFT: case OIS::KC_A: mDirection.x -= mMove; break; case OIS::KC_RIGHT: case OIS::KC_D: mDirection.x += mMove; break; case OIS::KC_PGDOWN: case OIS::KC_E: mDirection.y -= mMove; break; case OIS::KC_PGUP: case OIS::KC_Q: mDirection.y += mMove; break; } return true; } bool keyReleased(const OIS::KeyEvent &e) { switch (e.key) { case OIS::KC_UP: case OIS::KC_W: mDirection.z += mMove; break; case OIS::KC_DOWN: case OIS::KC_S: mDirection.z -= mMove; break; case OIS::KC_LEFT: case OIS::KC_A: mDirection.x += mMove; break; case OIS::KC_RIGHT: case OIS::KC_D: mDirection.x -= mMove; break; case OIS::KC_PGDOWN: case OIS::KC_E: mDirection.y += mMove; break; case OIS::KC_PGUP: case OIS::KC_Q: mDirection.y -= mMove; break; } return true; } protected: Real mRotate; // 旋转常量 Real mMove; // 运动常量 SceneManager *mSceneMgr; // 当前的场景管理器 SceneNode *mCamNode; // 当前摄像机附着的场景节点 bool mContinue; // 是否要继续渲染 Vector3 mDirection; // 指向正确的移动方向 }; class TutorialApplication : public ExampleApplication { public: void createCamera(void) { // create camera, but leave at default position mCamera = mSceneMgr->createCamera("PlayerCam"); mCamera->setNearClipDistance(5); } void createScene(void) { mSceneMgr->setAmbientLight(ColourValue(1, 1, 1)); // add the ninja Entity *ent = mSceneMgr->createEntity("Ninja", "ninja.mesh"); SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode("NinjaNode"); node->attachObject(ent); // create the light Light *light = mSceneMgr->createLight("Light1"); light->setType(Light::LT_POINT); light->setPosition(Vector3(250, 150, 250)); light->setDiffuseColour(ColourValue::White); light->setSpecularColour(ColourValue::White); // Create the scene node node = mSceneMgr->getRootSceneNode()->createChildSceneNode("CamNode1", Vector3(-400, 200, 400)); // Make it look towards the ninja node->yaw(Degree(-45)); // Create the pitch node node = node->createChildSceneNode("PitchNode1"); node->attachObject(mCamera); // create the second camera node/pitch node node = mSceneMgr->getRootSceneNode()->createChildSceneNode("CamNode2", Vector3(0, 200, 400)); node = node->createChildSceneNode("PitchNode2"); } void createFrameListener(void) { // Create the FrameListener mFrameListener = new TutorialFrameListener(mWindow, mCamera, mSceneMgr); mRoot->addFrameListener(mFrameListener); // Show the frame stats overlay mFrameListener->showDebugOverlay(true); } }; #if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32 #define WIN32_LEAN_AND_MEAN #include "windows.h" INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT) #else int main(int argc, char **argv) #endif { // Create application object TutorialApplication app; try { app.go(); } catch(Exception& e) { #if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32 MessageBox(NULL, e.getFullDescription().c_str(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL); #else fprintf(stderr, "An exception has occurred: %s\n", e.getFullDescription().c_str()); #endif } return 0; }
相关文章推荐
- Ogre基础教程4:监听器类与无缓冲输入处理
- Ogre基础教程5:有缓冲输入
- OGRE 3D基础五:缓冲输入
- Ogre笔记五:基础教程二—摄像机、阴影和光照处理
- ogre学习笔记-基础教程345
- 基础教程五(缓冲输入)
- Ogre笔记二:基础教程一—场景管理器、场景节点和实体
- [OGRE]基础教程来七发:来谈一谈缓冲绑定
- [OGRE]基础教程来七发:来谈一谈缓冲绑定
- 网络编程2--毕向东java基础教程视频学习笔记
- 2013/12/12 基础教程笔记1
- .黑马程序员之C#编程基础学习笔记:不断要求用户输入一个数字,当用户输入end的时候显示刚才输入的数字中的最大值。
- OGRE基础教程四 Frame Listeners and Unbuffered Input
- Opencv基础教程笔记2
- <<Python基础教程>>学习笔记 | 第02章 | 列表和数组
- 黑马程序员之WinForm编程基础学习笔记:页面上有一张图片,默认是隐藏的,用户在文本框中输入身份证号(131226198105223452),点击按钮,如果年龄大于18岁则显示图片。
- [Matlab]基础教程学习笔记(二):程序控制结构
- Ogre基础教程8:多个以及双场景管理器
- Python基础教程 第3章: 使用字符串 学习笔记
- 菜鸟也学Ogre-缓冲输入