当前位置:   article > 正文

Python中pygame模块pygame.sprite.groupcollision碰撞检测的详解与测试_groupcollide

groupcollide

在游戏开发中,非常重要的编程工作就是进行碰撞检测。在python的pygame模块中的sprite精灵类提供了多种方便快捷的碰撞检测方法。比如矩形碰撞检测、圆形碰撞检测、遮罩碰撞检测,这些方法基本都是单个对单个的物体进行检测,如果涉及到敌我双方都有很多对象时,比如飞机大战中的我方子弹与地方飞机的碰撞检测,用上述方法可能就得进行循环嵌套,这样略显麻烦。
针对分组对象的碰撞检测,pygame中还有一种简单的碰撞检测方法:pygame.sprite.groupcollision(),网上关于介绍它的详细使用方法的文章不多,我经过反复研究和测试,终于弄清楚了它的使用方法、使用场景以及使用效果,希望对你有参考价值。

一、 功能说明

官方文档如下:
Find all sprites that collide between two groups.
groupcollide(group1, group2, dokill1, dokill2, collided = None) -> Sprite_dict
This will find collisions between all the Sprites in two groups. Collision is determined by comparing the Sprite.rect attribute of each Sprite or by using the collided function if it is not None.
Every Sprite inside group1 is added to the return dictionary. The value for each item is the list of Sprites in group2 that intersect.
If either dokill argument is True, the colliding Sprites will be removed from their respective Group.
The collided argument is a callback function used to calculate if two sprites are colliding. It should take two sprites as values and return a bool value indicating if they are colliding. If collided is not passed, then all sprites must have a “rect” value, which is a rectangle of the sprite area, which will be used to calculate the collision.
简要解释如下:
找出两个精灵组中发生碰撞的所有精灵,主要通过比较每个精灵的Sprite.rect属性来实现。参数含义如下:
Group1:第一个精灵组
Group2:第二个精灵组
Dokill1:设置为True或者False,当设置为True时,当发生碰撞时group1中的相应精灵对象将被删除;当设置为False时,不论是否发生碰撞,group1保持不变。
Dokill2:设置为True或者False,当设置为True时,当发生碰撞时group2中的相应精灵对象将被删除,不论是否发生碰撞,group1保持不变。
Collided是个回调函数,使用默认即可。
返回值是个字典,未发生碰撞时,字典为空。发生碰撞时,字典的keys是group1中发生碰撞的对象(一直以为字典的keys值是个字符串之类的东西,没想到还可以是对象),values是一个列表,其元素是group2中与每一个group1发生碰撞的所有对象。

二、实例测试

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)
  • 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遍历),对每个对象添加一个爆炸效果即可。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/340239?site
推荐阅读
相关标签
  

闽ICP备14008679号