Search code examples
progress-bar2dgodotgdscripttopdown

How can I create a MOBA health bar in Godot?


I want to make a health bar for my 2D top down character which is similar to the MOBA games.

For instance, this is the image of a health bar in the game called Leauge of Legend:

https://i.sstatic.net/8Ekpe.png

This is the health bar of a level 1 character in the game

https://i.sstatic.net/2dv4G.png

This is the health bar of a level 13 character in the game (sorry for the blurry image)

As you can see, when the character's health increases, the health bar has more "sticks" inside it, which let the player know how much health the character has with only a glance.

I have no idea how to create this kind of health bar, so it would be great if you can give me a code sample or at least a few hints. I couldn't find any tutorials related to what I intend to make, so any of your efforts are deeply appreciated.


Solution

  • In Godot you have the node TextureProgress, which can be used as an Healthbar by choosing the Textures for your progress bar and an overlay (a border) for the healhbar.

    Now you could put you sticks on the "Over" Texture and change the image by calling a function, everytime the maximum amount of life changed:

    #Images you define that should be set. 
    export var max_sticks_bar : StreamTexture 
    export var min_sticks_bar : StreamTexture 
    
    func change_upper_image() -> void:
            if max_value >= 500: # as an example I change the image to one with more sticks
                texture_over = max_sticks_bar 
            else:
                texture_over = min_sticks_bar 
    

    This is not optimal, because you would need an Image for every single threshold you would like to show. And the lines would be randomly set without a real reference to the actual max life.

    The better way would be to draw the lines yourself by using the _draw() function of the TextureProgress. This allows you to draw the lines dynamically everytime the update() function is called. In my example I will draw a stick for every 50 life:

    # function to call, if you change the max_life
    func set_max_life(life: float) -> void: 
        max_value = life
        update()
    
            
    func _draw():
        var bar_height = rect_size.y
        var bar_width = rect_size.x
        #could be dynamic. You maybe want smaller lines if there are a to many
        var line_width = 10
        var line_color = Color.black
        #should also be dynamic. Determines after how much life a line is drawn
        var life_per_line = 50  
        #lets say we wnat to draw lines from the top to the middle of the bar
        var line_height = bar_height/2
        
        #how many lines should be drawn
        var lines_to_draw : int = int(max_value / life_per_line)
        
        if (lines_to_draw > 0):
            var pixel_per_line = int(bar_width / lines_to_draw)
            var draw_pos_x = pixel_per_line
            for i in lines_to_draw:
                if (draw_pos_x < bar_width):
                    draw_line(Vector2(draw_pos_x,0), Vector2(draw_pos_x, line_height), line_color, line_width)
                draw_pos_x = draw_pos_x + pixel_per_line
    

    This would look like this (The "Over" Image in my example is just the border around the bar. The sticks are drawn, when I change the maximum life by clicking one of the buttons): enter image description here

    Note: By using the Draw Function you will draw on to the canvas item (TextureProgress Node) so whatever you draw is above any of the images you set in the node itself.