PyGame中两个类无法交互求助:碰撞检测失效问题排查
碰撞检测失效问题的解决方案
问题根源
你的代码存在两个核心问题导致碰撞检测无法正常工作:
- 实例不统一:Rock类的
__init__方法中新建了self.player = Player(),这是一个完全独立于主循环中你控制的player的新实例,两者的位置状态毫无关联,所以碰撞检测永远无法匹配。 - 移动方向错误:Player类的移动逻辑搞反了方向,按左键时x坐标应该减少,右键时x坐标应该增加,否则人物移动方向和按键操作不符。
修复步骤
- 修改Rock类的初始化方法,让它接收外部的Player实例作为参数,不再内部新建Player。
- 修正Player类的移动方向逻辑。
- 创建Rock对象时,将主循环中控制的
player传入。
修改后的完整代码
import pygame import random import time from pygame.locals import * vec = pygame.math.Vector2 pygame.init() FPS = 30 RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255) WHITE = (255, 255, 255) GRAY = (127, 127, 127) BLACK = (0, 0, 0) BLUEGREEN = (0, 255, 170) MARRON = (115, 0, 0) LIME = (180, 255, 100) PINK = (255, 100, 180) PURPLE = (240,0,255) GRAY = (127,127,127) MAGENTA = (255,0,230) BROWN = (100,40,0) FORESTGREEN = (0,50,0) NAVYBLUE = (0,0,100) RUST = (210,150,75) DANYELLOW = (255,200,0) HIGHLIGHTER = (255,255,100) SKYBLUE = (0,255,255) LIGHTGRAY = (200,200,200) DARKGRAY = (50,50,50) TAN = (230,220,170) COFFEEBROWN =(200,190,140) MOONGLOW = (235,245,255) HEIGHT = 800 WIDTH = 500 Font = pygame.font.SysFont('timesnewroman', 30) gamedisplay = pygame.display.set_mode((HEIGHT, WIDTH)) clock = pygame.time.Clock() class Player(): def __init__(self): # 状态属性 self.right_image = pygame.Surface((30, 30)) self.right_image.fill(RED) self.left_image = pygame.Surface((30, 30)) self.left_image.fill(RED) self.up_image = pygame.Surface((30, 30)) self.up_image.fill(RED) self.down_image = pygame.Surface((30, 30)) self.down_image.fill(RED) self.health = 100 self.hunger = 100 self.thrist = 100 self.temperature = 100 # 位置与显示 self.x = 50 self.y = 50 self.plyrimg = pygame.Surface((40, 40)) self.rect_plyr = self.plyrimg.get_rect() # 初始化玩家初始位置 self.rect_plyr.topleft = (self.x, self.y) # 移动属性 self.width = 40 self.height = 60 self.vel = 8 def player_movement(self): keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: self.rect_plyr.x -= self.vel if keys[pygame.K_RIGHT]: self.rect_plyr.x += self.vel if keys[pygame.K_UP]: self.rect_plyr.y -= self.vel if keys[pygame.K_DOWN]: self.rect_plyr.y += self.vel def interact(self,rct): if self.rect_plyr.colliderect(rct): print('hey') else: print('h') def Draw(self, display): display.blit(self.plyrimg, self.rect_plyr) # 地形类 class Rock(): def __init__(self, player): # 状态属性 self.health = 400 # 位置与显示 self.x = 50 self.y = 50 self.rckimg = pygame.Surface((40, 40)) self.rect_rck = self.rckimg.get_rect() self.player = player # 接收外部传入的玩家实例 # 其他属性 self.width = 40 self.height = 60 self.vel = 5 self.rect_rck.center = (200 // 2, 200 // 2) def Draw(self, display): display.blit(self.rckimg, self.rect_rck) def Multiply(self): self.player.interact(self.rect_rck) class plant(): def __init__(self): pass # 主循环相关实例 player = Player() rock = Rock(player) # 创建岩石时传入主玩家实例 def Game(): gamedisplay.fill(GREEN) player.player_movement() player.Draw(gamedisplay) rock.Draw(gamedisplay) rock.Multiply() # 菜单类 class menu(): def __init__(self): pass # 主循环 while True: clock.tick(FPS) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit() # 避免退出后报错 Game() pygame.display.update()
额外优化说明
- 给Player的rect设置了初始位置
topleft = (self.x, self.y),确保玩家初始位置符合预期。 - 在退出pygame后添加了
exit(),避免程序崩溃报错。
内容的提问来源于stack exchange,提问作者loudmounth artist
相关产品推荐
相关产品推荐

