版本:cocoscreator 3.8.2
目录
游戏中常用的碰撞检测
1. 角色砍一刀,检测敌方是否在攻击范围内。
2. 子弹飞行时,是否击中角色。
3. 角色移动时,和障碍物、地图边缘的碰撞检测,碰撞则不能行走。
4. 角色AOE法术,检测敌方是否在法术攻击范围内。
5. 等等
AABB,Axis-Aligned Bounding Box,轴对齐包围盒,判断投影是否重叠方法来检测碰撞,AABB表示没有旋转的矩形。
cocos提供的碰撞检测方法,intersection-2d.ts:
/**
* @en Test rect and rect
* @zh 测试矩形与矩形是否相交
*/
function rectRect (a: Rect, b: Rect): boolean {
// jshint camelcase:false
const a_min_x = a.x;
const a_min_y = a.y;
const a_max_x = a.x + a.width;
const a_max_y = a.y + a.height;
const b_min_x = b.x;
const b_min_y = b.y;
const b_max_x = b.x + b.width;
const b_max_y = b.y + b.height;
return a_min_x <= b_max_x
&& a_max_x >= b_min_x
&& a_min_y <= b_max_y
&& a_max_y >= b_min_y;
}
判断红色和蓝色Node是否碰撞,下图是有碰撞的,输出为true。

const isHit: boolean = Intersection2D.rectRect(this.red.getComponent(UITransform).getBoundingBox(), this.blue.getComponent(UITransform).getBoundingBox()); console.log(isHit); //true
其中getBoundingBox()获取的Rect,值(x,y,width,height)中的x,y是矩形左下角的坐标位置。
this.red.getComponent(UITransform).getBoundingBox()
该方法不能检查旋转的图形,如下图,红色旋转了45°,碰撞检测仍然输出为true,这是不对的。

带旋转的矩形OBB,Oriented Bounding Box,有向包围盒。cocos没有提供OBB的碰撞检测,需要自己实现。
最可靠方法是分离轴定理(SAT),具体实现可用AI,挺复杂的,平时也用不着旋转的矩形碰撞检测。
总结:
1. 不带旋转的矩形叫轴对齐包围盒AABB,碰撞检测可直接使用cocos提供方法。
2. 带旋转的矩形叫有向包围盒OOB,碰撞检测得自己实现。
3. 碰撞检测方法不受锚点影响,例如(0.5,0.5)或(0,0)都能正确检测。
4.矩形碰撞常用于攻击范围、障碍物碰撞检测等。
圆形之间检测主要判断圆心距离是否超过了两个圆的半径之和。
cocos提供的圆形碰撞检测,intersection-2d.ts:
/**
* @en Test circle and circle
* @zh 测试圆形与圆形是否相交
*/
function circleCircle (c1p: Readonly<Vec2>, c1r: number, c2p: Readonly<Vec2>, c2r: number): boolean {
const distance = Vec2.distance(c1p, c2p);
return distance < (c1r + c2r);
}
如下图两圆,半径分别是25和50,检测结果是true。

const isHit: boolean = Intersection2D.circleCircle(v2(this.red.position.x, this.red.position.y), 25, v2(this.blue.position.x, this.blue.position.y), 50); console.log(isHit); //true
总结:
1. 圆形碰撞常用于飞行射击游戏中,子弹和飞机的碰撞。
找到离圆心最近的矩形顶点,判断圆心和顶点的距离小于圆半径,则碰撞。
cocos提供的方法,intersection-2d.ts:
/**
* @en Test rect and circle
* @zh 测试矩形与圆形是否相交
*/
function rectCircle (rect: Rect, cp: Readonly<Vec2>, cr: number): boolean {
const cx = cp.x;
const cy = cp.y;
const rx = rect.x;
const ry = rect.y;
const rw = rect.width;
const rh = rect.height;
// temporary variables to set edges for testing
let testX = cx;
let testY = cy;
// which edge is closest?
if (cx < rx) testX = rx; // test left edge
else if (cx > rx + rw) testX = rx + rw; // right edge
if (cy < ry) testY = ry; // top edge
else if (cy > ry + rh) testY = ry + rh; // bottom edge
// get distance from closest edges
const distX = cx - testX;
const distY = cy - testY;
const distance = Math.sqrt((distX * distX) + (distY * distY));
// if the distance is less than the radius, collision!
if (distance <= cr) {
return true;
}
return false;
}
red是矩形,blue是半径50的圆形,检测结果是true。

const isHit: boolean = Intersection2D.rectCircle(this.red.getComponent(UITransform).getBoundingBox(), v2(this.blue.position.x, this.blue.position.y), 50); console.log(isHit); //true
线段与线段
线段与矩形
线段与多边形
矩形与多边形
多边形与多边形
多边形与圆形
点是否在一个多边形中
点到直线距离
这些都可以在cocos源码intersection-2d.ts中找到。
浙公网安备 33010602011771号