在游戏开发中,非常重要的编程工作就是进行碰撞检测。在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)

发生碰撞之后的状态显示如下,可以看出,四架飞机和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遍历),对每个对象添加一个爆炸效果即可。

Python中pygame模块pygame.sprite.groupcollision碰撞检测的详解与测试相关推荐

  1. python os模块安装方法_基于python中pygame模块的Linux下安装过程(详解)

    一.使用pip安装Python包 大多数较新的Python版本都自带pip,因此首先可检查系统是否已经安装了pip.在Python3中,pip有时被称为pip3. 1.在Linux和OS X系统中检查 ...

  2. Python中第三方库Requests库的高级用法详解

    Python中第三方库Requests库的高级用法详解 虽然Python的标准库中urllib2模块已经包含了平常我们使用的大多数功能,但是它的API使用起来让人实在感觉不好.它已经不适合现在的时代, ...

  3. python数组相减_对Python 中矩阵或者数组相减的法则详解

    对Python 中矩阵或者数组相减的法则详解 最近在做编程练习,发现有些结果的值与答案相差较大,通过分析比较得出结论,大概过程如下: 定义了一个计算损失的函数: def error(yhat,labe ...

  4. python中requests库的用途-python中requests库session对象的妙用详解

    在进行接口测试的时候,我们会调用多个接口发出多个请求,在这些请求中有时候需要保持一些共用的数据,例如cookies信息. 妙用1 requests库的session对象能够帮我们跨请求保持某些参数,也 ...

  5. 站长在线Python精讲:在Python中使用正则表达式的sub()方法替换字符串详解

    欢迎你来到站长在线的站长学堂学习Python知识,本文学习的是<在Python中使用正则表达式的sub()方法替换字符串详解>. 在Python中使用正则表达式的sub()方法替换字符串. ...

  6. 站长在线Python精讲:在Python中使用正则表达式的split()方法分割字符串详解

    欢迎你来到站长在线的站长学堂学习Python知识,本文学习的是<在Python中使用正则表达式的split()方法分割字符串详解>. 使用正则表达式分割字符串 在Python中使用正则表达 ...

  7. python url解码_对python中url参数编码与解码的实例详解

    一.简介 在python中url,对于中文等非ascii码字符,需要进行参数的编码与解码. 二.关键代码 1.url编码 对字符串编码用urllib.parse包下的quote(string, saf ...

  8. getpid php,对python中的os.getpid()和os.fork()函数详解

    如下所示: import os import sys import time processNmae = 'parent' print "Program executing ntpid:%d ...

  9. 站长在线python精讲:在Python中使用len()函数计算字符串的长度详解

    欢迎你来到站长在线的站长学堂学习Python知识,本文学习的是<在Python中使用len()函数计算字符串的长度详解>.本知识点主要内容有:在Python中使用len()函数计算字符串在 ...

最新文章

  1. Django Request对象3.3
  2. 数据库分享一: MySQL的Innodb缓存相关优化
  3. 【转摘】PYTHON 正则表达式
  4. 图片预览组件PhotoView
  5. C++11新特性之新类型与初始化
  6. cf552 G Minimum Possible LCMn个数,求最小得一对lcm
  7. 日志分析系统分类有哪些_SEO优化中网站日志起到的重要性作用
  8. [网络安全自学篇] 十一.虚拟机VMware+Kali安装入门及Sqlmap普及
  9. H - Square Card HDU - 7063
  10. SpringBoot+MyBatis+Redis实现SSO单点登录系统(二)
  11. HTTP Error 500.19 – Internal Server Error – 0x80070021 (IIS 8.5)
  12. xserver源码分析
  13. 如何制作和使用自签名证书
  14. qq一键登录 android,QQ帐号通Android全新登场:一键快捷登录腾讯应用
  15. mysql 删除分区报错_MySQL分区管理
  16. JUJU 猫论坛系统克隆准备工具 V1.0.0.0 Beta 测试版(菜鸟也能轻松制作万能克隆光盘)...
  17. 最合理的关键词密度是多少?
  18. 2021莆田六中一高考成绩查询入口,2021,我们来了 ——莆田六中2021届《青春•励志•圆梦》高三高考动员誓师大会...
  19. Python zip zip_longest
  20. openwrt默认mac地址配置(MT7620a)

热门文章

  1. VLC 实现的简单播放器
  2. mysql 计算 两个字段 之差_MYSQL计算两个字段日期差
  3. 如何实现Android指纹登录
  4. OSChina 周四乱弹 —— 二次元世界很不安全
  5. 基于盛大云IaaS部署CloudFoundry平台
  6. 谷歌Android专利侵权拖累一大片厂商
  7. python通过经纬度算出距离_Python中如何利用经纬度进行距离计算
  8. icloud文档本地存储_如何在iCloud存储上省钱
  9. Word中插入的公式再次打开后字体变大的问题
  10. 零识区块链对话:Web3.0与元宇宙的关系?