zoukankan      html  css  js  c++  java
  • Ogre: 建立一个简单的框架——响应键盘事件

    [转载请保证内容的完整性和正确性]

    建立一个简单的框架——响应键盘事件

    上一节我们在场景中添加了一个机器人,这一节我们将建立一个FrameListener类(顾名思义,这是一个侦听类),来控制模型进行移动。

    创建FrameListener类

    FrameListener类主要负责事件的侦听,如帧结束、键盘输入等事件。它继承自ExampleFrameListener类,如果需要的话还可以继承KeyListener(键盘事件)、MouseListener(鼠标事件)和JoyStickListener(游戏杆事件)。这里只有键盘事件。

    1 //DemoFrameListener.h
    2  class DemoFrameListener : public ExampleFrameListener, public OIS::KeyListener {
    3  public:
    4      DemoFrameListener(RenderWindow* _win, Camera* _cam, bool bufferKeys,
    5          bool bufferMouse, bool bufferJoy);
    6      bool keyPressed(const OIS::KeyEvent& arg);
    7      bool keyReleased(const OIS::KeyEvent& arg);
    8      bool frameEnded(const FrameEvent& evt);
    9  }; 
     1 //DemoFrameListener.cpp
     2  DemoFrameListener::DemoFrameListener(RenderWindow* _win, Camera* _cam, bool bufferKeys,
     3          bool bufferMouse, bool bufferJoy)
     4          : ExampleFrameListener(_win, _cam, bufferKeys, bufferMouse, bufferJoy) {
     5 
     6  }
     7 
     8  bool DemoFrameListener::keyPressed(const OIS::KeyEvent& arg) {
     9      return true;
    10  }
    11 
    12  bool DemoFrameListener::keyReleased(const OIS::KeyEvent& arg) {
    13      return true;
    14  }
    15 
    16  bool DemoFrameListener::frameEnded(const FrameEvent& evt) {
    17      return true;
    18  } 

    在Application类中添加新的方法。

    1 //DemoApplication.cpp
    2  void DemoApplication::createFrameListener(void) {
    3      mFrameListener = new DemoFrameListener(mWindow, mCamera, true, true, true);
    4      mRoot->addFrameListener(mFrameListener);
    5  } 

    这时运行代码,还是能看到和上一节一样的机器人,但是鼠标、键盘都不能移动摄像机了。接下来我们将添加自己的控制方法。

    创建Manager类

    在添加控制方法之前,我们要先优化一下代码结构。上一节中我们把添加模型的代码写到了Application类中,这次我们要创建一个Manager类,来统一管理这些模型资源。

     1 //DemoManager.h
     2  class DemoManager
     3  {
     4  public:
     5      DemoManager(Ogre::SceneManager* _sm);
     6      ~DemoManager(void);
     7      void Update();
     8      void SetDeltaT(float _dt);
     9  private:
    10      Ogre::SceneManager* sm;
    11      float deltaT;
    12      Ogre::SceneNode* rootsn;
    13      Ogre::SceneNode* node;
    14  }; 

    添加构造函数中的代码

    1 //DemoManager.cpp
    2  DemoManager::DemoManager(Ogre::SceneManager* _sm) : sm(_sm) {
    3      Ogre::Entity* ent = sm->createEntity("Robot", "robot.mesh");
    4      rootsn = sm->getRootSceneNode();
    5      node = rootsn->createChildSceneNode("RobotNode");
    6      node->attachObject(ent);
    7  } 

    其他函数中也略作修改。

    1 //DemoApplication.h
    2  //添加变量
    3  private:
    4      DemoManager* demoManager;
     1 //DemoApplication.cpp
     2  //修改两个函数
     3  void DemoApplication::createScene(void) {
     4      mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
     5      Light* l = mSceneMgr->createLight("MainLight");
     6      l->setPosition(20, 80, 50);
     7 
     8      demoManager = new DemoManager(mSceneMgr);
     9  }
    10 
    11  void DemoApplication::createFrameListener(void) {
    12      mFrameListener = new DemoFrameListener(mWindow, mCamera, true, true, true, demoManager);
    13      mRoot->addFrameListener(mFrameListener);
    14  }
    1 //DemoFrameListener.h
    2  //修改构造函数声明
    3 DemoFrameListener(RenderWindow* _win, Camera* _cam, bool bufferKeys,
    4      bool bufferMouse, bool bufferJoy, DemoManager* _dm);
    1 //DemoFrameListener.cpp
    2  //修改构造函数
    3 DemoFrameListener::DemoFrameListener(RenderWindow* _win, Camera* _cam, bool bufferKeys,
    4      bool bufferMouse, bool bufferJoy, DemoManager* _dm)
    5      : ExampleFrameListener(_win, _cam, bufferKeys, bufferMouse, bufferJoy), demoManager(_dm) {
    6 
    7  } 

    这是运行代码可以看到和之前一样的界面,但是我们的代码结构已经得到了优化,分为了三部分:Application(管理结构)、FrameListener(处理事件)和Manager(管理资源)。

    添加键盘事件

    我们将添加6个按键,WASD进行平移,QE进行水平旋转。

    首先,为了能够让移动不受帧率的影响,我们让移动随时间变化。我们要传给Manager类每一帧间隔的时间。

    1 //DemoManager.cpp
    2  void DemoManager::SetDeltaT(float _dt) {
    3      deltaT = _dt;
    4  } 

    然后定义键盘事件:

     1 //DemoFrameListener.cpp
     2  bool DemoFrameListener::keyPressed(const OIS::KeyEvent& arg) {
     3      Ogre::Vector3 movement(0, 0, 0);
     4      float yaw(0);
     5 
     6      switch (arg.key) {
     7      case OIS::KC_W:
     8          movement.z -= 1000;
     9          break;
    10      case OIS::KC_S:
    11          movement.z += 1000;
    12          break;
    13      case OIS::KC_A:
    14          movement.x -= 1000;
    15          break;
    16      case OIS::KC_D:
    17          movement.x += 1000;
    18          break;
    19      case OIS::KC_Q:
    20          yaw += 5;
    21          break;
    22      case OIS::KC_E:
    23          yaw -= 5;
    24          break;
    25      }
    26 
    27      demoManager->SetMovement(movement);
    28      demoManager->SetRotation(yaw);
    29      return true;
    30  } 

    为了方便,我们再定义一个退出程序的按键。

     1 //DemoFrameListener.cpp
     2  bool DemoFrameListener::keyReleased(const OIS::KeyEvent& arg) {
     3      if (arg.key == OIS::KC_ESCAPE) {
     4      _exit = true;
     5      }
     6      return true;
     7  }
     8 
     9  bool DemoFrameListener::frameEnded(const FrameEvent& evt) {
    10      ExampleFrameListener::frameEnded(evt);
    11      if (demoManager) {
    12          demoManager->SetDeltaT(evt.timeSinceLastFrame);
    13          demoManager->Update();
    14      }
    15 
    16      return (!_exit);
    17  } 

    然后在Manager中接收按键事件:

     1 //DemoManager.cpp
     2  void DemoManager::Update() {
     3      node->translate(movement * deltaT);
     4      node->yaw(Ogre::Radian(yaw * deltaT));
     5 
     6      movement = Ogre::Vector3(0, 0, 0);
     7      yaw = 0;
     8  }
     9 
    10  void DemoManager::SetMovement(Ogre::Vector3 _movement) {
    11      movement = Ogre::Vector3(_movement);
    12  }
    13 
    14  void DemoManager::SetRotation(float _yaw) {
    15      yaw = _yaw;
    16  } 

    这里可以看出,我们对3D模型做的变换其实就是对场景节点做的变换。

    运行这段代码,我们虽然可以控制模型机器人,但是需要一下一下地按键。要改善这个问题就要修改FrameListener类,其中有keyPressed和keyReleased两个方法,分别是按下键盘和释放键盘,略作修改就能实现长按事件。

  • 相关阅读:
    /usr/bin/ld: 找不到 /usr/lib64/libatomic.so.1.0.0
    linux Version mismatch error. This is libtool 2.4.6 Debian-2.4.6-2
    java播放语音文件
    java冒泡排序
    java递归求和
    常见芯片标号说明
    keil5 新建 stm32项目 步骤
    st-link 升级固件时报错“is not in the DFU mode”
    数码管 段选位选
    C51 定时器
  • 原文地址:https://www.cnblogs.com/fks143/p/4337533.html
Copyright © 2011-2022 走看看