Why can't my enemy healthbar shrink after it collides with a bullet?

Viewed 50

So I am currently making a game where the hotdog shoots bullets that should damage the Enemy. But after the bullet-enemy collision, The red healthbar that signifies its health does not shrink at all. Any tips on how to fix this? Thanks in advance.

import pygame
import random
import math

# Screen parameters
pygame.init()
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption("SPPACCE")
bg = pygame.image.load("bg.png")
font = pygame.font.SysFont('comicsans', 30, True)
clock = pygame.time.Clock()
score = 0

# Player parameters
class Player(object):
    def __init__(self, x, y, height, width):
        self.x = x
        self.y = y
        self.height = height
        self.width = width
        self.player_vel = 5

    def draw(self, screen):
        screen.blit(player_char, (self.x, self.y))
       

# Enemy parameters
class Enemy(object):
    def __init__(self, x, y, height, width, end):
        self.x = x
        self.y = y
        self.height = height
        self.width = width
        self.enemy_vel = 1.5
        self.end = end   
        self.path = [self.x, self.end]
        self.hitbox = (self.x + 17, self.y + 2, 65, 65)
        self.health = 10
        self.visible = True


    def draw(self, screen):
        self.move()
        if self.visible:
            self.hitbox = (self.x + 0, self.y, 65, 65)
            pygame.draw.rect(screen, (255, 0, 0), self.hitbox, 2)
            screen.blit(enemy_char, (self.x, self.y))

            # Health bars
            pygame.draw.rect(screen, (0, 0, 0), (self.hitbox[0], self.hitbox[1] - 20, 65, 10))
            pygame.draw.rect(screen, (255, 0, 0), (self.hitbox[0], self.hitbox[1] - 20, 65 - (6.5 * (10 - self.health)), 10))            
    
    def move(self):
        if self.enemy_vel > 0:
            if self.x < self.path[1] + self.enemy_vel:
                self.x += self.enemy_vel
            else:
                self.enemy_vel = self.enemy_vel * -1
                self.x += self.enemy_vel
        else:
            if self.x > self.path[0] - self.enemy_vel:
                self.x += self.enemy_vel
            else:
                self.enemy_vel = self.enemy_vel * -1
                self.x += self.enemy_vel

    def hit(self):
        if self.health > 0:
            self.health -= 1
        else: 
            self.visible = False

                
# Player Projectile parameters
class Projectile(object):
    def __init__(self, x, y, color, radius):
        self.x = x
        self.y = y
        self.color = color
        self.radius = radius
        self.vel = 12.5
    
    def draw(self, screen):
        pygame.draw.circle(screen, self.color, (self.x, self.y), self.radius)

# Images
player_char = pygame.image.load('sprites/hotdog.png')
enemy_char = pygame.image.load('sprites/hamburger.png')

def blit(): # This draws the sprites
    player.draw(screen)
    enemy.draw(screen)
    for projectile in projectiles:
        projectile.draw(screen)
    score_text = font.render("Score: " + str(score), 1, (0, 109, 255))
    version = font.render("Version 01 ", 1, (51, 153, 255))
    screen.blit(score_text, (0, 0))
    screen.blit(version, (520, 0))


shootloop = 0

if shootloop > 0:
    shootloop += 1
if shootloop > 2:
    shootloop = 0

player = Player(300, 400, 64, 64) 
enemy = Enemy(random.randint(10, 100), random.randint(20, 100), 64, 64, 480)
projectiles = []
run = True


while run:
    clock.tick(60)
    screen.fill((0, 0, 0))
    screen.blit(bg, (0, 0))
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    # Movement keys with playeborders
    keys = pygame.key.get_pressed()
    if keys[pygame.K_s] and player.y < 480 - player.height - player.player_vel:
        player.y += player.player_vel
    if keys[pygame.K_w] and player.y > 280:
        player.y -= player.player_vel
    if keys[pygame.K_d] and player.x < 640 - player.width - player.player_vel:
        player.x += player.player_vel
    if keys[pygame.K_a] and player.x > player.player_vel:
        player.x -= player.player_vel
    
    for projectile in projectiles:
        if projectile.y - projectile.radius < enemy.hitbox[1] + enemy.hitbox[3] and projectile.y + projectile.radius > enemy.hitbox[1]:
            if projectile.x + projectile.radius > enemy.hitbox[0] and projectile.x - projectile.radius < enemy.hitbox[0] + enemy.hitbox[2]:
                score += 1
                projectiles.pop(projectiles.index(projectile))
                

        if projectile.y < 640 and projectile.y > 0:
            enemy.hit
            projectile.y -= projectile.vel
            
        else:
            projectiles.pop(projectiles.index(projectile))
    
    # Player shooting
    if keys[pygame.K_SPACE] and shootloop == 0:
        if len(projectiles) < 1:
            projectiles.append(Projectile(round(player.x + player.width //2), 
            round(player.y + player.height //2), [255, 150, 0], 7))
    
    blit()
    pygame.display.update()

I followed TechwithTim's tutorial by the way. Also, I think this is enough to run the code.

2 Answers

There are two issues with your code. The first, as @Apple points out, is that you are not correctly calling enemy.hit().

The other issue is that the enemy.hit() is not being called in the correct spot. It needs to be called after the collision is detected, and the existing code has it where the projectile moves up:

for projectile in projectiles:
    if projectile.y - projectile.radius < enemy.hitbox[1] + enemy.hitbox[3] and projectile.y + projectile.radius > enemy.hitbox[1]:
        if projectile.x + projectile.radius > enemy.hitbox[0] and projectile.x - projectile.radius < enemy.hitbox[0] + enemy.hitbox[2]:
            score += 1
            projectiles.pop(projectiles.index(projectile))

    if projectile.y < 640 and projectile.y > 0:
        enemy.hit                                   # <<-- HERE
        projectile.y -= projectile.vel
    else:
        projectiles.pop(projectiles.index(projectile))

If you change it to apply the hit() when the projectile collides, it seems to work as desired:

for projectile in projectiles:
    if projectile.y - projectile.radius < enemy.hitbox[1] + enemy.hitbox[3] and projectile.y + projectile.radius > enemy.hitbox[1]:
        if projectile.x + projectile.radius > enemy.hitbox[0] and projectile.x - projectile.radius < enemy.hitbox[0] + enemy.hitbox[2]:
            # Enemy was hit by the projectile
            score += 1
            enemy.hit()                                 # <<-- HERE
            projectiles.pop(projectiles.index(projectile))

    if projectile.y < 640 and projectile.y > 0:
        # move the projectile up
        projectile.y -= projectile.vel
    else:
        # projectile went off-screen
        projectiles.pop(projectiles.index(projectile))

Please don't forget to add comments to your code, they really really help.

I don't know if it's the only issue, but you are missing a set of parentheses when you are attempting to call the hit method:

enemy.hit

Should be

enemy.hit()
Related