Pygame不使用Sprite,用colliderect()检测碰撞并隐藏物体的问题
问题分析与修复方案
你的代码主要有几个关键问题导致colliderect()报错,同时还有一些逻辑问题影响功能实现,下面逐一说明并给出修复后的完整代码:
核心问题点
- 碰撞检测传参错误:
self.red.colliderect(self)里的self是Enemy1类的实例对象,而colliderect()需要传入的是pygame.Rect类型对象,不是类实例。 - 未独立维护Rect属性:你依赖
pygame.draw.rect()的返回值作为碰撞检测的Rect,但这个返回值仅代表当前帧绘制的矩形,且在初始化时就绘制会导致不必要的渲染,应该每个类单独维护一个pygame.Rect对象,根据自身坐标实时更新。 - 坐标顺序搞反:Enemy1类里绘制矩形时用了
(self.y,self.x,self.w,self.h),pygame的矩形参数是(x, y, 宽, 高),这里x和y顺序颠倒了,导致矩形位置错乱。 - 重复处理事件队列:代码里有两个
pygame.event.get()循环,会导致部分事件被丢弃(比如退出事件可能被第一个循环吃掉,第二个循环检测不到),必须合并成一个循环。 - 碰撞检测逻辑未触发:你定义了
collide方法但从未调用,且方法逻辑需要接收玩家的Rect作为参数。
修复后的完整代码
import random import pygame pygame.init() # 窗口设置 w = 600 h = 600 win = pygame.display.set_mode((w, h)) # 颜色定义 WHITE = (255, 255, 255) BLACK = (0, 0, 0) def main(): class Enemy1(): def __init__(self, color, radius, x=100, y=100): self.color = color self.radius = radius self.x = x self.y = y self.w = 50 self.h = 50 self.appear = True # 独立维护Rect对象,用于碰撞检测和绘制 self.rect = pygame.Rect(self.x, self.y, self.w, self.h) def draw(self): if self.appear: # 根据当前rect绘制矩形,同时更新rect的位置(防止坐标修改后rect未同步) self.rect.x = self.x self.rect.y = self.y pygame.draw.rect(win, self.color, self.rect) def check_collision(self, player_rect): if self.appear and self.rect.colliderect(player_rect): self.appear = False class Player(): def __init__(self): self.x = 300 self.y = 300 self.w = 100 self.h = 100 self.color = WHITE self.appear = True # 独立维护Rect对象 self.rect = pygame.Rect(self.x, self.y, self.w, self.h) def draw(self): if self.appear: self.rect.x = self.x self.rect.y = self.y pygame.draw.rect(win, self.color, self.rect) def handle_key(self, event, step=20): if event.type == pygame.KEYDOWN: if event.key == pygame.K_UP: self.y -= step elif event.key == pygame.K_DOWN: self.y += step elif event.key == pygame.K_LEFT: self.x -= step elif event.key == pygame.K_RIGHT: self.x += step # 限制玩家不超出窗口 self.x = max(0, min(self.x, w - self.w)) self.y = max(0, min(self.y, h - self.h)) # 创建实例 player = Player() enemies = [ Enemy1((229, 190, 237), 20, 200, 150), Enemy1((124, 144, 219), 15, 30, 130), Enemy1((115, 107, 146), 25, 150, 50) ] # 主循环 running = True clock = pygame.time.Clock() while running: win.fill(BLACK) # 事件处理 for event in pygame.event.get(): if event.type == pygame.QUIT: running = False player.handle_key(event) # 绘制所有对象 player.draw() for enemy in enemies: enemy.draw() # 碰撞检测 player_rect = player.rect for enemy in enemies: enemy.check_collision(player_rect) pygame.display.update() clock.tick(60) pygame.quit() main()
关键修改说明
- 每个类都新增了
self.rect属性,专门用于碰撞检测和绘制参考,每次绘制前都会同步当前的x、y坐标,确保Rect位置准确。 - 把Enemy1的
collide方法改成check_collision,接收玩家的Rect作为参数,直接用self.rect.colliderect(player_rect)做碰撞判断。 - 合并了事件处理循环,避免事件丢失,同时给玩家加了窗口边界限制,防止移出屏幕。
- 把绘制相关的方法统一命名为
draw,逻辑更清晰,Enemy1的坐标顺序也修正为正确的(x, y, w, h)。 - 将敌人实例存入列表,方便批量处理绘制和碰撞检测,代码更简洁。
内容的提问来源于stack exchange,提问作者Dakota Dolph
相关产品推荐
相关产品推荐

