You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pygame红色飞船生命值异常持续减少问题排查求助

问题排查与修复

我看到你遇到了红色飞船生命值持续减少的问题,咱们一步步来找出根源并修复:

1. 红色子弹击中黄色飞船时的事件触发错误

在handle_bullet函数中,处理红色子弹的部分有个明显的逻辑错误:当红色子弹击中黄色飞船时,你错误发送了red_hit事件(导致红色生命值被扣除),但正确逻辑应该发送yellow_hit事件(让黄色生命值减少)。这是红色生命值被错误扣除的直接原因之一。

错误代码段:

if yellow.colliderect(bullet):
    pygame.event.post(pygame.event.Event(red_hit))  # 这里应该触发yellow_hit事件
    red_bullet.remove(bullet)

2. 子弹遍历与移除的迭代异常

直接在for循环中遍历子弹列表并调用remove()方法会破坏Python迭代器的正常运行,可能导致命中的子弹没有被及时从列表中移除。这样,在后续的每一帧中,这个“残留”的子弹会持续触发碰撞事件,导致生命值不断减少,直到飞船移动脱离碰撞范围或者子弹最终被移出屏幕。

解决这个问题的正确方式是遍历子弹列表的副本,避免迭代时修改原列表的结构。

修复后的完整代码

下面是修正后的代码,我已经修复了上述两个核心问题,同时优化了获胜逻辑的处理:

import pygame
import os
import time

pygame.font.init()

width , height = 900 , 500
dispay_surface = pygame.display.set_mode((width, height))
pygame.display.set_caption("first game")

teal = (153,255,255)
light_green = (102,255,102)
BLACK = (0,0,0)
RED = (255,0,0)
YELLOW = (255,255,0)

BORDER = pygame.Rect(width//2,0,10,height)

health_font = pygame.font.SysFont('comicsans', 40)

fps = 60
VEL = 5
BULLET_VEL = 7
max_bullet = 10

spaceship_width, spaceship_height = 55, 40

yellow_hit = pygame.USEREVENT +1
red_hit = pygame.USEREVENT +2

#making the space ship and rotating it correctly
yellow_spaceship_image = pygame.image.load(
    os.path.join('Assets','spaceship_yellow.png'))
yellow_spaceship_nr = pygame.transform.scale(
    yellow_spaceship_image, (spaceship_width, spaceship_height))
yellow_spaceship = pygame.transform.rotate(yellow_spaceship_nr, 90)

red_spaceship_image = pygame.image.load(
    os.path.join('Assets','spaceship_red.png'))
red_spaceship_nr= pygame.transform.scale(
    red_spaceship_image, (spaceship_width, spaceship_height))
red_spaceship = pygame.transform.rotate(red_spaceship_nr, -90)

space_background = pygame.transform.scale(pygame.image.load(os.path.join('Assets','space.png')),(width,height))

def draw_window(red,yellow,red_bullet,yellow_bullet,red_health,yellow_health):
    dispay_surface.blit(space_background,(0,0))
    #showing the health
    red_health_text = health_font.render("health: " + str(red_health), 1 , teal)
    yellow_health_text = health_font.render("health: " + str(yellow_health), 1, teal)
    dispay_surface.blit(red_health_text,(width - red_health_text.get_width()- 10 , 10))
    dispay_surface.blit(yellow_health_text, (10 , 10))

    #use to draw the ship
    dispay_surface.blit(yellow_spaceship,(yellow.x, yellow.y))
    dispay_surface.blit(red_spaceship,(red.x, red.y))

    #drawing a border so the 2 spaceship can't go on top of each other
    pygame.draw.rect(dispay_surface,BLACK,BORDER)

    for bullet in red_bullet:
        pygame.draw.rect(dispay_surface,RED,bullet)
    for bullet in yellow_bullet:
        pygame.draw.rect(dispay_surface,YELLOW,bullet)

    pygame.display.update()

#getting yellow ship to move when player input
def yellow_mov(keys_pressed,yellow):
    if keys_pressed[pygame.K_d] and yellow.x + VEL + yellow.width < BORDER.x: #right
        yellow.x += VEL
    if keys_pressed[pygame.K_a] and yellow.x - VEL > 0: #left
        yellow.x -= VEL
    if keys_pressed[pygame.K_w] and yellow.y - VEL > 0: #up
        yellow.y -= VEL
    if keys_pressed[pygame.K_s] and yellow.y - VEL + yellow.height < height - 15 : #down
        yellow.y += VEL

#getting red to move
def red_mov(keys_pressed,red):
    if keys_pressed[pygame.K_RIGHT] and red.x + VEL + red.width < width: #right
        red.x += VEL
    if keys_pressed[pygame.K_LEFT] and red.x - VEL >BORDER.x + BORDER.width: #left
        red.x -= VEL
    if keys_pressed[pygame.K_UP] and red.y - VEL > 0: #up
        red.y -= VEL
    if keys_pressed[pygame.K_DOWN] and red.y - VEL + red.height < height - 15: #down
        red.y += VEL

def handle_bullet(yellow_bullet,red_bullet,yellow,red):
    # 遍历黄色子弹的副本,避免迭代时修改原列表
    for bullet in yellow_bullet[:]:
        bullet.x += BULLET_VEL
        if red.colliderect(bullet):
            pygame.event.post(pygame.event.Event(red_hit))
            yellow_bullet.remove(bullet)
        elif bullet.x > width:
            yellow_bullet.remove(bullet)

    # 遍历红色子弹的副本,同时修复事件触发错误
    for bullet in red_bullet[:]:
        bullet.x -= BULLET_VEL
        if yellow.colliderect(bullet):
            pygame.event.post(pygame.event.Event(yellow_hit))  # 修正为yellow_hit事件
            red_bullet.remove(bullet)
        elif bullet.x < 0 :
            red_bullet.remove(bullet)

#keep window running
def main():
    #determin the player position
    red = pygame.Rect(700,300,spaceship_width,spaceship_height)
    yellow = pygame.Rect(100,300,spaceship_width,spaceship_height)

    red_bullet = []
    yellow_bullet = []

    red_health = 10
    yellow_health = 10

    clock = pygame.time.Clock()
    run = True
    while run:
        clock.tick(fps)
        winner_text = ""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False

            #Shoot the bullet
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LCTRL and len(yellow_bullet) < max_bullet:
                    bullet = pygame.Rect(yellow.x + yellow.width, yellow.y + yellow.height//2 , 10 ,5)
                    yellow_bullet.append(bullet)
                if event.key == pygame.K_RCTRL and len(red_bullet) < max_bullet:
                    bullet = pygame.Rect(red.x , red.y + red.height//2 , 10 ,5)
                    red_bullet.append(bullet)

            if event.type == red_hit:
                red_health -= 1
            if event.type == yellow_hit:
                yellow_health -= 1

        # 检测两艘飞船碰撞(可选功能,根据需求开启)
        if red.colliderect(yellow):
            pygame.event.post(pygame.event.Event(red_hit))
            pygame.event.post(pygame.event.Event(yellow_hit))

        # 获胜判断逻辑
        if red_health <=0:
            winner_text = "yellow wins"
        if yellow_health <=0:
            winner_text = "red wins"
        if winner_text:
            print(winner_text)
            # 可添加显示获胜文本的代码,这里简单打印后退出
            run = False

        keys_pressed = pygame.key.get_pressed()
        yellow_mov(keys_pressed,yellow)
        red_mov(keys_pressed,red)

        handle_bullet(yellow_bullet,red_bullet,yellow,red)

        draw_window(red,yellow,red_bullet,yellow_bullet,red_health,yellow_health)

    pygame.quit()

if __name__ == '__main__':
    main()

额外说明

  • 我添加了可选的飞船碰撞检测逻辑,如果你不需要这个功能,可以删除对应的代码块。如果保留,建议添加冷却机制(比如用pygame.time.get_ticks()控制碰撞触发间隔),避免生命值快速耗尽。
  • 优化了获胜逻辑的位置,避免在事件循环中重复赋值,同时添加了简单的游戏结束流程。

内容的提问来源于stack exchange,提问作者potato-sam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 14:53:15