pygame中的边界框碰撞问题
我想做一个类似Google的 Block Breaker的砖块破坏游戏,但在球与砖块的碰撞方面遇到了麻烦。大多数时候球在砖块边侧的碰撞会被忽略,直接穿进砖块里。
注释掉的代码是我尝试的另一种碰撞检测方式,但同样也不能正确工作。
我该如何正确地判断球是否与砖块的侧边、底部还是顶部发生了碰撞?
def step(self,ball):
myrect = g.Rect(self.x,self.y,self.width,self.height)
ballrect = g.Rect(ball.x,ball.y,ball.size,ball.size)
if myrect.colliderect(ballrect) and ball.collidecooldown < 1:
ctop = ball.y - myrect.bottom
cbottom = self.y - ballrect.bottom
cleft = ball.x - myrect.right
cright = self.x - ballrect.right
cy = abs(min(ctop,cbottom))
cx = abs(min(cleft,cright))
if cy < cx:
ball.vel[1]*=-1
else:
ball.vel[0]*=-1
self.alive = False
ball.collidecooldown = 1
"""
ctop = ballrect.bottom > myrect.top and ballrect.bottom < myrect.bottom
cbottom = ballrect.top < myrect.bottom and myrect.top > ballrect.bottom
cright = ballrect.left < myrect.right and ballrect.left > myrect.left
cleft = ballrect.right > myrect.left and ballrect.right < myrect.right
if ctop or cbottom:
ball.vel[1]*=-1
if cright or cleft:
ball.vel[0]*=-1
self.alive = False
ball.collidecooldown = 1
"""
解决方案
让我们为那个函数写一个文档字符串,描述它的职责:
def step(self, ball):
"""Moves the ball by one step, adjusting position and velocity upon bounce.
Pre-condition: ball is not inside the self brick.
Post-condition: ball is not inside the self brick.
"""
也就是说,仅仅在反弹时把X 方向或Y 方向的速度反向还不够。你还需要移动球(也许移动一步?),让它不再处于正在碰撞的砖块内部。
前置条件和后置条件表明,你可能想要抽出一个辅助函数来验证“没有碰撞”的性质,并调用它两次。
你在这里采取的是一种 更容易请原谅再许可(EAFP) 的做法。球就直接冲过去,后续再处理后果。你发现这种“请原谅”的方式可能需要恢复“没有碰撞”的不变量。
对这个游戏问题的典型算法做法是先看再跳 look before you leap。也就是说,很多开发者会选择先构造一个拟议位置(pp = ball + velocity),并判断未来的位置是否会与砖块发生碰撞。如果不会,则直接推进球的位置;如果会,那么在球进入砖块位置之前就将速度反向。
我鼓励你分享这个正在开发中的游戏的GitHub链接。所谓“自有砖块会检查与球的交互”的做法似乎有点奇怪。我本来期望球会负责识别附近的砖块,并与之正确交互。但也许如果能够看到更宏观的体系结构,设计选择背后的原因就会变得更明显。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。