前言
最近在做一个2d打砖块游戏,一番百度谷歌后找到了这个算法,比较好的符和预期在此记录一下。
分离轴定理(SAT | Separating Axis Theorem)通常用于2D凸多边形之间和凸多边形与圆形做碰撞检测的算法。
基本原理
简单来说,有两个凸多边形在平面中如果存在一条直线将他俩分隔开,那么这两个凸多边形必不相交,如图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/f4d84da98e4c433caa709c6688a3c083.png
显然,检查所有角度的分离轴是不合理的,基于凸多边形的性质,我们只需要以两个多边形的所有边的法向量作为分离轴来做检测即可。图中黄色的线就是直角三角形的斜边的法向量。
完整的算法流程
- 获取两个多边形所有边的集合。
- 计算每条边的法向量作为分离轴。
- 遍历所有分离轴分别计算两个多边形的顶点在分离轴上的投影,取最大值和最小值。
- 检测第三步取到的两个多边形的投影在该分离轴上是否相交,相交则两多边形在该方向上发生碰撞。
想必大家此时知道了SAT的原理但是对如何实现这个算法还是一头雾水。下面我们就一步一步的来完成这个算法。
从问题入手,一个问题一个问题的解决,相信能让大家的思路更加清晰。
1.如何取到多边形的边?
这里需要大家高中所学的向量知识作为基础,关于向量的基本知识就不再这里赘述了。
首先在绘制多边形时我们是能拿到多边形的所有顶点的,我们顺时针遍历多边形的顶点让他们两两相减就能得到多边形的边向量。
2.如何计算每条边的法向量?
如图所示:
设向量p = (x,y), 向量的左法向量left = (-y,x),向量的右法向量right = (y,-x);
3.如何取到多边形各个点在分离轴上的投影?
如图,p就是向量a在向量b上的投影。
|p| = |a|cosθ;
根据向量点积的基本知识
a·b = |a||b|cosθ
所以 |p| = |a|cosθ = a·b / |b|,我们将b设为单位向量,已知单位向量的模|b|等于1,所以 |p| = |a|cosθ = a·b,至此我只需要求出a和b的点积便能得到a在b上投影的大小了。
4.如何判断求得的两个投影是否相交?
一图了然
完成以上步骤,我们就准备好了完成SAT算法的所有条件了,可以着手去实现代码了。
补充:圆形与多边形的碰撞检测需要补充一条圆心到多边形最近的点的向量作为分离轴。圆与圆之间的碰撞检测只需要判断两圆心的距离是否小于两圆半径之和。