關于引擎本身不再多加描述,我也沒搞明白,但是最近又要用,學習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();