非缓冲输入,个人觉得不怎么好用,但是在某些特殊场景下可能会有大用。
首先,我们了解一下这一节教程想实现个什么东西:
我们将把一个忍者放到屏幕中,并在场景中加上点光源。
当你点击鼠标左键,灯光会打开或关闭。按住鼠标右键,则开启“鼠标观察”模式(也就是你用摄像机四处观望,想想一下你玩3D游戏的场景)。
按下1、2键,以选择从哪一个视口来观看场景。
#include "ExampleApplication.h"
class TutorialFrameListener : public ExampleFrameListener
{
public:
TutorialFrameListener(RenderWindow* win, Camera* cam, SceneManager *sceneMgr)
: ExampleFrameListener(win, cam, false, false)
{
// 键盘和鼠标状态追踪
mMouseDown = false;
mToggle = 0.0;
// Populate the camera and scene manager containers
mCamNode = cam->getParentSceneNode();
mSceneMgr = sceneMgr;
// 设置旋转和移动速度
mRotate = 0.13;
mMove = 250;
}
bool frameStarted(const FrameEvent &evt)
{
mMouse->capture();
mKeyboard->capture();
//Escape键被按下时程序退出
if(mKeyboard->isKeyDown(OIS::KC_ESCAPE))
return false;
//左击鼠标控制灯的开关
bool currMouse = mMouse->getMouseState().buttonDown(OIS::MB_Left);
if (currMouse && ! mMouseDown)
{
Light *light = mSceneMgr->getLight("Light1");
light->setVisible(! light->isVisible());
}
mMouseDown = currMouse;
//事件之间的休息时间
mToggle -= evt.timeSinceLastFrame;
//按1、2键,能够转换摄像机的视口
if ((mToggle < 0.0f ) && mKeyboard->isKeyDown(OIS::KC_1))
{
mToggle = 0.5f;
mCamera->getParentSceneNode()->detachObject(mCamera);
mCamNode = mSceneMgr->getSceneNode("CamNode1");
mCamNode->attachObject(mCamera);
}
else if ((mToggle < 0.0f) && mKeyboard->isKeyDown(OIS::KC_2))
{
mToggle = 0.5f;
mCamera->getParentSceneNode()->detachObject(mCamera);
mCamNode = mSceneMgr->getSceneNode("CamNode2");
mCamNode->attachObject(mCamera);
}
//按下方向键或W、A、S、D键时,进行mCamNode的平移
Vector3 transVector = Vector3::ZERO;
if (mKeyboard->isKeyDown(OIS::KC_UP) || mKeyboard->isKeyDown(OIS::KC_W))
transVector.z -= mMove;
if (mKeyboard->isKeyDown(OIS::KC_DOWN) || mKeyboard->isKeyDown(OIS::KC_S))
transVector.z += mMove;
if (mKeyboard->isKeyDown(OIS::KC_LEFT) || mKeyboard->isKeyDown(OIS::KC_A))
transVector.x -= mMove;
if (mKeyboard->isKeyDown(OIS::KC_RIGHT) || mKeyboard->isKeyDown(OIS::KC_D))
transVector.x += mMove;
//E键或者PageDown键进行向下移动,用Q键或者PageUp键进行向上移动
if (mKeyboard->isKeyDown(OIS::KC_PGUP) || mKeyboard->isKeyDown(OIS::KC_Q))
transVector.y += mMove;
if (mKeyboard->isKeyDown(OIS::KC_PGDOWN) || mKeyboard->isKeyDown(OIS::KC_E))
transVector.y -= mMove;
//摄像机旋转
mCamNode->translate(transVector*evt.timeSinceLastFrame,Node::TS_LOCAL);
if (mMouse->getMouseState().buttonDown(OIS::MB_Right))
{
mCamNode->yaw(Degree(-mRotate * mMouse->getMouseState().X.rel), Node::TS_WORLD);
mCamNode->pitch(Degree(-mRotate * mMouse->getMouseState().Y.rel), Node::TS_LOCAL);
}
return true;
//return ExampleFrameListener::frameStarted(evt);
}
protected:
bool mMouseDown; // 鼠标左键是否在上一帧被按下
Real mToggle; // 直到下一次触发的时间
Real mRotate; // 滚动常量
Real mMove; // 移动常量
SceneManager *mSceneMgr; // 当前场景管理器
SceneNode *mCamNode; // 当前摄像机所附在的场景节点
};
class TutorialApplication : public ExampleApplication
{
public:
TutorialApplication()
{
}
~TutorialApplication()
{
}
protected:
void createCamera(void)
{
// create camera, but leave at default position
mCamera = mSceneMgr->createCamera("PlayerCam");
mCamera->setNearClipDistance(5);
}
void createScene(void)
{
//创建一个相对较暗的环境
mSceneMgr->setAmbientLight(ColourValue(0.25, 0.25, 0.25));
//添加一个忍者
Entity *ent = mSceneMgr->createEntity("Ninja", "ninja.mesh");
SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode("NinjaNode");
node->attachObject(ent);
//添加一个光源
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));
node->yaw(Degree(-45));
node->attachObject(mCamera);
// create the second camera node
node = mSceneMgr->getRootSceneNode()->createChildSceneNode("CamNode2", Vector3(0, 200, 400));
}
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;
}