写在前面:
首先,在制作该人物血条前,我需要声明以下几点:
1.人物的血条属于简易制作的退格方式,不是连续的进度条类型。
2.该血条制作纯属快速开发完成,没有达到精细的程度,高手可以绕道。
以以上两点为前提,我粗略的讲述一下我在OGRE中用CEGUI制作血条的过程。
首先,人物头像我用了一张比较炫的魔剑士的图片:
(背景透明)
紧接着,为了配合整体色调,我我选取了一种紫色的血条单元:
有了血条单元(这里我称之为紫星),之后,用图片制作工具拼接制作了11张图片,
从0星紫星一直到10星紫星,取名为purple_x.jpg(x为紫星数量),为了便于理解,这里附
一张九星紫星的图片:
到此为止,素材准备好了,便开始在OGRE中完成我的程序部分了,
以下是我完成图片,文字,及窗口绘制部分的代码,我将其封装在一个函数中:
(CEGUI为0.8.3版本)
//-------------------------------------【CreateSrcBloodShowW()函数】-------------------------------------
// Desc:创建主模型血量显示的窗口
//------------------------------------------------------------------------------------------------------
void NinthCEGUI::CreateSrcBloodShowW(float ratio /* = 1.6f */)
{
CEGUI::WindowManager& wmgr = CEGUI::WindowManager::getSingleton();
//创建退格血条,血量数量,人物头像三个窗口
m_BloodW = wmgr.createWindow("WindowsLook/StaticImage", "Beyond/Blood");
m_BloodNumW = wmgr.createWindow("OgreTray/StaticText", "Beyond/BloodNum");
m_HeadW = wmgr.createWindow("WindowsLook/StaticImage", "Beyond/head");
//载入相关图片
CEGUI::ImageManager::getSingleton().addFromImageFile("head", "head.png");
for (size_t i = 0; i <= 10; i++)
CEGUI::ImageManager::getSingleton().addFromImageFile("purple"+
Ogre::StringConverter::toString(i), "purple_"+ Ogre::StringConverter::toString(i)+".jpg");
//将图片添加到窗口中
MyCEGUISystem::getSingletonPtr()->addImageToWindow(m_HeadW, "head", 0.0f, 0.0f, 0.16f/ratio, 0.16f);
MyCEGUISystem::getSingletonPtr()->addImageToWindow(m_BloodW, "purple10", 0.11f / ratio, 0.085f, 0.25f/ratio, 0.035f);
m_BloodNumW->setArea(CEGUI::UDim(0.135f / ratio, 0), CEGUI::UDim(0.05f, 0),
CEGUI::UDim(0.5f / ratio , 0), CEGUI::UDim(0.04f, 0));
//去除头像窗口的边框,并设置背景为透明
m_HeadW->setProperty("FrameEnabled", "false");
m_HeadW->setProperty("BackgroundEnabled", "false");
//去掉血量窗口的文本边框和背景,设置文本为浅紫色
m_BloodNumW->setProperty("FrameEnabled", "false");
m_BloodNumW->setProperty("BackgroundEnabled", "false");
m_BloodNumW->setProperty("TextColours", "tl:FFFFAAFF tr:FFFFAAFF bl:FFFFAAFF br:FFFFAAFF");
//添加到根窗口
CEGUI::Window* root = CEGUI::System::getSingleton().getDefaultGUIContext().getRootWindow();
root->addChild(m_BloodW);
root->addChild(m_BloodNumW);
root->addChild(m_HeadW);
}
我在退格血条的上方显示了血量的具体数值,为了配合整体色调,将其设置为浅紫色,
以下是我自己封装完成的MyCEGUISystem中的addFromImageFile和addImageToWindow具体细节:
//----------------------------------【addFromImageFile()函数】--------------------------------------
// Desc:添加一张图片
//--------------------------------------------------------------------------------------------------
void MyCEGUISystem::addFromImageFile(const CEGUI::String& imageName, const CEGUI::String& fileName)
{
CEGUI::ImageManager::getSingleton().addFromImageFile(imageName, fileName);
}
//----------------------------------【createImageWindow()函数】-------------------------------------
// Desc:创建静态图片窗口
//--------------------------------------------------------------------------------------------------
void MyCEGUISystem::addImageToWindow(CEGUI::Window* window,const CEGUI::String& imageName,
float left /* = 0.0f */, float top /* = 0.0f */, float width /* = 1.0f */, float height/* = 1.0f */)
{
window->setArea(CEGUI::UDim(left, 0.0f), CEGUI::UDim(top, 0.0f),
CEGUI::UDim(width, 0.0f), CEGUI::UDim(height, 0.0f));
window->setProperty("Image", imageName);
}
之所以CreateSrcBloodShowW()函数中使用ratio参数是因为适应游戏窗口的变化,以致于人物头像和血条不至于变形,
这里的ratio=窗口宽度/窗口高度。
-------------------------------------------------------------------------------------------------------------------------------
人物头像,血量,血条的创建部分描述过了,接下来便讲述一下人物血量及血条的更新显示部分,
以下是frameRenderingQueued()中相关部分的核心代码:
//血量及退格血条更新
m_NinthCEGUI->getSrcBloodNumW()->setText(m_RoleName + ":" + Ogre::StringConverter::toString((int)m_HP));
static int ibloodPart = -1;
int i = 0;
while (1)
{
if (m_HP <= i * MODEL_MAX_BLOOD / 10)
{
if (ibloodPart != i)
{
m_NinthCEGUI->getSrcBloodW()->setProperty("Image", "purple" + Ogre::StringConverter::toString(i));
ibloodPart = i;
}
else
break;
}
else
{
i++;
if (i > 10)
break;
}
}
有了以上代码,便会在每一帧中更新人物的血量,一旦退格血条越出了血量每X/10(X=0,1,2...9)边界,便会自动更新绘制并显示。
最后,我附上一张完整的整体效果图以便于大家理解: