Designing Unique Healthbars

In the last tutorial we reconstructed Game Maker’s internal draw_healthbar function. This allowed us to understand how it was implemented and gave us a foundation we could build more unique healthbars. In this tutorial, we are going to build two popular styles of healthbar: Draining style, as seen in many fighting games, and an RPG style that displays the number values.

Draining Style Healthbar

If you have played a fighting game before, you probably noticed in many, that the healthbar doesn’t just drop in big chunks but rather, ┬áit appears to drain out of it. The exact style we will be building here is one similar to the one found in the Tekken series. The design is we will have a black background, and two bars that will represent health. One will be our standard health that drops immediately, while the other will be behind it and will drain out over time. We are also going to simplify this by only have the option for horizontal bars.

The Arguments

For this system, we are going to have eight arguments. As is standard, the first four are for X/Y coordinates, width and height and the fifth is the amount of life. The next two are the colours you want, with barCol1 being the top most colour and barCol2 is the draining colour behind it. The final argument is the direction the bar will go, in this case, we will only accept 0 (drain right) and 1 (drain left).

x1 = argument0; // X anchor point
y1 = argument1; // Y anchor point
x2 = argument2; // width
y2 = argument3; // height
amount = argument4 / 100;
barCol1 = argument5;
barCol2 = argument6;
dirBar = argument7;

Next we will create the standard background, but in this case, we will set it to be black by default.

//Background of Bar
draw_set_color(c_black);
draw_rectangle(x1, y1, x2, y2, false);

Now we are onto the interesting part of the code. There are two health bars that overlap each other. The top bar will change in the traditional, immediate transition style. Whereas the bottom bar will drain over a short period of time.

To start, we will put a upper cap which only draws the top bar to the fullest extent. Next, we put an else if check to see if the amount is less than full and greater than empty. This is followed by a check that compares a variable, lastHealth, to the current amount. If lastHealth is greater, we begin to decrease it, in this case by 0.1. With this happening, we can draw our health bars.

We have two different directions that the bars can move, but other than the math for getting it to shift, the design is the same. First we set the color for the bottom bar, and then draw the rectangle. With this bar, we don’t multiply the second coordinate by the amount, but rather we use the lastHealth variable. This is what will allow it to drain out. We follow this up with the top bar color and draw it in the standard way, using the amount variable.

//Draining Health
if (amount >= 1)
{
    lastHealth = amount;
    draw_set_color(barCol1);
    draw_rectangle(x1, y1, x2, y2, false);
}
else if (amount < 1 && amount > 0)
{
    if (lastHealth >= amount)
    {
        lastHealth -= 0.01;
    }
    if (dirBar == 0)
    {
        draw_set_color(barCol2);
        draw_rectangle(x1, y1, x1 + ((x2-x1)*lastHealth), y2, false);
        draw_set_color(barCol1);
        draw_rectangle(x1, y1, x1 + ((x2-x1)*amount), y2, false);
    }
    else if (dirBar == 1)
    {
        draw_set_color(barCol2);
        draw_rectangle(x2, y1, x2 - ((x2-x1)*lastHealth), y2, false);
        draw_set_color(barCol1);
        draw_rectangle(x2, y1, x2 - ((x2-x1)*amount), y2, false);
    }
}

You can test this out by throwing an object into a room, calling this function in the Draw Event and some method of decreasing your health variable, such as a Spacebar Press. You now have a functioning Tekken-style health system!

Download the completed file

 

RPG Style Healthbar

So far, we have been basing all our health systems based on a 0-1 ratio. It works great for most games, but in games where the characters have changing levels of max health, it doesn’t quite fit the bill. Often, I will see people creating complex systems that will compare the level of the player to the damage being applied and adjust it there. While that method does work, it makes it a lot harder to balance and requires exponentially more effort to build. A better method is to let the health system take care of itself.

The Arguments

Once again, we are going to simplify the design and state from the start that the health will ONLY reduce towards the left. The first four arguments are the same as before, the placement and size of the bar. The fifth argument is the amount, but notice that we no longer have it dividing by 100. Instead, we will be using the sixth argument, total, for this division. The next two arguments are the colors we want for the bar and the font. Next we have an argument which we will use to align the text, which accept one of three choices: fa_left, fa_center, and fa_right. Finally, the last argument is for a buffer, which will mean how far away, in pixels, from the edge do you want the text to appear.

x1 = argument0; // X anchor point
y1 = argument1; // Y anchor point
x2 = argument2; // width
y2 = argument3; // height
amount = argument4;
total = argument5;
barCol = argument6;
fontCol = argument7;
align = argument8;
buffer = argument9;

Again, we are placing a black bar for the background of this.

//Background of Bar
draw_set_color(c_black);
draw_rectangle(x1, y1, x2, y2, false);

Now we can set the color for this bar and draw the full rectangle. As you can see, in this case we need to compare the amount against the total possible health. If it is greater than the total, we draw the bar and since we are going to see the numbers, we cap the actual amount so you cannot go over the maximum. If it is less than the total and above zero, we draw the health bar rectangle with the width being adjusted by a percentage derived from dividing the amount by the total. We also place a bottom cap, which will set the amount of health to 0 if it drops below.

draw_set_color(barCol);

if (amount > total)
{
    draw_rectangle(x1, y1, x2, y2, false);
    amount = total;
}
else if (amount > 0)
{
    draw_rectangle(x1, y1, x1 + ((x2-x1)*(amount/total)), y2, false);
}
else if amount

Finally, we are ready to add the text we will need. We start with setting the color and the alignment for the font. Based on the alignment, we can then draw the text. For aligning left, we add a buffer to the x coordinate and use some concatenation to build the string with a slash “/” separating the amount from the total. Notice that there is no horizontal buffer for when it is center aligned.

//Health Text
draw_set_color(fontCol);
draw_set_halign(align);
if align == fa_left
{
    draw_text(x1 + buffer, y1 + buffer, string(amount) + string(" / ") + string(total));
} else if align == fa_center
{
    draw_text(x1 + x2/2, y1 + buffer, string(amount) + string(" / ") + string(total));
} else if align == fa_right
{
    draw_text(x2 - buffer, y1 + buffer, string(amount) + string(" / ") + string(total));
}

There you go! Just call this function as we have previously. Put what ever numbers you want for the total and it should work perfectly. Consider yourself as having leveled up!

Download the completed file

4 thoughts on “Designing Unique Healthbars

  1. it only works for one direction. how do drain to the left on the player 2 side. fighting games feature two fighters so readers can’t learn much from this if they can only code the left side.

  2. With the code found here you should be able to have it work in both directions. The draining bar does go both ways. The last parameter is for direction, 0 drains right and 1 drains left. The RPG bar doesn’t do this, but you can just combine the two systems to create whatever you want!

  3. Hello. I had a huge question. So Instead of downloading the scripts and doing it that way, I tried to just copy the code into a draw event itself and setting the x1,x2,y1,y2,etc variables in a create event in an object rather than calling the scripts in those events. It wasnt working so I downloaded the file and looked at how you did it. Seeing what you did, I was confused as to why yours worked and mine didn’t. I don’t see any real difference in our approaches aside from yours being maybe a bit cleaner. Thanks for this tho, I really wanted a healthbar to work like this.

  4. I would have to look at the code to understand, but if the amount variable is not updated in the draw event (or at least a step event) then the value would never update. Were you drawing a box that never changed?

Leave a Reply