鱼C论坛

 找回密码
 立即注册
查看: 975|回复: 8

[已解决]关于pygame的碰撞检测函数spritecollide

[复制链接]
发表于 2018-8-1 10:49:35 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x


  1. #初始化小球列表和pygame小球组
  2. balls = []
  3. group = pygame.sprite.Group()
  4. for i in range(5):
  5.               ....进行相关生成小球(ball)操作.....
  6.    
  7.         balls.append(ball)
  8.         group.add(ball)

  9. for each in group:
  10.             group.remove(each)

  11.             if pygame.sprite.spritecollide(each,group,False,pygame.sprite.collide_circle):
  12.                 #如果检测到碰撞,进行相关操作
  13.             group.add(each)
  14. 这里有个问题,每次group.remove,检测后再add回去。
  15. 因为group是个列表,假设group是【1,3,5,7,9】 那么第一次是1去和3,5,7,9进行检测
  16. group.add() 就是【3,5,7,9,1】
  17. 那么下次循环会从5开始,跳过3,为啥还能检测成功。

复制代码
最佳答案
2018-8-1 14:12:44

假如3和5,2个球刚好挨到,但此时的碰撞检测中没有3,那么2个球的图片像素点还是任然移动,并且会相交,但只要这2个图片,也就是这2个动画精灵存在像素的重叠,spritecollide方法就会被触发,即使挨到没检测到,但直到相交到某一点被检测到后,speed列表中的值就会取反。所以运行时,你看到2个球像是刚一碰到就分开,实际上你将帧率调到1,你会发现2个球是相交后再互相弹开,帧率调到满足流畅度的30时,你感觉它们是刚好挨到就弹开了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-8-1 11:34:14 | 显示全部楼层
虽然下次是从5开始,跳过了3,但是每次检测时group列表都会被打乱,即使第一次循环完,each都不会是3,但是group已经变成了[7,9,3,5,1],只要3球与其他球相撞,那么在while循环中,就一定会被检测到。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-1 11:52:56 | 显示全部楼层
lomiss 发表于 2018-8-1 11:34
虽然下次是从5开始,跳过了3,但是每次检测时group列表都会被打乱,即使第一次循环完,each都不会是3,但是 ...
  1. 假设是[1,3,5,7,9]
  2. ① 1-->3,5,7,9碰撞检测,新列表[3,5,7,9,1]
  3. ② 5-->3,7,9,1碰撞检测,新列表[3,7,9,1,5]
  4. ③ 9-->3,7,1,5碰撞检测,新列表[3,7,1,5,9]
  5. ④ 5-->3,7,1,9碰撞检测。新列表[3,7,1,9,5]
  6. ⑤ 5-->3,7,1,9碰撞检测,新列表[3,7,1,9,5]
  7. 我可以断定1,5,9的碰撞检测结果,但是我无法确定3和7是否发生了碰撞啊。
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-1 12:11:17 | 显示全部楼层
一删一补就回来了,而且都在group的一边。
假如你注释掉那两行代码,你会发现球总是在抖来抖去,无法移动。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-1 12:31:30 | 显示全部楼层
无符号整形 发表于 2018-8-1 12:11
一删一补就回来了,而且都在group的一边。
假如你注释掉那两行代码,你会发现球总是在抖来抖去,无法移动 ...

就是有个疑问,如果按照列表的相关操作,那么不是每个球都能被检测到啊。
  1. 假设是[1,3,5,7,9]
  2. ① 1-->3,5,7,9碰撞检测,新列表[3,5,7,9,1]
  3. ② 5-->3,7,9,1碰撞检测,新列表[3,7,9,1,5]
  4. ③ 9-->3,7,1,5碰撞检测,新列表[3,7,1,5,9]
  5. ④ 5-->3,7,1,9碰撞检测。新列表[3,7,1,9,5]
  6. ⑤ 5-->3,7,1,9碰撞检测,新列表[3,7,1,9,5]
  7. 我可以断定1,5,9的碰撞检测结果,但是我无法确定3和7是否发生了碰撞啊。
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-1 12:38:33 | 显示全部楼层

因为这个碰撞检测是在主循环中,第一次检测不到,就第二次了,然后直到检测到为止
第一次循环检测
  1. group = [1,3,5,7,9]
  2. for each in group:
  3.     group.remove(each)
  4.     group.append(each)
  5.     print(each)
  6.     print(group)
  7. 输出:
  8. 1
  9. [3, 5, 7, 9, 1]
  10. 5
  11. [3, 7, 9, 1, 5]
  12. 9
  13. [3, 7, 1, 5, 9]
  14. 5
  15. [3, 7, 1, 9, 5]
  16. 5
  17. [3, 7, 1, 9, 5]
复制代码

第二次循环检测
  1. group = [3, 7, 1, 9, 5]
  2. for each in group:
  3.     group.remove(each)
  4.     group.append(each)
  5.     print(each)
  6.     print(group)

  7. 输出       
  8. 3
  9. [7, 1, 9, 5, 3]
  10. 1
  11. [7, 9, 5, 3, 1]
  12. 5
  13. [7, 9, 3, 1, 5]
  14. 1
  15. [7, 9, 3, 5, 1]
  16. 1
  17. [7, 9, 3, 5, 1]
复制代码

第三次循环检测
  1. group = [7, 9, 3, 5, 1]
  2. for each in group:
  3.     group.remove(each)
  4.     group.append(each)
  5.     print(each)
  6.     print(group)
  7. 输出
  8. 7
  9. [9, 3, 5, 1, 7]
  10. 3
  11. [9, 5, 1, 7, 3]
  12. 1
  13. [9, 5, 7, 3, 1]
  14. 3
  15. [9, 5, 7, 1, 3]
  16. 3
  17. [9, 5, 7, 1, 3]
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-1 13:08:12 | 显示全部楼层
lomiss 发表于 2018-8-1 12:38
因为这个碰撞检测是在主循环中,第一次检测不到,就第二次了,然后直到检测到为止
第一次循环检测

  1. while running:
  2.         for event in pygame.event.get():
  3.             if event.type == QUIT:
  4.                 sys.exit()

  5.         screen.blit(background,(0,0))
  6.         for each in balls:
  7.             each.move()
  8.             screen.blit(each.image,each.rect)
  9.         for each in group:
  10.             group.remove(each)
  11.             if pygame.sprite.spritecollide(each,group,False,pygame.sprite.collide_circle):
  12.                 each.speed[0] = -each.speed[0]
  13.                 each.speed[1] = -each.speed[1]
  14.             group.add(each)
  15. 我懂你的意思了,但是有一个问题,如果我有两个球在移动的时候重叠(即发生碰撞)
  16. 但是此时刚好gorup组循环到不能检测到这两个球是否发生碰撞的那个情况下,即上面我提到的3和7不能检测到是否碰撞
  17. 那么碰撞检测不是就失效了吗
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-1 14:12:44 | 显示全部楼层    本楼为最佳答案   

假如3和5,2个球刚好挨到,但此时的碰撞检测中没有3,那么2个球的图片像素点还是任然移动,并且会相交,但只要这2个图片,也就是这2个动画精灵存在像素的重叠,spritecollide方法就会被触发,即使挨到没检测到,但直到相交到某一点被检测到后,speed列表中的值就会取反。所以运行时,你看到2个球像是刚一碰到就分开,实际上你将帧率调到1,你会发现2个球是相交后再互相弹开,帧率调到满足流畅度的30时,你感觉它们是刚好挨到就弹开了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-1 14:50:39 | 显示全部楼层
本帖最后由 小小小小的鱼丶 于 2018-8-1 14:57 编辑
lomiss 发表于 2018-8-1 14:12
假如3和5,2个球刚好挨到,但此时的碰撞检测中没有3,那么2个球的图片像素点还是任然移动,并且会相交, ...


多谢。也就是说因为帧率的原因,我重叠部分的多少(也就是第一次重叠就被检测到和再次移动后才被检测到)被眼睛给忽略了是把。~~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-19 09:07

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表