Question

I have a UIImageView which contains my main Character, and I have made the UIImageView appear circle see below code for creating my character

copter = [[UIImageView alloc] initWithFrame:CGRectMake(100, 500, 90, 90)];
[copter setContentMode:UIViewContentModeScaleAspectFit];
copter.layer.cornerRadius = roundf(copter.frame.size.width/2.0);
copter.layer.masksToBounds = YES;
[copter startAnimating];
[[self view] addSubview:copter];
[self setBat:copter];

I am having trouble with my collision between my character and other objects in the game. The collision is being detected on the rectangle rather than the circle. I have searched everywhere for an answer to fix this but no luck.

Here is my collision code I am using:

 self.batVelocity += [link duration]*FBDownardBatAccelerationIpad;

 [[self copter] setFrame:CGRectOffset([[self copter] frame], 0, [self batVelocity])];

 UIView *removeBlock = nil;
 for (UIView *block in [self blocks]) {
      [block setFrame:CGRectOffset([block frame], [link duration]*FBSidewaysVelocityIpad, 0)];
       if (CGRectIntersectsRect([[self copter] frame], [block frame])) {
             [self failed];

So basically I need the circle bounds of the character to collide with a rectangle object, not the rectangle bounds of which the circle is in. I hope that makes sense.

Thanks in advance

Was it helpful?

Solution 2

Right, so first you check for overlapping rectangles (which you've already done). When you find an overlap, then you need to refine the collision test. For each corner of the offending rectangle, compute the distance from the center of your character to the corner of the offending rectangle. If the distance from the center to any of the corners is less than the radius of the circle, then you have a collision. To optimize the code a little bit, compute (dx * dx + dy * dy) and compare that to the radius squared. That way you don't have to compute any square roots.

Upon further review, you also need to do an edge check in addition to the corner check. For example, if the top y value is above the center of the circle and the bottom y value is below the center of the circle, then compute the difference in x between the rectangle left edge and the center of the circle, and if that distance is less than the radius, then a collision has occurred. Likewise for the other three edges of the rectangle.

Here's some pseudo-code for the corner checking

int dx, dy, radius, radiusSquared;

radiusSquared = radius * radius;
for ( each rectangle that overlaps the player rectangle )
{
    for ( each corner of the rectangle )
    {
        dx = corner.x - center.x;
        dy = corner.y - center.y;
        if ( dx * dx + dy * dy < radiusSquared )
            Collision!!!
    }
}

OTHER TIPS

I'd use a CGPathRef or CGMutablePathRef. So as @user3386109 suggests, check for collision between rects first, then if you have a pathRef for your sprite or whatever it is you can use CGPathContainsPoint(). Quartz has a few other comparison functions for CGPathRef for Rects as well, and for comparing a path against a second path, check the docs. I find CGPathRef to be quite efficient, but don't forget to release it with a CGPathRelease() to match every CGPathCreate or CGPathCopy() function or the leaks can add up real fast..

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top