Search code examples
objective-cioscocoa-touchcollision-detectionquartz-2d

Cocoa iOS Make a Rectangle into a Circle with Collisions


So I have a UIView called fallingBall that currently collides nicely with my UIView called theBlockView. I am using CGRectIntersectsRect(theBlockView.frame, fallingBall.frame) to detect this collision.

That's all very well, so now I would like my fallingBall to actually be round, and I would also like the top corners of theBlockView to be rounded. To do this, I used the following code:

//round top right-hand corner of theBlockView
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:theBlockView.bounds 
                                           byRoundingCorners:UIRectCornerTopRight
                                           cornerRadii:CGSizeMake(10.0, 10.0)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = theBlockView.bounds;
maskLayer.path = maskPath.CGPath;
theBlockView.layer.mask = maskLayer;

//round the fallingBall view
[[fallingBall layer] setCornerRadius:30];

But, funnily enough, though they look nice and rounded, the views are still rectangles. So my question is: how can I make CGRectIntersectsRect treat them as the shapes that they look like? Is there a function that works the same but uses the view's alpha to detect collisions?

Thanks for your time!


Solution

  • Actually, let me answer my own question!

    OK, so I spent the greater part of the last 10 hours looking around, and I came across this post: Circle-Rectangle collision detection (intersection) - check out what e.James has to say!

    I wrote a function to help with this: first, declare the following structs:

    typedef struct
    {
        CGFloat x; //center.x
        CGFloat y; //center.y
        CGFloat r; //radius
    } Circle;
    typedef struct
    {
        CGFloat x; //center.x
        CGFloat y; //center.y
        CGFloat width;
        CGFloat height;
    } MCRect;
    

    Then add the following function:

    -(BOOL)circle:(Circle)circle intersectsRect:(MCRect)rect
    {
    
        CGPoint circleDistance = CGPointMake(abs(circle.x - rect.x), abs(circle.y - rect.y) );
    
        if (circleDistance.x > (rect.width/2 + circle.r)) { return false; }
        if (circleDistance.y > (rect.height/2 + circle.r)) { return false; }
    
        if (circleDistance.x <= (rect.width/2)) { return true; } 
        if (circleDistance.y <= (rect.height/2)) { return true; }
    
        CGFloat cornerDistance_sq = pow((circleDistance.x - rect.width/2), 2) + pow((circleDistance.y - rect.height/2), 2);
    
        return (cornerDistance_sq <= (pow(circle.r, 2)));
    }
    

    I hope this helps someone!