Pygame怪物碰撞士兵后重置失效问题求助
问题分析与修复方案
核心问题
怪物碰撞后消失是因为pygame.sprite.groupcollide的第四个参数设为True,该参数会将碰撞的怪物从精灵组中移除(杀死),导致怪物不再被渲染。同时士兵生命值的递减逻辑和游戏结束逻辑也需要完善。
具体修复步骤
修改碰撞检测参数
将士兵与怪物的碰撞检测代码中,groupcollide的第四个参数(是否杀死怪物)改为False,避免怪物被移除:collisions = pygame.sprite.groupcollide(soldiers, monsters, False, False, pygame.sprite.collide_mask)调整怪物reset函数
原reset函数中额外增加了怪物生命值,若不需要碰撞后给怪物加血,移除该逻辑:def reset(self): self.rect.left = SCREEN_WIDTH # 移除 self.health +=3,保留位置重置即可正确处理士兵生命值递减
每次碰撞时调用士兵的reduce_health()方法(或直接减1),并检查生命值是否归零以触发游戏结束:for soldier, monster_list in collisions.items(): # 每次碰撞士兵生命值减1 soldier.reduce_health() for monster in monster_list: monster.reset() # 检查是否游戏结束 if soldier.health <=0: game_over = True完善游戏结束逻辑
在主循环结束后加入游戏结束后的提示显示,确保玩家能看到失败信息。
完整修改后的代码
import pygame import os pygame.init() SCREEN_WIDTH = 800 SCREEN_HEIGHT = 550 screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) # Constants GRAVITY = 1 BULLET_SPEED = 7 MONSTER_SPEED = 3 # Initialize fonts pygame.font.init() LOSE_FONT = pygame.font.SysFont('comicsans', 30) # Load images background = pygame.image.load(os.path.join('caractors', 'colorful_sky.jpg')).convert() ground = pygame.image.load(os.path.join('caractors', 'd_land.png')).convert_alpha() ground = pygame.transform.scale(ground, (SCREEN_WIDTH, ground.get_height())) # Define classes class Soldier(pygame.sprite.Sprite): def __init__(self): super().__init__() self.image = pygame.image.load(os.path.join('caractors', 'soldier.png')).convert_alpha() self.image = pygame.transform.scale(self.image, (95, 125)) self.rect = self.image.get_rect(bottomleft=(50, 502)) self.mask = pygame.mask.from_surface(self.image) self.gravity = 0 self.max_bullets = 3 self.health = 3 self.max_hit = 3 self.hits = 0 # Variable to track the number of hits taken # Font for displaying health self.font = pygame.font.Font(None, 20) # You can adjust the font size and style as needed self.show_health = True # Flag to indicate whether to show health def draw_health(self, screen): if self.show_health: health_text = self.font.render(f'Health: {self.health}', True, (255, 0, 0)) # 修改文本更清晰 text_rect = health_text.get_rect(center=(self.rect.centerx, self.rect.top - 10)) screen.blit(health_text, text_rect.topleft) def update(self): self.gravity += GRAVITY self.rect.y += self.gravity if self.rect.bottom >= 502: self.rect.bottom = 502 def jump(self): if self.rect.bottom >= 502 and self.gravity >= 0: self.gravity = -18 def move_left(self): self.rect.x -= 5 def move_right(self): self.rect.x += 5 def reduce_health(self): self.hits += 1 self.health -= 1 class Monster(pygame.sprite.Sprite): def __init__(self): super().__init__() self.image = pygame.image.load(os.path.join('caractors', 'monster.png')).convert_alpha() self.image = pygame.transform.scale(self.image, (55, 57)) self.rect = self.image.get_rect(bottomright=(SCREEN_WIDTH, 502)) self.mask = pygame.mask.from_surface(self.image) self.health = 3 # Font for displaying health self.font = pygame.font.Font(None, 20) # You can adjust the font size and style as needed self.show_health = True # Flag to indicate whether to show health def draw_health(self, screen): if self.show_health: health_text = self.font.render(f'Health: {self.health}', True, (255, 0, 0)) # 修改文本更清晰 text_rect = health_text.get_rect(center=(self.rect.centerx, self.rect.top - 10)) screen.blit(health_text, text_rect.topleft) def update(self): self.rect.x -= MONSTER_SPEED if self.rect.right <= 0: self.rect.left = SCREEN_WIDTH def reset(self): self.rect.left = SCREEN_WIDTH # 移除加血逻辑,仅重置位置 def reduce_health(self): self.health -= 1 class Bullet(pygame.sprite.Sprite): def __init__(self, x, y): super().__init__() self.image = pygame.Surface((5, 5)) self.image.fill((255, 0, 0)) self.rect = self.image.get_rect(midleft=(x, y)) def update(self): self.rect.x += BULLET_SPEED def draw_lose(screen, text): lose_text = LOSE_FONT.render(text, 1, (255, 0, 0)) screen.blit(lose_text, (SCREEN_WIDTH//2 - lose_text.get_width()//2, SCREEN_HEIGHT//2 - lose_text.get_height()//2)) # 居中显示 pygame.display.flip() pygame.time.delay(4000) def main(): screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption('Runner') all_sprites = pygame.sprite.Group() soldiers = pygame.sprite.Group() monsters = pygame.sprite.Group() bullets = pygame.sprite.Group() soldier = Soldier() monster = Monster() all_sprites.add(soldier, monster) soldiers.add(soldier) monsters.add(monster) clock = pygame.time.Clock() run = True game_over = False # Flag to indicate game over state while run and not game_over: clock.tick(60) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE and len(bullets) < soldier.max_bullets: bullet = Bullet(soldier.rect.right - 20, soldier.rect.centery + 20) all_sprites.add(bullet) bullets.add(bullet) keys = pygame.key.get_pressed() if keys[pygame.K_UP]: soldier.jump() if keys[pygame.K_LEFT]: soldier.move_left() if keys[pygame.K_RIGHT]: soldier.move_right() hits = pygame.sprite.groupcollide(monsters, bullets, False, True) for monster, bullet_list in hits.items(): monster.health -= len(bullet_list) if monster.health <= 0: monster.rect.left = SCREEN_WIDTH monster.health = 3 # 修改碰撞检测参数,不杀死怪物 collisions = pygame.sprite.groupcollide(soldiers, monsters, False, False, pygame.sprite.collide_mask) for soldier, monster_list in collisions.items(): # 调用reduce_health方法减少生命值 soldier.reduce_health() for monster in monster_list: monster.reset() # 检查生命值是否归零,触发游戏结束 if soldier.health <= 0: game_over = True all_sprites.update() screen.blit(background, (0, 0)) screen.blit(ground, (0, SCREEN_HEIGHT - ground.get_height() + 20)) all_sprites.draw(screen) for monster in monsters: monster.draw_health(screen) for soldier in soldiers: soldier.draw_health(screen) pygame.display.flip() # 游戏结束显示 if game_over: draw_lose(screen, "YOU LOSE") pygame.quit() if __name__ == '__main__': main()
内容的提问来源于stack exchange,提问作者Naviidad
相关产品推荐
相关产品推荐

