Ogre笔记03——Getting User Input and Using the Frame Listener
1.利用FrameListener控制每一帧动作的一般步骤
In order to receive notifications of frame events, you should create a subclass of FrameListener and override the methods for which you would like to customise the resulting processing. You should then callRoot::addFrameListener passing an instance of this class. There is no limit to the number of frame listeners you can register, allowing you to register multiple listeners for different purposes. Frame events only occur when Ogre is in continuous rendering mode, i.e. afterRoot::startRendering is called.
// Step1 : Create a class inheriting from Ogre::FrameListener class ExampleFrameListener : public Ogre::FrameListener { private: // member variables, eg. Which SceneNode to control each frame Ogre::SceneNode* _node; public: // constructors and destructors... // what to do before each frame bool frameStarted(const Ogre::FrameEvent &evt) // Called after all render targets have had their rendering commands issued, // but before render windows have been asked to flip their buffers over. bool frameRenderingQueued (const FrameEvent &evt) // Called just after a frame has been rendered. bool frameEnded (const FrameEvent &evt) }; // Step2 : Add a new member variable to hold the pointer to the FrameListener Ogre::FrameListener* FrameListener; // Create a new function to create the FrameListener and add it to mRoot void createFrameListener() { FrameListener = new ExampleFrameListener(_SinbadNode); mRoot->addFrameListener(FrameListener); } // Done!
2.FrameListener
Ogre中使用了帧监听器来控制每一帧的显示行为,FrameListener这一概念是来自Observer Pattern(观察者模式)的设计模式。当有关帧的事件发生时,Ogre::Root会遍历所有添加到他上面的FrameListener,并会调用每个FrameListener相应的方法。
3.FrameListener中的事件信息
Elapsed time in seconds since the last event.
Real
timeSinceLastFrame(相邻两帧的间隔时间,一般用这个多)Elapsed time in seconds since the last event of the same type, i.e.
例如,若想获得比较匀速的移动,可以这样子:Ogre::Vector3(10,0,0) * evt.timeSinceLastFrame);
4.增加输入支持(Using OIS)
// Step1 : Initialise an OIS::InputManager OIS::ParamList pl; size_t windowHnd = 0; std::ostringstream windowHndStr; m_win->getCustomAttribute("WINDOW", &windowHnd); windowHndStr << windowHnd; pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str())); m_InputManager = OIS::InputManager::createInputSystem( pl ); // Legend Line 1 creates a ParamList object. This is basically a typedef for a std::map. It is used to pass parameters to classes (similar to the Ogre::NameValuePairList). Line 2 creates a size_t object that we will use to retrieve a window handle from our render window. Line 3 creates a std::ostringstream - we use this to "stringify" the size_t object created in line 2. Line 4 populates the size_t object with the window handle. 'm_win' in this example is a pointer to an initialised Ogre::RenderWindow Line 5 performs the stringification - we need a string representation of the window handle. Line 6 inserts into our parameter list the string "WINDOW", and the string object we created above. Line 7 actually creates the OIS input system. Note: m_InputManager is a pointer to an OIS::InputManager object. // Step2 : Create OIS::Mouse and OIS::Keyboard objects m_Mouse = static_cast<OIS::Mouse*>(m_InputManager->createInputObject(OIS::OISMouse, false)); // True or false, buffered(true) or unbuffered(false) m_Keyboard = static_cast<OIS::Keyboard*>(m_InputManager->createInputObject(OIS::OISKeyboard, false)); // Step3 : Tell OIS about the dimensions of the window unsigned int width, height, depth; int top, left; m_win->getMetrics(width, height, depth, left, top); const OIS::MouseState &ms = m_Mouse->getMouseState(); ms.width = width; ms.height = height; // Step4 : Detect the input m_Keyboard->capture(); // Update the event state if (m_Keyboard->isKeyDown(OIS::KC_ESCAPE)) return false;// Done!// 谨记在FrameListener的析构函数中要delete OIS::Keyboard和OIS::Mouse Objects
参考链接:使用OIS输入系统。