为什么类冲突在PyGame中不起作用



我正在做一个游戏,你可以向雪人扔雪球。以下是Snowman类和Snowball类的定义:

class Snowman:
def __init__(self,start,end,a,b):
self.x = random.randrange(0,310)
self.y = 0
self.r = pygame.Rect(self.x,self.y,a,b)
class Snowball:
def __init__(self,a,b):
self.x = mousex
self.y = mousey
self.r = pygame.Rect(self.x,self.y,a,b)

正如您所看到的,类的r属性是它们的矩形。

下面是一个控制雪人AI的脚本。

for s in snowmen:
s.y += 0.5
#above_makes_the_snowmen_approach_the_bottom_of_the_screen.
#below_is_supposed_to_check_for_snowball_collision.
for b in bullets:
if s.r.colliderect(b.r):
snowmen.remove(s)
bullets.remove(b)
print(b.r.colliderect(s.r))
#above_is_a_debugger_that_reports_the_collision.
if s.y < 640:
blit(asnowman,(50,78),(s.x,s.y))
else:
snowmen.remove(s)

问题是,当我向其中一个雪人扔雪球时,调试器会报告False,雪人不会死。我该如何解决这个问题?

请参阅如何在pygame中检测碰撞?。在碰撞测试之前,您需要更新矩形的位置:

s.r.topleft = round(s.x), round(s.y)
b.r.topleft = round(b.x), round(b.y)
if s.r.colliderect(b.r):

注意,不能去掉xy属性,因为pygame.Rect应该表示屏幕上的一个区域,而pygame.Rect对象只能存储积分数据。

Rect对象的坐标都是整数。[…]


另请阅读如何在迭代时从列表中删除项目?。一个可能的解决方案是迭代列表的副本:

for s in snowmen[:]:
s.y += 0.5
s.r.topleft = round(s.x), round(s.y)
for b in bullets[:]:
b.r.topleft = round(b.x), round(b.y)
if s.r.colliderect(b.r):
snowmen.remove(s)
bullets.remove(b)
break

当创建对象时,初始化每个类中的Rect对象以匹配xy属性时,它们不会保持同步。这意味着你只会在矩形的初始位置发生碰撞,而不是物体后来移动到的位置。

解决此问题的最简单方法可能是添加几行代码来更新s.r和/或b.r,但您也可以开始使用pygame.sprite.Sprite,它将更新其rect属性以匹配其xy属性(我认为反之亦然(。如果你想让你自己的类表现得有点像Sprite,而不需要一直走下去,我建议把xy变成property描述符,它们引用Rect,成为真理的唯一来源:

class Snowman:
def __init__(self,start,end,a,b):
self.r = pygame.Rect(random.randrange(0,310),0,a,b)
@property
def x(self):
return self.r.left
@x.setter
def x(self, value):
self.r.left = value
@property
def y(self):
return self.r.top
@y.setter
def y(self, value):
self.r.top = value

最新更新