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

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

这次主要做了一个角色创建的小Demo。 用了火炬之光里面的图片资源(谁让这个游戏是用Ogre开发的呢,大爱)。

  • 使用了 CEGUI的ImageButton
  • 使用了文本窗口的一些特殊属性
  • 使用了输入框输入英文(暂时不支持输入法)。

效果图:选择角色, 第一个头像图片是鼠标移动上去的效果。

第二个头像图片是鼠标点击后的效果

点击头像后,会有人物出现。人物会原地播放动画。 当在输入框中输入名字的时候, 会出现开始按钮。 如果删除掉名字, 开始按钮消失。

开始游戏后,载入另一个UI

下面是实现过程。

先把代码贴上:

Main.cpp

#include "MyGUISystem.h"
#include "BaseApplication.h"
using namespace Ogre;
class Demo : public BaseApplication
{enum CharaType{CHARA_A,ChARA_B,CHARA_C};
public:Demo():mCharaAnimState1(0), mCharaAnimState2(0){ }virtual ~Demo(){   }bool frameRenderingQueued(const Ogre::FrameEvent& evt){if(mShutDown)return false;//这里需要update否则Tooltip不会显示MyGUISystem::getSingletonPtr()->update(evt.timeSinceLastFrame);//这里需要addTime才能使动画动起来if(mCharaAnimState1)mCharaAnimState1->addTime(evt.timeSinceLastFrame);if(mCharaAnimState2)mCharaAnimState2->addTime(evt.timeSinceLastFrame);return BaseApplication::frameRenderingQueued(evt);}void createScene(){mCharaNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();mCharaEntA = mSceneMgr->createEntity("sinbad", "sinbad.mesh");mCharaEntB = mSceneMgr->createEntity("jaiqua", "jaiqua.mesh");mCharaEntC = mSceneMgr->createEntity("ninja", "ninja.mesh");createParticle();setupGUI();}void setupGUI(){MyGUISystem::getSingletonPtr()->init();//角色图片按钮的Imageset创建CEGUI::ImagesetManager::getSingleton().create("chara_image.imageset");//载入角色创建窗口MyGUISystem::getSingletonPtr()->loadLayout("CharaCreateWindow");MyGUISystem::getSingletonPtr()->getWindow("StartBtn")->hide();//创建图片资源MyGUISystem::createImageset("CharaIntroA", "chara_introa.tga");MyGUISystem::createImageset("CharaIntroB", "chara_introb.tga");MyGUISystem::createImageset("CharaIntroC", "chara_introc.tga");//从XML载入动画CEGUI::AnimationManager::getSingleton().loadAnimationsFromXML("Intro_Anim.xml");createGUIEvent();}void createGUIEvent(){MyGUISystem::subscribeEvent("CharaImgBtnA", CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&Demo::charaSelctedHandler, this));MyGUISystem::subscribeEvent("CharaImgBtnB", CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&Demo::charaSelctedHandler, this));MyGUISystem::subscribeEvent("CharaImgBtnC", CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&Demo::charaSelctedHandler, this));//当输入框中的文本变化时触发的事件MyGUISystem::subscribeEvent("NameInputbox", CEGUI::Editbox::EventTextChanged,CEGUI::Event::Subscriber(&Demo::inputAcceptedHandler, this));MyGUISystem::subscribeEvent("StartBtn", CEGUI::PushButton::EventClicked,CEGUI::Event::Subscriber(&Demo::startHandler, this));}void createLight(){mSceneMgr->setAmbientLight(ColourValue(0.3, 0.3, 0.3));mSceneMgr->createLight()->setPosition(20, 80, 50);}void createParticle(){//创建一个粒子系统Ogre::ParticleSystem* particle = mSceneMgr->createParticleSystem("chara_particle", "chara_particle");Ogre::SceneNode* particleNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();particleNode->attachObject(particle);particleNode->setPosition(0, -25, 0);}void createChara(CharaType charaType){//因为只用一个场景节点绑定个对象,所以这里要重置所有位置、方位和缩放参数mCharaNode->detachAllObjects();mCharaNode->resetOrientation();mCharaNode->setPosition(0, 0, 0);mCharaNode->setScale(1, 1, 1);//根据角色类型创建角色,并设定参数使得正好在屏幕中间出现。大小适中。switch(charaType){case CHARA_A:mCharaType = CHARA_A;mCharaNode->attachObject(mCharaEntA);mCharaNode->setScale(3, 3, 3);//sinbad有上下2部分的Idle动画,所以这里分开使用mCharaAnimState1 = mCharaEntA->getAnimationState("IdleBase");mCharaAnimState2 = mCharaEntA->getAnimationState("IdleTop");mCharaAnimState2->setLoop(true);mCharaAnimState2->setEnabled(true);break;case ChARA_B:mCharaType = ChARA_B;mCharaNode->attachObject(mCharaEntB);mCharaNode->setScale(2, 2, 2);mCharaNode->setPosition(0, -15, 0);mCharaNode->yaw(Ogre::Degree(180));mCharaAnimState1 = mCharaEntB->getAnimationState("Turn");mCharaAnimState2 = 0;break;case CHARA_C:mCharaType = CHARA_C;mCharaNode->attachObject(mCharaEntC);mCharaNode->setScale(0.2, 0.2, 0.2);mCharaNode->setPosition(0, -15, 0);mCharaNode->yaw(Ogre::Degree(180));mCharaAnimState1 = mCharaEntC->getAnimationState("Idle3");mCharaAnimState2 = 0;break;}if(mCharaAnimState1){mCharaAnimState1->setLoop(true);mCharaAnimState1->setEnabled(true);}}
private:bool charaSelctedHandler(const CEGUI::EventArgs& e){//根据参数e得到获得事件的窗口const CEGUI::WindowEventArgs& windowArgs = static_cast<const CEGUI::WindowEventArgs&>(e);CEGUI::String charaType = windowArgs.window->getName();CEGUI::String charaDetail;if(charaType == "CharaImgBtnA"){charaDetail = (CEGUI::utf8*)Ogre::UTFString(L"哦,朋友,我是厉害的Sinbad战士。我帅不?").asUTF8_c_str();createChara(CHARA_A);}if(charaType == "CharaImgBtnB"){charaDetail = (CEGUI::utf8*)Ogre::UTFString(L"别看我是女人,我是很厉害的神箭手哦:)").asUTF8_c_str();createChara(ChARA_B);}if(charaType == "CharaImgBtnC"){charaDetail = (CEGUI::utf8*)Ogre::UTFString(L"别看我是忍者,其实我是大法师,只是/n伪装成忍者= =!").asUTF8_c_str();createChara(CHARA_C);}MyGUISystem::getSingletonPtr()->getWindow("CharaDetailText")->setText(charaDetail);return true;}bool startHandler(const CEGUI::EventArgs& e){//清理工作mSceneMgr->clearScene();//这里需要清除指针,否则退出会有错误mCharaAnimState1 = mCharaAnimState2 = 0;//场景开始,载入介绍GUIMyGUISystem::getSingletonPtr()->loadLayout("IntroWindow");switch(mCharaType){case CHARA_A:MyGUISystem::setProperty("IntroTopImg", "Image", "set:CharaIntroA image:full_image");break;case ChARA_B:MyGUISystem::setProperty("IntroTopImg", "Image", "set:CharaIntroB image:full_image");break;case CHARA_C:MyGUISystem::setProperty("IntroTopImg", "Image", "set:CharaIntroC image:full_image");break;}//介绍文本CEGUI::String str = (CEGUI::utf8*)Ogre::UTFString(L"很久很久以前......").asUTF8_c_str();MyGUISystem::getSingletonPtr()->getWindow("IntroText")->setText(str);//得到动画CEGUI::Animation* anim = CEGUI::AnimationManager::getSingleton().getAnimation("IntroAnim");//实例化动画CEGUI::AnimationInstance* inst = CEGUI::AnimationManager::getSingleton().instantiateAnimation(anim);//动画的应用窗口inst->setTargetWindow(MyGUISystem::getSingletonPtr()->getWindow("IntroText"));//动画开始inst->start();return true;}bool inputAcceptedHandler(const CEGUI::EventArgs& e){mCharaName = MyGUISystem::getSingletonPtr()->getWindow("NameInputbox")->getText().c_str();if(mCharaName !=  ""){//如果输入框有文本的话,显示开始按钮MyGUISystem::getSingletonPtr()->getWindow("StartBtn")->show();}else{//否则隐藏按钮MyGUISystem::getSingletonPtr()->getWindow("StartBtn")->hide();}return true;}bool mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id ){MyGUISystem::getSingletonPtr()->injectMouseButtonDown(MyGUISystem::convertButton(id));return true;}bool mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id ){MyGUISystem::getSingletonPtr()->injectMouseButtonUp(MyGUISystem::convertButton(id));return true;}bool mouseMoved( const OIS::MouseEvent &arg ){MyGUISystem::getSingletonPtr()->injectMouseMove(arg.state.X.rel, arg.state.Y.rel);return true;}//这里需要注入keychar和键盘事件才能在Editbox中输入字符(不接受输入法)bool keyPressed( const OIS::KeyEvent &arg ){CEGUI::System::getSingleton().injectKeyDown(arg.key);CEGUI::System::getSingleton().injectChar(arg.text);if(arg.key == OIS::KC_ESCAPE)mShutDown = true;return true;}bool keyReleased( const OIS::KeyEvent &arg ){CEGUI::System::getSingleton().injectKeyUp(arg.key);return true;}
private:Ogre::String            mCharaName;             //角色名字Ogre::Entity*         mCharaEntA;             //角色AOgre::Entity*          mCharaEntB;             //角色BOgre::Entity*          mCharaEntC;             //角色COgre::SceneNode*       mCharaNode;             //角色节点Ogre::AnimationState* mCharaAnimState1;       //角色动画状态Ogre::AnimationState*   mCharaAnimState2;       //备用角色动画状态CharaType             mCharaType;             //保存选择的角色类型
};
INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
{Demo demo;try{demo.go();}catch(Ogre::Exception& e){MessageBox(0, e.getFullDescription().c_str(), "Exception", MB_OK);}
}

代码没有什么特别的解释。 这个Demo的实现主要是CEGUI的ImageButton的使用。

首先, 使用官方的Imageset编辑器对一张图片进行编辑,实际操作也就是把一张图片进行切片。 每个部分都在一个文件中定义一个UV坐标。这个Demo里使用的Imageset文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<Imageset Name="CharaImageset" Imagefile="./logo.tga" ><Image Name="Logo" XPos="208" YPos="0" Width="608" Height="146" /><Image Name="HoverA" XPos="0" YPos="553" Width="128" Height="128" /><Image Name="HoverB" XPos="129" YPos="553" Width="128" Height="128" /><Image Name="HoverC" XPos="256" YPos="552" Width="128" Height="128" /><Image Name="NormalA" XPos="0" YPos="424" Width="128" Height="128" /><Image Name="NormalB" XPos="129" YPos="424" Width="128" Height="128" /><Image Name="NormalC" XPos="257" YPos="425" Width="128" Height="128" /><Image Name="PushedA" XPos="1" YPos="682" Width="128" Height="128" /><Image Name="PushedB" XPos="129" YPos="682" Width="128" Height="128" /><Image Name="PushedC" XPos="256" YPos="681" Width="128" Height="128" /><Image Name="HoverStart" XPos="255" YPos="255" Width="125" Height="50" /><Image Name="NormalStart" XPos="252" YPos="255" Width="125" Height="50" /><Image Name="PushedStart" XPos="252" YPos="255" Width="125" Height="50" /><Image Name="Intro_Bottom" XPos="2" YPos="334" Width="1006" Height="90" />
</Imageset>

接下来就是在Layout文件中使用这个Imageset的各个图片资源了。

火炬之光里的创建角色的角色按钮使用的是RadioButton, 由于ImageButton在游戏里用的最多,所以我打算用ImageButton实现角色选择的按钮。

下面展示Layout文件中某一个ImageButton的使用:

  <Window Type="TaharezLook/ImageButton" Name="CharaImgBtnA" ><Property Name="Font" Value="SimHei-14" /><Property Name="Tooltip" Value="杩欐槸瑙掕壊A" /><Property Name="HoverImage" Value="set:CharaImageset image:HoverA" /><Property Name="NormalImage" Value="set:CharaImageset image:NormalA" /><Property Name="PushedImage" Value="set:CharaImageset image:PushedA" /><Property Name="UnifiedAreaRect" Value="{{0.14953,0},{0.0922273,0},{0.252194,0},{0.289911,0}}" /><Window Type="TaharezLook/StaticText" Name="CharaTextA" ><Property Name="Font" Value="SimHei-14" /><Property Name="Text" Value="瑙掕壊A" /><Property Name="HorzExtent" Value="58" /><Property Name="VertExtent" Value="16.25" /><Property Name="TextColours" Value="tl:FF0000FF tr:FF0000FF bl:FF0000FF br:FF0000FF" /><Property Name="FrameEnabled" Value="False" /><Property Name="HorzFormatting" Value="HorzCentred" /><Property Name="UnifiedAreaRect" Value="{{0.00228956,0},{-0.0175811,0},{1.00038,0},{0.97344,0}}" /><Property Name="BackgroundEnabled" Value="False" /><Property Name="MousePassThroughEnabled" Value="True" /></Window></Window>

先定义一个ImageButton, 然后设置它的属性:

HoverImage: 鼠标移到上面的时候显示的图片

NormalImage: 平常时候显示的图片

PushedImage: 鼠标点击后显示的图片

Tooltip是鼠标停留在这个控件上一段时间后出现的提示文本。

以这个ImageButton为父窗口,建立一个StaticText, 这个文本窗口我们是用来显示按钮的文字的。由于ImageButton不能直接定义文本,要么通过图片直接绘制文本,要么在它上面建立一个文本窗口。

文本窗口既然在ImageButton上面,那么就需要对它设置一些特殊属性,否则我们点击ImageButton就得不到响应。

首先去除文本窗口的  Background和Frame, 就是背景和边框。

然后要使底下的ImageButton响应操作,需要设置上面的窗口MousePassThroughEnabled属性为True。 这个属性会忽略设置窗口的鼠标操作而传递到下面的控件。

在Main.cpp代码中, 使用EventTextChanged来响应文本的输入变化。 如果文本框里的文本变化了(即玩家输入了名字)那么开始按钮就会出现。 对Window调用show()和hide()就可以控制窗口的显示与否。

当选择了一个角色后,场景中间会建立一个人物实体。 可以只用一个场景节点来实现角色的切换的效果。只有当一个实体依附(attach)在一个节点时,场景中才会绘制出这个实体。所以我们建立3个人物的实体, 需要显示某个的时候Attach就行。

最后把这个例子中所需要的资源(layout、 imageset、animationXML文件以及材质、纹理图片等)放入Ogre可以定位的路径下。 比如就放在exe的目录中, 然后在resource配置中在一个资源组中添加 FileSystem=./

希望本文对你有所帮助。

OGRE+CEGUI游戏教程(3)----角色创建相关推荐

  1. C#开发Unity游戏教程循环遍历做出判断及Unity游戏示例

    C#开发Unity游戏教程循环遍历做出判断及Unity游戏示例 Unity中循环遍历每个数据,并做出判断 很多时候,游戏在玩家做出判断以后,游戏程序会遍历玩家身上大量的所需数据,然后做出判断,即首先判 ...

  2. C#开发Unity游戏教程之判断语句

    C#开发Unity游戏教程之判断语句 游戏执行路径的选择--判断 玩家在游戏时,无时无刻不在通过判断做出选择.例如,正是因为玩家做出的选择不同,才导致游戏朝着不同的剧情发展,因此一个玩家可以对一个游戏 ...

  3. C#开发Unity游戏教程之游戏对象的行为逻辑方法

    C#开发Unity游戏教程之游戏对象的行为逻辑方法 游戏对象的行为逻辑--方法 方法(method),读者在第1章新建脚本时就见过了,而且在第2章对脚本做整体上的介绍时也介绍过,那么上一章呢,尽管主要 ...

  4. C#开发Unity游戏教程之使用脚本变量

    C#开发Unity游戏教程之使用脚本变量 使用脚本变量 本章前面说了那么多关于变量的知识,那么在脚本中要如何编写关于变量的代码,有规章可循吗?答案是有的.本节会依次讲解变量的声明.初始化.赋值和运算. ...

  5. Quick-Cocos2d-x初学者游戏教程(二) -------------------- Quick内部的代码结构及相应的原理...

    Quick-Cocos2d-x初学者游戏教程(二) 上一章我们已经了解了Quick的一些基础知识,所以本章我们将开始深入到Quick内部,了解它内部的代码结构,同时在解析的过程中学到相应的原理,并学会 ...

  6. matlab制作打地鼠游戏,scratch编程制作打地鼠的游戏教程

    scratch编程制作打地鼠的游戏教程Sk1少儿编程网-https://www.pxcodes.com Sk1少儿编程网-https://www.pxcodes.com 首先,新建背景和角色,从背景库 ...

  7. [游戏] - 游戏教程

    http://www.gameres.com/ 中国最大的游戏开发制作类交流平台,面向全球华语游戏开发人群,提供游戏教程.部分游戏源代码.作品下载.人才招聘.相关新闻.技术交流论坛等 http://w ...

  8. 用计算机玩游戏教程,Wegame怎么用手机玩电脑游戏 Wegame手机玩电脑游戏教程

    许多玩家朋友都知道wearticle的新功能可以让玩家在手机上玩英雄联盟,穿越火线,地下城与勇士这些热门腾讯网游,却不知道怎么设置成用手机玩电脑游戏,其实只需要简单阅读Wearticle手机玩电脑教程 ...

  9. 计算机游戏物体运动代码,Flash游戏教程:控制物体运动三法 -电脑资料

    教程|控制 现在用Flash开发的游戏是越来越多了, 方法一:通过单击按钮实现物体的单位运动 这种方法一般在需要按键的游戏中使用.你也可以给某个实体加上这段代码,然后通过单击这个实体达到某种游戏效果. ...

最新文章

  1. epoll的LT和ET模式
  2. 设置vs2008代码区的背景色
  3. 社区发现 实践_实践社区可以为您的组织做什么
  4. 并发安全的mysql序列实现
  5. python restful风格_总结python bottle框架支持jquery ajax的RESTful风格的PUT和DELETE方法
  6. Java交替打印两个字符串
  7. 微信小程序-组件使用
  8. AtCoder Regular Contest 102 (ARC102) E - Stop. Otherwise... 排列组合
  9. U盘文件或目录损坏且无法读取修复方法?
  10. 通过爬虫获取免费IP代理,搭建自己的IP池(https)
  11. 百度绿萝算法更新 众多网站摊上事了
  12. 如何查看Windows 桌面壁纸的位置
  13. Python循环结构——while
  14. sel2000服务器自动关闭,管家婆辉煌:轻松处理SQL 2000数据库自动停止
  15. cs231n笔记--到底什么是梯度消散
  16. 编程之美之数独求解器的C++实现方法
  17. 采用CCG和kkt条件编制两阶段鲁棒优化程序,以储能、发电、风电和光伏容量作为第一阶段变量
  18. 补交20145226蓝墨云班课 -- Arrays和String单元测试
  19. 短信验证php_php实现登录短信验证
  20. 学习笔记——Git的简单使用

热门文章

  1. 2021年茶艺师(初级)考试及茶艺师(初级)最新解析
  2. Android:使用ZXing生成二维码(支持添加Logo图案)
  3. 联通版iPhone年底前将不会具有WIFI功能
  4. Quartz 快速入门案例,看这一篇就够了
  5. java sequence_一种java生成数据库sequence的方法技术
  6. QT treewidget 双击信号与自定义槽】
  7. netfilter 理解
  8. AI数学基础之:奇异值和奇异值分解
  9. 非关系型数据库 入门简介
  10. java搜索目录特定文件夹