Skip to content Skip to sidebar Skip to footer

How To Put A Health Bar Over The Sprite In Pygame

By the title, I'm hoping that my the player would have a health bar attached to their head. If they move, the health bar also moves. Say sprite is my player. Hey sprite! He has a h

Solution 1:

See haw to draw a bar in How can I display a smooth loading bar in pygame?. Create a function that draws a health bar:

defdraw_health_bar(surf, pos, size, borderC, backC, healthC, progress):
    pygame.draw.rect(surf, backC, (*pos, *size))
    pygame.draw.rect(surf, borderC, (*pos, *size), 1)
    innerPos  = (pos[0]+1, pos[1]+1)
    innerSize = ((size[0]-2) * progress, size[1]-2)
    rect = (round(innerPos[0]), round(innerPos[1]), round(innerSize[0]), round(innerSize[1]))
    pygame.draw.rect(surf, healthC, rect)

Add a method draw_health to the class Player and use the function draw_health_bar:

classPlayer(pygame.sprite.Sprite):
    # [...]defdraw_health(self, surf):
        health_rect = pygame.Rect(0, 0, self.original_image.get_width(), 7)
        health_rect.midbottom = self.rect.centerx, self.rect.top
        max_health = 10
        draw_health_bar(surf, health_rect.topleft, health_rect.size, 
                (0, 0, 0), (255, 0, 0), (0, 255, 0), self.health/max_health)    

Call the method in the main application loop:

while run:
    # [...]

    wn.fill((255, 255, 255))
    all_sprites.draw(wn)
    player.draw_health(wn)    # <---
    pygame.display.update()

See also Sprite.


Minimal example:

repl.it/@Rabbid76/PyGame-HealthBar

import pygame
import math

defdraw_health_bar(surf, pos, size, borderC, backC, healthC, progress):
    pygame.draw.rect(surf, backC, (*pos, *size))
    pygame.draw.rect(surf, borderC, (*pos, *size), 1)
    innerPos  = (pos[0]+1, pos[1]+1)
    innerSize = ((size[0]-2) * progress, size[1]-2)
    rect = (round(innerPos[0]), round(innerPos[1]), round(innerSize[0]), round(innerSize[1]))
    pygame.draw.rect(surf, healthC, rect)
    
classPlayer(pygame.sprite.Sprite):
    def__init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.original_image = pygame.image.load('CarBlue64.png')
        self.original_image = pygame.transform.rotate(self.original_image, 90)
        self.image = self.original_image
        self.rect = self.image.get_rect(center=(x, y))
        self.direction = pygame.math.Vector2((0, -1))
        self.velocity = 5
        self.position = pygame.math.Vector2(x, y)
        self.health = 10defpoint_at(self, x, y):
        self.direction = pygame.math.Vector2(x, y) - self.rect.center
        if self.direction.length() > 0:
            self.direction = self.direction.normalize()
        angle = self.direction.angle_to((0, -1))
        self.image = pygame.transform.rotate(self.original_image, angle)
        self.rect = self.image.get_rect(center=self.rect.center)

    defmove(self, x, y, clamp_rect):
        self.position -= self.direction * y * self.velocity
        self.position += pygame.math.Vector2(-self.direction.y, self.direction.x) * x * self.velocity
        self.rect.center = round(self.position.x), round(self.position.y)

        test_rect = self.rect.clamp(clamp_rect)
        if test_rect.x != self.rect.x:
            self.rect.x = test_rect.x
            self.position.x = self.rect.centerx
            self.health = max(0, self.health - 1)
        if test_rect.y != self.rect.y:
            self.rect.y = test_rect.y
            self.position.y = self.rect.centery
            self.health = max(0, self.health - 1)

    defdraw_health(self, surf):
        health_rect = pygame.Rect(0, 0, self.original_image.get_width(), 7)
        health_rect.midbottom = self.rect.centerx, self.rect.top
        max_health = 10
        draw_health_bar(surf, health_rect.topleft, health_rect.size, 
                (0, 0, 0), (255, 0, 0), (0, 255, 0), self.health/max_health)    

window = pygame.display.set_mode((250, 250))
clock = pygame.time.Clock()

player = Player(200, 200)
all_sprites = pygame.sprite.Group(player)

run = Truewhile run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = Falseelif event.type == pygame.MOUSEMOTION:
            player.point_at(*event.pos)

    keys = pygame.key.get_pressed()
    mouse_buttons = pygame.mouse.get_pressed()
    ifany(keys) orany(mouse_buttons):
        player.move(0, -1, window.get_rect())

    window.fill((127, 127, 127))
    pygame.draw.rect(window, (255, 0, 0), window.get_rect(), 3)
    all_sprites.draw(window)
    player.draw_health(window)
    pygame.display.update()

pygame.quit()
exit()

Solution 2:

Rabbid's answer worked for me, however I am using Python 3.8.2 and continually got deprication errors as well as compilation errors when trying to output an .exe. The progress variable is a float and results in this error:

    pygame.draw.rect(surf, healthC, (*innerPos, *innerSize))
DeprecationWarning: an integeris required (got type float).  Implicit conversion to integers using __int__ is deprecated, and may be removed in a future version of Python.

Multiplication by the variable progress in the function draw_health_bar needs to be raised to an int to get away from that. It doesn't seem to affect the visual appearance of the health bar at all. This is the culprit line updated with the int.

innerSize = (int((size[0]-2) * progress), size[1]-2)

Full updated code below. I prefer complete names for things so as not to confuse myself what variables mean, so I've done that, but everything else is the same except for the int I added.

def draw_health_bar(surface, position, size, color_border, color_background, color_health, progress):
     pygame.draw.rect(surface, color_background, (*position, *size))
     pygame.draw.rect(surface, color_border, (*position, *size), 1)
     innerPos  = (position[0]+1, position[1]+1)
     innerSize = (int((size[0]-2) * progress), size[1]-2)
     pygame.draw.rect(surface, color_health, (*innerPos, *innerSize))

Sorry if this posting this breaks StackOverflow's rules. First time posting and I thought this was helpful info to newbs like me who try this code out.

Post a Comment for "How To Put A Health Bar Over The Sprite In Pygame"