【唠叨】

本节来讲讲简单的物理碰撞检测(非Box2D物理碰撞):矩形、圆之间的碰撞检测。


【3.x】

将数学类 CCPoint、CCRect 改为v3.x版本的 Vec2、Rect 就好了。




【简单碰撞检测】

在一些游戏中经常会遇到碰撞检测的情况,如愤怒的小鸟飞出去后,是否与石头发生碰撞。

虽然说有一个Box2D物理碰撞引擎,但是在这里还是需要掌握一下简单的碰撞检测方法。

(1)矩形与矩形

(2)圆与圆

(3)矩形与圆


1、矩形与矩形


1.1、提出问题

问题:假设有两个矩形rect1,rect2,判断两矩是否碰撞相交(部分区域重叠)。

如下四幅图中,图1、2、4发生碰撞,图3未发生碰撞。


1.2、解决方案

由图可知,判断方法只要计算一下两个矩形相交部分是否能够成一个小矩形。

判断方法如下:(可用于计算相交部分的小矩形信息)

//boolcollision_RectWithRect(CCRectrect1,CCRectrect2){//计算相交部分的矩形//左下角坐标:(lx,ly)//右上角坐标:(rx,ry)floatlx=max(rect1.getMinX(),rect2.getMinX());floatly=max(rect1.getMinY(),rect2.getMinY());floatrx=min(rect1.getMaxX(),rect2.getMaxX());floatry=min(rect1.getMaxY(),rect2.getMaxY());//判断是否能构成小矩形if(lx>rx||ly>ry)returnfalse;//矩形不相交elsereturntrue;//发生碰撞}//


当然也可以使用cocos2dx引擎中的CCRect类已经存在的一个判断矩形碰撞的函数。

////返回bool。相交为truerect1.intersectsRect(rect2);//////intersectsRect()函数的源码如下:boolCCRect::intersectsRect(constCCRect&rect)const{return!(getMaxX()<rect.getMinX()||rect.getMaxX()<getMinX()||getMaxY()<rect.getMinY()||rect.getMaxY()<getMinY());}//


2、圆与圆

2.1、提出问题

问题:假设有两个圆circle1,circle2,判断两圆是否碰撞相交(部分区域重叠)。

如下三幅图中,图1、2发生碰撞,图3未发生碰撞。


2.2、解决方案

圆的碰撞检测比较简单,只要判断两圆心距离是否小于半径相加(r1+r2)即可。

判断方法如下:

//boolcollision_CircleWithCircle(CCPointp1,floatr1,CCPointp2,floatr2){//计算圆心距离floatdist=p1.getDistance(p2);//判断两圆是否相交returndist<(r1+r2);}//


3、矩形与圆

3.1、提出问题

问题:假设有矩形rect、圆circle,判断矩形和圆是否碰撞相交(部分区域重叠)。

如下四幅图中,图1、2、4发生碰撞,图3未发生碰撞。

3.2、解决方案

矩形和圆的判断比较复杂,请看以下分析。

(1)首先,我们让圆在矩形外沿着矩形的边滚一圈,然后将圆心移动的轨迹连线,就可以得到一个圆角矩形。

(2)如下图红色区域为圆角矩形,显然我们只要判断圆心是否在圆角矩形区域内部即可。

(3)如果除去圆角矩形四个角上的4个四分之一圆的部分,仅仅让你判断圆心是否落在剩下的区域内,你应该能很快想出解决办法吧?

只要判断圆心是否在两个矩形的任意其中之一的内部即可。

(4)然后再判断圆心是否在四个角上的四分之一圆的区域部分即可。

显然,只要判断圆心与矩形的四个顶点的距离是否小于圆的半径即可。

(5)综合上诉:(3)(4)的判断,即可得出圆是否矩形相交。


判断方法如下:

//boolcollision_RectWithCircle(CCRectrect,CCPointp,floatr){//获取矩形信息//左下角坐标:(lx,ly)//右上角坐标:(rx,ry)floatlx=rect.getMinX();floatly=rect.getMinY();floatrx=rect.getMaxX();floatry=rect.getMaxY();//计算圆心到四个顶点的距离floatd1=p.getDistance(ccp(lx,ly));floatd2=p.getDistance(ccp(lx,ry));floatd3=p.getDistance(ccp(rx,ly));floatd4=p.getDistance(ccp(rx,ry));//判断是否碰撞//判断距离是否小于半径if(d1<r||d2<r||d3<r||d4<r)returntrue;//是否在圆角矩形的,横向矩形内if(p.x>(lx-r)&&p.x<(rx+r)&&p.y>ly&&p.y<ry)returntrue;//是否在圆角矩形的,纵向矩形内if(p.x>lx&&p.x<rx&&p.y>(ly-r)&&p.y<(ry+r))returntrue;//不发生碰撞returnfalse;}//