一個基本的例子:
#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;
// set the rotation and move speed
mRotate = 0.13;
mMove = 250;
// continue rendering
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;
} // switch
return true;
}
protected:
Real mRotate; // The rotate constant
Real mMove; // The movement constant
SceneManager *mSceneMgr; // The current SceneManager
SceneNode *mCamNode; // The SceneNode the camera is currently attached to
bool mContinue; // Whether to continue rendering or not
Vector3 mDirection; // Value to move in the correct direction
};
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(0.25, 0.25, 0.25));
// 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));
node->yaw(Degree(-45));
node->attachObject(mCamera);
// create the second camera node/pitch 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;
}
按照理論來說
unbuffered:不斷的響應按鍵信息,直到按鍵放開。例如,按下上下左右,使得角色持續移動。
一般來講適合于3D場景漫游過程,當在每幀渲染之前,系統捕獲輸入設備狀態,并根據這些狀態對場景中的物體和攝象機進行控制。
buffered:在一個按鍵放開之前,只處理一次輸入信息。
例如呼出主菜單。適合于GUI界面的情況(如設置菜單),輸入設備狀態可以被發送到各GUI元素進行處理(如按鈕被按下)。
這個例子試圖說明緩沖輸入和非緩沖輸入的區別,但是讓我困惑的是為什么采用了緩沖輸入系統還能響應持續按鍵呢?編譯后運行按住WSAD照樣移動攝像機。