第一种:(来源:碰撞检测 - LearnOpenGL CN)
const cPoint = this.circleNode.position;
const bPoint = this.boxNode.position;
const bwhPoint = new cc.Vec2(this.boxNode.width/2, this.boxNode.height/2);
//圆到矩形的向量 1,在矩形外 2,矩形内
const box_circle_v2 = cPoint.sub(bPoint);
//控制再矩形宽高范围内
/**
* 1,在矩形外 向量在矩形边上
* 2,在矩形内 向量在矩形内 与圆的坐标重合
*/
const clampPoint = cc.pClamp(box_circle_v2, cc.pNeg(bwhPoint) ,bwhPoint);
/**
*获的p点的实际坐标 相对于坐标系
*/
const p = bPoint.add(clampPoint);
/**
* 矩形外 两者不重合 距离不等于 0
* 矩形内 两者坐标重合 距离 等于 0
*/
const l = p.sub(cPoint).mag();
console.log(l);
return l < this.circleNode.getComponent(cc.CircleCollider).radius;
第二种:(来源:怎样判断平面上一个矩形和一个圆形是否有重叠? - 知乎)
/**
* 该方法有些需要注意的地方 相对来说 较抽象
* 1,矩形中心 到 圆心的 向量 diffV2 转换到 第一象限
* 2,矩形外围到圆心的距离 使用 正的 halfV2 = cc.v2(width/2,height/2)
* 个人理解:转换到第一象限 与 halfV2 向量有关系,因为half 一直都在 矩形的右上方 为正。 我们把矩形分成四等分:左上、左下、右上、右下
* 不管圆在矩形的那个部分 都可以转换至 右上来继续计算 (对称)。
* 这里其实也可以理解为 halfV2 与 diffV2 都做了 相同的转换,每个部分的矩形顶点到圆心的距离向量
* 3,当half向量到 圆心的 向量中有负数 则为 0 => diffV2 - halfV2 (注意方向)
* 接上两个理解,因为圆不管是在上 在右 都是直接使用其中的一个x或者y 即可表示距离矩形的多远。x、y都为0,说明圆心在矩形内
*
*/
const cPoint = this.circleNode.position;
const bPoint = this.boxNode.position;
//固定了参考点,圆心到矩形的距离
const halfV2 = cc.v2(this.boxNode.width/2, this.boxNode.height/2);
//圆与矩形的直接的向量 转移到第一象限
const diffV2 = cc.pCompOp(cPoint.sub(bPoint),Math.abs);
//圆到矩形的最短距离 注意方向
const LenV2 = diffV2.sub(halfV2);
const maxV2 = cc.v2(Math.max(LenV2.x,0),Math.max(LenV2.y,0));
return maxV2.mag() < this.circleNode.getComponent(cc.CircleCollider).radius;
第三种:
//点在多边形内
function pointInPolygon (point, polygon) {
var inside = false;
var x = point.x;
var y = point.y;
var length = polygon.length;
for ( var i = 0, j = length-1; i < length; j = i++ ) {
var xi = polygon[i].x, yi = polygon[i].y,
xj = polygon[j].x, yj = polygon[j].y,
intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
if ( intersect ) inside = !inside;
}
return inside;
}
/**
* !#en Calculate the distance of point to line.
* !#zh 计算点到直线的距离。如果这是一条线段并且垂足不在线段内,则会计算点到线段端点的距离。
* @method pointLineDistance
* @param {Vec2} point - The point
* @param {Vec2} start - The start point of line
* @param {Vec2} end - The end point of line
* @param {boolean} isSegment - whether this line is a segment
* @return {boolean}
*/
function pointLineDistance(point, start, end, isSegment) {
var dx = end.x - start.x;
var dy = end.y - start.y;
var d = dx*dx + dy*dy;
var t = ((point.x - start.x) * dx + (point.y - start.y) * dy) / d;
var p;
if (!isSegment) {
p = cc.v2(start.x + t * dx, start.y + t * dy);
}
else {
if (d) {
if (t < 0) p = start;
else if (t > 1) p = end;
else p = cc.v2(start.x + t * dx, start.y + t * dy);
}
else {
p = start;
}
}
dx = point.x - p.x;
dy = point.y - p.y;
return Math.sqrt(dx*dx + dy*dy);
}
矩形与圆是否碰撞:
/**
* !#en Test polygon and circle
* !#zh 测试矩形与圆形是否相交
* @method polygonCircle
* @param {Vec2[]} polygon - The Polygon, a set of points
* @param {Object} circle - Object contains position and radius
* @return {boolean}
* @typescript polygonCircle(polygon: Vec2[], circle: {position: Vec2, radius: number}): boolean
*/
function polygonCircle (polygon, circle) {
var position = circle.position;
if (pointInPolygon(position, polygon)) {
return true;
}
for (var i = 0, l = polygon.length; i < l; i++) {
var start = i === 0 ? polygon[polygon.length - 1] : polygon[i- 1];
var end = polygon[i];
if (pointLineDistance(position, start, end, true) < circle.radius) {
return true;
}
}
return false;
}