文档章节

圆与旋转矩形的碰撞检测(下篇)

piggybear
 piggybear
发布于 2015/02/16 10:28
字数 1029
阅读 23
收藏 0

本文翻译自《Circle and Rotated Rectangle Collision Detection》,敬请勘误。


圆与旋转矩形的碰撞检测

本文我将解释如何实现圆和旋转矩形的碰撞检测。碰撞检测用于确定对象A是否碰撞了对象B。圆包含圆心位置x,y和一个半径。矩形包含左上角的x,y位置、宽度、长度和一个可以旋转的角度。我们假设矩形沿着它的中心点旋转。


我将使用一个小程序、图片和代码来展示这一点。为了更好地理解圆和不旋转矩形之间的碰撞检测,可以阅读这篇文章


程序示例

这里有一个程序示例来展示碰撞检测。如果检测到碰撞,图形就变为蓝色。绿色轮廓形状表示该用于计算的状态。橙色的线将未旋转圆的圆心与矩形上最近的一个点连接。你可以设置一个角度,点击按钮使其旋转。点击或者拖动某个地方使圆形移动。


设置一个角度实现圆形和矩形碰撞检测

想法很简单。为了计算方便,我们需要在矩形角度为0时,记下两个形状的位置。如果我们将矩形旋转一个角度,计算将会有一点复杂。将矩形保持0度角时候通过简单的加法就可以很容易地获得其他点的位置坐标。左上角为(x,y),右上角为(x+width, y),左下角为(x, y+height)。

c1.png

这里我们不旋转矩形,而是用同样的角度旋转圆。将圆心放在矩形角度为0时的位置。单点比较容易旋转。如下简图所示,蓝色区域代表我们所看到的矩形在旋转。黑色区域用于计算。我们用0度调整形状,换言之,我们将矩形设为0度,用矩形的角度来旋转圆。


所用的公式如下所示。变量cx/cy代表圆心点,originX/originY代表旋转圆的点,x’/y’为旋转点。

x’= cos(theta) * (cx – originX) – sin(theta) * (cy – originY) + originX

y’= sin(theta) * (cx – originX) + cos(theta) * (cy – originY) + originY

c2.png

找到离未旋转的圆和矩形最近的点,我们需要做的就是分别为x和y做if-else判断。


对于x,使用矩形的left x(rx)和right x(rx+width)与圆心x(cx)做比较。如果cx在rx的左边,那么rx离x最近。如果cx在rx+width的右边,那么rx+width离x最近。最后如果以上两点都不符合,那么cx本身离x最近。如下图所示,红色线表示x的位置。

c3.png


对于y,与x的规则相同。如果圆心y(cy)在top y(ry)的上面,那么ry离y点最近。如果cy在bottom y(ry+height)的下面,ry+heigh离y最近。如果以上两点都不符合,那么cy离y最近。

c4.png


最后,我们需要计算未旋转圆的圆心和我们所找到的最近点的距离。我使用勾股定理计算这个最近距离(a^2 + b^2 = c^2)。然后将这个值与圆的半径作比较,如果这个距离远远小于半径,那么这两个图形就会发生碰撞。

c5.png

代码实例

1
2
3
4
5
6
7
8
9
10
11
// Rotate circle's center point backdouble unrotatedCircleX = Math.cos(rect.angle) * (circle.x - rect.centerX) - 
Math. sin (rect.angle) * (circle.y - rect.centerY) + rect.centerX; double  unrotatedCircleY  = Math. sin (rect.angle) * (circle.x - rect.centerX) + 
Math. cos (rect.angle) * (circle.y - rect.centerY) + rect.centerY;  // Closest point in the rectangle to the center of circle rotated backwards(unrotated)double closestX, closestY; // Find the unrotated closest x point from center of unrotated circleif (unrotatedCircleX  < rect.x)
closestX = rect.x; else  if  (unrotatedCircleX  > rect.x + rect.width)
closestX = rect.x + rect.width; else
closestX = unrotatedCircleX ;  // Find the unrotated closest y point from center of unrotated circleif (unrotatedCircleY < rect.y)
closestY = rect.y; else  if  (unrotatedCircleY > rect.y + rect.height)
closestY = rect.y + rect.height; else
closestY = unrotatedCircleY;  // Determine collisionboolean collision = false; double distance = findDistance(unrotatedCircleX , unrotatedCircleY, closestX, closestY);if (distance < circle.radius)
collision =  true // Collisionelse
collision =  false ;
1
2
3
4
5
6
7
8
9
/**
  * Pythagorean theorem
  * @param fromX
  * @param fromY
  * @param toX
  * @param toY
  */ public  double  findDistance( double  fromX,  double  fromY,  double  toX,  double  toY){
  double  a = Math. abs (fromX - toX);
  double  b = Math. abs (fromY - toY);      return  Math. sqrt ((a * a) + (b * b));}


本文转载自:http://blog.csdn.net/aa294194253/article/details/39208495

共有 人打赏支持
piggybear
粉丝 3
博文 237
码字总数 37552
作品 0
西安
技术主管
26、《每周一点canvas动画》——3D旋转与碰撞

各位同学实在不好意思,最近忙着面试找工作,耽搁了一个星期。由于前一篇文章的关注的量比较多,让我决定以后的文章尽量多加一些高质量的DEMO和配图。可能这比较耗费时间,但质量才是王道,希...

qq_39759115
04/17
0
0
2.5d 游戏开发引擎--IndieLib

IndieLib是一个 2.5d引擎,使用它可以简化游戏开发的难度,提高游戏开发的速度。内部它使用Direct3d做硬件加速,但它并没有使用DirectDraw或者 ID3DXSprite,而是直接将材质渲染在多边形上。...

匿名
2012/03/31
4.8K
0
用Go和Korok写一个Flappybird游戏-3

在 前一节,我们实现了游戏主场景,设计了游戏状态并添加了简单的物理。本章将继续完善游戏物理和游戏状态。本节你将学会: 如何处理连续的滚动效果 如何处理碰撞检测 实现无限的游戏内容 注...

ntop
06/11
0
0
13.7-全栈Java笔记:打飞机游戏实战项目|Rectangle|intersects|Plane

碰撞类检测技术 游戏中,碰撞是遇到最频繁的技术。当然,很多游戏引擎内部已经做了碰撞检测处理,我们只需调用即可。本节课是从碰撞的原理进行讲解,大家自己去实现基本的碰撞检测。 矩形检测...

全栈Java
06/26
0
0
LibGDX_7.4: 碰撞检测 与 矩形包围区域(Rectangle)

本文链接: http://blog.csdn.net/xietansheng/article/details/50188157 LibGDX 基础教程(总目录) 1. Rectangle 概述 Rectangle 类表示一个 2D 矩形,封装了 2D 矩形的 左下角坐标 和 宽高...

xietansheng
2015/12/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Java中的移位运算符

国庆给自己放了个小长期二十几天,回来继续更新专栏 上一篇文章我们说了Java里的二进制,知道了计算机是以0和1来处理数据的,在阅读源码的过程中,经常会看到这些符号<< ,>>,>>>,这些符号...

SuShine
18分钟前
2
0
linux版QQ

下载地址在这 http://yun.tzmm.com.cn/index.php/s/XRbfi6aOIjv5gwj Appimage包不用做什么别的处理,安装啥的都不需要。。找到文件所在目录,终端中修改一下文件的权限 chmod 777 QQ-2017112...

悲催的古灵武士
24分钟前
1
0
咕泡-MyBatis 实用篇作业

1. Mapper在spring管理下其实是单例,为什么可以是一个单例? 首先,mapper 内部不包含 成员字段,无状态单例是安全的 另外,一直存在不用每次调用都new 一个新实例 2. MyBatis在Spring集成下...

职业搬砖20年
27分钟前
2
0
MQTT协议的初浅认识之连接建立

MQTT百科 MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议。它工作在 TCP/IP协议族上,是为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布...

亚林瓜子
44分钟前
1
0
OpenStack部署都有哪些方式

对于每一个刚接触到OpenStack的新人而言,安装无疑是最困难的,同时这也客观上提高了大家学习OpenStack云计算的技术门槛。想一想,自己3年前网上偶然接触到OpenStack时,一头茫然,手动搭建一...

tututu_jiang
44分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部