您的位置:首页 > 其它

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坐标(即,屏幕上的准确位置)。

代码 :

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: