Ogre笔记八:基础教程五—缓冲输入

      没太多好说的,这一章要实现的目标跟上一章一样,但是用到的方法相比较而言高级一点,我懒得解释直接复制教程里的。

缓冲输入的介绍:

      在上一次课里,我们使用的是无缓冲的输入,也就是说,在每一帧里我们查询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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值