Detecting individual touches on Multiple UIImageviews? - ios

i have added around 15 to 16 UIImageviews on my View using the following code
- (void) setUpCellsUsingImage: (UIImage *) masterImage
{
rows = 4;
cols = 4;
containerCellHeight=hight/4;
containerCellWidth=width/4;
NSInteger row, col;
CGImageRef tempSubImage;
CGRect tempRect;
CGFloat yPos, xPos;
UIImage * aUIImage;
UIImageView *label;
cellArray = [[NSMutableArray new] autorelease];
int i =0;
for (row=0; row < rows; row++) {
yPos = row * containerCellHeight;
for (col=0; col < cols; col++) {
xPos = col * containerCellWidth;
label = [[UIImageView alloc]init];
tempRect = CGRectMake(xPos, yPos, containerCellWidth, containerCellHeight);
tempSubImage = CGImageCreateWithImageInRect(masterImage.CGImage, tempRect);
aUIImage = [UIImage imageWithCGImage: tempSubImage];
imgView = [[UIImageView alloc] initWithImage:aUIImage];
imgView.tag =i;
i++;
NSLog(#"original tags = %d",label.tag);
[cellArray addObject: aUIImage];
aUIImage = nil;
CGImageRelease(tempSubImage);
}
}
}
now i know i can determine which imageview has been touched with the help of tag of imageView but i dont know how to check for the tags in touchesBegan method.. what can i possibly do to differentiate uiimageview on basis of touch??
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:imgView];
NSLog(#"touch %#",imgView.tag);
}
new code:
- (void) setUpCellsUsingImage: (UIImage *) masterImage
{
rows = 4;
cols = 4;
containerCellHeight=hight/4;
containerCellWidth=width/4;
NSInteger row, col;
CGImageRef tempSubImage;
CGRect tempRect;
CGFloat yPos, xPos;
UIImage * aUIImage;
UIImageView *label;
cellArray = [[NSMutableArray new] autorelease];
int i =0;
for (row=0; row < rows; row++) {
yPos = row * containerCellHeight;
for (col=0; col < cols; col++) {
xPos = col * containerCellWidth;
label = [[UIImageView alloc]init];
tempRect = CGRectMake(xPos, yPos, containerCellWidth, containerCellHeight);
tempSubImage = CGImageCreateWithImageInRect(masterImage.CGImage, tempRect);
aUIImage = [UIImage imageWithCGImage: tempSubImage];
imgView = [[UIImageView alloc] initWithImage:aUIImage];
[self.view addSubview:imgView]; // i add the uiimageview here
imgView =CGRectMake(xPos, yPos, containerCellWidth-1, containerCellHeight-1);
imgView.tag =i;
i++;
NSLog(#"original tags = %d",label.tag);
[cellArray addObject: aUIImage];
aUIImage = nil;
CGImageRelease(tempSubImage);
}
}
}
- (void)viewDidLoad {
UIImage *mImage = [UIImage imageNamed:#"menu.png"];
hight = mImage.size.height;
width = mImage.size.width;
[self setUpCellsUsingImage:mImage];
[`super viewDidLoad];`
}

Please try this:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:imgView];
UIView *hitView = [self.view hitTest:location withEvent:event];
NSLog(#"hitView %#",hitView);
UIImageView *hitImageView = nil;
if([hitView isKindOfClass:[UIImageView class]]) {
hitImageView = (UIImageView *)hitImageView;
}
NSLog(#"touched %#", hitImageView);
}

You can use UIGestureRecognizers as of iOS 3.2. I would recommend using one UIImageView for the menu you have and adding the UITapGestureRecognizer to detect single taps. Then use locationInView in the action to see where in the image the user touched.
...
UITapGestureRecognizer *tapRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(menuSelect:)];
[imageView addGestureRecognizer:tapRecognizer];
[tapRecognizer release];
}
- (void)menuSelect:(UIGestureRecognizer *)gesture {
// get location CGPoint for touch from recognizer
}
This is a link to the very helpful Apple guide to recognizers.

Related

How to create buttons around circle with some radius

i try to create programmatically a number of buttons. I what that buttons will created around the circle like on image 1. Now i have some results, i can rotate buttons, but don't know how to set offset between them. Now i have this result: image 2 Here is my code. And thanks for any help!
viewDidload in ViewController
CGPoint point = self.view.center;
NSArray *arrayWithImages = #[#"red", #"pink", #"green", #"blue", #"purple", #"orange", #"yellow"];
NSArray *arrayWithAngle = #[#(0), #(M_PI / 3.8f), #(M_PI / 1.8), #(M_PI / -6), #(M_PI / 6), #(M_PI / -1.8), #(M_PI / -3.8)];
NSMutableArray *arrayWithPlacePoint = [self generatePointForRound:point andAngle:arrayWithAngle andRadius:25.0f];
NSLog(#"array with place point = %#", arrayWithPlacePoint);
for (NSInteger i = 0; i < [arrayWithImages count]; i++) {
PetalObject *petal = [[PetalObject alloc] initWithImageName:arrayWithImages andRotation:arrayWithAngle andIndex:i andPointsArray:arrayWithPlacePoint andCentrPoint:point];
[self.view addSubview:petal.petalButton];
}
I try to generate some x,y point which should be a creation point of each new button
- (NSMutableArray *)generatePointForRound:(CGPoint )centrPoint andAngle:(NSArray *)arrayAngle andRadius:(float)radiusValue {
CGPoint currentPoint;
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int i = 0; i < [arrayAngle count]; i++) {
CGFloat x1 = centrPoint.x + (radiusValue * sin([[arrayAngle objectAtIndex:i] doubleValue]));
CGFloat y1 = centrPoint.y + (radiusValue * cos([[arrayAngle objectAtIndex:i] doubleValue]));
currentPoint = CGPointMake(x1, y1);
[array addObject:[NSValue valueWithCGPoint:currentPoint]];
}
return array;
}
And here is my PetalObject in which i create my buttons
-(id)initWithImageName:(NSArray *)imageNameArray andRotation:(NSArray *)angleArray andIndex:(NSInteger )index andPointsArray:(NSMutableArray *)pointsArray andCentrPoint:(CGPoint )centerPoint {
self.isRecorded = NO;
self.isComplited = NO;
UIImage *image = [UIImage imageNamed:imageNameArray[index]];
CGPoint point = [[pointsArray objectAtIndex:index] CGPointValue];
self.petalButton = [[UIButton alloc] initWithFrame:CGRectMake(point.x - 43 , point.y - 180, 86, 168)];
//self.petalButton.transform = CGAffineTransformMake(cos(angle),sin(angle),-sin(angle),cos(angle),boundsPoint.x-boundsPoint.x*cos(angle)+boundsPoint.y*sin(angle),boundsPoint.y-boundsPoint.x*sin(angle)-boundsPoint.y*cos(angle));
[self.petalButton setBackgroundImage:image forState:UIControlStateNormal];
CGFloat angle = [[angleArray objectAtIndex:index] floatValue];
[self.petalButton setTransform:CGAffineTransformMakeRotation(angle)];
return self;
}
Image 1:
Image 2:
Screenshot
And code:
- (void)viewDidLoad {
[super viewDidLoad];
for (NSInteger index = 0; index < 6; index ++) {
UIButton * button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 50, 20)];
button.layer.anchorPoint = CGPointMake(-0.5, 0.5);
button.backgroundColor = [UIColor greenColor];
button.center = CGPointMake(self.view.center.x + CGRectGetWidth(button.frame) / 2.0, self.view.center.y);
button.transform = CGAffineTransformMakeRotation(M_PI * 2 * index / 6.0);
[self.view addSubview:button];
}
}
The key point is anchorPoint, you set all the button with same anchorPoint and frame, then apply different transform.

how to drag dynamically created UIImageview in obj c (xcode)

i have gone through the many tutorials to drag an image on screen using touchesmoved method
but most of them are not for dynamically created imageviews
in my project i created 5 UIImageview programatically,
now i want that user can drag them on screen>> i also follow this answer
Question but all in vain , no success so far>
the code for creating the dynamically imageview is
for (int i = 0; i < index ; i++)
{
UIImageView *imageView1 = [[UIImageView alloc] initWithImage:
[UIImageimageNamed:image_name]];
self.imageView1.userInteractionEnabled = YES;
imageView1.frame = CGRectMake(xvalue, yvalue, 80.0f, 80.0f);
self.view.userInteractionEnabled = YES;
[self.view addSubview:imageView1];
}
Thanks in advance for good replies
I'm a little confused with how you are creating UIImageViews because you are using a for-loop but a static name. So you might have 15 UIImageViews with the name "imageView1".
But anyways, this shouldn't matter at all if you are using the code in the question you linked to. Perhaps you put the lines in out of order... this is the proper order. (If it doesn't work let me know, along with the errors you get)
//-(void)ViewDidLoad? {???? is this your function??
int xvalue = 0;//?? not sure where you declared these
int yvalue = 0;//?? not sure where you declared these
for (int i = 0; i < index ; i++) {
UIImageView *imageView1 = [[UIImageView alloc] initWithImage:
[UIImageimageNamed:image_name]];
self.imageView1.userInteractionEnabled = YES;
imageView1.frame = CGRectMake(xvalue, yvalue, 80.0f, 80.0f);
self.view.userInteractionEnabled = YES;
[self.view addSubview:imageView1];
}
self.elements=[myElements getElements];
imagesElements = [[NSMutableArray alloc]init];
for(ElemetsList *item in self.elements) {
UIImageView *oneelement = [[UIImageView alloc] initWithImage:[UIImage imageNamed:item.imgElement]];
oneelement.frame = CGRectMake(item.positionX, item.positionY, item.width, item.height);
oneelement.userInteractionEnabled=YES;
[imagesElements addObject:oneelement];
}
for(UIImageView *img in imagesElements) {
[self.view addSubview:img];
}
//}? End Function, whatever it may be...?
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
for(UIImageView *img in imagesElements)
{
if([self view] == img)
{
CGPoint location = [touch locationInView:self.view];
img.center=location;
}
}
}
If you just want to hard-code in the moving for one image try this:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
imageView1.center=[touch locationInView:self.view];
}
There are plenty of ways to address this issue. You can add UIPanGestureRecognizer to each UIImageView at the time its creation, or you can use touchesBegan:, touchesMoved: on self (assuming it's a UIViewController) and traverse each UIImageView to see if its frame contains the point of the touch.

multiple pinch gestures on different images on the same UIView

I am using Xcode 4.4 and target is iOS 5.
As on the title, I would like to create multiple pinch gestures for different images. I use two type of images. One is set as a background and the 2nd type of image is a stamp that is pasted on the image that is set as background. To do this I am using UIGestureRecognizer. Everything is fine until I paste the stamp type of image and try to zoom that image. I can zoom but when I zoom the image, the image has has been set as background zooms as well.
With the code below, I can paste different images (stamp type), tap and drag them individually but not when I try all the content zooms as well. Why isn't working?
Thank you in advance
- (void)viewDidLoad{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSLog(#"menuListType=%# ; menuID=%#", self.category.menuListType ,self.menu.menuID);
UIImage *aImage;
NSString *imagepath = [NSString stringWithFormat:#"%#%#",[FileUtility getPDFImageFolderPath], self.menu.imageID];
if (self.menu.imageID == nil || [self.menu.imageID isEqualToString:#""]) {
// self.canvasView.image = [UIImage imageNamed:#"NotExistFile.jpg"];
aImage = [UIImage imageNamed:#"NotExistFile.jpg"];
} else {
// self.canvasView.image = [UIImage imageWithContentsOfFile:imagepath];
aImage = [UIImage imageWithContentsOfFile:imagepath];
// self.canvasView = [[[UIImageView alloc] initWithImage:self.canvasView.image] autorelease];
}
// Choose image base and set as background
if ([self.category.menuListType isEqualToString:#"4"]) {
//set size
int imageW = aImage.size.width;
int imageH = aImage.size.height;
float scale = (imageW > imageH ? 500.0f/imageH : 500.0f/imageW);
CGSize resizedSize = CGSizeMake(imageW * scale, imageH * scale);
UIGraphicsBeginImageContext(resizedSize);
[aImage drawInRect:CGRectMake(0, 0, resizedSize.width, resizedSize.height)];
UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.canvasView.contentMode = UIViewContentModeTop;
self.canvasView.image = resizedImage;
if (self.menu.imageID == nil || [self.menu.imageID isEqualToString:#""]) {
} else {
self.canvasView = [[[UIImageView alloc] initWithImage:self.canvasView.image] autorelease];
}
} else {
// Paste image and set as background
UIImage *captureImage;
NSString *capturepath = [NSString stringWithFormat:#"%#%#",[FileUtility getPDFImageFolderPath], #"capture.png"];
if ([FileUtility fileExist:capturepath]) {
captureImage = [UIImage imageWithContentsOfFile:capturepath];
} else {
captureImage = [UIImage imageNamed:#"NotExistFile3.png"];
}
self.canvasView.contentMode = UIViewContentModeTop;;
self.canvasView.image = captureImage;
self.canvasView = [[[UIImageView alloc] initWithImage:self.canvasView.image] autorelease];
// Prepare Gestures
iViewsTapidx = 0;
iViewsDblTapidx = 0;
ivMax = sizeof(iViews) / sizeof(iViews[0]);
isTaped = NO;
isDblTaped = NO;
_width = 100;
// Initialization code
// Single tap
UITapGestureRecognizer *tapg =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(tapAction:)];
[self.itemView addGestureRecognizer:tapg];
// Double tap
UITapGestureRecognizer *doubleTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(doubleTapAction:)];
doubleTap.numberOfTapsRequired = 2;
[self.itemView addGestureRecognizer:doubleTap];
// longPress(長押し)
UILongPressGestureRecognizer *longPress =
[[UILongPressGestureRecognizer alloc] initWithTarget:self
action:#selector(longPressAction:)];
[self.itemView addGestureRecognizer:longPress];
// drag
UIPanGestureRecognizer *pan =
[[UIPanGestureRecognizer alloc] initWithTarget:self
action:#selector(panAction:)];
[self.itemView addGestureRecognizer:pan];
//pinch
UIPinchGestureRecognizer *pinchGestureRognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(handlePinch:)];
[self.itemView addGestureRecognizer:pinchGestureRognizer];
// Stamp Image
int i = 0;
CGPoint tapPoint = CGPointMake(self.canvasView.center.x, self.canvasView.center.y);
int parcent = aImage.size.width / _width; // Prepare image to paste
// Show stamp
*(iViews+i) = [[UIImageView alloc] initWithImage:aImage];
(*(iViews+i)).frame = CGRectMake(tapPoint.x - aImage.size.width/parcent/2,
tapPoint.y - aImage.size.height/parcent/2,
aImage.size.width/parcent,
aImage.size.height/parcent);
(*(iViews+i)).tag = i+1;
[self.itemView addSubview:*(iViews+i)];
iViewsTapidx = i;
isTaped = YES;
self.itemView.userInteractionEnabled = YES;
}
[self showAnimation];
}
// tap
-(void)tapAction:(UITapGestureRecognizer *) sender{
CGPoint tapPoint = [sender locationInView:self.itemView];
NSLog(#">>>tap x=%.2f, y=%.2f", tapPoint.x, tapPoint.y);
int i =0;
isTaped = NO;
for (i = 0; i < ivMax; i++) {
if (CGRectContainsPoint((*(iViews+i)).frame, tapPoint)) {
isTaped = YES;
iViewsTapidx = i;
NSLog(#"i = %d", i);
break;
}
}
}
// doubleTap
-(void)doubleTapAction:(UITapGestureRecognizer *) sender{
NSLog(#">>>doubleTap");
CGPoint tapPoint = [sender locationInView:self.itemView];
isTaped = NO;
isDblTaped = NO;
int i =0;
for (i = 0; i < ivMax; i++) {
if (CGRectContainsPoint((*(iViews+i)).frame, tapPoint)) {
isDblTaped = YES;
iViewsDblTapidx = i;
break;
}
}
// remove
if (isDblTaped) {
NSLog(#"remove %d", i);
(*(iViews+i)).tag = 0;
[*(iViews+i) removeFromSuperview];
}
}
// longPress
- (void)longPressAction:(UILongPressGestureRecognizer *) sender{
if ([sender state] == UIGestureRecognizerStateBegan) {
NSLog(#">>>longPress 1");
}else if ([sender state] == UIGestureRecognizerStateEnded) {
CGPoint tapPoint = [sender locationInView:self.itemView];
NSLog(#">>>longPress 2 x=%.2f, y=%.2f", tapPoint.x, tapPoint.y);
int i =0;
for (i = 0; i < ivMax; i++) {
NSLog(#"i = %d", i);
if ((*(iViews+i)).tag == 0) {
break;
}
}
if (i < ivMax) {
//Stamp imapge
UIImage *stampImage;
NSString *imagepath = [NSString stringWithFormat:#"%#%#",[FileUtility getPDFImageFolderPath], self.menu.imageID];
if (self.menu.imageID == nil || [self.menu.imageID isEqualToString:#""]) {
stampImage = [UIImage imageNamed:#"NotExistFile.jpg"];
} else {
stampImage = [UIImage imageWithContentsOfFile:imagepath];
}
int parcent = stampImage.size.width / _width; // Set stamp image
//Sow stamp image
*(iViews+i) = [[UIImageView alloc] initWithImage:stampImage];
(*(iViews+i)).frame = CGRectMake(tapPoint.x - stampImage.size.width/parcent/2,
tapPoint.y - stampImage.size.height/parcent/2,
stampImage.size.width/parcent,
stampImage.size.height/parcent);
(*(iViews+i)).tag = i+1;
[self.itemView addSubview:*(iViews+i)];
iViewsTapidx = i;
isTaped = YES;
}
}
}
// drag
- (void)panAction:(UIPanGestureRecognizer *) sender{
NSLog(#">>>pan");
if (isTaped) {
CGPoint p = [sender translationInView:self.itemView];
CGPoint movePoint = CGPointMake((*(iViews+iViewsTapidx)).center.x + p.x,
(*(iViews+iViewsTapidx)).center.y + p.y);
(*(iViews+iViewsTapidx)).center = movePoint;
// NSLog(#">>>pan x=%.2f, y=%.2f --> x=%.2f, y=%.2f", p.x, p.y, movePoint.x, movePoint.y);
NSLog(#">>>pan x=%.2f, y=%.2f", p.x, p.y);
[sender setTranslation:CGPointZero inView:self.itemView];
}
}
-(void) handlePinch:(UIGestureRecognizer *) sender {
UIPinchGestureRecognizer *pinchGesture = (UIPinchGestureRecognizer *) sender;
if (pinchGesture.state == UIGestureRecognizerStateBegan || pinchGesture.state == UIGestureRecognizerStateChanged) {
//UIView *view = pinchGesture.view;
// UIView *view = self.itemView;
self.itemView.transform = CGAffineTransformScale(self.itemView.transform, pinchGesture.scale, pinchGesture.scale);
pinchGesture.scale = 1;
NSLog(#"zoom");
}
}
You will have to add Gesture Recognizer on Uiimageview, Look here for doing so : UIGestureRecognizer on UIImageView
Yet another way is to use UIScrolliew as your container instead of UIView and use the - (UIView*)viewForZoomingInScrollView:(UIScrollView *)aScrollView {
return imageView;
}
here imageView is the image you want to zoom,this will zoom that only image you are pinching its tested and works fine.

Adding subviews to a UIView at initialization

In the initialization method for a UIView subclass I am adding several UIImageViews. When the view is rendered they are present in the subviews array and have valid frame rects, but are not drawn on the screen. Does anyone know why this happens?
- (id) initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (!self)
return nil;
[self commonInit];
return self;
}
- (void) commonInit {
_padding = 128.0f;
// Add the chord views here
_chordImages = [NSArray arrayWithObjects:[UIImage imageNamed:#"fn_maj_x_x_x_x_1_e_1_fn"], [UIImage imageNamed:#"en_maj_x_x_x_x_1_e_1_en"], [UIImage imageNamed:#"dn_maj_x_x_x_x_1_d_1_f#"], [UIImage imageNamed:#"an_min_x_x_x_x_1_a_1_en"], nil];
CGFloat containerWidth = [self bounds].size.width;
NSLog(#"containerWidth: %f",containerWidth);
CGFloat chordWidth = [[_chordImages objectAtIndex:0] size].width;
NSLog(#"chordWidth: %f",chordWidth);
CGFloat chordMarkerWidth = [[[GVChordMarkerView alloc] initWithFrame:CGRectMake(0, 0, 12, 12)] frame].size.width;
NSLog(#"chordMarkerWidth: %f",chordMarkerWidth);
// [self setFrame:CGRectMake(chordXPosition, 0, [self bounds].size.width, [self bounds].size.height]);
CGFloat chordXPosition = 0;
CGFloat chordXSpacing = (containerWidth/4 - (chordMarkerWidth + chordWidth));
chordXPosition += containerWidth/4;
for (NSUInteger i = 0; i < [_chordImages count]; i++) {
chordXPosition += chordXSpacing;
CGRect chordImageViewFrame = CGRectMake(chordXPosition, 0, [[_chordImages objectAtIndex:0] size].width, [[_chordImages objectAtIndex:0] size].height);
UIImageView *chordImageView = [[UIImageView alloc] initWithFrame:chordImageViewFrame];
[self addSubview:chordImageView];
chordXPosition += (chordMarkerWidth + chordWidth);
}
NSLog(#"Finished");
}
Could it be that your UIImageview is just empty? Where did you add the image?

Why am not getting collision detection with CGRectIntersectsRect in IOS?

I have 4 elements: greenball, yellowball, orangeball, and redball that fall from the top of the screen
I also have an element, blueball, that follows my touch.
All of these things are working great! :D
However, I want to detect when the greenball intersects with the blueball
my blue ball is placed in the view at viewDidLoad, the 4 balls are placed on the view based on an nstimer that calls onTimer.
All 5 balls are created on the same layer:
[self.view insertSubview:greenImage belowSubview:bottomBar]
I can detect when the redball and greenball collide:
if (CGRectIntersectsRect(greenImage.frame, redImage.frame)) {
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"title" message:#"points" delegate:nil cancelButtonTitle:#"cool" otherButtonTitles:nil];
[message show];
[message release];
}
If I replace "redImage" for "blueball" I don't get the alert. I assume this may be because they aren't declared in the same method.
Any ideas on how to detect this collision?
thanks!
--- EDIT ---
Using the suggestion below I'm doing the following:
greenImage = [[UIImageView alloc] initWithImage:green];
greenImage.frame = CGRectMake(startX,0,43,43);
[self.view insertSubview:greenImage belowSubview:bottomBar];
[UIView beginAnimations:nil context:greenImage];
[UIView setAnimationDuration:5 * speed];
greenImage.frame = CGRectMake(startX, 500.0, 43,43);
CGFloat r1 = greenImage.frame.size.width * .5;
CGFloat r2 = blueBall.frame.size.width * .5;
if(CGPointDistance(greenImage.center, blueBall.center) < (r1 + r2)){
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"notice" message:#"hit!" delegate:nil cancelButtonTitle:#"cool" otherButtonTitles:nil];
[message show];
[message release];
}
below this method I have:
CGFloat CGPointDistance(CGPoint p1, CGPoint p2)
{
return sqrtf((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y));
}
get an error:
conflicting types for 'CGPointDistance'
and a warning:
implicit declaration of function 'CGPointDistance'
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...
CGFloat CGPointDistance(CGPoint p1, CGPoint p2)
{
return sqrtf((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y));
}
It looks like your "balls" are views... Assuming the "ball" fills the frame, the radius will be 1/2 the width...
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);
}
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...
// 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]];
}
maybe this will help some, just a little modification to the code above.
-(CGFloat)CGPointDistance:(CGPoint)p1 p2:(CGPoint)p2
{
return sqrtf(powf(p1.x - p2.x) + powf(p1.y-p2.y));
}
-(BOOL)DidCollide:(View*)v1 v2:(View*)v2 v1Radius:(CGFloat)v1Radius v2Radius:(CGFloat)v2Radius
{
CGFloat r1 = v1.frame.size.width * v1Radius;
CGFloat r2 = v2.frame.size.width * v2Radius;
return [self PointDistance:v1.center p2:v2.center] < (r1 + r2)
}
and to check for collision your just do
if([self DidCollide:view1 v2:view2 v1Radius:radius v2Radius:radius])
{
//do something
}

Resources