用户设计ExampleApplication的派生类生成自己的程序,而在ExampleApplication.h+ExampleFrameListener.h中规定的各种代码入口则构成了一个基本完整的3D/游戏开发框架。
ExampleApplication的运行入口为go()。go()-+-->setup()-+-->createScene()。其中createScene()为纯虚函数。使用场景管理器创建相关实体/灯光的代码应写在ExampleApplication派生类的createScene()中作为对该函数的重写。
特别说明:Ogre采用右手坐标系,其中x/y/z轴的正方向分别为右/上/外。
注:go()-+-->setup()意为在go()函数代码中会包含对setup()的调用。-+-->为个人使用的简记符号,形如一把沾染万千臭气的肮脏利刃。
在用户撰写的派生类中,如果无需对摄像机进行调整,则无需再对其进行声明。因为ExampleApplication中已经对其进行了声明,并使用setup()-+-->createCamera()对其进行设置与初始化:
mCamera->setPosition(Vector3(0,0,500));
mCamera->lookAt(Vector3(0,0,-300));
mCamera->setNearClipDistance(5);
这里,mCamera为ExampleApplication中的protected成员,故可以被其public派生类直接使用。同样以m起始的成员还包括mRoot,mSceneMgr,mFrameListener等。
同样,go()-+-->setup()-+-->createFrameListener()。应该重写该函数,在其中生成适合的FrameListener,并将其注册。如:
//ShrewMouseFrameListener类为用户自定义的FrameListener
mFrameListener= new ShrewMouseFrameListener(_miceManager, mWindow, mCamera);
mRoot->addFrameListener(mFrameListener);
一种比较好的设计方法是,将场景管理器指针mSceneMgr赋予自己的FrameListener类,使其可以在每一帧更新场景。
一种更好的设计方法,是将更新场景的代码封装成一个类作为游戏逻辑管理器(如上面代码中的_miceManager),将mSceneMgr赋予它,再把它赋予自己的FrameListener。
对于逻辑的更新应该写在用户FrameListener中的frameStarted (const FrameEvent &evt)和/或frameEnded (const FrameEvent &evt )中,调用如上文_miceManager一类的游戏逻辑管理器中的相关更新函数。其中evt.timeSinceLastFrame为实用性很强的计时器,可帮助完成游戏逻辑中的各种计时功能,故在逻辑管理器中的更新函数应包含该参数,如:
bool frameEnded(const FrameEvent& evt){
_miceManager->update(evt.timeSinceLastFrame);
return true;
}
在ExampleFrameListener.h中还处理了OIS提供的输入信息,包括键盘(A,S,D,F)与鼠标等。
其中,键盘的控制在函数processUnbufferedKeyInput()中,而鼠标控制在函数processUnbufferedMouseInput()中。
默认的输入处理方式为非缓冲处理方式(ExampleFrameListener的构造函数中键盘,鼠标与手柄参数默认值为false)。可在生成用户FrameListener时制定该三值为true以使用OIS的缓冲模式。
要使用该模式接收键盘输入,应在用户FrameListener类中实现接口OIS::KeyListener,并在构造函数中将自身注册到键盘管理器mKeyboard中以便在键盘发出消息时通过keyPressed()与keyReleased()通知我们,并重写keyPressed()与keyReleased()两个函数(可能需要用一个bool变量监视ESC是否按下,若按下则需要在frameEnded()函数中返回false以在该帧结束时结束程序)。
class ShrewMouseFrameListener: public ExampleFrameListener, public OIS::KeyListener
{
public: ShrewMouseFrameListener(ShrewMouseManager * miceManager, RenderWindow* win, Camera* cam, bool bufferedKeys, bool bufferedMouse, bool bufferedJoy ):ExampleFrameListener(win, cam, bufferedKeys, bufferedMouse, bufferedJoy),_miceManager(miceManager)
{
_exit = false;
mKeyboard->setEventCallback(this);
}
bool keyPressed( const OIS::KeyEvent &arg )
{
...
}
bool keyReleased( const OIS::KeyEvent &arg )
{
...
}
bool frameEnded(const FrameEvent& evt)
{
...
return !_exit;
}
}
根据一些已有的代码研究,游戏逻辑更新画面的设计应采用FrameListener-+-->实体统一管理器-+-->实体个体。其中每一步都要传递场景管理器指针。
该框架的UI需要通过.overlays文件的脚本编写来辅助实现。