OGRE基础教程五 Buffered Input

来源:互联网 发布:灌篮高手 爱知学院 编辑:程序博客网 时间:2024/05/21 05:40

英语水平有限,欢迎大家批评指正微笑

本文并没有将原文全部翻译,只是将其中的一些知识点翻译总结了一下,想要查看详细讲解的话,可以到原文处看一下,附上英文原文地址:http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Basic+Tutorial+5&structure=Tutorials

Buffered Input in a Nutshell

Introduction

  前面的教程中我们使用了非缓存输入,即每一帧我们都查询OIS::KeyboardOIS::Mouse实例的状态来查看什么键或鼠标按钮被按下。缓存输入使用监听器接口来通知你的程序有事件发生。例如,当一个键被按下,KeyListener::keyPressed事件被执行,当按钮被松开,KeyListener::keyReleased事件被执行,在所有已注册的KeyListener类中。他关心的是记录触发次数或前一帧键是否是未被按下的。

  OIS也支持非缓存Joystick事件通过OIS::JoystickListener接口。

  对应OIS监听器系统有一件重要的事情需要注意,那就是每个KeyboardMouseJoystick对象只能有一个监听器。这样是为了简单(也为了速度)。调用setEventCallback函数乘以次数,最后注册的侦听器得到事件。如果你要多个对象得到KeyMouseJoystick事件,你就必须写一条消息自己分配。还有注意我们仍要在frameRenderingQueued方法中调用Keyboard::captureMouse::captureOIS不使用线程来确定键盘和鼠标的状态,所以你就必须说明应该什么时候捕获输入。

The KeyListener Interface

  OIS KeyListener接口提供两个纯虚函数,keyPressed函数(每次一个键被按下时调用),keyReleased函数(每次一个键被松开时调用)。传给这些函数的参数是一个KeyEvent,它包含了被按下或松开的按键代码。

The MouseListener Interface

  MouseListener接口只是比KeyListener接口稍微复杂一点。它包含两个函数来查看鼠标按钮被按下或松开:MouseListener::mousePressedMouseListener::mouseReleased。它还有一个mouseMoved函数,当鼠标移动时就会被调用。这些函数都接收一个MouseEvent对象,它将鼠标的当前状态放在了“state”变量中。对应MouseState对象需要注意的最重要的事情就是它不仅包含了鼠标上一个动作的XY相对坐标(即,自上一次MouseListener::mouseMoved函数被调用它所移动的距离),还包含了XY决定坐标(即,他们在屏幕上的真正位置)。

The Code

Variables

  Real mRotate;         // 旋转常量

  Real mMove;           // 移动常量

  SceneNode *mCamNode;  // camera当前绑定的场景节点

  Vector3 mDirection;    // 移动的正确方向,包含了每一帧中我们应该如何                                              //移动camera的信息

createFrameListener method

  添加如下代码到createFrameListener方法中:

  // Populate the camera container

  mCamNode = mCamera->getParentSceneNode();

  // set the rotation and move speed

  mRotate = 0.13;

  mMove = 250;

  OIS mMousemKeyboard对象以及从BaseApplicationcreateFrameListener方法中得到。那里我们调用这些对象的setEventCallback方法来注册侦听器:

  // Do not add this code to the project!

  mMouse->setEventCallback(this);

  mKeyboard->setEventCallback(this);

  最后,我们需要初始化mDirection为零向量(因为我们初始时不移动):

  mDirection = Ogre::Vector3::ZERO;

Key Bindings

  继续之前,我们应绑定ESC键用来退出程序。keyPressed方法改下为:

  bool keyPressed(const OIS::KeyEvent& evt)

  {

   switch (evt.key)

   {

   case OIS::KC_ESCAPE:

       mShutDown = true;

       break;

   default:

      break;

   }

   return true;

  }

  把如下代码添加到frameRenderingQueued方法中,以使程序响应键盘输入:

  if (mWindow->isClosed()) return false;

   if (mShutDown) return false;

   mKeyboard->capture();

   mMouse->capture();

mTrayMgr->frameRenderingQueued(evt);

现在在前面的switch语句中添加其他的键绑定代码。第一通过按12允许用户在视点间转换:

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;

下面添加键盘动作,每当用户按下绑定有动作的按键,我们都将增加或减少(根据方向)mMove

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;

现在我们要撤销mDirection向量的改变,无论何时按键被按下来停止动作。在keyReleased方法中添加如下代码:

switch (evt.key)

{

case OIS::KC_UP:

case OIS::KC_W:

   mDirection.z = 0;

   break;

case OIS::KC_DOWN:

case OIS::KC_S:

   mDirection.z = 0;

   break;

case OIS::KC_LEFT:

case OIS::KC_A:

   mDirection.x = 0;

   break;

case OIS::KC_RIGHT:

case OIS::KC_D:

   mDirection.x = 0;

   break;

case OIS::KC_PGDOWN:

case OIS::KC_E:

   mDirection.y = 0;

   break;

case OIS::KC_PGUP:

case OIS::KC_Q:

   mDirection.y = 0;

   break;

default:

   break;

}

return true;

现在mDirection根据输入更新,我们需要使变化发生。在frameRenderingQueued函数中添加代码:

mCamNode->translate(mDirection*evt.timeSinceLastFrame, Ogre::Node::TS_LOCAL);

Mouse Bindings

我们将通过鼠标左键来开关光源,mousePressed函数有MouseEventMouseButtonID两个参数。我们通过MouseButtonID来确定哪个按钮被按下,将mousePressed函数修改为:

Ogre::Light *light = mSceneMgr->getLight("Light1");

switch (id)

{

case OIS::MB_Left:

   light->setVisible(! light->isVisible());

   break;

default:

   break;

}

return true;

每当鼠标移动时,我们就查看鼠标右键是否按下。如果是,我们就旋转camera根据相对移动。我们可以通过传个这个函数的MouseEvent对象来得到鼠标的相对动作。它包含了一个叫做state包含了MouseState(主要是关于鼠标的详细信息)的变量。MouseState::buttonDown会告诉我们某一特定的鼠标按钮是否被按下,XY变量会告诉我们鼠标的相对动作。将mouseMoved函数改为:

if (evt.state.buttonDown(OIS::MB_Right))

{

   mCamNode->yaw(Ogre::Degree(-mRotate * evt.state.X.rel), Ogre::Node::TS_WORLD);

   mCamNode->pitch(Ogre::Degree(-mRotate * evt.state.Y.rel), Ogre::Node::TS_LOCAL);

}

return true;

编译运行程序,鼠标右键按下时camera就可以自由观察场景。

 

原创粉丝点击