OGRE+CEGUI游戏教程(1)----GUI框架

 转载文章请注明出处:http://blog.csdn.net/pizzazhang 

  源码和可执行程序链接http://code.google.com/p/pizzaprojects/downloads/list

  今天起我会陆续更新一些原创的Ogre结合CEGUI的游戏教程。想到什么就做什么,没有固定的内容,不过基本是游戏里可以用到的。 

  请先确保学习完了Ogre Wiki上的基础和中级教程后再来讨论这里的教程。因为一些基础的Ogre知识这里不会多做解释。

  今天先建立一个用来演示的框架。其中我们已经有了BaseFramework框架,这个框架里已经帮你弄好了一些资源、场景管理器等设置,当然还有一个Overlay,但我们的GUI不打算使用Overlay,所以我们需要一个GUI框架。所以赶紧来做一个GUI框架使用吧!

 

MyGUISystem.h

[cpp]  view plain copy
  1. class MyGUISystem  
  2. {  
  3. public:  
  4.     virtual ~MyGUISystem();  
  5.     //把OIS的鼠标ID转换成CEGUI的鼠标ID  
  6.     static CEGUI::MouseButton convertButton(OIS::MouseButtonID buttonId);  
  7.     //销毁资源  
  8.     bool destroy();  
  9.     //初始化CEGUI, 必须在RenderWindow创始后初始, 只在第一次调用有效  
  10.     bool init();  
  11.     //GUI更新  
  12.     void update(float timeSinceLastFrame);  
  13.     /** 
  14.     根据图片构造Imageset 
  15.     params: 
  16.     @name       创建的Imageset名称, 全局唯一 
  17.     @filename   创建Imageset的图片名称 
  18.     */  
  19.     static void createImageset(const std::string& name, const std::string& filename);  
  20.     //加载layout  
  21.     bool loadLayout(const std::string& layoutName);  
  22.     //得到指定名称的窗口  
  23.     inline CEGUI::Window* getWindow(const std::string& windowName)   
  24.     {  
  25.         return getGUIWindowManager()->getWindow(windowName);   
  26.     }  
  27.     //销毁指定名称的窗口  
  28.     bool destroyWindow(const std::string& windowName);  
  29.     /* 
  30.     *   给指定名称的窗口设定属性 
  31.     params: 
  32.     @windowName 窗口名称 
  33.     @key            XML标签  key值 
  34.     @value          XML标签  value值 
  35.     */  
  36.     static void setProperty(const std::string& windowName, const std::string& key,   
  37.         const std::string& value);  
  38.     /** 
  39.     注册CEGUI控件事件 
  40.     params: 
  41.     @windowName     要注册事件的控件名称 
  42.     @eventName      注册的控件事件 
  43.     @subscriber     事件触发时的回调函数 
  44.     */  
  45.     static void subscribeEvent(const CEGUI::String& windowName,   
  46.         const CEGUI::String &eventName,   
  47.         const CEGUI::Event::Subscriber &subscriber);  
  48.     //得到窗口管理器,用来获取管理GUI的窗口对象的管理器  
  49.     inline CEGUI::WindowManager* getGUIWindowManager()  
  50.     {  
  51.         return CEGUI::WindowManager::getSingletonPtr();  
  52.     }  
  53.     // 注入CEGUI鼠标点击事件  
  54.     bool injectMouseButtonDown(CEGUI::MouseButton id)   
  55.     {  
  56.         return mGUISystem->injectMouseButtonDown(id);  
  57.     }  
  58.     bool injectMouseButtonUp(CEGUI::MouseButton id)   
  59.     {  
  60.         return mGUISystem->injectMouseButtonUp(id);   
  61.     }  
  62.     // 注入CEGUI鼠标移动事件  
  63.     bool injectMouseMove(float xRel, float yRel)  
  64.     {  
  65.         return mGUISystem->injectMouseMove(xRel, yRel);  
  66.     }  
  67.     //显示/隐藏GUI鼠标  
  68.     inline void showGUICursor(bool showCursor)  
  69.     {  
  70.         if(showCursor)  
  71.         {  
  72.             CEGUI::MouseCursor::getSingleton().show();  
  73.         }  
  74.         else  
  75.         {  
  76.             CEGUI::MouseCursor::getSingleton().hide();  
  77.         }  
  78.         //隐藏系统鼠标  
  79.         ShowCursor(false);  
  80.     }  
  81.     /* 
  82.     *   设置默认鼠标样式 
  83.     params: 
  84.     @schemeName 样式名称 
  85.     @mouseName      样式中的鼠标名称 
  86.     */  
  87.     inline void setDefaultMouseCursor(const std::string& schemeName, const std::string& mouseName)   
  88.     {  
  89.         CEGUI::System::getSingleton().setDefaultMouseCursor(schemeName, mouseName);  
  90.         CEGUI::MouseCursor::getSingleton().setImage(mGUISystem->getDefaultMouseCursor());  
  91.     }  
  92. public:  
  93.     /* 
  94.     *   单件实例方法 
  95.     */  
  96.     static MyGUISystem* getSingletonPtr()  
  97.     {  
  98.         if(ms_singleton == NULL)  
  99.         {  
  100.             ms_singleton = new MyGUISystem;  
  101.         }  
  102.         return ms_singleton;  
  103.     }  
  104. private:  
  105.     //单件实例指针  
  106.     static MyGUISystem* ms_singleton;  
  107. private:  
  108.     CEGUI::OgreRenderer* mGUIRender;  
  109.     CEGUI::System*       mGUISystem;  
  110. private:  
  111.     /* 
  112.     *   私有化实例函数,实现单件 
  113.     */  
  114.     MyGUISystem()  
  115.         :mGUIRender(0), mGUISystem(0)  
  116.     {}  
  117.     MyGUISystem(const MyGUISystem&);  
  118.     MyGUISystem& operator=(const MyGUISystem&);  
  119. };  

这里采用一个简单的单价模式来实现GUI系统。 其中最重要的方法是 loadLayout,createImageset , setProperty和subscribeEvent。

 loadLayout方法主要是载入layout,但是传入的参数是指定layout的根窗口,把它作为GUISheet进行显示。

createImageset是载入图片资源让CEGUI转化为纹理供有StaticImage的地方使用。

setProperty主要用来设置窗口的属性,尤其是StaticImage的设置。

subscribeEvent用来注册GUI事件。

 

下面是实现文件:

MyGUISystem.cpp

[cpp]  view plain copy
  1. #include "MyGUISystem.h"  
  2. #include <cassert>  
  3. //-----------------------------------------------------------------------------  
  4. MyGUISystem* MyGUISystem::ms_singleton = NULL;  
  5. //-----------------------------------------------------------------------------  
  6. MyGUISystem::~MyGUISystem()  
  7. {  
  8.     destroy();  
  9. }  
  10. //-----------------------------------------------------------------------------  
  11. bool MyGUISystem::destroy()  
  12. {  
  13.     CEGUI::OgreRenderer::destroySystem();  
  14.     delete ms_singleton;  
  15.     ms_singleton = 0;  
  16.     return true;  
  17. }  
  18. //-----------------------------------------------------------------------------  
  19. CEGUI::MouseButton MyGUISystem::convertButton(OIS::MouseButtonID buttonId)  
  20. {  
  21.     switch(buttonId)  
  22.     {  
  23.     case OIS::MB_Left:  
  24.         return CEGUI::LeftButton;  
  25.     case OIS::MB_Right:  
  26.         return CEGUI::RightButton;  
  27.     case OIS::MB_Middle:  
  28.         return CEGUI::MiddleButton;  
  29.     default:  
  30.         return CEGUI::LeftButton;  
  31.     }  
  32. }  
  33. //-----------------------------------------------------------------------------  
  34. bool MyGUISystem::init()  
  35. {  
  36.     if(!mGUIRender)  
  37.     {  
  38.         mGUIRender = &CEGUI::OgreRenderer::bootstrapSystem();  
  39.         mGUISystem = CEGUI::System::getSingletonPtr();  
  40.         //加载GUI主题, 设置默认参数  
  41.         CEGUI::Imageset::setDefaultResourceGroup("Imagesets");  
  42.         CEGUI::Font::setDefaultResourceGroup("Fonts");  
  43.         CEGUI::Scheme::setDefaultResourceGroup("Schemes");  
  44.         CEGUI::WidgetLookManager::setDefaultResourceGroup("LookNFeel");  
  45.         CEGUI::WindowManager::setDefaultResourceGroup("Layouts");  
  46.         CEGUI::SchemeManager::getSingleton().create("TaharezLook.scheme");  
  47.         CEGUI::FontManager::getSingleton().create("SimHei-14.font");  
  48.         mGUISystem->setDefaultFont("SimHei-14");  
  49.         /* 
  50.          *  此处设置图片资源(Imageset) 
  51.          */  
  52.         //设置默认鼠标样式  
  53.         setDefaultMouseCursor("TaharezLook""MouseArrow");  
  54.         //设置GUI鼠标是否可见  
  55.         showGUICursor(true);  
  56.         return true;  
  57.     }  
  58.     return false;  
  59. }  
  60. //-----------------------------------------------------------------------------  
  61. void MyGUISystem::update(float timeSinceLastFrame)  
  62. {  
  63.     mGUISystem->injectTimePulse(timeSinceLastFrame);  
  64. }  
  65. //-----------------------------------------------------------------------------  
  66. void MyGUISystem::createImageset(const std::string& name, const std::string& filename)  
  67. {  
  68.     CEGUI::ImagesetManager::getSingleton().createFromImageFile(name, filename);  
  69. }  
  70. //-----------------------------------------------------------------------------  
  71. bool MyGUISystem::loadLayout(const std::string& layoutName)  
  72. {  
  73.     CEGUI::Window *guiSheet;  
  74.     // 检测给定layout的文件是否加载,没有加载则加载  
  75.     if(!getGUIWindowManager()->isWindowPresent(layoutName))  
  76.     {  
  77.         // 从 .layout脚本文件读取一个UI布局设计,并将其放置到GUI资源组中。  
  78.         guiSheet = getGUIWindowManager()->loadWindowLayout(layoutName + ".layout");  
  79.     }  
  80.     else  
  81.     {     
  82.         // 如果已经加载则直接显示  
  83.         guiSheet = getGUIWindowManager()->getWindow(layoutName);  
  84.     }  
  85.     // 接下来我们告诉CEGUI显示哪份UI布局。当然我们可以随时更换显示的UI布局。  
  86.     mGUISystem->setGUISheet(guiSheet);  
  87.     //显示UI布局  
  88.     guiSheet->show();  
  89.     return true;  
  90. }  
  91. //-----------------------------------------------------------------------------  
  92. bool MyGUISystem::destroyWindow(const std::string& windowName)  
  93. {  
  94.     getGUIWindowManager()->destroyWindow(windowName);  
  95.     return true;  
  96. }  
  97. //-----------------------------------------------------------------------------  
  98. void MyGUISystem::subscribeEvent(const CEGUI::String& windowName,  
  99.     const CEGUI::String &eventName, const CEGUI::Event::Subscriber &subscriber)  
  100. {  
  101.     CEGUI::WindowManager::getSingleton().getWindow(CEGUI::String(windowName))  
  102.         ->subscribeEvent(eventName,subscriber);  
  103. }  
  104. //-----------------------------------------------------------------------------  
  105. void MyGUISystem::setProperty(const std::string& windowName,   
  106.     const std::string& key, const std::string& value)  
  107. {  
  108.     MyGUISystem::getSingletonPtr()->getWindow(windowName)->setProperty(key, value);  
  109. }  
  110. //-----------------------------------------------------------------------------  

update中我们让GUI系统更新时间,如果你需要实现GUI的动画效果,那么这个方法必须在Ogre的每帧进行调用。

在init中我们设置了GUI的一些默认资源,其中的字体我使用的是黑体14号。这是一个中文字体,CEGUI本身是使用UTF-8编码的,那么理论上是可以显示中文的。但是还需要一些小小的步骤才行。

 

CEGUI中显示中文的步骤:

1. 将编辑好的layout文件使用VC Studio打开(不要使用记事本),然后在文件->高级保存选项中把文件保存为UTF-8。

2.从WINDOW/Fonts文件夹中找一个中文字体的文件, 比如我使用的simhei.ttf

3.新建一个xml字体文件, 比如SimHei-14.Font,然后写上:

[html]  view plain copy
  1. <?xml version="1.0" ?>  
  2. <Font Name="SimHei-14" Filename="simhei.ttf" Type="FreeType" Size="14" NativeHorzRes="1024" NativeVertRes="768" AutoScaled="true"/>  

Name就是我们需要在程序中使用的字体名。

4.之后可以直接在layout文件中 有Text属性的地方使用中文, 如果要在代码中设置Text的中文,需要这么使用:

CEGUI::String str = (CEGUI::utf8*)Ogre::UTFString(L"你需要的中文").asUTF8_c_str()

 

这个GUI框架的使用很简单, 在Ogre窗口配置好后,使用MyGUISystem::getSingletonPtr()->init()对GUI系统初始化, 在Ogre渲染循环里对GUI系统update, 然后就可以使用了。

 

下篇文章会使用这个框架做一个游戏里要找NPC对话, 点击NPC后镜头与NPC拉近,然后弹出GUI对话框, 如果要退出游戏按ESC弹出退出的GUI菜单,并且带有GUI的动画效果。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
CEGUI(Crazy Eddie’s GUI http://www.cegui.org.uk)是一个自由免费的GUI库,基于LGPL协议,使用C++实现,完全面向对象设计。CEGUI开发者的目的是希望能够让游戏开发人员从繁琐的GUI实现细节中抽身出来,以便有更多的开发时间可以放在游戏性上。 CEGUI的渲染需要3D图形API的支持,如OpenGL或Direct3D。另外,使用更高级的图形库也是可以的,比如OGRE、Irrlicht和RenderWare等,关键需求可以简化为二点: 纹理(Texture)的支持直接写屏(RHW的顶点格式、正交投影、或者使用shader实现) 本书截止日时,CEGUI的最新版本是0.6.0(本书的讨论也是基于此版本),本书光盘提供了SDK和全部源码的下载。 除此之外,CEGUI还同步提供了官方界面编辑器LayoutEditor和ImageSet编辑器,以方便UI和图像集的制作。作为界面编辑器,它需要系统级界面以提供编辑器操作,0.3.0版是基于MFC实现的;而在0.4.0版本以后,改为基于wxWidgets(跨平台的本地UI框架,这里的UI指Window操作系统底层,如:Windows、Unix和Mac,详见http://www.wxwidgets.org)实现。 目前将CEGUI作为游戏界面库开发的游戏已经有好多种,国内的天龙八部,巨人等游戏就是很好的例子。 CEGUI的功能是非常强大的,而且使用也非常的灵活,可以和脚本配合。可以通过配置文件自定义窗口外观。通过布局文件实现窗口布局等等特性,使得游戏的界面开发更加方便。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值