前面我們已經學會了如何使用Mogre來建立一個3D遊戲,但是那是建立在一個叫做MogreFramework.dll的基礎上。如果我們想直接利用Ogre的封裝API來創建遊戲,又是如何做到呢?
1.首先需要遵循一定的創建順序。具體來說,包括一下步驟:
CreateRoot();
DefineResources();
SetupRenderSystem();
CreateRenderWindow();
InitResources();
CreateScene();
StartRenderLoop();
下面我們分別解釋。
1)CreateRoot
還記得我們之前說的,在Ogre的世界裏面,對象的組織是按照node的方式來建立的,因此,一開始我們需要建立一個root node。例如:
mRoot = new Root();
2) DefineResources
創建完root node之後,我們需要加載遊戲中所用到的資源。我們一般將資源路徑信息存放在config文件中。因此需要先解析config文件的內容,例如:
ConfigFile cf = new ConfigFile();
cf.Load("resources.cfg", "/t:=", true);
ConfigFile.SectionIterator seci = cf.GetSectionIterator();
String secName, typeName, archName;
while (seci.MoveNext())
{
secName = seci.CurrentKey;
ConfigFile.SettingsMultiMap settings = seci.Current;
foreach (KeyValuePair<string, string> pair in settings)
{
typeName = pair.Key;
archName = pair.Value;
ResourceGroupManager.Singleton.AddResourceLocation(archName, typeName, secName);
}
}
注意,上面的代碼只是解析了資源文件的路徑和類別,但是並沒有將資源加載到內存中。
3)SetupRenderSystem
之後我們需要設置Render System。例如究竟是使用DirectX3D還是OpenGL,是否全屏和顯示模式等。例如:
RenderSystem rs = mRoot.GetRenderSystemByName("Direct3D9 Rendering Subsystem"); // or use "OpenGL Rendering Subsystem"
mRoot.RenderSystem = rs;
rs.SetConfigOption("Full Screen", "No");
rs.SetConfigOption("Video Mode", "800 x 600 @ 32-bit colour");
4)CreateRenderWindow
設置完RenderSystem之後,我們需要創建RenderWindow,就是用來顯示我們以後創建遊戲對象的視窗。例如:
mRoot.Initialise(true, "Main Ogre Window");
如果我們想要將RenderWindow嵌在Windows Form裏面,代碼如下:
NameValuePairList misc = new NameValuePairList();
misc["externalWindowHandle"] = handle.ToString();
RenderWindow win = mRoot.CreateRenderWindow("Main RenderWindow", 800, 600, false, misc);
5)InitializeResourceGroups
在2)中我們制定了資源的路徑和group信息,但是我們並沒有將資源加載到內存中。爲了實現資源加載,我們需要調用:
ResourceGroupManager.Singleton.InitialiseAllResourceGroups();
這樣,我們在遊戲中需要的紋理和貼圖就可以使用了,否則就會看到一個沒有白色的空殼。(如果是一個3D物體的話)
6)CreateScene
準備工作已經就緒,我們可以開始創建遊戲場景了。包括SceneManager, Entity, SceneNode, Camera, Light, Viewport等。具體內容可以查看學習系列的(1)-(4)節。
7)StartRenderingLoop
遊戲場景已經建立完畢,之後我們可以啓動Rendering了。通過功能,遊戲場景會被渲染和顯示出來。
mRoot.StartRendering();
當然了,如果我們希望每次渲染frame的時候都能夠添加自己的控制邏輯,可以使用
while (mRoot.RenderOneFrame())
{
// Do other things here, such as sleep for a short period of time
}
注意,這裏面有一個重要的topic沒有涵蓋,就是Game Input System。通常我們可以使用DirectX Input System.
示例代碼:
using System; using System.Collections.Generic; using System.Windows.Forms; using Mogre; using System.Drawing; namespace Tutorial05 { static class Program { [STAThread] static void Main() { OgreStartup ogre = new OgreStartup(); ogre.Go(); } } class OgreStartup { Root mRoot = null; float ticks = 0; public void Go() { CreateRoot(); DefineResources(); SetupRenderSystem(); CreateRenderWindow(); InitResources(); CreateScene(); StartRenderLoop(); } void CreateRoot() { mRoot = new Root(); } void DefineResources() { ConfigFile cf = new ConfigFile(); cf.Load("resources.cfg", "/t:=", true); ConfigFile.SectionIterator seci = cf.GetSectionIterator(); String secName, typeName, archName; while (seci.MoveNext()) { secName = seci.CurrentKey; ConfigFile.SettingsMultiMap settings = seci.Current; foreach (KeyValuePair<string, string> pair in settings) { typeName = pair.Key; archName = pair.Value; ResourceGroupManager.Singleton.AddResourceLocation(archName, typeName, secName); } } } void SetupRenderSystem() { if (!mRoot.ShowConfigDialog()) throw new Exception("The user canceled the configuration dialog."); //// Setting up the RenderSystem manually. //RenderSystem rs = mRoot.GetRenderSystemByName("Direct3D9 Rendering Subsystem"); // // or use "OpenGL Rendering Subsystem" //mRoot.RenderSystem = rs; //rs.SetConfigOption("Full Screen", "No"); //rs.SetConfigOption("Video Mode", "800 x 600 @ 32-bit colour"); } void CreateRenderWindow() { mRoot.Initialise(true, "Main Ogre Window"); //// Embedding ogre in a windows hWnd. The "handle" variable holds the hWnd. //NameValuePairList misc = new NameValuePairList(); //misc["externalWindowHandle"] = handle.ToString(); //mWindow = mRoot.CreateRenderWindow("Main RenderWindow", 800, 600, false, misc); } void InitResources() { TextureManager.Singleton.DefaultNumMipmaps = 5; ResourceGroupManager.Singleton.InitialiseAllResourceGroups(); } void CreateScene() { SceneManager mgr = mRoot.CreateSceneManager(SceneType.ST_GENERIC); Camera cam = mgr.CreateCamera("Camera"); mRoot.AutoCreatedWindow.AddViewport(cam); Entity ent = mgr.CreateEntity("ninja", "ninja.mesh"); mgr.RootSceneNode.CreateChildSceneNode().AttachObject(ent); cam.Position = new Vector3(0, 200, -400); cam.LookAt(ent.BoundingBox.Center); mRoot.FrameEnded += new FrameListener.FrameEndedHandler(FrameEnded); ticks = Environment.TickCount; } void StartRenderLoop() { mRoot.StartRendering(); //// Alternate Rendering Loop //while (mRoot.RenderOneFrame()) //{ // // Do other things here, such as sleep for a short period of time //} } bool FrameEnded(FrameEvent evt) { if (Environment.TickCount - ticks > 5000) return false; return true; } } }