圆、矩形、线段碰撞检测

// 矩形和圆形碰撞检测
bool IsCirlceCollisionRect(float circleXPos, float circleYPos, float radius, float rectX, float rectY, float rectW, float rectH)
{
    float arcR  = radius;
    float arcOx = circleXPos;
    float arcOy = circleYPos;

    //分别判断矩形4个顶点与圆心的距离是否<=圆半径;如果<=,说明碰撞成功   
    if(((rectX-arcOx) * (rectX-arcOx) + (rectY-arcOy) * (rectY-arcOy)) <= arcR * arcR)   
        return true;   
    if(((rectX+rectW-arcOx) * (rectX+rectW-arcOx) + (rectY-arcOy) * (rectY-arcOy)) <= arcR * arcR)   
        return true;   
    if(((rectX-arcOx) * (rectX-arcOx) + (rectY+rectH-arcOy) * (rectY+rectH-arcOy)) <= arcR * arcR)   
        return true;   
    if(((rectX+rectW-arcOx) * (rectX+rectW-arcOx) + (rectY+rectH-arcOy) * (rectY+rectH-arcOy)) <= arcR * arcR)   
        return true;

    //判断当圆心的Y坐标进入矩形内时X的位置,如果X在(rectX-arcR)到(rectX+rectW+arcR)这个范围内,则碰撞成功   
    float minDisX = 0;   
    if(arcOy >= rectY && arcOy <= rectY + rectH)
    {   
        if(arcOx < rectX)   
            minDisX = rectX - arcOx;   
        else if(arcOx > rectX + rectW)   
            minDisX = arcOx - rectX - rectW;   
        else    
            return true;   
        if(minDisX <= arcR)   
            return true;   
    }

    //判断当圆心的X坐标进入矩形内时Y的位置,如果X在(rectY-arcR)到(rectY+rectH+arcR)这个范围内,则碰撞成功
    float minDisY = 0;   
    if(arcOx >= rectX && arcOx <= rectX + rectW)
    {   
        if(arcOy < rectY)   
            minDisY = rectY - arcOy;   
        else if(arcOy > rectY + rectH)   
            minDisY = arcOy - rectY - rectH;   
        else  
            return true;   
        if(minDisY <= arcR)   
            return true;   
    }

    return false; 
}

// 线段和线段碰撞检测
bool IsLineCollisionLine(cocos2d::CCPoint p1, cocos2d::CCPoint p2, cocos2d::CCPoint p3, cocos2d::CCPoint p4)
{
    float x1 = p1.x, x2 = p2.x, x3 = p3.x, x4 = p4.x;
    float y1 = p1.y, y2 = p2.y, y3 = p3.y, y4 = p4.y;

    float d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
    // If d is zero, there is no intersection
    if (d == 0) 
        return false;

    // Get the x and y
    float pre = (x1*y2 - y1*x2), post = (x3*y4 - y3*x4);
    float x = ( pre * (x3 - x4) - (x1 - x2) * post ) / d;
    float y = ( pre * (y3 - y4) - (y1 - y2) * post ) / d;

    // Check if the x and y coordinates are within both lines
    if ( x < MIN(x1, x2) || x > MAX(x1, x2) ||
        x < MIN(x3, x4) || x > MAX(x3, x4) )
        return false;

    if ( y < MIN(y1, y2) || y > MAX(y1, y2) ||
        y < MIN(y3, y4) || y > MAX(y3, y4) ) 
        return false;

    return true;
}

static float mult(cocos2d::CCPoint a, cocos2d::CCPoint b, cocos2d::CCPoint c)
{
    return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
}

bool IsLineCollisionLine2(cocos2d::CCPoint aa, cocos2d::CCPoint bb, cocos2d::CCPoint cc, cocos2d::CCPoint dd)
{
    if ( MAX(aa.x, bb.x)<MIN(cc.x, dd.x) )
        return false;

    if ( MAX(aa.y, bb.y)<MIN(cc.y, dd.y) )
        return false;

    if ( MAX(cc.x, dd.x)<MIN(aa.x, bb.x) )
        return false;

    if ( MAX(cc.y, dd.y)<MIN(aa.y, bb.y) )
        return false;

    if (mult(cc, bb, aa)*mult(bb, dd, aa)<0.0001f)
        return false;

    if (mult(aa, dd, cc)*mult(dd, bb, cc)<0.0001f)
        return false;

    return true;
}

// 线段和矩形碰撞检测
bool IsLineCollisionRect(cocos2d::CCPoint lineStartPoint, cocos2d::CCPoint lineEndPoint, cocos2d::CCPoint rectleftBottomPoint, float width, float height)
{
    // 因为这个方法专门进行射线光束的碰撞检测,所以暂不进行线段在矩形内的碰撞检测
    cocos2d::CCPoint leftLineStartPoint = rectleftBottomPoint;
    cocos2d::CCPoint leftLineEndPoint   = cocos2d::CCPoint(leftLineStartPoint.x, leftLineStartPoint.y+height);

    cocos2d::CCPoint rightLineStartPoint= cocos2d::CCPoint(leftLineStartPoint.x+width, leftLineStartPoint.y);
    cocos2d::CCPoint rightLineEndPoint  = cocos2d::CCPoint(leftLineStartPoint.x+width, leftLineStartPoint.y+height);

    cocos2d::CCPoint topLineStartPoint  = cocos2d::CCPoint(leftLineStartPoint.x, leftLineStartPoint.y+height);
    cocos2d::CCPoint topLineEndPoint    = cocos2d::CCPoint(leftLineStartPoint.x+width, leftLineStartPoint.y+height);

    cocos2d::CCPoint bottomLineStartPoint= cocos2d::CCPoint(leftLineStartPoint.x, leftLineStartPoint.y);
    cocos2d::CCPoint bottomLineEndPoint  = cocos2d::CCPoint(leftLineStartPoint.x+width, leftLineStartPoint.y);
    
    cocos2d::CCPoint leftBottomLineStartPoint= rectleftBottomPoint;
    cocos2d::CCPoint rightTopLineEndPoint    = rightLineEndPoint;

    cocos2d::CCPoint leftTopLineStartPoint   = leftLineEndPoint;
    cocos2d::CCPoint rightBottomLineEndPoint = rightLineStartPoint;


    do 
    {
        if (IsLineCollisionLine2(lineStartPoint, lineEndPoint, leftLineStartPoint, leftLineEndPoint))
            break;

        if (IsLineCollisionLine2(lineStartPoint, lineEndPoint, rightLineStartPoint, rightLineEndPoint))
            break;

        if (IsLineCollisionLine2(lineStartPoint, lineEndPoint, topLineStartPoint, topLineEndPoint))
            break;

        if (IsLineCollisionLine2(lineStartPoint, lineEndPoint, bottomLineStartPoint, bottomLineEndPoint))
            break;

        if (IsLineCollisionLine2(lineStartPoint, lineEndPoint, leftBottomLineStartPoint, rightTopLineEndPoint))
            break;

        if (IsLineCollisionLine2(lineStartPoint, lineEndPoint, leftTopLineStartPoint, rightBottomLineEndPoint))
            break;

        return false;
    } 
    while (false);

    return true;
}

static  bool  IsRectCollisionRect2(cocos2d::CCPoint rect1CenterPoint, float rect1W, float rect1H, cocos2d::CCPoint rect2CenterPoint, float rect2W, float rect2H)
{
    cocos2d::CCPoint leftTopPoint     = cocos2d::CCPoint(rect2CenterPoint.x-rect2W/2.0f, rect2CenterPoint.y+rect2H/2.0f);
    cocos2d::CCPoint leftBottomPoint  = cocos2d::CCPoint(rect2CenterPoint.x-rect2W/2.0f, rect2CenterPoint.y-rect2H/2.0f);
    cocos2d::CCPoint rightTopPoint    = cocos2d::CCPoint(rect2CenterPoint.x+rect2W/2.0f, rect2CenterPoint.y+rect2H/2.0f);
    cocos2d::CCPoint rightBottomPoint = cocos2d::CCPoint(rect2CenterPoint.x+rect2W/2.0f, rect2CenterPoint.y-rect2H/2.0f);

    if ( (leftTopPoint.x>(rect1CenterPoint.x-rect1W/2.0f)) && (leftTopPoint.x<(rect1CenterPoint.x+rect1W/2.0f)) 
        && (leftTopPoint.y>(rect1CenterPoint.y-rect1H/2.0f)) && (leftTopPoint.y<(rect1CenterPoint.y+rect1H/2.0f)))
        return true;

    if ( (leftBottomPoint.x>(rect1CenterPoint.x-rect1W/2.0f)) && (leftBottomPoint.x<(rect1CenterPoint.x+rect1W/2.0f)) 
        && (leftBottomPoint.y>(rect1CenterPoint.y-rect1H/2.0f)) && (leftBottomPoint.y<(rect1CenterPoint.y+rect1H/2.0f)))
        return true;

    if ( (rightTopPoint.x>(rect1CenterPoint.x-rect1W/2.0f)) && (rightTopPoint.x<(rect1CenterPoint.x+rect1W/2.0f)) 
        && (rightTopPoint.y>(rect1CenterPoint.y-rect1H/2.0f)) && (rightTopPoint.y<(rect1CenterPoint.y+rect1H/2.0f)))
        return true;

    if ( (rightBottomPoint.x>(rect1CenterPoint.x-rect1W/2.0f)) && (rightBottomPoint.x<(rect1CenterPoint.x+rect1W/2.0f)) 
        && (rightBottomPoint.y>(rect1CenterPoint.y-rect1H/2.0f)) && (rightBottomPoint.y<(rect1CenterPoint.y+rect1H/2.0f)))
        return true;

    return false;
}

// 矩形和矩形碰撞检测
bool  IsRectCollisionRect(cocos2d::CCPoint rect1CenterPoint, float rect1W, float rect1H, cocos2d::CCPoint rect2CenterPoint, float rect2W, float rect2H)
{
    if (IsRectCollisionRect2(rect1CenterPoint, rect1W, rect1H, rect2CenterPoint, rect2W, rect2H))
        return true;
    
    if (IsRectCollisionRect2(rect2CenterPoint, rect2W, rect2H, rect1CenterPoint, rect1W, rect1H))
        return true;

    return false;
}
原文地址:https://www.cnblogs.com/mrblue/p/3407668.html