Pygame | 9 – Sprite的碰撞检测

碰撞检测有

两个精灵之间的矩形检测

pygame.sprite.collide_rect(first, second) #返回布尔值

精灵与组之间的矩形检测

#第一个参数是精灵,

#第二个参数是精灵组,

#第三个参数为True,则碰撞检测后,组中所有碰撞的精灵被删除

#返回 组中被碰撞的精灵

collide_list = pygame.sprite.spritecollide(sprite,group,False)

两个组之间的矩形检测

#前两个参数都是组

#后两个参数,代表发生碰撞时,是否删除精灵

#该函数返回一个字典

#第一个组中的每一个精灵都会添加到字典中

#第二组中与之碰撞的精灵会添加到字典相应的条目中

hit_list = pygame.sprite.groupcollide(group1,group2,True,False)

实例

Groupcollide返回值的形态和使用的理解是个难点,举例说明:比如group1有三架飞机对象p1、p2、p3,group2有八个子弹对象b1、b2、b3、b4、b5、b6、b7、b8,假如p1与b1、b4、b7发生碰撞,p2与b2、b5、b8发生碰撞,groupcollide(group1, group2, 1, 1)返回值是如下的字典:{p1:[b1, b4, b7], p2:[b2, b5, b8]}。

做了个小的测试程序,对上面各种情形进行测试:界面中间布置了四架飞机,上方布置了20颗子弹,子弹从上方匀速往下运行,进行碰撞检测,下图为运行之初的状态显示。

子弹往下运动,调用下面的函数进行碰撞检测:

co_dict = pygame.sprite.groupcollide(plane_list, bullet_list, 1, 1)

发生碰撞之后的状态显示如下,可以看出,四架飞机和14颗发生碰撞的子弹都消失了,因为dokill1和dokill2两个参数都被设置为1,也就是说发生碰撞的飞机和子弹都从plane_list 和bullet_list中删除了,此时plane_list是个空的sprite组了,bullet_list的长度也变成6了(刚开始的长度为20)。

此时打印返回值co_dict结果如下:

{<PlayerPlane Sprite(in 1 groups)>: [<Bullet Sprite(in 0 groups)>, <Bullet Sprite(in 0 groups)>, <Bullet Sprite(in 0 groups)>], <PlayerPlane Sprite(in 1 groups)>: [<Bullet Sprite(in 0 groups)>, <Bullet Sprite(in 0 groups)>, <Bullet Sprite(in 0 groups)>, <Bullet Sprite(in 0 groups)>], <PlayerPlane Sprite(in 1 groups)>: [<Bullet Sprite(in 0 groups)>, <Bullet Sprite(in 0 groups)>, <Bullet Sprite(in 0 groups)>], <PlayerPlane Sprite(in 1 groups)>: [<Bullet Sprite(in 0 groups)>, <Bullet Sprite(in 0 groups)>, <Bullet Sprite(in 0 groups)>, <Bullet Sprite(in 0 groups)>]}

从上可以看出,返回值是个字典,其有4个键值对,每个键为发生碰撞的飞机精灵对象,每个值为与某一飞机发生碰撞的子弹精灵对象列表。

从上面的测试结果可以看出,groupcollide不仅可以进行碰撞检测并返回碰撞结果,还可以对参与碰撞检测的对象进行修改,如果将上述函数的dokill1的参数改为0,则plane_list中的飞机保持不变,bullet_list中发生碰撞的子弹被移除了,运行效果如下:

对于需要分组碰撞检测的情形,比如坦克大战,飞机大战,用groupcollide进行检测就便利多了,只需一行代码就可以代替繁杂的多层循环嵌套了,同时还可以参与碰撞检测的对象进行修改,对于碰撞后消失的对象,不需要另外再进行if判断和手动删除了,确实是一举多得。

对于返回字典的使用,经常会遇到碰撞后需要进行爆炸显示,此时就可以对返回字典进行遍历(既可以对key遍历,也可以对value遍历),对每个对象添加一个爆炸效果即可。

pygame.sprite.spritecollideany()

如果精灵与组中的任何内容相交,则进行简单测试。

spritecollideany(sprite, group, collided = None) -> Sprite 与返回的精灵碰撞。

spritecollideany(sprite, group, collided = None) -> None 没有碰撞

如果精灵与组中的任何一个精灵发生碰撞,则返回该组中的一个精灵。 无碰撞时返回None。

如果您不需要pygame.sprite.spritecollide()函数的所有功能,则此函数会更快一些。

碰撞参数是一个回调函数,用于计算两个精灵是否发生碰撞。 它应该将两个精灵作为值并返回一个bool值,指示它们是否发生碰撞。 如果未传递碰撞,则所有精灵必须具有“rect”值,该值是精灵区域的矩形,将用于计算碰撞。

发表评论