Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>To determine if two circles intersect, you simply see if the distance between the centers is less than the sum if their radii. For example...</p> <pre><code>CGFloat CGPointDistance(CGPoint p1, CGPoint p2) { return sqrtf((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y)); } </code></pre> <p>It looks like your "balls" are views... Assuming the "ball" fills the frame, the radius will be 1/2 the width...</p> <pre><code>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) &lt; (r1 + r2); } </code></pre> <p>OK -- I have hacked up a quick sample. You can almost drop it into your view controller. Don't use it for production stuff... just as an example of how you can do stuff... You can put this at the top and the rest of your controller below it...</p> <pre><code>// 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) &lt; (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) &lt; 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 &lt; views.count; ++i) { id v = [views objectAtIndex:i]; if (![v isKindOfClass:[Ball class]]) continue; Ball *ball1 = v; for (size_t j = i+1; j &lt; 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]]; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload