Page 1 of 1

Simple GUI with health bars and spells (whatever) bar

Posted: Thu Nov 29, 2007 8:05 pm
by eMgz
hi all
I think that theres lots of questions on how to make a GUI for a basic game, so i decided to post here some useful hints on how to make one with simple rectangles, textures and some cool stuff like modifying the color based on amount of health, decrease/increase bar values with some kind of interpolation and add icons to a spell or ability bar

class definition (put it in a .h)

Code: Select all

class CGUIGame {

private:
	video::IVideoDriver* driver;
	int x1Bar, y1Bar, x2Bar, y2Bar;

	int	maxHealthBarValue; //bar size
	double deltaHealthBar;	   //interpolation
	double healthBarValue;  //current bar value

	int maxManaBarValue;
	double deltaManaBar;
	double manaBarValue;

	video::ITexture* GUITextures[10];

public:

	CGUIGame(video::IVideoDriver* videoDriver, int x1, int y1, int x2, int y2, int maxHealthValue, int maxManaValue); //constructor
	~CGUIGame(); //destructor :O
	void renderGUIGame(); //render the GUI, must be called AFTER the 3D draw, or it  wont show
	void setHealthBarValue(int healthValue); //change bar values
	void setManaBarValue(int manaValue);

};
class constructor (put it in a .cpp)

Code: Select all

CGUIGame::CGUIGame(video::IVideoDriver* videoDriver, int x1, int y1, int x2, int y2, int maxHealthValue, int maxManaValue){
        //class constructor
	driver = videoDriver;
        
        //health and mana bars size
	x1Bar = x1;
	y1Bar = y1;
	x2Bar = x2;
	y2Bar = y2;
        
        //max bar values
	maxHealthBarValue = maxHealthValue;
	maxManaBarValue = maxManaValue;

        //current bar values
	healthBarValue = maxHealthValue;
	manaBarValue = maxManaValue;

	deltaHealthBar = healthBarValue;
	deltaManaBar = manaBarValue;

	//load textures

        //load some texture for spellbar and make it transparent with ColorKey 0 (black) and put it into a texture array
	GUITextures[0] = driver->getTexture("../Content/Textures/spellbar.bmp");
	driver->makeColorKeyTexture(GUITextures[0], video::SColor(0,0,0,0));

        //same for the status bar (health and mana)
	GUITextures[1] = driver->getTexture("../Content/Textures/statusbar.bmp");
	driver->makeColorKeyTexture(GUITextures[1], video::SColor(0,0,0,0));

        //load some icons for the spellbar
	GUITextures[5] = driver->getTexture("../Content/Textures/icon_firebolt.bmp");

	GUITextures[6] = driver->getTexture("../Content/Textures/icon_fireblaze.bmp");

	GUITextures[7] = driver->getTexture("../Content/Textures/icon_firenova.bmp");
}
this method render the GUI, MUST BE CALLED AFTER THE 3D DRAW, in the main loop, otherwise it ll be overwrite

Code: Select all

void CGUIGame::renderGUIGame(){

	float delta; //status bar variation
	core::dimension2d<s32> screenSize = driver->getScreenSize();

	double x=17; //spell bar position
	double y=screenSize.Height*0.85;;

	double iconSpace = 30;
	core::position2d<s32> iconPos = core::position2d<s32>(x+50, y+23);

        //here is some cool stuff, it changes the bar value from X to Y smoothly
	if ((int)deltaHealthBar != (int)healthBarValue){
		delta = healthBarValue - deltaHealthBar;
		if (delta > 0)
			healthBarValue -= 0.2;
		if (delta < 0)
			healthBarValue += 0.2;
	}
        
        //same for mana
	if ((int)deltaManaBar != (int)manaBarValue){
		delta = manaBarValue - deltaManaBar;
		if (delta > 0)
			manaBarValue -= 0.2;
		if (delta < 0)
			manaBarValue += 0.2;
	}

	//another cool stuff,  it draws the health bar according to its value (green for high, decreasing to yellow till red), and some others rectangles for a cool look
	driver->draw2DImage(GUITextures[1], core::position2d<s32>(x1Bar-50, y1Bar-29), core::rect<s32>(0,0,605,94), 0, video::SColor(255,255,255,255), true);

	driver->draw2DRectangle(video::SColor(255, 100, 100, 100), core::rect<s32>(x1Bar, y1Bar, (maxHealthBarValue*5)+x2Bar, y2Bar));

	driver->draw2DRectangle(video::SColor(255, 125, 125, 125), core::rect<s32>(x1Bar+1, y1Bar+1, maxHealthBarValue*5+x2Bar-1, y2Bar-1));

	driver->draw2DRectangle(video::SColor(255, 150, 150, 150), core::rect<s32>(x1Bar+3, y1Bar+3, maxHealthBarValue*5+x2Bar-3, y2Bar-3));

	driver->draw2DRectangle(core::rect<s32>(x1Bar+3, y1Bar+3, healthBarValue*5+x2Bar-3, y2Bar-3),

							video::SColor(255, 255-healthBarValue*2.55, healthBarValue*2.55, 0),

							video::SColor(255, 255-healthBarValue*2.55, healthBarValue*2.55, 0),

							video::SColor(255, 255-healthBarValue*2.55, healthBarValue*2.55-150, 0),

							video::SColor(255, 255-healthBarValue*2.55, healthBarValue*2.55-150, 0));

	//mana bar
	driver->draw2DRectangle(video::SColor(255, 100, 100, 100), core::rect<s32>(x1Bar, y1Bar+20, maxManaBarValue*5+x2Bar, y2Bar+20));

	driver->draw2DRectangle(video::SColor(255, 125, 125, 125), core::rect<s32>(x1Bar+1, y1Bar+21, maxManaBarValue*5+x2Bar-1, y2Bar+19));

	driver->draw2DRectangle(video::SColor(255, 150, 150, 150), core::rect<s32>(x1Bar+3, y1Bar+23, maxManaBarValue*5+x2Bar-3, y2Bar+17));

	driver->draw2DRectangle(core::rect<s32>(x1Bar+3, y1Bar+23, manaBarValue*5+x2Bar-3, y2Bar+17),

							video::SColor(255, 100, 100, 200),

							video::SColor(255, 100, 100, 200),

							video::SColor(255, 0, 0, 100),

							video::SColor(255, 0, 0, 100));

	
        //draw the spells bar and the icons on it according to the iconSpace
	driver->draw2DImage(GUITextures[0], core::position2d<s32>(x+3, y), core::rect<s32>(0,0,456,73), 0, video::SColor(255,255,255,255), true);

	for (int i=5; i<=7; i++){
		driver->draw2DImage(GUITextures[i], iconPos);
		iconPos.X += iconSpace;
	}
}
and now, just two simple methods to change bar values, changing the delta value for the smooth thing

Code: Select all

void CGUIGame::setHealthBarValue(int healthValue){
	deltaHealthBar = healthValue;
}

void CGUIGame::setManaBarValue(int manaValue){
	deltaManaBar = manaValue;
}
usage:

Code: Select all

gameGUI = new CGUIGame(driver, 52, 37, 58, 53, 100, 100);
...

while(device->run()){
      ...

      driver->beginScene(true, true, 0 );
      smgr->drawAll(); //IMPORTANT: CALL AFTER SceneManager drawAll;
      gameGUI->renderGUIGame();

      ...
      driver->endScene();
}
the final result should be something like this
Image

or http://img136.imageshack.us/my.php?image=guiqu4.jpg

and you can find the textures at http://www.inf.ufrgs.br/~efmiglioranza/ ... xtures.zip

hope you enjoy :)

Posted: Thu Nov 29, 2007 8:13 pm
by dlangdev
awesome code, i could use it in my pet project as well. maybe the admin could put this thread in a code sampler collection, though.

Posted: Thu Nov 29, 2007 8:35 pm
by Eagle
Thanks eMgz, this will come in really handy!

well done~

always~
Vickie ;)

Posted: Tue Sep 02, 2008 3:46 pm
by pera
I used this code, and changed it a bit. I reduced it to one bar class CGUIBar, if someone needs just one bar (could be placed over the enemies head or so).

Here is CGUIBar.h:

Code: Select all

using namespace irr;
using namespace core;

class CGUIBar {

private:
	video::IVideoDriver* driver;
	int x1Bar, y1Bar, x2Bar, y2Bar;
	int barSize;
	int   maxBarValue; //bar size
	int deltaBar;   //interpolation
	double BarValue;   //current bar value
	stringw m_Name;
	video::ITexture* BarTexture;

public:

	CGUIBar(int x1, int y1, int x2, int y2, int maxBarValue, video::ITexture* texture, stringw name); //constructor
	~CGUIBar(); //destructor :O
	void renderGUIBars(video::IVideoDriver* driver); //render the bars, must be called AFTER the 3D draw, or it  wont show
	void setBarValue(s32 healthValue); //change bar values
	void changeValueBy(s32 Value);
	int getBarValue();
	stringw getName() {return m_Name;}
}; 
Here is CGUIBar.cpp:

Code: Select all

#include "CGUIBar.h"
CGUIBar::CGUIBar(int x1, int y1, int x2, int y2, int maxValue, video::ITexture* texture, stringw name)
{
   //class constructor
       
   //bars size
   x1Bar = x1;
   y1Bar = y1;
   x2Bar = x2;
   y2Bar = y2;

   barSize = (x2Bar-3) - (x1Bar+3);
   //max bar values
   maxBarValue = maxValue;

   //current bar values
   BarValue = maxValue;

   deltaBar = maxValue;

   //bar name (asociated with skill/ability name)
   m_Name = name;

   //texture
   BarTexture = texture;

} 

void CGUIBar::renderGUIBars(video::IVideoDriver* driver){

   double delta; //status bar variation
   core::dimension2d<s32> screenSize = driver->getScreenSize();

   double x=17; //spell bar position
   double y=35;

        //here is some cool stuff, it changes the bar value from X to Y smoothly
   if ((int)deltaBar != (int)BarValue){
      delta = BarValue - deltaBar;
      if (delta > 0)
         BarValue -= 0.2;
      if (delta < 0)
         BarValue += 0.2;
   }
       
 
   //another cool stuff,  it draws the bar according to its value (green for high, decreasing to yellow till red), and some others rectangles for a cool look
	if(BarTexture)
	{
		driver->draw2DImage(BarTexture, core::position2d<s32>(x1Bar-50, y1Bar-29), core::rect<s32>(0,0,605,94), 0, video::SColor(255,255,255,255), true);
	}

	driver->draw2DRectangle(video::SColor(255, 100, 100, 100), core::rect<s32>(x1Bar, y1Bar, x2Bar, y2Bar));

	driver->draw2DRectangle(video::SColor(255, 125, 125, 125), core::rect<s32>(x1Bar+1, y1Bar+1, x2Bar-1, y2Bar-1));

	driver->draw2DRectangle(video::SColor(255, 150, 150, 150), core::rect<s32>(x1Bar+3, y1Bar+3, x2Bar-3, y2Bar-3));

	driver->draw2DRectangle(core::rect<s32>(x1Bar+3, y1Bar+3, x1Bar+3+(s32)(barSize*BarValue/maxBarValue), y2Bar-3),

						video::SColor(255, (s32)(255-BarValue*(255/maxBarValue)), (s32)(BarValue*(255/maxBarValue)), 0),

						video::SColor(255, (s32)(255-BarValue*(255/maxBarValue)), (s32)(BarValue*(255/maxBarValue)), 0),

						video::SColor(255, 180, 180, 0),

						video::SColor(255, 180, 180, 0));

} 

void CGUIBar::setBarValue(s32 Value)
{
   deltaBar = (int)Value;
}

int CGUIBar::getBarValue()
{
   return deltaBar;
}

void CGUIBar::changeValueBy(s32 Value)
{
   deltaBar += (int)Value;
   if (deltaBar < 0)
   {
	   deltaBar = 0;
   }
   if (deltaBar > maxBarValue)
   {
	   deltaBar = maxBarValue;
   }
}
here is usage:

Code: Select all

//add health bar
	ITexture* texture = 0;//driver->getTexture("media/Icons/bar.png");
	healthBar = new CGUIBar(20, 40, 200, 60, 20, texture, L"Health");
and render it in the render loop after drawAll()

ps. I could add drawing text in render function with bar name: "Health" beside the bar, it would be more complete.

cheers.

Posted: Thu Jan 01, 2009 10:06 am
by grunt
I haved used this code and graphics in my project. Where did the graphics come from. Did you make them and can I use them for my project or are they from a game and I will have to make my own?

Posted: Thu Jan 01, 2009 4:31 pm
by vitek
The code should really be seperated out. The progress bar is a distinct concept from a 'game'. The progress bar should probably be a derived IGUIElement so that it can be used with the Irrlicht gui. That would allow you to put progress bars on loading screens and stuff like that.

In case you hadn't already seen it, Acki posted code for a progress bar a while ago. It may require just a little bit of updating, but it is available here.

Travis

Posted: Tue Feb 24, 2009 4:40 pm
by Katsankat
Found this progressBar while searching in the forums... Was really useful however the code from above was cleaned a bit.

http://www.mediafire.com/file/jhqoz5z0w ... essBar.zip (3.02 KB) contains : main.cpp, CGUIBar.cpp, CGUIBar.h

Posted: Thu Mar 19, 2009 9:17 am
by Katsankat
well after some discussion on IRC here are the files to integrate the progressbar into irrlicht 1.5 and create one with a

Code: Select all

IGUIProgressBar* mybar = guienv->addProgressBar();
just like you create a StaticText or a ScrollBar. Then set/get its value in a simple way.

The class is effectively derived from IGUIElement as Vitek pointed out.


For version 1.5 : 9 files from irrlicht engine have to be modified, they are in the archive along with an example of use : http://www.mediafire.com/file/hyyfijmnk ... essBar.zip

After suggestion from Hybrid, for the latest development version, revision 2297 : here is the patch along with an example of use http://www.mediafire.com/file/jmmnzozmm ... xample.zip