How to determine the collision of a circle with a rectangle?

I looked EVERYWHERE for guidance on how to make this work (beautifully), and so far, every solution I came up with was ugly or didn't work. I have a circular sprite, enemy. Then I have a sprite that is in the shape of an arrow.

When checking for an arrow collision with an enemy, I use CGRectIntersect(rect1, rect2) but ... circles are not rectangles! The clash is disgusting.

So my question is: how do I check for a collision inside a circular object? Do I have to make many corrections, or is there something there that has been done for this purpose?

+4
source share
3 answers

Collision detection of a circle and a rectangle is nothing but simple. Here's a C ++ class class that performs this type of test ( source with many other examples of intersection testing ). There is also an answer to SO that only shows pseudo code. N + developers also explain their approach to detecting collisions with a rectangle and a rectangle . If this seems too much to you, you are usually advised to look for a simpler approach.;)

For example, since you mentioned an β€œarrow”, which means a pointed, thin object that tends to fly relatively straight in one direction, with the arrow always pointing in the direction of flight. If this is not the case, I may be living on another planet, otherwise I will use this assumption.

This means that you can very easily change the type of collision of an arrow from a rectangle to a circle. The circle should only be such that it covers the arrow. Depending on the graphics and design of the game, it may even be enough for the collision circle to be at the very top of the arrowhead. You can then implement Joshua’s proposal to test collisions with the circle and surroundings.

An alternative for very thin arrows would be to consider the arrow as a line, then you can work with a fairly simple test of intersecting a circle of a circle .

+3
source

I found a very convenient page ( http://www.migapro.com/circle-and-rotated-rectangle-collision-detection/ ) with some code and a nice demo and ported this solution to Objective-C.

when I ported the code, I also changed it so that the coordinate provided in CGRect is actually the center of the rectangle and not the top left corner according to the source code. This allows you to use it for Cocos2D objects such as CCSprite, very easily.

The code (which seems to work very well) is shown below:

 @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 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 
+7
source

I have no idea if Cocos provides a function for this, but the math is really very simple.

You take the two center points of the circles and get the distance between them using the standard distance formula. float distance = sqrt(pow((x2-x1), 2) + pow((y2-y1), 2) and check if this is less than the sum of the radius of the two circles that you are checking.

 BOOL checkCircleCollision(CGPoint center1, float radius1, CGPoint center2, float radius2) { float distance = sqrt(pow((center2.x-center1.x), 2) + pow((center2.y-center1.y), 2); return distance < (radius1 + radius2); } BOOL optimized_CheckCircleCollision(CGPoint center1, float radius1, CGPoint center2, float radius2) { float a = center2.x - center1.x; float b = center2.y - center1.y; float c = radius1 + radius2; float distanceSqrd = (a * a) + (b * b); return distanceSqrd < (c * c); } 
+2
source

Source: https://habr.com/ru/post/1379898/


All Articles