关于引擎本身不再多加描述,我也没搞明白,但是最近又要用,学习ing
首先这次先生成一个空白窗口,不使用SDK带的Example。
文件:
MyApplication.h
MyListener.h
main.cpp
首先需要了解一下Ogre程序的基本结构,在Ogre里使用一个叫场景管理器(SceneManager)的类来管理在屏幕上显示的各种物体,
这个类是个抽象类(class Ogre::SceneManager abstract),只起到定义接口的作用。
不可以直接实例化这个类,只能由Root节点调用createSceneManager方法来生成特定类型的SceneManager
OGRE里有很多种场景管理器。有的场景管理器渲染地面,有的场景管理器渲染BSP表等等。
与场景(Scene)相关的概念:实体,节点。
实体:简单的说实体就相当于空间中的一个物体,例如游戏中的一个角色。
场景节点:要想在场景中使用实体,必须还要用到节点(SceneNode),它会与实体绑定在一起,当控制这个节点进行各种位移旋转操作时
其对应的实体也就跟着相应的进行操作。
##注:
根据以前玩游戏的经验,在游戏(比如飞行射击)中判断一个物体是否被打中也都是以圆点为中心的一个区域而非物体(飞机)本身
外壳的形状可能也是由于这个原因。
##
接下来再来了解一下一个重要的函数void MyApplication::go()
这是一个入口函数,这一次在我的main方法里就只有两行代码:
MyApplication app;
app.go();
现在来看看go里有做了些什么事情。
void go()
{
//step 1 to 3 should be in this order
CreateRoot();
SetupRenderSystem();
CreateRenderWindow();
SetupInputSystem();
CreateFrameListener();
StartRenderLoop();
}
前面的三步需要按特定的顺序来进行,后面的则不一定。各个函数的功能由函数名自说明了,内容也很简单。
调用go后,首先需要创建根节点m_pRoot = new Root()这是整个引擎中最核心的一个对象,在做其它事情前必须要首先创建它。
接下来设置渲染系统SetupRenderSystem() :
if(!m_pRoot->showConfigDialog())
exit(0);
Ogre有个默认的设置对话框,直接调用它就可以了,如果用户取消这一步,那么直接退出程序就好。
创建窗口这一步,可以有多种选择,因为部分内容跟具体的操作系统相关,可以使用Windows SDK或者MFC生成窗口,也可以使用
Ogre默认的窗口系统,为了简便,这里使用Ogre默认窗口
m_pRoot->initialise(true, "MyApplication Rendering Window");
由于是空的窗口,所以不需要生成场景及做相关的工作。在这次的程序中,将要监听一个键盘事件,按下ESC的时候退出程序。
这部分工作在接下的两个函数SetupInputSystem和CreateFrameListener中完成。
FrameListener是一个帧监听器,显示器上的图像都是一帧一帧的显示出来的,我们可以在这切换这些帧的时候做一些处理工作,
比如,获取和处理键盘事件。在Ogre的主循环中大概可能会是这个样子:
- Root object调用frameStarted方法在所有已经注册的FrameListeners中。
- Root object渲染一帧。
- Root object调用frameEnded方法在所有已经注册的FrameListeners中。
在这里添加一个MyListener类用来做这件事情。
class CombatListener : public FrameListener
{
public:
CombatListener(OIS::Keyboard *pkeyboard)
: m_pKeyboard(pkeyboard)
{
}
bool frameStarted(const FrameEvent& evt)
{
m_pKeyboard->capture();
return !(m_pKeyboard->isKeyDown(OIS::KC_ESCAPE));
}
private:
OIS::Keyboard *m_pKeyboard;
};
同样的,Ogre也已经准备好了一个基类,只需要继承再稍加修改就可以了,其中OIS是
Object Oriented Input System,
它本身不属于Ogre,是一个简单易用的跨平台开源系统,可以用它来处理键盘鼠标和游戏手柄等设备。
这里我在每一帧开始的时候获取键盘状态,当ESC键按下时,返回false,这将导致程序正常退出。
OIS使用一个统一的InputManager,它比较难配置,但一旦正确地创建之后,非常好使用。
首先在SetupInputSystem方法中加入
size_t windowHnd = 0;
std::ostringstream windowHndStr;
OIS::ParamList pl;
RenderWindow *win = m_pRoot->getAutoCreatedWindow();
win->getCustomAttribute("WINDOW", &windowHnd);
windowHndStr<<windowHnd;
pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
m_pInputManager = OIS::InputManager::createInputSystem(pl);
说明一点,getCustomAttribute方法的功能是用来获取特定平台的信息,在API上用一个词Horrid来形容这个方法,哈哈,无奈D3D需要这些信息。
下面再把下面的代码回到SetupInputSystem方法中就OK了。
try
{
m_pKeyboard = static_cast<OIS::Keyboard*>(
m_pInputManager->createInputObject(OIS::OISKeyboard, false));
}
catch(const OIS::Exception &e)
{
throw Exception(42, e.eText, "MyApplication::SetupInputSystem()");
}
InputSystem设置好了,就可以使用帧监听器了,在创建帧监听器的方法中:
m_pListener = new MyListener(m_pKeyboard);
m_pRoot->addFrameListener(m_pListener);
好,到这里程序基本上完成了,剩下只需要启动渲染循环(StartRenderLoop)就可以让程序跑起来了
m_pRoot->startRendering();