算法一:矩形与圆的碰撞

第一种:(来源:碰撞检测 - 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;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值