检测凸多边形碰撞的一种简单的方法是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. PHP中类的继承和构造函数的继承

    PHP4.x 版本: PHP 4.x 的构造函数名与类名相同. 子类的构造函数名与子类名相同(废话). 在子类里父类的构造函数不会自动执行. 要在子类里执行父类的构造函数,必须执行类似以下语句: $t ...

  2. Linux C 文件输入输出函数 fopen()、getc()/fgetc()、putc()/fputc()、fclose()、fprintf()、fscanf()、fgets()、fputs()、fseek()、ftell()、fgetpos()、fsetpos() 详解

      fopen(打开文件) 定义函数 FILE * fopen(const char * path,const char * mode); 函数说明 参数path字符串包含欲打开的文件路径及文件名,参 ...

  3. word20161210

    gateway / 网关 gateway account / 网关帐户 Gateway Service for NetWare / NetWare 网关服务 GDI objects / GDI 对象 ...

  4. Git 常用命令合集

    $ git init          建立git仓库(一般都是在github上新建好,直接克隆到本地) $ git clone **.git       克隆git仓库 $ git add -A   ...

  5. 1.reset.css的设置

    /* reset css */ *, ::before, ::after{ /*选择所有的标签 */ margin: 0; padding: 0; /*清除移动端默认的 点击高亮效果*/ -webki ...

  6. 难道这就是JavaScript中的"闭包"

    其实对于JavaScript中的"闭包"还没真正理解,这次在实际Coding中似乎遇到了"闭包"的问题,仅此摘录,以待深究. 表现为jQuery的post方法回 ...

  7. 去掉UITableView多余的空白行分割线

    一.问题描述 在学习和开发中经常会遇到下面的问题,UITableView的UITableViewCell很少或者没有时,但UITableView有很多的空白行分割线.如下图: 如何去掉UITableV ...

  8. c/c++优化结构控制

    一.表达式优化--使用替换程序中的乘除法 c/c++中的加减运算效率远远高于乘除运算,由于移位指令的执行速度和乘除法差不多,所以可以使用移位的方式来替换程序中的乘除法.一个数向右移一位,等于该数乘以2 ...

  9. [jquery]添加行内容后根据下拉菜单选择内容对比之前已有选项,若有重置再提示

    今天页面上一个添加列内容时,要对选择内容与之前已有选项内容作对比,防止用户重复选择内容 页面HTML代码 <ul class="list-group xj-list-NObor xj- ...

  10. eclipse中如何安装插件ADT及SDK工具

    1.如何在eclipse中安装ADT 首先下载ADT Plugin 下载地址: http://tools.android-studio.org/index.php/adt-bundle-plugin ...