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
相关产品推荐
相关产品推荐

