Multi-touch co-ordinates problem iPhone - iphone

I am trying to find the coordinates of both touches in a multi touch. This code throws a SIGABRT on the line 'UITouch *touch2 = ...'. could anyone please tell me where I'm going wrong?
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSArray *touchArray = [touches allObjects];
UITouch *touch1 = [touchArray objectAtIndex:0];
UITouch *touch2 = [touchArray objectAtIndex:1];
CGPoint firstTouch = [touch1 locationInView:self.view];
CGPoint secondTouch = [touch2 locationInView:self.view];
}

Most likely there is only one touch in the array. You should check that the array contains an index before you try to retrieve the object at that index:
NSUInteger count = [array count];
id obj = (count > 1)? [array objectAtIndex:1] : nil;
id obj2 = (count > 2)? [array objectAtIndex:2] : nil;

If you want to get a double click event, you need to check the value of tapCount of each UITouch object instead of whether touches has two objects.
for (UITouch *touch in touches) {
if (touch.tapCount==1) {
// do something
} else if (touch.tapCount==2) {
// do something else
}
}

Related

Iphone Detect each Fingers and Draw Line (Using cocos2d/openGL for Drawing)

I understand the basics of how multi-touch Event works
When a figer touches the view/screen that view will receive ccTouchesBegan with a set of UITouch.
UITouch will hold the location (CGPoint) and its unique for each finger.
If more than one finger touches the view at the same time , 2 UITouch will be send to the view.
Sometime view will receive ccTouchesBegan with 2 UITouch's or ccTouchesBegan will be called twise for each finger touch one after another.
If finger1 is moving view will receive ccTouchesMoved with one UITouch.
My question is how to draw lines with each finger touch seperately , put the 1 or 2 fingers on the screen and draw line for each finger touch began/moved/end?
The below code works when there is only single touch but for multi touch it wont work because of the above point 3 and 4.
Exactly like this
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count] > 0) {
// handle multi touch
UITouch *touch1 = [[touches allObjects] objectAtIndex:0];
CGPoint touchLocation1 = [touch1 locationInView: [touch1 view]];
touchLocation1 = [[CCDirector sharedDirector] convertToGL: touchLocation1];
Edge *temEdge1 = (Edge*)[temEdges objectAtIndex:0];
[[temEdge1 end] updateXY:touchLocation1];
[[temEdge1 start] updateXY:touchLocation1];
if ([touches count] > 1) {
UITouch *touch2 = [[touches allObjects] objectAtIndex:1];
CGPoint touchLocation2 = [touch2 locationInView: [touch2 view]];
touchLocation2 = [[CCDirector sharedDirector] convertToGL: touchLocation2];
Edge *temEdge2 = (Edge*)[temEdges objectAtIndex:1];
[[temEdge2 end] updateXY:touchLocation2];
[[temEdge2 start] updateXY:touchLocation2];
}
}
}
-(void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count] > 0) {
// handle multi touch
UITouch *touch1 = [[touches allObjects] objectAtIndex:0];
CGPoint touchLocation1 = [touch1 locationInView: [touch1 view]];
touchLocation1 = [[CCDirector sharedDirector] convertToGL: touchLocation1];
Edge *temEdge1 = (Edge*)[temEdges objectAtIndex:0];
[[temEdge1 end] updateXY:touchLocation1];
if ([touches count] > 1) {
UITouch *touch2 = [[touches allObjects] objectAtIndex:1];
CGPoint touchLocation2 = [touch2 locationInView: [touch2 view]];
touchLocation2 = [[CCDirector sharedDirector] convertToGL: touchLocation2];
Edge *temEdge2 = (Edge*)[temEdges objectAtIndex:1];
[[temEdge2 end] updateXY:touchLocation2];
}
}
}
-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count] > 0) {
// handle multi touch
UITouch *touch1 = [[touches allObjects] objectAtIndex:0];
CGPoint touchLocation1 = [touch1 locationInView: [touch1 view]];
touchLocation1 = [[CCDirector sharedDirector] convertToGL: touchLocation1];
Edge *temEdge1 = (Edge*)[temEdges objectAtIndex:0];
[[temEdge1 end] updateXY:touchLocation1];
if ([touches count] > 1) {
UITouch *touch2 = [[touches allObjects] objectAtIndex:1];
CGPoint touchLocation2 = [touch2 locationInView: [touch2 view]];
touchLocation2 = [[CCDirector sharedDirector] convertToGL: touchLocation2];
Edge *temEdge2 = (Edge*)[temEdges objectAtIndex:1];
[[temEdge2 end] updateXY:touchLocation2];
}
}
}
-(void)draw
{
[super draw];
glLineWidth(5.f);
ccDrawColor4B(0, 0, 255, 255);
for (Edge *temEdge in temEdges) {
CGPoint start = [[temEdge start] toCCP];
CGPoint end = [[temEdge end] toCCP];
ccDrawLine(start , end);
}
}
You can try to associate arrays of touch positions with different touches(something like NSDictionary with UITouches as keys and NSArrays of points as values). Then you can draw these lines using ccDrawLine or any other way if your draw method. Just do not forget to store these arrays somwhere where current touch ends.

Adding UIImageView Objects in UIView to NSMutableArray

I believe I may be dealing with some view issues which are not allowing me to detect and add UIImageView objects to an array. I could really use some suggestions.
I've got a number of UIImageViews with images linked to a UIView that sits on top of a UIViewController (the UIView was added to help with drawRect and some additional advantages). So, when I touch an image and 'drag and drop' it, I want to add that image to an array upon being dropped.
My touchesBegan gets the location of the touch and checks UIImageView is being touched and then centers on that view as follows:
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self]; //can't use self.view in a UIView, this may be causing issues?
startLocation = location; // for reference as needed
NSLog(#"Image x coord: %f", location.x);
NSLog(#"Image y coord: %f", location.y);
if ([touch view] == obiWan_Block)
{obiWan_Block.center = location;}
else if ([touch view] == r2d2_Block)
{r2d2_Block.center = location;}
else if ([touch view] == you_Block)
{you_Block.center = location;}
}
Then, I drag the UIImageView around with touchesMoved and finally, 'drop' the image with touchesEnded. When the UIImageView is drop in a certain area of the screen, I 'snap' it to a specific location. It's at this point I want to place this UIImageView into an array, but I'm having no luck. I believe I'm getting confused on the various views being touched and what's getting added via addObject to my NSMutableArray. Or, I could be missing something completely. Here's my touchedEnded method:
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self];
UIView *temp = [touch view];
UIImageView *currentImageView = (UIImageView *)[touch view]; //DON'T THINK THIS IS RIGHT
NSLog(#"Current Image View is: %#", currentImageView);
if ((location.x > dropZone.origin.x) && (location.y >= dropZone.origin.y) && ([touch view] != NULL))
{
CGRect frame = temp.frame;
if (touchCount == 0) {
frame.origin.x = 15;
frame.origin.y = 180;
temp.frame = frame;
[quoteArray addObject: currentImageView];
touchCount++;
}
else if (touchCount == 1) {
frame.origin.x = 70;
frame.origin.y = 180;
temp.frame = frame;
[quoteArray addObject: currentImageView];
touchCount++;
}
....
I have an NSLog statement to check if addObject is working as follows:
NSLog(#"the quote array contains %d items. Contents = %#",[quoteArray count], quoteArray);
The log always says:
the quote array contains 0 items. Contents = (null)
Please advise and thanks!
Your last part of code shows that you have uninitialized quoteArray. Check code when you create it, I guess you missed something in your init method. Because if array was correct then NSLog should show below:
NSArray *quoteArray = [NSArray array];
NSLog(#"%#", quoteArray);
2011-11-17 17:37:00.506 TestApp[1382:207] ( )

Looping through an array to remove a touched object (iPhone/Cocos2d)

I am using cocos2d to build a game. I have an array of CCSprites and I want to be able to touch them and delete the one that was touched.
Right now I have this...
-(void) spawn {
mySprite = [CCSprite spriteWithFile:#"image.png"];
mySprite.position = ccp(positionX,positionY);
[myArray addObject:mySprite];
[self addChild:mySprite];
}
- (void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch* touch = [touches anyObject];
CGPoint location = [touch locationInView: [touch view]];
NSUInteger i, count = [myArray count];
for (i = 0; i < count; i++) {
mySprite = (CCSprite *)[myArray objectAtIndex:i];
if (CGRectContainsPoint([mySprite boundingBox], location)) {
[self removeChild:mySprite cleanup:YES];
}
}
I have never done this before. Does anyone have a solution?
Thanks,
Michael
- (void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch* touch = [touches anyObject];
CGPoint location = [touch locationInView: [touch view]];
NSMutableArray *spritesToDelete = [[NSMutableArray alloc] init];
for(CCSprite* mySprite in myArray) {
if (CGRectContainsPoint([mySprite boundingBox], location))
[spritesToDelete addObject:mySprite];
for(CCSprite* deadSprite in spritesToDelete) {
[self removeChild:deadSprite cleanup:YES];
[myArray removeObject:deadSprite];
}
}
This code uses a for-each to create an array of the objects that meet your condition, and then removes them.

how to store CGPoint in array

Hi I am trying to store the move points in the NSMutableArray so I have tries like this
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *move = [[event allTouches] anyObject];
CGPoint MovePoint = [move locationInView:self.view];
if (MovePointsArray==NULL) {
MovePointsArray=[[NSMutableArray alloc]init];
}
[MovePointsArray arrayWithObjects:[NSValue valueWithCGPoint:MovePoint]];
}
but this doesn't work how can i store these points in NSMutableArray
You should use addObject: in the last line:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *move = [[event allTouches] anyObject];
CGPoint MovePoint = [move locationInView:self.view];
if (MovePointsArray==NULL) {
MovePointsArray=[[NSMutableArray alloc]init];
}
[MovePointsArray addObject:[NSValue valueWithCGPoint:MovePoint]];
}
You should do like this :
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *move = [[event allTouches] anyObject];
CGPoint MovePoint = [move locationInView:self.view];
if (MovePointsArray == NULL) {
MovePointsArray = [[NSMutableArray arrayWithObjects:[NSValue valueWithCGPoint:MovePoint, nil];
}
else {
[MovePointsArray addObject:[NSValue valueWithCGPoint:MovePoint]];
}
}
don't forget to retain / relase the array as you don't see to use a property accessor.
Best, you should alloc/init the array in your init method and then only do here :
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *move = [[event allTouches] anyObject];
CGPoint MovePoint = [move locationInView:self.view];
[MovePointsArray addObject:[NSValue valueWithCGPoint:MovePoint]];
}
If you want to get an array using method arrayWithObjects you must also add nil as the last element of the array.
like so:
[MovePointsArray arrayWithObjects:[NSValue valueWithCGPoint:MovePoint], nil];
but to add an object to an existing array you should use addObject method
[MovePointsArray addObject:[NSValue valueWithCGPoint:MovePoint]];

Detecting if a specific sprite was touched on Cocos2d-iphone

I was following Ray`s tutorial for making a simple iPhone game (here: http://goo.gl/fwPi) , and decided that i wanted the enemies to be eliminated when they get touched.
My initial approach was to spawn a small CCSprite sprite on the touch location, then use CGRectMake to create a bounding box of said sprite to detect if the enemy sprite was touched. Much like Ray does with the projectile/enemy. But of course, my way of doing it isnt working and i cant dig myself out of this hole.
Here is the relevant code snippet. Any help is appreciated:
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
// Choose one of the touches to work with
UITouch *touch = [touches anyObject];
CGPoint location = [self convertTouchToNodeSpace: touch];
location = [[CCDirector sharedDirector] convertToGL:location];
CCSprite *touchedarea = [CCSprite spriteWithFile:#"Icon-72.png" rect:CGRectMake(location.x, location.y, 2, 2)];
touchedarea.tag = 2;
[self addChild:touchedarea];
[_touchedareas addObject:touchedarea];
}
- (void)update:(ccTime)dt {
NSMutableArray *touchedareasToDelete = [[NSMutableArray alloc] init];
for (CCSprite *touchedarea in _touchedareas) {
CGRect touchedareaRect = CGRectMake(
touchedarea.position.x,
touchedarea.position.y,
touchedarea.contentSize.width,
touchedarea.contentSize.height);
NSMutableArray *targetsToDelete = [[NSMutableArray alloc] init];
for (CCSprite *target in _targets) {
CGRect targetRect = CGRectMake(
target.position.x - (target.contentSize.width/2),
target.position.y - (target.contentSize.height/2),
target.contentSize.width,
target.contentSize.height);
if (CGRectIntersectsRect(touchedareaRect, targetRect)) {
[targetsToDelete addObject:target];
}
}
for (CCSprite *target in targetsToDelete) {
[_targets removeObject:target];
[self removeChild:target cleanup:YES];
}
if (targetsToDelete.count > 0) {
[touchedareasToDelete addObject:touchedarea];
}
[targetsToDelete release];
}
for (CCSprite *touchedarea in touchedareasToDelete) {
[_touchedareas removeObject:touchedarea];
[self removeChild:touchedarea cleanup:YES];
}
[touchedareasToDelete release];
}
That looks like a very difficult way to go about doing it. I havent been coding long myself but maybe the following might help you.
lets say u have a nsmutablearray called enemies and you add the new enemy object to this array when ever you create one. enemy object would be a ccnode and have a ccsprite within it called _enemySprite
then do the touch
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSSet *allTouches = [event allTouches];
UITouch * touch = [[allTouches allObjects] objectAtIndex:0];
//UITouch* touch = [touches anyObject];
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
int arraysize = [enemies count];
for (int i = 0; i < arraysize; i++) {
if (CGRectContainsPoint( [[[enemies objectAtIndex:i] _enemySprite] boundingBox], location)) {
//some code to destroy ur enemy here
}
}
// NSLog(#"TOUCH DOWN");
}
hope this helps
Another way of doing it is that calculating distance between touch position and your sprites.. If touch is close enough to one of your sprites, you can kill it.. Something like this..
for (CCSprite *sprite in anArrayThatCOntainsAllYourSprites) {
float distance = pow(sprite.position.x - location.x, 2) + pow(sprite.position.y - location.y, 2);
distance = sqrt(distance);
if (distance <= 10) {
sprite.dead = YES;
}
}