我不明白为什么 enemy/player 射击的弹药在他们死后不会消失 pygame

I cant figure out why the ammo the enemy/player is shooting doesnt dissapear after they die pygame

我正在尝试在我的游戏中进行 bossfight。 Boss 是一只向玩家发射弹丸的黄蜂。玩家在与boss战斗时,每隔一段时间就会获得额外的弹药。

唯一的问题是我不知道如何在bossfight后重置一切并让游戏正常继续。 Boss 弹丸继续掉落,但从与 Boss 死亡的位置不同的位置。

我在 bossfight 中使用了两个不同的 类:BossProjectile。我对玩家的射弹和敌人的射弹有不同的类。我会附上游戏的图片。

import pygame
from pygame.locals import *
from random import randint
from time import sleep

class Bee(pygame.sprite.Sprite):
    def __init__(self, x, y, alive, speed, score):
        pygame.sprite.Sprite.__init__(self)
        self.alive = alive
        self.speed = speed
        self.score = score
        self.image = beeImg
        self.rect = self.image.get_rect(center = (x, y))
        self.shootfreq = 1 *1000
        self.last_shot = pygame.time.get_ticks()
        self.ammo = 1
    def update(self):
        key_input = pygame.key.get_pressed()
        if key_input[pygame.K_LEFT]:
            self.rect.x -= self.speed
            if self.rect.left < 20:
                self.rect.x += self.speed
        elif key_input[pygame.K_RIGHT]:
            if self.rect.right > screen_width - 50:
                self.rect.x -= self.speed
            self.rect.x += self.speed
    def shoot(self):  
        if self.ammo > 0:
            newShot = PlayerProjectile(self.rect.x, self.rect.y, 8, beeSting)
            self.ammo -= 1
            playerprojectiles.add(newShot)
        else:
            print("no ammo")

class Honey(pygame.sprite.Sprite):
    def __init__(self, x, y,speed):
        pygame.sprite.Sprite.__init__(self)
        self.speed = speed
        self.image = honeyImg
        self.image = pygame.transform.scale(honeyImg, (60,60))
        self.rect = self.image.get_rect(center = (x, y))
        
    def update(self):
        self.rect.y += 5
        if self.rect.y > screen_height:
            self.kill()

class Boss(pygame.sprite.Sprite):
    def __init__(self, hp, speed, projectile, image, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.speed = speed
        self.hp = hp
        self.projectile = projectile
        self.x = x
        self.y = y
        self.image = image
        self.rect = self.image.get_rect(center = (x, y))
        self.side = 1
        self.shoot = False
        self.lastshot = pygame.time.get_ticks()
        self.shootfreq = 0.5 * 1000
    
    def update(self):
        if bossNow:

            if self.rect.right == screen_width -20:
                self.side = -1
                self.image = pygame.transform.flip(self.image, True, False)
            
            if self.rect.left == 20:
                self.side = 1
                self.image = pygame.transform.flip(self.image, True, False)
                
            self.timern = pygame.time.get_ticks() 

            self.rect.x += self.speed * self.side
            
            if self.rect.y > screen_height:
                self.kill()
        else:
            self.kill()

class Projectile(pygame.sprite.Sprite):
    def __init__(self, x, y,speed, image, pos):
        pygame.sprite.Sprite.__init__(self)
        self.speed = speed
        self.image = image
        self.image = pygame.transform.scale(self.image, (40,40))
        self.rect = self.image.get_rect(center = (x+40, y+40))
        self.pos = pos
    def update(self):
        if bossNow:
            self.rect.y += self.speed
            if self.rect.y > screen_height:
                self.kill()
        else:
            self.kill()

class PlayerProjectile(pygame.sprite.Sprite):
    def __init__(self, x, y,speed, image):
        pygame.sprite.Sprite.__init__(self)
        self.speed = speed
        self.image = image
        self.image = pygame.transform.scale(self.image, (30,30))
        self.rect = self.image.get_rect(center = (x+75, y+75))
        
    def update(self):
        self.rect.y -= self.speed
        if self.rect.y > screen_height:
            self.kill()
    
class Area():
    def __init__(self, x=0 , y=0, width=10, height=10, color=None, state=False):
    
        self.rect = pygame.Rect(x,y,width,height)
        self.fill_color = color
        
    def collidepoint(self,xpos, ypos):
        return self.rect.collidepoint(xpos,ypos)
    
    def color(self, new_color):
        self.fill_color = new_color
    
    def fill(self):
        pygame.draw.rect(screen, self.fill_color, self.rect)


    def outline(self, frame_color, thickness):
        pygame.draw.rect(screen, frame_color, self.rect, thickness)
    
    def collidepoints(self,x,y):
        return self.rect.collidepoint(x,y)
    
class Label(Area):
    def set_text(self, text, fsize=12, text_color=(0,0,0)):
        self.image = pygame.font.SysFont('Bauhaus 93', fsize).render(text, True, text_color)

    def draw(self, shift_x= 0, shift_y=0):
        self.fill()
        screen.blit(self.image, (self.rect.x + shift_x, self.rect.y + shift_y))
        
    def collidepoints(self,x,y):
        return self.rect.collidepoint(x,y)
    def changesize(self, newHeight, newWidth, x, y):
        self.height = newHeight
        self.width = newWidth
        self.rect = pygame.Rect(x,y,self.width,self.height)

pygame.init()

#game variables 
clock = pygame.time.Clock()
last_hun = pygame.time.get_ticks()
last_attack = pygame.time.get_ticks()
attack_freq = 1 * 1000
hun_frequency = 0.5 * 1000 #milliseconds
fps = 60
bossNow = False
honeySpeed = 6
screen_width = 720
screen_height = 484
YELLOW = (150, 174, 217)
DARK_BLUE = (74, 78, 105)
BLUE = (74, 78, 105)
GREEN = (0, 255, 0)
RED = (255, 0 , 0)
WHITE = (225,232,244)
lastplayerattack = pygame.time.get_ticks()
playerattackfreq = 1 * 1000

screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Bee on the Run!')
bgImg = pygame.image.load("background.png")
beeImg = pygame.image.load("bee.png")
honeyImg = pygame.image.load("honey.png")
waspImg = pygame.image.load("wasp.png")
poisonTooth = pygame.image.load("poisonousTooth.png")
beeSting = pygame.image.load("beeStinger.png")

scoreboard = Label(10, 10, 80, 80, YELLOW, False)
scoreboard.outline(DARK_BLUE, 20)
scoreboard.color(BLUE)
scoreboard.fill()

player = Bee(screen_width/2-50, screen_height/2 +200, True, 8, 0)
honeyGroup = pygame.sprite.Group()
playerGroup = pygame.sprite.Group()
playerGroup.add(player)

WaspBoss = Boss(100, 5, "hello world", waspImg, 150, 80)
WaspBoss.image = pygame.transform.scale(WaspBoss.image,(130,130))

bossGroup = pygame.sprite.Group()
bossGroup.add(WaspBoss)

projectileGroup = pygame.sprite.Group()

playerprojectiles = pygame.sprite.Group()

run = True
while run:
    clock.tick(fps)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == KEYDOWN:
            if event.key == K_UP:
                player.shoot()

    time_now = pygame.time.get_ticks()
    if time_now - last_hun > hun_frequency:
        newHoney = Honey(randint(50, screen_width - 50),0, honeySpeed)
        honeyGroup.add(newHoney)
        last_hun = time_now  
    if time_now - lastplayerattack > playerattackfreq:
        player.ammo += 1
        lastplayerattack = time_now  
    if bossNow:
        if time_now - last_attack > attack_freq:
            newProjectile = Projectile(WaspBoss.rect.x, WaspBoss.rect.y, 8, poisonTooth, 1)
            projectileGroup.add(newProjectile)
            last_attack = time_now 
    
    #draw pics
    player.update()
    if bossNow == False:
        honeyGroup.update()
    if bossNow:
        bossGroup.update()
        projectileGroup.update()
        playerprojectiles.update()
    
    hits = pygame.sprite.spritecollide(player, honeyGroup, False, pygame.sprite.collide_mask)
    if hits:
        print(f"touched")
        hits[0].kill()
        player.score += 1000
        print(player.score)
    hits2 = pygame.sprite.spritecollide(player, projectileGroup, False, pygame.sprite.collide_mask)
    if hits2:
        print(f"touched")
        hits2[0].kill()
        player.kill()
    
    hits3 = pygame.sprite.spritecollide(WaspBoss, playerprojectiles, False, pygame.sprite.collide_mask)
    bossHits = 0
    if hits3:
        print(f"touched")
        hits3[0].kill()
        WaspBoss.kill()
        bossHits+1
        if bossHits == 10:
            bossNow = False
            WaspBoss.kill()
            
    #hits4 = pygame.sprite.spritecollide(projectileGroup, playerprojectiles, False, pygame.sprite.collide_mas
        
    

 
    screen.blit(bgImg,(0,0))
    playerGroup.draw(screen)
    
    if bossNow == False:
        honeyGroup.draw(screen)
    elif bossNow:
        bossGroup.draw(screen)
        projectileGroup.draw(screen)
        playerprojectiles.draw(screen)
        
        
    if player.score >= 100:
        bossNow = True
    else:
        bossNow = False
    #scoreboard.outline(YELLOW, 20)
    #scoreboard.fill()           
    
    if player.score < 100:
        scoreboard.set_text(str(player.score), 60)
        scoreboard.changesize(80, 80, 10,10)
    elif player.score >= 100 and player.score < 1000:
        scoreboard.set_text(str(player.score), 60)
        scoreboard.changesize(80, 120, 10,10)
    elif player.score >= 1000 and player.score <10000:
        scoreboard.set_text(str(player.score), 60)
        scoreboard.changesize(80, 160, 10,10)
    elif player.score >= 10000 and player.score <100000:
        scoreboard.set_text(str(player.score), 60)
        scoreboard.changesize(80, 200, 10,10)
    else:
        scoreboard.set_text("99999", 60)
        
    #scoreboard.draw()
    
    pygame.display.update()
    
pygame.quit()

问题是以下代码块总是将 BossNow 重置为 True,即使在 boss 已经被打败之后也是如此。

if player.score >= 100:
    bossNow = True
else:
    bossNow = False

所以,你必须添加一些东西来防止这种情况发生。我会为此使用 BossDefeated 变量。
为了实现这一点,您必须进行以下更改:

1:通过在游戏循环之前添加以下行,将 BossDefeated 变量初始化为 False:

BossDefeated=False

2:通过将第一个代码块更改为以下内容,使 BossDefeated 变量生效:

if player.score >= 100 and not BossDefeated:
    bossNow = True
else:
    bossNow = False

3:在每次调用 WaspBoss.kill 后添加以下行,将打败 Boss 时设置的 BossDefeated 变量设置为 True:

BossNow=True

我们还需要在Boss.update的函数定义中添加下面这行,以获取BossDefeated的变化到全局范围内。

global BossDefeated

如您所愿,完整代码如下:

import pygame
from pygame.locals import *
from random import randint
from time import sleep

class Bee(pygame.sprite.Sprite):
    def __init__(self, x, y, alive, speed, score):
        pygame.sprite.Sprite.__init__(self)
        self.alive = alive
        self.speed = speed
        self.score = score
        self.image = beeImg
        self.rect = self.image.get_rect(center = (x, y))
        self.shootfreq = 1 *1000
        self.last_shot = pygame.time.get_ticks()
        self.ammo = 1
    def update(self):
        key_input = pygame.key.get_pressed()
        if key_input[pygame.K_LEFT]:
            self.rect.x -= self.speed
            if self.rect.left < 20:
                self.rect.x += self.speed
        elif key_input[pygame.K_RIGHT]:
            if self.rect.right > screen_width - 50:
                self.rect.x -= self.speed
            self.rect.x += self.speed
    def shoot(self):  
        if self.ammo > 0:
            newShot = PlayerProjectile(self.rect.x, self.rect.y, 8, beeSting)
            self.ammo -= 1
            playerprojectiles.add(newShot)
        else:
            print("no ammo")

class Honey(pygame.sprite.Sprite):
    def __init__(self, x, y,speed):
        pygame.sprite.Sprite.__init__(self)
        self.speed = speed
        self.image = honeyImg
        self.image = pygame.transform.scale(honeyImg, (60,60))
        self.rect = self.image.get_rect(center = (x, y))
        
    def update(self):
        self.rect.y += 5
        if self.rect.y > screen_height:
            self.kill()

class Boss(pygame.sprite.Sprite):
    def __init__(self, hp, speed, projectile, image, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.speed = speed
        self.hp = hp
        self.projectile = projectile
        self.x = x
        self.y = y
        self.image = image
        self.rect = self.image.get_rect(center = (x, y))
        self.side = 1
        self.shoot = False
        self.lastshot = pygame.time.get_ticks()
        self.shootfreq = 0.5 * 1000
    
    def update(self):
        global BossDefeated
        if bossNow:

            if self.rect.right == screen_width -20:
                self.side = -1
                self.image = pygame.transform.flip(self.image, True, False)
            
            if self.rect.left == 20:
                self.side = 1
                self.image = pygame.transform.flip(self.image, True, False)
                
            self.timern = pygame.time.get_ticks() 

            self.rect.x += self.speed * self.side
            
            if self.rect.y > screen_height:
                self.kill()
                BossDefeated=True
        else:
            self.kill()
            BossDefeated=True

class Projectile(pygame.sprite.Sprite):
    def __init__(self, x, y,speed, image, pos):
        pygame.sprite.Sprite.__init__(self)
        self.speed = speed
        self.image = image
        self.image = pygame.transform.scale(self.image, (40,40))
        self.rect = self.image.get_rect(center = (x+40, y+40))
        self.pos = pos
    def update(self):
        if bossNow:
            self.rect.y += self.speed
            if self.rect.y > screen_height:
                self.kill()
        else:
            self.kill()

class PlayerProjectile(pygame.sprite.Sprite):
    def __init__(self, x, y,speed, image):
        pygame.sprite.Sprite.__init__(self)
        self.speed = speed
        self.image = image
        self.image = pygame.transform.scale(self.image, (30,30))
        self.rect = self.image.get_rect(center = (x+75, y+75))
        
    def update(self):
        self.rect.y -= self.speed
        if self.rect.y > screen_height:
            self.kill()
    
class Area():
    def __init__(self, x=0 , y=0, width=10, height=10, color=None, state=False):
    
        self.rect = pygame.Rect(x,y,width,height)
        self.fill_color = color
        
    def collidepoint(self,xpos, ypos):
        return self.rect.collidepoint(xpos,ypos)
    
    def color(self, new_color):
        self.fill_color = new_color
    
    def fill(self):
        pygame.draw.rect(screen, self.fill_color, self.rect)


    def outline(self, frame_color, thickness):
        pygame.draw.rect(screen, frame_color, self.rect, thickness)
    
    def collidepoints(self,x,y):
        return self.rect.collidepoint(x,y)
    
class Label(Area):
    def set_text(self, text, fsize=12, text_color=(0,0,0)):
        self.image = pygame.font.SysFont('Bauhaus 93', fsize).render(text, True, text_color)

    def draw(self, shift_x= 0, shift_y=0):
        self.fill()
        screen.blit(self.image, (self.rect.x + shift_x, self.rect.y + shift_y))
        
    def collidepoints(self,x,y):
        return self.rect.collidepoint(x,y)
    def changesize(self, newHeight, newWidth, x, y):
        self.height = newHeight
        self.width = newWidth
        self.rect = pygame.Rect(x,y,self.width,self.height)

pygame.init()

#game variables 
clock = pygame.time.Clock()
last_hun = pygame.time.get_ticks()
last_attack = pygame.time.get_ticks()
attack_freq = 1 * 1000
hun_frequency = 0.5 * 1000 #milliseconds
fps = 60
bossNow = False
honeySpeed = 6
screen_width = 720
screen_height = 484
YELLOW = (150, 174, 217)
DARK_BLUE = (74, 78, 105)
BLUE = (74, 78, 105)
GREEN = (0, 255, 0)
RED = (255, 0 , 0)
WHITE = (225,232,244)
lastplayerattack = pygame.time.get_ticks()
playerattackfreq = 1 * 1000

screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Bee on the Run!')
bgImg = pygame.image.load("background.png")
beeImg = pygame.image.load("bee.png")
honeyImg = pygame.image.load("honey.png")
waspImg = pygame.image.load("wasp.png")
poisonTooth = pygame.image.load("poisonousTooth.png")
beeSting = pygame.image.load("beeStinger.png")

scoreboard = Label(10, 10, 80, 80, YELLOW, False)
scoreboard.outline(DARK_BLUE, 20)
scoreboard.color(BLUE)
scoreboard.fill()

player = Bee(screen_width/2-50, screen_height/2 +200, True, 8, 0)
honeyGroup = pygame.sprite.Group()
playerGroup = pygame.sprite.Group()
playerGroup.add(player)

WaspBoss = Boss(100, 5, "hello world", waspImg, 150, 80)
WaspBoss.image = pygame.transform.scale(WaspBoss.image,(130,130))

bossGroup = pygame.sprite.Group()
bossGroup.add(WaspBoss)

projectileGroup = pygame.sprite.Group()

playerprojectiles = pygame.sprite.Group()

BossDefeated=False
run = True
while run:
    clock.tick(fps)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == KEYDOWN:
            if event.key == K_UP:
                player.shoot()

    time_now = pygame.time.get_ticks()
    if time_now - last_hun > hun_frequency:
        newHoney = Honey(randint(50, screen_width - 50),0, honeySpeed)
        honeyGroup.add(newHoney)
        last_hun = time_now  
    if time_now - lastplayerattack > playerattackfreq:
        player.ammo += 1
        lastplayerattack = time_now  
    if bossNow:
        if time_now - last_attack > attack_freq:
            newProjectile = Projectile(WaspBoss.rect.x, WaspBoss.rect.y, 8, poisonTooth, 1)
            projectileGroup.add(newProjectile)
            last_attack = time_now 
    
    #draw pics
    player.update()
    if bossNow == False:
        honeyGroup.update()
    if bossNow:
        bossGroup.update()
        projectileGroup.update()
        playerprojectiles.update()
    
    hits = pygame.sprite.spritecollide(player, honeyGroup, False, pygame.sprite.collide_mask)
    if hits:
        print(f"touched")
        hits[0].kill()
        player.score += 1000
        print(player.score)
    hits2 = pygame.sprite.spritecollide(player, projectileGroup, False, pygame.sprite.collide_mask)
    if hits2:
        print(f"touched")
        hits2[0].kill()
        player.kill()
    
    hits3 = pygame.sprite.spritecollide(WaspBoss, playerprojectiles, False, pygame.sprite.collide_mask)
    bossHits = 0
    if hits3:
        print(f"touched")
        hits3[0].kill()
        WaspBoss.kill()
        BossDefeated=True
        bossHits+1
        if bossHits == 10:
            bossNow = False
            WaspBoss.kill()
            BossDefeated=True
            
    #hits4 = pygame.sprite.spritecollide(projectileGroup, playerprojectiles, False, pygame.sprite.collide_mas
        
    

 
    screen.blit(bgImg,(0,0))
    playerGroup.draw(screen)
    
    if bossNow == False:
        honeyGroup.draw(screen)
    elif bossNow:
        bossGroup.draw(screen)
        projectileGroup.draw(screen)
        playerprojectiles.draw(screen)
        
        
    if player.score >= 100 and not BossDefeated:
        bossNow = True
    else:
        bossNow = False
    #scoreboard.outline(YELLOW, 20)
    #scoreboard.fill()           
    
    if player.score < 100:
        scoreboard.set_text(str(player.score), 60)
        scoreboard.changesize(80, 80, 10,10)
    elif player.score >= 100 and player.score < 1000:
        scoreboard.set_text(str(player.score), 60)
        scoreboard.changesize(80, 120, 10,10)
    elif player.score >= 1000 and player.score <10000:
        scoreboard.set_text(str(player.score), 60)
        scoreboard.changesize(80, 160, 10,10)
    elif player.score >= 10000 and player.score <100000:
        scoreboard.set_text(str(player.score), 60)
        scoreboard.changesize(80, 200, 10,10)
    else:
        scoreboard.set_text("99999", 60)
        
    #scoreboard.draw()
    
    pygame.display.update()
    
pygame.quit()