太空射击第08课: 改进的碰撞

太空射击第08课: 改进的碰撞
在本课中,我们将讨论如何更改处理精灵之间冲突的方式 。
视频
可以在这里找到本教程的视频
碰撞是怎么回事?
在上一次教程中,我们添加了图形,将精灵从普通矩形更改为更漂亮的PNG图像 。然而,这带来了一个问题:有时游戏会认为玩家和流星之间发生了碰撞,而看起来他们根本没有击中 。为了理解发生了什么,让我们看一个图:
中的默认冲突类型是使用()函数,该函数使用两个精灵的rect属性来计算它们是否重叠 。这被称为AABB碰撞,它非常快速可靠 。但是,如果精灵图像不是矩形,那么您会遇到类似于图片中的矩形重叠情况 。这时()函数返回值为True,玩家会感到沮丧,因为他们觉得自己应该成功地躲过了流星 。
如果您遇到这种情况,可以尝试以下几种方法:
通过使用()函数,您可以使用较小的矩形,从而减少可计为重叠的空间量 。根据精灵的形状,这可以很好地工作 。请注意上图中机翼的尖端是在矩形外的 。这意味着在某些情况星似乎会穿过机翼,而不会算作撞击 。这其实是个好情况!以游戏中事物移动的速度,玩家不会直接注意到这一点,而只会觉得他们“逃脱”了一个非常接近的闪避 。他们不会感到沮丧,而是会觉得自己做得很好 。
另一种选择是使用圆形边界框 。对于流星,这是一个非常好的选择 。它不太适合这艘船,但同样,机翼在碰撞之外不是一件坏事 。
设置精灵的半径
根据上面的选项,我们将为流星与玩家的碰撞选择圆圈 。使这变得容易 - 我们只需要在每个精灵上设置一个self.新属性:.
让我们从玩家开始 。碰撞圈应该有多大?可能需要一点点实验才能获得正确的值 。以下是在玩家精灵()__中执行此操作的方法:
self.rect = self.image.get_rect()self.radius = 25pygame.draw.circle(self.image, RED, self.rect.center, self.radius)
关于绘图知识可以在这里了解详细信息:基础:第21课——draw类绘制图形
我们在玩家图像的顶部绘制一个红色圆圈,以便我们可以看到它的外观 。让我们对流星做同样的事情:
self.rect = self.image.get_rect()self.radius = int(self.rect.width / 2)pygame.draw.circle(self.image, RED, self.rect.center, self.radius)
在这种情况下,我们正在提前计划一下 。我们可能会决定使用不同大小的流星图像 。通过将半径设置为图像宽度的 1 2 \frac{1}{2} 21?,我们可以做到这一点,而无需稍后调整代码 。
以下是我们最终得到的结果:
你可以看到,对于玩家精灵来说,我们的半径可能太大了——它实际上在y轴上比飞船的大小大 。为了更接近上面的例子,让我们设置玩家self. = 20 。
对于流星,我们希望突出一点角,所以让我们将圆圈缩放到大小的85%:

太空射击第08课: 改进的碰撞

文章插图
self.radius = int(self.rect.width * .85 / 2)
更改碰撞类型
【太空射击第08课: 改进的碰撞】要让游戏开始使用这些圆圈进行碰撞测试,我们只需要更改命令以使用圆圈函数而不是AABB函数:
# check to see if a mob hit the playerhits = pygame.sprite.spritecollide(player, mobs, False, pygame.sprite.collide_circle)if hits:running = False
一旦你尝试了一下,并且你对碰撞的工作方式感到满意,你就可以删除红色圆圈 。我建议你只是注释掉命令,而不是删除它们,以防将来你想再次使用它们 。