要确定两个圆是否相交,您只需查看中心之间的距离是否小于它们的半径之和。例如...
CGFloat CGPointDistance(CGPoint p1, CGPoint p2)
{
return sqrtf((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y));
}
看起来你的“球”是视图......假设“球”填充框架,半径将是宽度的 1/2......
BOOL BallsCollide(UIView *v1, UIView *v2)
{
CGFloat r1 = v1.frame.size.width * .5;
CGFloat r2 = v2.frame.size.width * .5;
return CGPointDistance(v1.center, v2.center) < (r1 + r2);
}
好的——我已经破解了一个快速样本。你几乎可以把它放到你的视图控制器中。不要将它用于生产...只是作为您如何做东西的示例...您可以将它放在顶部,将控制器的其余部分放在它下面...
// I do not recommend using this approach for naything non-trivial,
// but it demonstrates the very simple collision detection for circle shapes.
@interface Ball : UIView {
}
@property (nonatomic, strong) UIColor *origColor;
@property (nonatomic, strong) UIColor *color;
+ (id)ballWithRadius:(CGFloat)radius color:(UIColor*)color;
- (BOOL)doesIntersectWith:(Ball*)ball;
@end
@implementation Ball
@synthesize color = _color;
@synthesize origColor = _origColor;
+ (id)ballWithRadius:(CGFloat)radius color:(UIColor*)color
{
CGFloat diameter = radius * 2;
Ball *ball = [[Ball alloc] initWithFrame:CGRectMake(0, 0, diameter, diameter)];
ball.color = ball.origColor = color;
ball.backgroundColor = [UIColor clearColor];
return ball;
}
- (BOOL)doesIntersectWith:(Ball *)ball
{
// Two circles overlap if the sum of their radii
// is less than the distance between the two centers.
CGFloat r1 = self.frame.size.width * .5;
CGFloat r2 = ball.frame.size.width * .5;
CGFloat diffX = self.center.x - ball.center.x;
CGFloat diffY = self.center.y - ball.center.y;
return (diffX*diffX) + (diffY*diffY) < (r1+r2)*(r1+r2);
}
- (BOOL)containsPoint:(CGPoint)point
{
// Contains a point if distance from center is less than radius
CGFloat r = self.frame.size.width *.5;
CGFloat diffX = self.center.x - point.x;
CGFloat diffY = self.center.y - point.y;
return (diffX*diffX) + (diffY*diffY) < r*r;
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
[self.color setFill];
[self.color setStroke];
CGContextSetLineWidth(context, 1);
CGContextFillEllipseInRect(context, self.bounds);
}
@end
@interface CollideVC() {
NSMutableDictionary *activeTouches;
NSMutableSet *currentCollisions;
}
@end
@implementation CollideVC
- (void)ball:(Ball*)ball touched:(UITouch*)touch
{
[activeTouches setObject:ball forKey:[NSValue valueWithPointer:(__bridge void*)touch]];
}
- (Ball*)getBallTouchedBy:(UITouch*)touch
{
return [activeTouches objectForKey:[NSValue valueWithPointer:(__bridge void*)touch]];
}
- (void)stopTouch:(UITouch*)touch
{
[activeTouches removeObjectForKey:[NSValue valueWithPointer:(__bridge void*)touch]];
}
- (void)ball:(Ball*)ball1 hasCollidedWith:(Ball*)ball2
{
[currentCollisions addObject:ball1];
[currentCollisions addObject:ball2];
ball1.color = ball2.color = [UIColor yellowColor];
[ball1 setNeedsDisplay];
[ball2 setNeedsDisplay];
}
// NOTE: You should delegate handling of collisions...
- (void)checkForCollisions
{
// Should filter those that don't actually need redisplay...
// For simplicity, all that were or are colliding get it...
[currentCollisions enumerateObjectsUsingBlock:^(Ball *ball, BOOL *stop) {
[ball setNeedsDisplay];
ball.color = ball.origColor;
}];
[currentCollisions removeAllObjects];
NSArray *views = self.view.subviews;
for (size_t i = 0; i < views.count; ++i) {
id v = [views objectAtIndex:i];
if (![v isKindOfClass:[Ball class]]) continue;
Ball *ball1 = v;
for (size_t j = i+1; j < views.count; ++j) {
v = [views objectAtIndex:j];
if (![v isKindOfClass:[Ball class]]) continue;
Ball *ball2 = v;
if ([ball1 doesIntersectWith:ball2]) {
[self ball:ball1 hasCollidedWith:ball2];
}
}
}
}
- (void)addBallWithRadius:(CGFloat)radius point:(CGPoint)point color:(UIColor*)color
{
Ball *ball = [Ball ballWithRadius:radius color:color];
ball.center = point;
[self.view addSubview:ball];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
CGPoint touchLocation = [touch locationInView:self.view];
for (Ball *ball in self.view.subviews) {
if ([ball containsPoint:touchLocation]) {
[self ball:ball touched:touch];
}
}
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
// Use relative distance so center does nt jump to tap location.
CGPoint prev = [touch previousLocationInView:self.view];
CGPoint curr = [touch locationInView:self.view];
CGPoint c = [self getBallTouchedBy:touch].center;
[self getBallTouchedBy:touch].center = CGPointMake(c.x+curr.x-prev.x, c.y+curr.y-prev.y);
}
// NOTE: This does not check the path between the moves, only the new point.
// So a fast movement "past" the other object will not get detected.
// If you want to do comple detection, use an existing engine
[self checkForCollisions];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
[self stopTouch:touch];
}
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[self touchesEnded:touches withEvent:event];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
activeTouches = [NSMutableDictionary dictionary];
currentCollisions = [NSMutableSet set];
[self addBallWithRadius:20 point:CGPointMake(110, 100) color:[UIColor blueColor]];
[self addBallWithRadius:20 point:CGPointMake(200, 200) color:[UIColor redColor]];
[self addBallWithRadius:20 point:CGPointMake(235, 250) color:[UIColor greenColor]];
}