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

Pygame怪物碰撞士兵后重置失效问题求助

问题分析与修复方案

核心问题

怪物碰撞后消失是因为pygame.sprite.groupcollide的第四个参数设为True,该参数会将碰撞的怪物从精灵组中移除(杀死),导致怪物不再被渲染。同时士兵生命值的递减逻辑和游戏结束逻辑也需要完善。

具体修复步骤

  1. 修改碰撞检测参数
    将士兵与怪物的碰撞检测代码中,groupcollide的第四个参数(是否杀死怪物)改为False,避免怪物被移除:

    collisions = pygame.sprite.groupcollide(soldiers, monsters, False, False, pygame.sprite.collide_mask)
    
  2. 调整怪物reset函数
    原reset函数中额外增加了怪物生命值,若不需要碰撞后给怪物加血,移除该逻辑:

    def reset(self):
        self.rect.left = SCREEN_WIDTH
        # 移除 self.health +=3,保留位置重置即可
    
  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
    
  4. 完善游戏结束逻辑
    在主循环结束后加入游戏结束后的提示显示,确保玩家能看到失败信息。

完整修改后的代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 07:49:53