检测凸多边形碰撞的一种简单的方法是SAT(Separating Axis Theorem),即分离轴定理。

原理:将多边形投影到一条向量上,看这两个多边形的投影是否重叠。如果不重叠,则认为这两个多边形是分离的,否则找下一条向量来继续投影。我们不需要比较很多条向量,因为已经在数学上证明,多边形每条边的垂直向量就是我们需要的向量。

1.AABB

让我们首先以AABB开始(AABB是一种两边分别平行于X-Y轴的矩形)

判断两个AABB是否碰撞,我们只需要投影两次,分别是投影在平行于X轴和Y轴的向量上

由上图可以看见,因为在Y轴方向的投影是分离的,因此可以直接得出结论,即这两个AABB是分离的。

function AABBvsAABB(aabb1, aabb2) {
//check X axis
if(aabb1.xMin > aabb2.xMax)
return false;
if(aabb1.xMax < aabb2.xMin)
return false;
//check Y axis
if(aabb1.yMin > aabb2.yMax)
return false;
if(aabb1.yMax < aabb2.yMin)
return false; return true;
}

效果:---点击运行---

(点击产生AABB,碰撞的变红,否则变黄)

2.圆

圆的碰撞检测也能用SAT,就是要把两个圆投影在两个圆心连线的向量上。比较半径和与圆心距离,如果半径和大于圆心距离则碰撞。

代码:

注:通常为了优化,都是用平方而不是开方(sqrt好慢的)

function CircleVsCircle(c1, c2) {
var xSqr = c1.centerX - c2.centerX;
xSqr *= xSqr;
var ySqr = c1.centerY - c2.centerY;
ySqr *= ySqr;
//get the distance^2
var distanceSqr = xSqr + ySqr; var radiusSum = c1.radius + c2.radius; if(distanceSqr <= radiusSum*radiusSum)
return true;
else
return false;
}

效果:---点击运行---

(点击产生圆)

3.多边形

(1)找出两个多边形所有边的垂直向量;

(2)将两个多边形投影到垂直向量上,判断投影是否相交,如果不相交则两个多边形不相交,否则选下一条垂直向量继续进行投影判断。

代码:

function PolyVsPoly(p1, p2) {
//check the normal in p1
for(var i = 0; i < p1.points.length-1; i++) {
var edge = Minus(p1.points[i], p1.points[i+1]);
var normal = Normal(edge); var isOverlap = CheckCollide(normal, p1, p2);
if(!isOverlap)
return false;
} //check normal in p2
for(var i = 0; i < p2.points.length-1; i++) {
var edge = Minus(p2.points[i], p2.points[i+1]);
var normal = Normal(edge); var isOverlap = CheckCollide(normal, p1, p2);
if(!isOverlap)
return false;
} return true;
} function CheckCollide(axis, p1, p2) {
var min1 = Dot(p1.points[0], axis);
var max1 = Dot(p1.points[0], axis);
for(var k = 1; k < p1.points.length; k++) {
var v = Dot(p1.points[k], axis);
if(v > max1)
max1 = v;
if(v < min1)
min1 = v;
} var min2 = Dot(p2.points[0], axis);
var max2 = Dot(p2.points[0], axis);
for(var k = 1; k < p2.points.length; k++) {
var v = Dot(p2.points[k], axis);
if(v > max2)
max2 = v;
if(v < min2)
min2 = v;
} if(!IsOverlap(min1, max1, min2, max2))
return false; return true;
}

效果:---点击运行---

(使用方向键来移动,碰撞的变红,否则变黄)

4.圆与多边形

(1)找出多边形每条边的垂直向量,多边形最接近圆心的点到圆形的直线的垂直向量

(2)将圆和多边形投影到垂直向量上,再进行判断。

(其实和多边形之间的碰撞很像,这里就不浪费篇幅了)

总结:

SAT很简单,就是投影 + 重叠判断。

SAT只适用于凸体,毕竟凹体中间空缺的部分在投影后信息就消失了。

一些关于SAT的网站:

http://gamedevelopment.tutsplus.com/tutorials/collision-detection-with-the-separating-axis-theorem--gamedev-169

多边形碰撞 -- SAT方法的更多相关文章

  1. 解决Hash碰撞冲突方法总结

    Hash碰撞冲突 我们知道,对象Hash的前提是实现equals()和hashCode()两个方法,那么HashCode()的作用就是保证对象返回唯一hash值,但当两个对象计算值一样时,这就发生了碰 ...

  2. 2D多边形碰撞器优化器

    http://www.unity蛮牛.com/thread-19827-1-1.html http://pan.baidu.com/s/1qW2mWS8 Asset Store Link: http: ...

  3. H5游戏开发之多边形碰撞检测

    2D多边形碰撞检测介绍这是一篇论证如何在2D动作游戏中执行碰撞检测的文章(Mario,宇宙入侵者等),为了保证它的高效性和精确性,碰撞检测是以多边形为基础的,而不是以sprite为基础.这是两种不同的 ...

  4. [Unity2D]Box Collider 2D盒子碰撞器

    盒子碰撞器(BoxCollider2D)是Unity2D中常用的碰撞器,所有为碰撞器,顾名思义,就是用于检测物体之间的碰撞情况的,Unity2D里面除了BoxCollider2D碰撞器之外还集成Box ...

  5. cocos 碰撞系统

    前面的话 本文将简要介绍 Cocos Creator 中的碰撞系统,Cocos Creator 内置了一个简单易用的碰撞检测系统,支持圆形.矩形以及多边形相互间的碰撞检测 编辑碰撞组件 当添加了一个碰 ...

  6. 结合谷歌地图多边形(polygon)与Sql Server 2008的空间数据类型计算某个点是否在多边形内的注意事项

    首先在利用 GEOGRAPHY::STPolyFromText(@GeoStr, 4326) 这样的函数把字符串转换为Geography类型时,字符串里经纬度的顺序是 “经度[空格]纬度”,即“lon ...

  7. HDOJ(1115)多边形重心

    Lifting the Stone http://acm.hdu.edu.cn/showproblem.php?pid=1115 题目描述:输入n个顶点(整数),求它们围成的多边形的重心. 算法:以一 ...

  8. unity触发器和碰撞器

    Unity中检测碰撞的方法有两种,一种是触发器一种是碰撞器,现在我来解释一下两种的区别. 触发器:有三种方法,分别是OnTriggerEnter,OnTriggerStay,OnTriggerExit ...

  9. iOS7 UIKit动力学-碰撞特性UICollisionBehavior 下

    上文讲到了为window加一个边界.实现碰撞的效果,接下来我们将提到一个托付方法: - (void)collisionBehavior:(UICollisionBehavior *)behavior ...

随机推荐

  1. Windows10更新提示语言不同不能保留程序和设置

    打开注册表编辑器(Win+R,输入regedit)定位到: HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Nls\Language 在右边窗口中拉到最 ...

  2. HDU 3966 Aragorn's Story 树链剖分

    Link: http://acm.hdu.edu.cn/showproblem.php?pid=3966 这题注意要手动扩栈. 这题我交g++无限RE,即使手动扩栈了,但交C++就过了. #pragm ...

  3. embed标签loop=true背景音乐无法循环

    在html网页中加入背景音乐并设置为循环播放.一开始用<embed>标签,设置loop="true", 但是结果发现在IE浏览器可以,但是在chrome浏览器却无法实现 ...

  4. Windows7 + Ubuntu双系统安装过程记录

    本文为在已安装Windows7系统的前提下安装Ubuntu Kylin 14.10系统的过程以及期间出现的各种问题的记录. Ubuntu系统下载 Ubuntu Kylin中文官方网站:http://w ...

  5. VMware中的Ubuntu网络设置

    网络配置: VMware安装后会有两个默认网卡,分别是VMnet8(192.168.83.1)和VMnet1(192.168.19.1),当然不同的机器上,这两个网卡的 IP会不同的.在windows ...

  6. ecshop二次开发常用文件位置

    语言包修改: /language/zh_cn/admin/common.php 商品详情页模板: /themes/**/goods.dwt  (最下方有changePrice() 点选属性或改变数量时 ...

  7. VR系统的分类

    转载请声明转载地址:http://www.cnblogs.com/Rodolfo/,违者必究. 根据用户参与和沉浸感的程度,通常把虚拟现实分为4大类:桌面虚拟现实系统.沉浸式虚拟现实系统.增强虚拟现实 ...

  8. sql server 对象资源管理器(二)

    SQL会缓存大量的数据页面,他还会缓存很多其他信息,包括存储过程的执行计划 ,特定用户的安全上下文等 如果这些信息没有在数据库中缓存,SQL都要重新计算一遍,花额外的时间,所以SQLSERVER对内存 ...

  9. codeigniter框架The URI you submitted has disallowed characters错误解决方法

    CI中URI传递参数时,出现:The URI you submitted has disallowed characters.错误 .原因:这是由于uri中存在CI不允许的字符 . 解决办法:在con ...

  10. 3.通过现有的PDB创建一个新的PDB

    实验说明:创建PDB除了可以通过种子PDB创建外,现在测试通过一个现有的用户PDB克隆创建新的PDB数据库 实验步骤: 1.创建测试数据 SQL> alter session set conta ...