Pygame 子弹雨碰撞和残影

问题描述

我正在制作一个简单的游戏,其中有一个您可以射击的敌人,并且您可以在一定程度上从左向右移动。这样做之后,我想当敌人的生命值 > 70 时,你必须躲避一波子弹。我看到它有 3 个问题,一个它有残像,它不是一颗子弹从它下来,就像把它一直画下来一样。两个我显示了文本,如果点击它应该将该文本更改为 You Lost,但这是行不通的。即使我输入了三个代码,它也应该在 70 生命值时触发 >+ 70 生命值,它会产生子弹并且它们停留在顶部,然后当我尝试射击时它们会下降。对不起,如果这很多,但我不知道如何解决它。这是我的代码

import pygame
import time
pygame.font.init()
WIDTH,HEIGHT = 900,500
WIN = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption("Boss fight")
FPS = 60
WHITE = (255,255,255)
BLACK = (0,0)
BLUE = (0,255)
RED = (255,0)
FLOOR = pygame.Rect(0,400,900,100)
SPEED = 1
BULLET_SPEED = 1
player = pygame.Rect(50,350,50,50)
numJumps = []
MAXBULLETS = 2
BOSS = pygame.Rect(700,300,100,100)
FONT = pygame.font.SysFont('comicsans',30)
BOSSHEALTH = 100
winText = ""
RESTART = pygame.USEREVENT + 1
LOST = pygame.USEREVENT + 2


def draw_window(playerBullets,rainBullets):
    WIN.fill(WHITE)
    pygame.draw.rect(WIN,BLACK,FLOOR)
    pygame.draw.rect(WIN,BLUE,player)
    pygame.draw.rect(WIN,RED,BOSS)
    boss_health = FONT.render("BOSS HEALTH: " + str(BOSSHEALTH),1,BLACK)
    WIN.blit(boss_health,(450,50))
    won = FONT.render(winText,BLACK)
    WIN.blit(won,(100,50))
    for bullet in playerBullets:
        pygame.draw.rect(WIN,bullet)
    for b in rainBullets:
        pygame.draw.rect(WIN,b)
    pygame.display.update()




def movement(p):
    keys_helds = pygame.key.get_pressed()
    if keys_helds[pygame.K_a] and p.x + SPEED > 0:
        p.x -= SPEED
    if keys_helds[pygame.K_d] and p.x < 400 + p.width:
        p.x += SPEED

def p_bullet_movement(playerBullets,boss,raining,player,rainBullets):
    for bullet in playerBullets:
        bullet.x += BULLET_SPEED
        if boss.colliderect(bullet):
            global BOSSHEALTH
            BOSSHEALTH-= 10
            playerBullets.remove(bullet)
        if BOSSHEALTH <= 70:
            global winText
            winText = "Bullet Rain!"
            raining = True
            for b in rainBullets:
                b.y += 1
                if player.colliderect(b):
                    pygame.event.post(pygame.event.Event(LOST))
                    rainBullets.remove(b)
                if b.y + BULLET_SPEED > HEIGHT:
                    rainBullets.remove(b)
            bullet1 = pygame.Rect(20,40,25)
            bullet2 = pygame.Rect(170,25)
            bullet3 = pygame.Rect(370,25)
            bullet4 = pygame.Rect(570,25)
            rainBullets.append(bullet1)
            rainBullets.append(bullet2)
            rainBullets.append(bullet3)
            rainBullets.append(bullet4)

        if BOSSHEALTH == 0:
            winText = "You Won!"





def main():
    playerBullets = []
    raining = False
    rainBullets = []
    clock = pygame.time.Clock()
    run = True
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE and not(raining):
                    bullet = pygame.Rect(player.x,player.y,25)
                    playerBullets.append(bullet)
            if event.type == LOST:
                global winText
                wintext = "You Lost!"
                 

        draw_window(playerBullets,rainBullets)
        movement(player)
        p_bullet_movement(playerBullets,BOSS,rainBullets)
        clock.tick(FPS)



if __name__ == '__main__':
    main() 

解决方法

它有一个残像,它不是一颗子弹从它下来就像一直画下来一样。

那是因为您每帧为每个 playerBullets 创建了 4 个新子弹。

我显示了两个文本,如果点击它应该将该文本更改为 You Lost,但这是行不通的。

那是因为您在此处设置了 wintext,而不是 winText

    if event.type == LOST:
        global winText
        wintext = "You Lost!"

即使我输入了三个代码,它也应该在 70 生命值时触发 >+ 70 生命值......

不,您检查 70:

...
if BOSSHEALTH <= 70:
   ...

它会产生子弹并且它们停留在顶部然后当我尝试射击时它们会下降。

看看你在这里缩进代码的方式:

def p_bullet_movement(playerBullets,boss,raining,player,rainBullets):
    for bullet in playerBullets:
        bullet.x += BULLET_SPEED
        if boss.colliderect(bullet):
            global BOSSHEALTH
            BOSSHEALTH-= 10
            playerBullets.remove(bullet)
        if BOSSHEALTH <= 70:
            global winText
            winText = "Bullet Rain!"
            raining = True
            for b in rainBullets:
                b.y += 1
                ...

如果 rainBullets,则为 bullet 中的每个 playerBullets 移动 BOSSHEALTH <= 70 中的每个对象。

因此,如果 BOSSHEALTH <= 70 不为真或 playerBullets 中没有对象,则永远不会到达 for b in rainBullets: 行。

,

由于在主循环中调用了 p_bullet_movement,因此您需要添加某种条件来限制添加到列表中的子弹数量。由于现在可以添加的子弹数量是无限的,因此它会继续每帧添加子弹,这就是您在图像后调用的。

一种解决方法是仅在列表为空时添加项目符号。

    if not rainBullets:
        rainBullets.append(bullet1)
        rainBullets.append(bullet2)
        rainBullets.append(bullet3)
        rainBullets.append(bullet4)