如何确定圆与矩形的碰撞?

Gab*_*iel 4 iphone xcode objective-c cocos2d-iphone

我已经找到了关于如何让它工作的好主意(很好),到目前为止我提出的每个解决方案都是丑陋或无法工作.我所拥有的是一个圆形的精灵,敌人.然后我有一个箭头形状的精灵.

当检查敌人中箭头的碰撞时,我会使用CGRectIntersect(rect1, rect2) 但是......圆圈不是矩形!碰撞很恶心.

所以我的问题是,如何检查圆形物体内的碰撞?我应该制作许多作品,还是有为此目的制作的东西?

PKC*_*oft 7

我找到了一个非常方便的页面(http://www.migapro.com/circle-and-rotated-rectangle-collision-detection/),其中包含一些代码和一个很好的演示,并将该解决方案移植到Objective-C.

当我移植代码时,我也改变了它,使得CGRect中提供的坐标实际上是矩形的中心,而不是原始代码的左上角.这使得它可以非常容易地用于像CCSprite这样的Cocos2D对象.

代码(对我来说似乎效果很好)如下所示:

@interface Cocosutil : NSObject

typedef struct {
    float overlapSize;
    BOOL intersects;
} ccIntersection;

+ (ccIntersection) intersectionOfCircleWithRadius:(float)radius 
                                          atPoint:(CGPoint)circlePt
                                     andRectangle:(CGRect)rect
                                     withRotation:(float)rotation;

@end

@implementation CocosUtil

#define CC_DEGREES_TO_RADIANS(__ANGLE__) ((__ANGLE__) * 0.01745329252f) // PI / 180

// Original code is from:
//
// http://www.migapro.com/circle-and-rotated-rectangle-collision-detection/
//
+ (ccIntersection) intersectionOfCircleWithRadius:(float)radius atPoint:(CGPoint)circlePt andRectangle:(CGRect)rect withRotation:(float)rotation {
    ccIntersection result;

    // Rotate circle's center point back
    float unrotatedCircleX =
        cosf(CC_DEGREES_TO_RADIANS(rotation)) * (circlePt.x - rect.origin.x) -
        sinf(CC_DEGREES_TO_RADIANS(rotation)) * (circlePt.y - rect.origin.y) + rect.origin.x;

    float unrotatedCircleY =
        sinf(CC_DEGREES_TO_RADIANS(rotation)) * (circlePt.x - rect.origin.x) +
        cosf(CC_DEGREES_TO_RADIANS(rotation)) * (circlePt.y - rect.origin.y) + rect.origin.y;

    // Closest point in the rectangle to the center of circle rotated backwards(unrotated)
    float closestX, closestY;

    // Find the unrotated closest x point from center of unrotated circle
    if (unrotatedCircleX  < (rect.origin.x - (rect.size.width/2.0f))) {
        closestX = rect.origin.x - (rect.size.width/2.0f);
    } else if (unrotatedCircleX  > rect.origin.x + (rect.size.width+rect.size.width/2.0f)) {
        closestX = rect.origin.x + (rect.size.width/2.0f);
    } else {
        closestX = unrotatedCircleX ;
    }

    // Find the unrotated closest y point from center of unrotated circle
    if (unrotatedCircleY < (rect.origin.y - (rect.size.height/2.0f))) {
        closestY = rect.origin.y - (rect.size.height/2.0f);
    } else if (unrotatedCircleY > (rect.origin.y + (rect.size.height/2.0f))) {
        closestY = rect.origin.y + (rect.size.height/2.0f);
    } else {
        closestY = unrotatedCircleY;
    }

    // Determine collision

    float distance = [CocosUtil distanceFrom:CGPointMake(unrotatedCircleX , unrotatedCircleY) to:CGPointMake(closestX, closestY)];

    if (distance < radius) {
        result.intersects = YES; // Collision
        result.overlapSize = radius - distance;
    } else {
        result.intersects = NO;
        result.overlapSize = 0.0f;
    }

    return result;
}

+ (float) distanceFrom:(CGPoint)from to:(CGPoint)to {

    float a = abs(from.x - to.x);
    float b = abs(from.y - to.y);

    return sqrt((a * a) + (b * b));
}

@end
Run Code Online (Sandbox Code Playgroud)

  • 虽然此链接可能会回答这个问题,但最好在此处包含答案的基本部分并提供参考链接.如果链接的页面发生更改,则仅链接的答案可能会无效. (2认同)