Pygame精灵碰撞检测无输出问题求助
碰撞检测失效问题排查与修复方案
我帮你揪出了代码里几个导致碰撞检测没反应的关键问题,咱们一个个来看:
1. 新生成的障碍物没加入碰撞检测组
你用objects列表管理障碍物,但新生成的障碍物只加到了列表里,没加入ob这个用于碰撞检测的精灵组。pygame.sprite.spritecollide只会检测目标精灵和指定组内的精灵,所以这些新障碍物根本没参与碰撞判断。
修复操作:
生成新障碍物时,同时把它加入ob和all_sprites组:
if event.type == pygame.USEREVENT+2: r = random.randrange(0,2) if r == 0: new_obstacle = Obsticles(832,300,64,64) objects.append(new_obstacle) ob.add(new_obstacle) all_sprites.add(new_obstacle)
2. 障碍物的rect位置没同步更新
你的Obsticles类有update方法,但objects里的障碍物没被调用这个方法;而且你移动障碍物时只改了self.x,没同步更新rect——而掩码碰撞依赖rect来确定检测范围,位置不同步自然碰不到。
修复操作:
移动障碍物时同步更新rect,移除时也要从组里删掉避免内存泄漏:
for i in objects: i.x -= 5 # 障碍物移动速度 i.rect.center = i.x, i.y # 同步更新rect位置 if i.x < -64: # 移出屏幕后删除 objects.pop(objects.index(i)) ob.remove(i) all_sprites.remove(i)
3. 玩家精灵绘制位置与rect不一致
你的Player.draw方法接收硬编码的300,300作为绘制位置,但碰撞检测用的是self.rect记录的self.x,self.y——相当于你把玩家画在A点,却在B点检测碰撞,肯定没反应。
修复操作:
修改Player类的draw和do方法,用自身的坐标绘制:
class Player(pygame.sprite.Sprite): # ... 其他代码不变 ... def draw(self, DS, veergindex, handle=0): # 去掉冗余的x,y参数,用自身的self.x,self.y DS.blit(self.paat,(self.x+self.handle[handle][0], self.y + self.handle[handle][1]),self.veerg[veergindex]) def do(self): '''Funktsioonide kokkupanek''' self.do_jumpt() # 调用自身的draw方法,不用硬编码坐标 self.draw(DS, index%self.kokku, 0)
4. 冗余的玩家实例定义
代码里先后两次创建p = Player(...),会导致实例混淆,建议删除开头的那个冗余定义。
修复后的核心代码片段
整理了关键修改后的游戏循环部分:
objects = [] '''Sprites''' sprites = pygame.sprite.Group() obsticles = Obsticles(832,300,64,64) p = Player(310, 200, 200, 'STlaev.png', 4, 1) all_sprites = pygame.sprite.Group(p,obsticles) ob = pygame.sprite.Group(obsticles) objects.append(obsticles) # 初始障碍物加入列表 x=0 while True: '''Game loop''' for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() if event.type == pygame.USEREVENT+2: r = random.randrange(0,2) if r == 0: new_obstacle = Obsticles(832,300,64,64) objects.append(new_obstacle) ob.add(new_obstacle) all_sprites.add(new_obstacle) '''Obsticle speed and deleting''' for i in objects: i.x -= 5 #the speed of the obsticle i.rect.center = i.x, i.y # 同步更新rect if i.x < -64: #deleting obsticle from the window objects.pop(objects.index(i)) ob.remove(i) all_sprites.remove(i) '''Background movement''' back_x = x % bg.get_rect().width DS.blit(bg, (back_x - bg.get_rect().width, 0)) if back_x < W: DS.blit(bg, (back_x, 0)) x -= 1 '''Sprites''' all_sprites.update() collided = pygame.sprite.spritecollide(p,ob,True,pygame.sprite.collide_mask) for i in collided: print('Collision.') objects.remove(i) # 碰撞后从列表移除 '''Funktsioonid''' keys(p) p.do() index+=1 redrawWindow() pygame.display.update() clock.tick(60)
为什么和自身碰撞有用?
因为测试自身碰撞时,你用的是同一个实例,rect位置和绘制位置完全一致,而且实例在碰撞组里,所以检测能正常触发。
内容的提问来源于stack exchange,提问作者Taavi Raudkivi
相关产品推荐
相关产品推荐

