这节我们研究下pygame的几种碰撞检测模式:

如上图,左侧是默认的检测模式:基于矩形的检测(这也是性能最好的模式), 右侧是基于圆形的检测(性能略差于矩形检测)。

矩形检测法虽然性能好,但是缺点也很明显:检测不准确,上图中"飞机与目标"从视觉上看,根本没碰到。

为了改进,pygame给这二种模式,新增了xxx_ratio的方法,允许指定检测时,指定二个目标的叠加程度,只有达到指定的叠加值,才认为是真正碰撞到了,参考下图:

注:ratio的值越大,表示叠加的部分越少!

我们写一个小程序来测试一下:

  1 import pygame
  2 from os import path
  3 from xml.dom.minidom import parse
  4
  5 SIZE = (WIDTH, HEIGHT) = (265, 320)
  6 FPS = 45
  7
  8 BLACK = 0, 0, 0
  9 WHITE = 255, 255, 255
 10
 11 pygame.init()
 12 pygame.mixer.init()
 13
 14 screen = pygame.display.set_mode(SIZE)
 15 pygame.display.set_caption("My Game")
 16 clock = pygame.time.Clock()
 17
 18 spritesheet_image_file_name = path.join(path.dirname(__file__), "../img/spritesheet_jumper.png")
 19 spritesheet_xml_file_name = path.join(path.dirname(__file__), "../img/spritesheet_jumper.xml")
 20 spritesheet_image = pygame.image.load(spritesheet_image_file_name)
 21 spritesheet_image.set_colorkey(BLACK)
 22 spritesheet_dom_tree = parse(spritesheet_xml_file_name)
 23 root_textures = spritesheet_dom_tree.documentElement
 24 sub_textures = root_textures.getElementsByTagName("SubTexture")
 25 dic_image = {}
 26
 27
 28 def get_image_rect(img_name):
 29     if dic_image.get(img_name):
 30         return dic_image[img_name]
 31     for texture in sub_textures:
 32         name = texture.getAttribute("name")
 33         if img_name == name:
 34             dic_image[img_name] = pygame.Rect(
 35                 int(texture.getAttribute("x")),
 36                 int(texture.getAttribute("y")),
 37                 int(texture.getAttribute("width")),
 38                 int(texture.getAttribute("height"))
 39             )
 40             return dic_image[img_name]
 41
 42
 43 def get_image(img_name):
 44     rect = get_image_rect(img_name);
 45     image = pygame.Surface((rect.width, rect.height))
 46     image.blit(spritesheet_image, (0, 0), rect)
 47     image.set_colorkey(BLACK)
 48     return image
 49
 50
 51 class Demo(pygame.sprite.Sprite):
 52     def __init__(self, image, pos):
 53         pygame.sprite.Sprite.__init__(self)
 54         self.image = image
 55         self.rect = self.image.get_rect()
 56         self.rect.x = pos[0]
 57         self.rect.y = pos[1]
 58
 59
 60 running = True
 61 pos1 = (20, 5)
 62 pos2 = (125, 110)
 63
 64 demo1 = Demo(get_image("bunny1_walk1.png"), pos1)
 65 demo2 = Demo(get_image("bunny2_stand.png"), pos2)
 66
 67 all_sprites = pygame.sprite.LayeredUpdates()
 68 all_sprites.add(demo1, layer=2)
 69 all_sprites.add(demo2, layer=1)
 70
 71 group2 = pygame.sprite.Group()
 72 group2.add(demo2)
 73
 74 while running:
 75     clock.tick(FPS)
 76
 77     for event in pygame.event.get():
 78         if event.type == pygame.QUIT:
 79             running = False
 80         if event.type == pygame.KEYDOWN:
 81             if event.key == pygame.K_LEFT:
 82                 demo1.rect.x += -3
 83             if event.key == pygame.K_RIGHT:
 84                 demo1.rect.x += 3
 85             if event.key == pygame.K_UP:
 86                 demo1.rect.y += -3
 87             if event.key == pygame.K_DOWN:
 88                 demo1.rect.y += 3
 89
 90     screen.fill(BLACK)
 91
 92     all_sprites.draw(screen)
 93
 94     pygame.draw.rect(screen, (0, 255, 0), demo2.rect, 1)
 95     pygame.draw.rect(screen, (255, 0, 0), demo1.rect, 1)
 96
 97     font = pygame.font.SysFont("Menlo", 25, True)
 98
 99     # 默认的检测模式(rect)
100     if pygame.sprite.spritecollide(demo1, group2, False):
101         pos_txt = font.render("hit:true", 1, (255, 255, 128))
102     else:
103         pos_txt = font.render("hit:false", 1, (255, 255, 128))
104     screen.blit(pos_txt, (150, 10))
105
106     pygame.display.update()
107
108 pygame.quit()

View Code

这是默认的Rect检测模式。把100行换成:

    # 矩形检测(至少要重叠1-0.7=30%才算发生了碰撞)if pygame.sprite.spritecollide(demo1, group2, False, pygame.sprite.collide_rect_ratio(0.7)):

再看下效果:

继续,换成圆形检测试下:

    # 圆形检测(至少要重叠1-0.7=30%才算发生了碰撞)if pygame.sprite.spritecollide(demo1, group2, False, pygame.sprite.collide_circle_ratio(0.7)):

那么,有没有一种方法能做到精确检测呢?当然有,有一种基于mask(在绘图软件中,也称为遮罩或蒙版)的检测方法,类似把背景去掉后,像素级的碰撞检测,当然性能也是最差的。

首先要在Sprite的类上,指定mask:

1 class Demo(pygame.sprite.Sprite):
2     def __init__(self, image, pos):
3         pygame.sprite.Sprite.__init__(self)
4         self.image = image
5         self.rect = self.image.get_rect()
6         self.rect.x = pos[0]
7         self.rect.y = pos[1]
8         #指定蒙版
9         self.mask = pygame.mask.from_surface(self.image)

View Code

然后把检测代码改成:

    # 基于mask的检测if pygame.sprite.spritecollide(demo1, group2, False, pygame.sprite.collide_mask):

好了,利用上面学到的知识,把上节的遗留问题:"player与enemy的碰撞检测不准确" 解决一下,效果如下:

优化前 优化后

源码示例:https://github.com/yjmyzz/kids-can-code/tree/master/part_17

转载于:https://www.cnblogs.com/yjmyzz/p/pygame-kidscancode-part17-mask-collide.html

pygame-KidsCanCode系列jumpy-part17-mask-collide碰撞检测相关推荐

  1. 用pygame实现网上游戏‘球球情侣‘(用pygame.mask完成碰撞检测)

    网上有个'球球情侣'游戏,游戏中有两个不同颜色的球,玩者首先用鼠标画曲线画出球移动的路径,分别右击两个球,使两球沿曲线移动,如果两球碰到一起,进入下一关.编写很多关是游戏公司的事,这里只编写最简单的一 ...

  2. canvas系列教程06 ——边界检测、碰撞检测

    边界检测 边界检测,即检测一个物体所处"运动环境的范围"(也就是边界). 边界限制(避免越界) if (ball.x < ball.radius) {//小球"碰到 ...

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

    在游戏开发中,非常重要的编程工作就是进行碰撞检测.在python的pygame模块中的sprite精灵类提供了多种方便快捷的碰撞检测方法.比如矩形碰撞检测.圆形碰撞检测.遮罩碰撞检测,这些方法基本都是 ...

  4. Pygame详解(十八):mask 模块

    pygame.mask Pygame 中处理图形遮罩的模块. 函数 pygame.mask.from_surface()  --  从指定 Surface 对象中返回一个 Mask pygame.ma ...

  5. 90.pygame游戏-玩个球(play the ball)最终版

    文章目录 游戏部分截图 游戏操作说明 代码 所有图片素材 音乐素材 下载链接 游戏部分截图 游戏操作说明 1.鼠标上下左右晃动,在摩擦板中摩擦,会使得灰色求变绿色 2.上下左右(W,S,A,D)四个键 ...

  6. pygame只能编写游戏_游戏框架搭建

    游戏框架搭建 目标 -- 使用 面相对象 设计 飞机大战游戏类 目标 明确主程序职责 实现主程序类 准备游戏精灵组 01. 明确主程序职责 回顾 快速入门案例,一个游戏主程序的 职责 可以分为两个部分 ...

  7. 用Python和Pygame写游戏-从入门到精通(1)

    From: http://eyehere.net/2011/python-pygame-novice-professional-1/ 博客刚开,打算做一个Pygame的系列,翻译自Will McGug ...

  8. python中的pygame模块使用方法_Pygame的基本使用

    Pygame有很多模块,每个模块又有很多方法,在此不能够逐一讲解,所以,我们通过一个实例来学习Pygame,然后再分解代码,讲解代码中的模块. 例:制作一个跳跃的小球游戏. 创建一个游戏窗口,然后在窗 ...

  9. mask rcnn 超详细代码解读(一)

    mask r-cnn 代码解读(一) 文章目录 1 代码架构 2 model.py 的结构 3 train过程代码解析 3.1 Resnet Graph 3.2 Region Proposal Net ...

  10. 用Python和Pygame写游戏-从入门到精通

    博客刚开,打算做一个Pygame的系列,翻译自Will McGugan的<Beginning Game Development with Python and Pygame –From Novi ...

最新文章

  1. linux zabbix_agentd命令 监控服务器参数 简介
  2. 【错误记录】Google Play 上架报错 ( 您还没有为此轨道选择任何国家或地区。至少要添加 1 个国家或地区才能发布此版本)
  3. 必须掌握的八个【cmd 命令行】[
  4. 【Scratch】青少年蓝桥杯_每日一题_2.23_小猫来回走
  5. 这就是搜索引擎--读书笔记五--索引的建立与更新
  6. 程序读取计算机设备管理器中各设备的状态(启用/禁用)?(转自大富翁)
  7. narwal无法连接机器人_库卡机器人控制系统主机出现MFC3故障维修
  8. 支持百万级TPS,Kafka是怎么做到的?
  9. Ansible 详细用法部署安装
  10. 数据结构与算法分析:第1、2章:引论和算法分析
  11. Mysql基础之 事务
  12. 判断日期yyyymmdd
  13. 如何用计算机管理员权限,怎么打开管理员权限,电脑怎么用管理员权限
  14. 利用python通过两点构成的空间直线和平面计算交点
  15. c语言考试可视化编辑器无法提交,一行代码解决The7升级后可视化编辑器不能正常工作的问题...
  16. c语言第七章函数实验总结,C语言学习与总结---第七章:函数 [01]
  17. 程序人生 - Nature封面:脑机接口突破,可将脑中“笔迹”转为屏幕字句,速度创纪录,准确率超高
  18. 国开计算机专业英语答案,国开电大计算机专业英语阅读(河北)形考三参考答案...
  19. python 群发邮件数量限制_用邮件群发平台群发邮件的数量有限制吗?一般可以发多少?...
  20. webpack打包时提示:The following entrypoint(s) combined asset size exceeds the recommended limit

热门文章

  1. vue项目内存溢出的解决
  2. Ubuntu 12.04系统天嵌Linux交叉编译开发工具的安装
  3. 社交口才:处理好人际关系的七种谈话技巧
  4. 通过Requst进行12306查票(2022-09-10)
  5. “Physically-Based Rendering for Indoor Scene Understanding Using Convolutional Neural Networks”论文阅读
  6. Ninth season twentieth episode,Joey held a celebrities party but did not invited his friends!!!!!!
  7. 企业如何CRM管理软件中受益
  8. 如何在Abaqus中用扫掠的方法画六面体网格
  9. win10系统开机出现grub,一步进入window系统
  10. Ubuntu下,用键盘定义鼠标按键