2D游戏中的碰撞检测:圆形与矩形碰撞检测Javascript

一,原理介绍

这回有点复杂,不过看懂了还是很好理解的。当然,我不敢保证这种算法在任何情况下都会起效果,如果有同学测试时,发现出现错误,请及时联系我。

我们首先来建立一个以圆心为原点的坐标系:

然后要检测碰撞就只有两种情况了。

情况一,矩形全部都在一个象限内,如图:

当然,图中只是举个例子,不一定是只在第二象限,任何一个象限都行,只要是矩形全在该象限。

这种情况比较好解决,首先,我们计算出矩形每个角的坐标,然后用勾股定律依次算出这个角到圆心的距离是否小于或者等于半径。设这个角与圆心横坐标之差为d1,纵坐标之差为d2,半径为r,公式表达如下:

如果有一个角满足要求说明产生碰撞,返回true。

但是有朋友懵了,怎么判断矩形是不是在一个象限内呢?很简单,只要判断这个矩形左上角和右下角是否在同一个象限内就可以了。于是我们得写个函数来实现判断某两个角是否在同一象限。

函数代码如下:

[javascript] view plain copy

  1. function isSameQuadrant(cood,objA,objB){
  2.     var coodX = cood.x;
  3.     var coodY = cood.y;
  4.     var xoA = objA.x
  5.     ,yoA = objA.y
  6.     ,xoB = objB.x
  7.     ,yoB = objB.y;
  8.     if(xoA-coodX>0 && xoB-coodX>0){
  9.         if((yoA-coodY>0 && yoB-coodY>0) || (yoA-coodY<0 && yoB-coodY<0)){
  10.             return true;
  11.         }
  12.         return false;
  13.     }else if(xoA-coodX<0 && xoB-coodX<0){
  14.         if((yoA-coodY>0 && yoB-coodY>0) || (yoA-coodY<0 && yoB-coodY<0)){
  15.             return true;
  16.         }
  17.         return false;
  18.     }else{
  19.         return false;
  20.     }
  21. }

这个函数原本是准备写到lufylegend中LMath静态类中的,参数原本是LPoint对象,但是这里可以用json,因为LPoint里的x,y属性可以写到json里,函数也就同样取得出值了。函数参数介绍:[cood创建的坐标系原点坐标, objA第一个点坐标, objB第二个点坐标] 这几个参数均为json对象,格式为:

[javascript] view plain copy

  1. {x:点的x坐标, y:点的y坐标}

函数中的代码还是很好理解的,就是判断一下两个点的x坐标都分别减去原点x坐标,看得出的数正负符号是否相同,然后又用同样的办法算出y轴上的符号是否相同,如果都相同就在同一象限。

有了这个函数,剩下得就好办了,直接代入开头给出的公式进行计算即可。

情况二,矩形跨度两个象限或者两个象限以上

这种情况更好办,我们就可以直接把圆看作一个边长为2r正方形,然后用矩形碰撞算法检测正方形和矩形的碰撞,如下图所示:

矩形碰撞的算法是什么呢?很easy,如图:

如果要横向判断碰撞的话,判断(x1-x2)的绝对值是否小于或者等于w1/2+w2/2,如果是则横向则有碰撞。纵向判断是一样的,判断(y1-y2)的绝对值是否小于或等于h1/2+h2/2即可。

有了这些算法,我们就可以实现情况2了。