0

I've just started to develop in iPhone and I've managed to make my buttons (six of them) to move with UIAccelerator. Problem I'm facing when they are colliding with each other. I want them to bounce back the same direction, and this works if I only use 2 buttons. But when there are multiple collisions with more than 2 buttons, they get overlapped and finally merged into each other.

Here's my code to set delegate itself:

UIAccelerometer *accel = [UIAccelerometer sharedAccelerometer];
accel.delegate = self;
accel.updateInterval = 1.0f/60.0f;

Delegate method of accelerator:

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration{
delta.x = acceleration.x * 5;
delta.y = acceleration.y * -5;

self.firstButton.center = CGPointMake(self.firstButton.center.x + delta.x, self.firstButton.center.y + delta.y);
self.secondButton.center = CGPointMake(self.secondButton.center.x + delta.x, self.secondButton.center.y + delta.y);
self.thirdButton.center = CGPointMake(self.thirdButton.center.x + delta.x, self.thirdButton.center.y + delta.y);
self.fourthButton.center = CGPointMake(self.fourthButton.center.x + delta.x, self.fourthButton.center.y + delta.y);
self.fifthButton.center = CGPointMake(self.fifthButton.center.x + delta.x, self.fifthButton.center.y + delta.y);
self.sixthButton.center = CGPointMake(self.sixthButton.center.x + delta.x, self.sixthButton.center.y + delta.y);

[self updateMovingObjects:self.firstButton];
[self updateMovingObjects:self.secondButton];
[self updateMovingObjects:self.thirdButton];
[self updateMovingObjects:self.fourthButton];
[self updateMovingObjects:self.fifthButton];
[self updateMovingObjects:self.sixthButton];
}

updateMovingObjects:

- (void)updateMovingObjects:(UIButton *)button{
/*** DETECT COLLISIONS ***/

// Right screen
if(button.center.x < button.frame.size.width / 2){
    button.center = CGPointMake(button.frame.size.width / 2, button.center.y); 
}
// Left screen
if(button.center.x > 320 - button.frame.size.width / 2){
    button.center = CGPointMake(320 - button.frame.size.width / 2, button.center.y); 
}
// Top screen
if(button.center.y < button.frame.size.height / 2){
    button.center = CGPointMake(button.center.x, button.frame.size.height / 2); 
}
// Bottom screen
if(button.center.y > 480 - 20 - 43 - button.frame.size.height / 2){
    button.center = CGPointMake(button.center.x, 480 - 20 - 43 - button.frame.size.height / 2); 
}

// Detect collision with objects
for (UIView *anotherView in [self.view subviews]) {
    if (button == anotherView){
        continue;
    }
    if(CGRectIntersectsRect(button.frame, anotherView.frame)){
        float_t vec = sqrtf(powf(delta.x, 2.0)+powf(delta.y, 2.0));
        // collided from left or bottom
        if( (button.center.x + button.frame.size.width / 2 >= anotherView.center.x - anotherView.frame.size.width / 2 &&
             button.center.x + button.frame.size.width / 2 <= anotherView.center.x - anotherView.frame.size.width / 2 + 15)
           ||  (button.center.y - button.frame.size.height / 2 <= anotherView.center.y + anotherView.frame.size.height / 2 &&
                button.center.y - button.frame.size.height / 2 >= anotherView.center.y + anotherView.frame.size.height / 2 - 15) ){
               button.center = CGPointMake(button.center.x - vec, button.center.y + vec);
           }
        // collided from top or right
        else{
            button.center = CGPointMake(button.center.x + vec, button.center.y - vec);
        }
    }
}

/*** END DETECT COLLISIONS ***/
}

Thanks in advance.

EDIT: I made for functions which detects if it was collided from left, right, bottom or top. And works much better now, but problem still remains with overlapping if I have them all at once moving, my guess is that it doesn't have the time calculate and thus get overlapped:

- (BOOL)collidedFromLeft:(UIButton *)button{
for (UIView *anotherView in [self.view subviews]) {
    if (button == anotherView){
        continue;
    }
    if(CGRectIntersectsRect(button.frame, anotherView.frame)){
        if(button.center.x + button.frame.size.width / 2 - delta.x < anotherView.center.x - anotherView.frame.size.width / 2 &&
           button.center.x + button.frame.size.width / 2 >= anotherView.center.x - anotherView.frame.size.width / 2){
            return YES;
        }
    }
}
return NO;

}

- (BOOL)collidedFromTop:(UIButton *)button{
for (UIView *anotherView in [self.view subviews]) {
    if (button == anotherView){
        continue;
    }
    if(CGRectIntersectsRect(button.frame, anotherView.frame)){
        if(button.center.y + button.frame.size.height / 2 - delta.y < anotherView.center.y - anotherView.frame.size.height / 2 &&
           button.center.y + button.frame.size.height / 2 >= anotherView.center.y - anotherView.frame.size.height / 2){
            return YES;
        }
    }
}
return NO;

}

- (BOOL)collidedFromRight:(UIButton *)button{
for (UIView *anotherView in [self.view subviews]) {
    if (button == anotherView){
        continue;
    }
    if(CGRectIntersectsRect(button.frame, anotherView.frame)){
        if(button.center.x - button.frame.size.width / 2 - delta.x > anotherView.center.x + anotherView.frame.size.width / 2 &&
           button.center.x - button.frame.size.width / 2 <= anotherView.center.x + anotherView.frame.size.width / 2){
            return YES;
        }
    }
}
return NO;

}

- (BOOL)collidedFromBottom:(UIButton *)button{
for (UIView *anotherView in [self.view subviews]) {
    if (button == anotherView){
        continue;
    }
    if(CGRectIntersectsRect(button.frame, anotherView.frame)){
        if(button.center.y - button.frame.size.height / 2 - delta.y > anotherView.center.y + anotherView.frame.size.height / 2 &&
           button.center.x - button.frame.size.width / 2 <= anotherView.center.y + anotherView.frame.size.height / 2){
            return YES;
        }
    }
}
return NO;

}

Then I check while they are moving:

if([self collidedFromLeft:button]){
    button.center = CGPointMake(button.center.x - 20, button.center.y);
}
if([self collidedFromRight:button]){
    button.center = CGPointMake(button.center.x + 20, button.center.y);
}
if([self collidedFromTop:button]){
    button.center = CGPointMake(button.center.x, button.center.y - 20);
}
if([self collidedFromBottom:button]){
    button.center = CGPointMake(button.center.x, button.center.y + 20);
}
Carnal
  • 21,744
  • 6
  • 60
  • 75
  • That's quite dangerous code you have, as i understand you want to call `updateMovingObjects` to make sure the argument button is not overlapped with other buttons, but in general while resolving the overlays of `button1` you can make other overlays with buttons: with `button2` resolving `button3`, with `button2-3` resolving `button4` and so on. And while growing, the overlay-delta might grow over 15px this way. – A-Live Jul 16 '12 at 09:24
  • Yeah I notice there's some leak in my code. I've searched every to find some examples to use in my situation, but can't find any =( – Carnal Jul 16 '12 at 09:44
  • The best approach i was able to find is the quadtree: http://stackoverflow.com/questions/4434335/quadtree-for-2d-collision-detection and http://stackoverflow.com/questions/4981866/quadtree-for-2d-collision-detection You might want to check the basics of 2D collisions detect http://en.wikipedia.org/wiki/Collision_detection and Quadtree itself: http://en.wikipedia.org/wiki/Quadtree Unfortunately, i'm not able to answer your question or to give a better guideline, please update your status in the future. – A-Live Jul 16 '12 at 11:51

0 Answers0