OGRE+CEGUI游戏教程(1)----GUI框架
2011-10-30 02:34
465 查看
转载文章请注明出处: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
class MyGUISystem
{
public:
virtual ~MyGUISystem();
//把OIS的鼠标ID转换成CEGUI的鼠标ID
static CEGUI::MouseButton convertButton(OIS::MouseButtonID buttonId);
//销毁资源
bool destroy();
//初始化CEGUI, 必须在RenderWindow创始后初始, 只在第一次调用有效
bool init();
//GUI更新
void update(float timeSinceLastFrame);
/**
根据图片构造Imageset
params:
@name 创建的Imageset名称, 全局唯一
@filename 创建Imageset的图片名称
*/
static void createImageset(const std::string& name, const std::string& filename);
//加载layout
bool loadLayout(const std::string& layoutName);
//得到指定名称的窗口
inline CEGUI::Window* getWindow(const std::string& windowName)
{
return getGUIWindowManager()->getWindow(windowName);
}
//销毁指定名称的窗口
bool destroyWindow(const std::string& windowName);
/*
* 给指定名称的窗口设定属性
params:
@windowName 窗口名称
@key XML标签 key值
@value XML标签 value值
*/
static void setProperty(const std::string& windowName, const std::string& key,
const std::string& value);
/**
注册CEGUI控件事件
params:
@windowName 要注册事件的控件名称
@eventName 注册的控件事件
@subscriber 事件触发时的回调函数
*/
static void subscribeEvent(const CEGUI::String& windowName,
const CEGUI::String &eventName,
const CEGUI::Event::Subscriber &subscriber);
//得到窗口管理器,用来获取管理GUI的窗口对象的管理器
inline CEGUI::WindowManager* getGUIWindowManager()
{
return CEGUI::WindowManager::getSingletonPtr();
}
// 注入CEGUI鼠标点击事件
bool injectMouseButtonDown(CEGUI::MouseButton id)
{
return mGUISystem->injectMouseButtonDown(id);
}
bool injectMouseButtonUp(CEGUI::MouseButton id)
{
return mGUISystem->injectMouseButtonUp(id);
}
// 注入CEGUI鼠标移动事件
bool injectMouseMove(float xRel, float yRel)
{
return mGUISystem->injectMouseMove(xRel, yRel);
}
//显示/隐藏GUI鼠标
inline void showGUICursor(bool showCursor)
{
if(showCursor)
{
CEGUI::MouseCursor::getSingleton().show();
}
else
{
CEGUI::MouseCursor::getSingleton().hide();
}
//隐藏系统鼠标
ShowCursor(false);
}
/*
* 设置默认鼠标样式
params:
@schemeName 样式名称
@mouseName 样式中的鼠标名称
*/
inline void setDefaultMouseCursor(const std::string& schemeName, const std::string& mouseName)
{
CEGUI::System::getSingleton().setDefaultMouseCursor(schemeName, mouseName);
CEGUI::MouseCursor::getSingleton().setImage(mGUISystem->getDefaultMouseCursor());
}
public:
/*
* 单件实例方法
*/
static MyGUISystem* getSingletonPtr()
{
if(ms_singleton == NULL)
{
ms_singleton = new MyGUISystem;
}
return ms_singleton;
}
private:
//单件实例指针
static MyGUISystem* ms_singleton;
private:
CEGUI::OgreRenderer* mGUIRender;
CEGUI::System* mGUISystem;
private:
/*
* 私有化实例函数,实现单件
*/
MyGUISystem()
:mGUIRender(0), mGUISystem(0)
{}
MyGUISystem(const MyGUISystem&);
MyGUISystem& operator=(const MyGUISystem&);
};
这里采用一个简单的单价模式来实现GUI系统。 其中最重要的方法是 loadLayout,createImageset , setProperty和subscribeEvent。
loadLayout方法主要是载入layout,但是传入的参数是指定layout的根窗口,把它作为GUISheet进行显示。
createImageset是载入图片资源让CEGUI转化为纹理供有StaticImage的地方使用。
setProperty主要用来设置窗口的属性,尤其是StaticImage的设置。
subscribeEvent用来注册GUI事件。
下面是实现文件:
MyGUISystem.cpp
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,然后写上:
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的动画效果。
源码和可执行程序链接http://code.google.com/p/pizzaprojects/downloads/list
今天起我会陆续更新一些原创的Ogre结合CEGUI的游戏教程。想到什么就做什么,没有固定的内容,不过基本是游戏里可以用到的。
请先确保学习完了Ogre Wiki上的基础和中级教程后再来讨论这里的教程。因为一些基础的Ogre知识这里不会多做解释。
今天先建立一个用来演示的框架。其中我们已经有了BaseFramework框架,这个框架里已经帮你弄好了一些资源、场景管理器等设置,当然还有一个Overlay,但我们的GUI不打算使用Overlay,所以我们需要一个GUI框架。所以赶紧来做一个GUI框架使用吧!
MyGUISystem.h
class MyGUISystem
{
public:
virtual ~MyGUISystem();
//把OIS的鼠标ID转换成CEGUI的鼠标ID
static CEGUI::MouseButton convertButton(OIS::MouseButtonID buttonId);
//销毁资源
bool destroy();
//初始化CEGUI, 必须在RenderWindow创始后初始, 只在第一次调用有效
bool init();
//GUI更新
void update(float timeSinceLastFrame);
/**
根据图片构造Imageset
params:
@name 创建的Imageset名称, 全局唯一
@filename 创建Imageset的图片名称
*/
static void createImageset(const std::string& name, const std::string& filename);
//加载layout
bool loadLayout(const std::string& layoutName);
//得到指定名称的窗口
inline CEGUI::Window* getWindow(const std::string& windowName)
{
return getGUIWindowManager()->getWindow(windowName);
}
//销毁指定名称的窗口
bool destroyWindow(const std::string& windowName);
/*
* 给指定名称的窗口设定属性
params:
@windowName 窗口名称
@key XML标签 key值
@value XML标签 value值
*/
static void setProperty(const std::string& windowName, const std::string& key,
const std::string& value);
/**
注册CEGUI控件事件
params:
@windowName 要注册事件的控件名称
@eventName 注册的控件事件
@subscriber 事件触发时的回调函数
*/
static void subscribeEvent(const CEGUI::String& windowName,
const CEGUI::String &eventName,
const CEGUI::Event::Subscriber &subscriber);
//得到窗口管理器,用来获取管理GUI的窗口对象的管理器
inline CEGUI::WindowManager* getGUIWindowManager()
{
return CEGUI::WindowManager::getSingletonPtr();
}
// 注入CEGUI鼠标点击事件
bool injectMouseButtonDown(CEGUI::MouseButton id)
{
return mGUISystem->injectMouseButtonDown(id);
}
bool injectMouseButtonUp(CEGUI::MouseButton id)
{
return mGUISystem->injectMouseButtonUp(id);
}
// 注入CEGUI鼠标移动事件
bool injectMouseMove(float xRel, float yRel)
{
return mGUISystem->injectMouseMove(xRel, yRel);
}
//显示/隐藏GUI鼠标
inline void showGUICursor(bool showCursor)
{
if(showCursor)
{
CEGUI::MouseCursor::getSingleton().show();
}
else
{
CEGUI::MouseCursor::getSingleton().hide();
}
//隐藏系统鼠标
ShowCursor(false);
}
/*
* 设置默认鼠标样式
params:
@schemeName 样式名称
@mouseName 样式中的鼠标名称
*/
inline void setDefaultMouseCursor(const std::string& schemeName, const std::string& mouseName)
{
CEGUI::System::getSingleton().setDefaultMouseCursor(schemeName, mouseName);
CEGUI::MouseCursor::getSingleton().setImage(mGUISystem->getDefaultMouseCursor());
}
public:
/*
* 单件实例方法
*/
static MyGUISystem* getSingletonPtr()
{
if(ms_singleton == NULL)
{
ms_singleton = new MyGUISystem;
}
return ms_singleton;
}
private:
//单件实例指针
static MyGUISystem* ms_singleton;
private:
CEGUI::OgreRenderer* mGUIRender;
CEGUI::System* mGUISystem;
private:
/*
* 私有化实例函数,实现单件
*/
MyGUISystem()
:mGUIRender(0), mGUISystem(0)
{}
MyGUISystem(const MyGUISystem&);
MyGUISystem& operator=(const MyGUISystem&);
};
这里采用一个简单的单价模式来实现GUI系统。 其中最重要的方法是 loadLayout,createImageset , setProperty和subscribeEvent。
loadLayout方法主要是载入layout,但是传入的参数是指定layout的根窗口,把它作为GUISheet进行显示。
createImageset是载入图片资源让CEGUI转化为纹理供有StaticImage的地方使用。
setProperty主要用来设置窗口的属性,尤其是StaticImage的设置。
subscribeEvent用来注册GUI事件。
下面是实现文件:
MyGUISystem.cpp
#include "MyGUISystem.h" #include <cassert> //----------------------------------------------------------------------------- MyGUISystem* MyGUISystem::ms_singleton = NULL; //----------------------------------------------------------------------------- MyGUISystem::~MyGUISystem() { destroy(); } //----------------------------------------------------------------------------- bool MyGUISystem::destroy() { CEGUI::OgreRenderer::destroySystem(); delete ms_singleton; ms_singleton = 0; return true; } //----------------------------------------------------------------------------- CEGUI::MouseButton MyGUISystem::convertButton(OIS::MouseButtonID buttonId) { switch(buttonId) { case OIS::MB_Left: return CEGUI::LeftButton; case OIS::MB_Right: return CEGUI::RightButton; case OIS::MB_Middle: return CEGUI::MiddleButton; default: return CEGUI::LeftButton; } } //----------------------------------------------------------------------------- bool MyGUISystem::init() { if(!mGUIRender) { mGUIRender = &CEGUI::OgreRenderer::bootstrapSystem(); mGUISystem = CEGUI::System::getSingletonPtr(); //加载GUI主题, 设置默认参数 CEGUI::Imageset::setDefaultResourceGroup("Imagesets"); CEGUI::Font::setDefaultResourceGroup("Fonts"); CEGUI::Scheme::setDefaultResourceGroup("Schemes"); CEGUI::WidgetLookManager::setDefaultResourceGroup("LookNFeel"); CEGUI::WindowManager::setDefaultResourceGroup("Layouts"); CEGUI::SchemeManager::getSingleton().create("TaharezLook.scheme"); CEGUI::FontManager::getSingleton().create("SimHei-14.font"); mGUISystem->setDefaultFont("SimHei-14"); /* * 此处设置图片资源(Imageset) */ //设置默认鼠标样式 setDefaultMouseCursor("TaharezLook", "MouseArrow"); //设置GUI鼠标是否可见 showGUICursor(true); return true; } return false; } //----------------------------------------------------------------------------- void MyGUISystem::update(float timeSinceLastFrame) { mGUISystem->injectTimePulse(timeSinceLastFrame); } //----------------------------------------------------------------------------- void MyGUISystem::createImageset(const std::string& name, const std::string& filename) { CEGUI::ImagesetManager::getSingleton().createFromImageFile(name, filename); } //----------------------------------------------------------------------------- bool MyGUISystem::loadLayout(const std::string& layoutName) { CEGUI::Window *guiSheet; // 检测给定layout的文件是否加载,没有加载则加载 if(!getGUIWindowManager()->isWindowPresent(layoutName)) { // 从 .layout脚本文件读取一个UI布局设计,并将其放置到GUI资源组中。 guiSheet = getGUIWindowManager()->loadWindowLayout(layoutName + ".layout"); } else { // 如果已经加载则直接显示 guiSheet = getGUIWindowManager()->getWindow(layoutName); } // 接下来我们告诉CEGUI显示哪份UI布局。当然我们可以随时更换显示的UI布局。 mGUISystem->setGUISheet(guiSheet); //显示UI布局 guiSheet->show(); return true; } //----------------------------------------------------------------------------- bool MyGUISystem::destroyWindow(const std::string& windowName) { getGUIWindowManager()->destroyWindow(windowName); return true; } //----------------------------------------------------------------------------- void MyGUISystem::subscribeEvent(const CEGUI::String& windowName, const CEGUI::String &eventName, const CEGUI::Event::Subscriber &subscriber) { CEGUI::WindowManager::getSingleton().getWindow(CEGUI::String(windowName)) ->subscribeEvent(eventName,subscriber); } //----------------------------------------------------------------------------- void MyGUISystem::setProperty(const std::string& windowName, const std::string& key, const std::string& value) { MyGUISystem::getSingletonPtr()->getWindow(windowName)->setProperty(key, value); } //-----------------------------------------------------------------------------
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,然后写上:
<?xml version="1.0" ?> <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的动画效果。
相关文章推荐
- OGRE+CEGUI游戏教程(1)----GUI框架
- OGRE+CEGUI游戏教程(1)----GUI框架
- OGRE+CEGUI游戏教程(4)----游戏逻辑脚本
- OGRE+CEGUI游戏教程(3)----角色创建
- OGRE+CEGUI游戏教程(5)--物品/装备和技能系统
- OGRE+CEGUI游戏教程(4)----游戏逻辑脚本
- OGRE+CEGUI游戏教程(2)----NPC对话演示
- OGRE+CEGUI游戏教程(5)--物品/装备和技能系统
- OGRE+CEGUI游戏教程(3)----角色创建
- OGRE+CEGUI游戏教程(4)----游戏逻辑脚本
- OGRE+CEGUI游戏教程(5)--物品/装备和技能系统
- OGRE+CEGUI游戏教程(2)----NPC对话演示
- OGRE+CEGUI游戏教程(3)----角色创建
- OGRE+CEGUI游戏教程(2)----NPC对话演示
- 关于OGRE基础教程6中CEGUI的layout文件can not locate的问题
- OGRE基础教程七 CEGUI and Ogre
- OGRE 引擎官方基础教程 (七) OGRE 和 CEGUI
- Ogre基础教程7:CEGUI 与 Ogre(未完成)
- Ogre笔记九:基础教程六—CEGUI和Ogre
- Ogre中级教程(九): 深入CEGUI