iOS CGRectIntersectsRect with multiple instances of UIImageView? - iphone

I have a layout for an application that needs to detect when an image collides with another image.
Here, the user creates multiple 'balls', the same instance of a UIImageView named 'imgView', on the screen by tapping the location they desire:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *myTouch = [[event allTouches] anyObject];
imgView = [[UIImageView alloc] initWithFrame:CGRectMake(40, 40, 40, 40)];
imgView.image = [UIImage imageNamed:#"ball.png"];
[self.view addSubview:imgView];
imgView.center = [myTouch locationInView:self.view];
}
(imgView is declared as a UIImageView in the header) :
UIImageView *imgView;
Now, I also have an image called 'staff'. It is a long bar that pans horizontally across the screen. I want the image 'staff' to detect EVERY collision it has with the variable 'imgView', or the balls the user has placed on the screen.
Therefore, the user could tap 10 different places on the screen and and 'staff' should be able to catch every single one.
I use this CGRectIntersectsRect code thats activated by an NSTimer:
-(void)checkCollision {
if( CGRectIntersectsRect(staff.frame,imgView.frame)) {
[self playSound];
}
}
However, the intersection is only detected with the LAST instance, or 'ball' the user created. The staff reacts to that one, but pans over the rest. Any help to fix my code to detect all instances would be greatly appreciated.

Each time you create a new ball, you are overriding your imgView instance variable. Thus, your checkCollision method only sees the latest value of imgView, namely the last ball created.
Instead, you could keep track of every ball on screen in an NSArray, then check for collisions against every element in that array. To do that, replace your imgView instance variable with, say:
NSMutableArray *imgViews
Then, sometime early on, say in viewDidLoad initialize the array:
imgViews = [[NSMutableArray alloc] init]
In -touchesEnded:withEvent: add the new UIImageView to the array:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *myTouch = [[event allTouches] anyObject];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(40, 40, 40, 40)];
imgView.image = [UIImage imageNamed:#"ball.png"];
[self.view addSubview:imgView];
imgView.center = [myTouch locationInView:self.view];
[imgViews addObject:imgView]
}
And finally, in checkCollision iterate through your array and perform your check on every element
- (void)checkCollision {
for (UIImageView *imgView in imgViews) {
if( CGRectIntersectsRect(staff.frame,imgView.frame)) {
[self playSound];
}
}

Related

Accessing presentationLayer of an animation to detect collisions

I have two objects: one that is moving by animation, and another that is moving when I drag it around with my finger. I want to be able to detect when the two "collide" using CGIntersectsRect. However, I've heard that in order to do this with animations, I need to access the presentation layer to grab values from there. I have no idea how to go about doing this, however. This is the animation code I have:
UIImage *flakeImage = [UIImage imageNamed:#"apple.png"];
UIImageView *flakeView = [[UIImageView alloc] initWithImage:flakeImage];
flakeView.frame = CGRectMake(200, -25.0, 25.0, 25.0);
[self.view addSubview:flakeView];
[UIView beginAnimations:nil context:(flakeView)];
[UIView setAnimationDuration:2];
flakeView.frame = CGRectMake(200, 800.0, 25.0, 25.0); ]
and here is the code for the object I move with my finger:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
// get current touch location
UITouch *touch = [[event touchesForView:self.view] anyObject];
CGPoint point = [touch locationInView:self.view];
// update location of the image
basketView.center = CGPointMake(point.x, basketView.center.y);
}
How can I access the presentationLayer of the flakeView animation so that I can detect when the two objects intersect?
You simply need to keep around a reference to both of your views. Then all you have to do is:
if(CGRectIntersectsRect(((CALayer*)basketView.layer.presentationLayer).frame,
((CALayer*)flakeView.layer.presentationLayer).frame)) {
//handle the collision
}

How to manage more than one UIImageView in iPhone

I wanna to create dynamically UIImageView on every tap on main view and also wanna to move all the created UIImageView by finger movement.I've got success to dynamic creation on every touch my code is below :
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint pt = [touch locationInView:self.view];
imgView = [[[UIImageView alloc] initWithFrame:CGRectMake(pt.x,pt.y, 100, 100)] autorelease];
imgFilepath = [[NSBundle mainBundle] pathForResource:#"img" ofType:#"png"];
img = [[UIImage alloc] initWithContentsOfFile:imgFilepath];
imgView.tag=i;
[imgView setImage:img];
[img release];
[self.view addSubview:imgView];
}
Now I wanna to move any of the dynamically created UIImageView by finger movement on it.
Thanks.
Set the userInteractionEnabled property of the UIImageView to yes in the method you create it (i. e. the method you posted):
imgView.userInteractionEnabled = YES;
then you will most probably need to subclass UIImageView and implement the following methods to move your image view around:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
Hint: in the touchesMoved: etc. method, you'll want to track where the user's finger moved -- after reading some more docs you'll most probably end up using -[UITouch locationInView:] -- you'll need to convert the coordinates to the superview of your image view and then move the image view itself in this case.
In touchesBegan detect the imageView you have touched. In touchesMoved move the selected imageView by setting it's center to the touch point moved.

Drag elements UIImageView. Using a NSMutableArray

.m
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];
Then I try to interact with the elements:
-(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;
}
}
}
But "if ([self view] == img)" is always "NO". Therefore, the elements do not drag.
How to drag and drop items if they are in the array?
When you add your image views, you make them subviews of self.view, therefore you need to test whether img is in the subviews array. It can't be equal to the view that contains it.

UIImageView pixel-perfect `touches began` for non-transparent parts of UIImage

developing iphone app, I have used a UIImageview and i have set an image of irregular shape
// uiimageview type shutter
shutter = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,32.5)];
//setting image on shutter
UIImage* shutterimg = [UIImage imageNamed:#"trayshutter.png"];
[shutter setImage:shutterimg];
// User interaction
shutter.userInteractionEnabled=YES;
and i get touches using touchesbegan
everything is fine, but issue is I also get events in all the rectangle area occupied by the CGRectMake (i.e. 0,0,320,32.5) of imageview, whereas i require events only on the image (which is of shape of -----|||||-----).
How can i make sure that i get events only on the image and not on the rest of area covered by cgrectmake ?
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if ([touch view] == yourDesiredImage) {
// Do something here
}
}
EDIT: maybe you can try UITapGestureRecognizer instead:
UITapGestureRecognizer * tapGestureRecognizer = [[UITapGestureRecognizer alloc] init];
[tapGestureRecognizer addTarget:self action:#selector(yourTouchMethod:)];
[tapGestureRecognizer setNumberOfTapsRequired:1];
[shutter addGestureRecognizer:tapGestureRecognizer];
[tapGestureRecognizer release];

find which view was clicked

I have a view controller where there are several uiview object. I need to know on which uiview user have tapped. how is this possible? any guidance will help a lot....
Thanks
Pankaj
Here is what you can do to get what you wanted ..... In this example i have created 7 views
UITapGestureRecognizer* gestureRecognizer;
UIView* myView;
for (int i = 0; i < 8; i++)
{
gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doSomthing:)];
gestureRecognizer.numberOfTapsRequired = 1;//or what ever you want
myView = [[UIView alloc] initWithFrame:CGRectMake(10, i*30, 30, 28)];
myView.backgroundColor = [UIColor redColor];
myView.tag = 100+i;
[self.view addSubview:myView];
[myView addGestureRecognizer:gestureRecognizer];
[myView release];
[gestureRecognizer release];
}
Now you need to implement the method like this
-(void)doSomthing:(id)sender
{
UIView* temp = [(UITapGestureRecognizer*)sender view];
// here you get the view you wanted
NSLog(#"view number :%d",temp.tag);
}
I think this should help you
Set a tag for every view to keep track of them.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// We only support single touches, so anyObject retrieves just that touch from touches
UITouch *touch = [touches anyObject];
NSLog(#"view %i", [touch view].tag);
}
you can add gestures to the uiview objects to find which object has been touched. see the documentation.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIGestureRecognizer_Class/Reference/Reference.html
for specific code just comment.
U can probably add a custom button with a tag on top of each view. Then u can know which view is tapped based on the button tag.
pls take a look at this. It may help.
http://www.iphonedevsdk.com/forum/iphone-sdk-development/13041-touch-event-subview.html