11

I am developing a 2d game for iPhone by using cocos2d.

I use many small sprite (image) in my game. I want to touch two similar types of sprite(image) and then both sprite(image) will be hidden.

How can I detect touch in a specific sprite(image) ?

Ólafur Waage
  • 68,817
  • 22
  • 142
  • 198
Md Nasir Uddin
  • 2,130
  • 8
  • 38
  • 59

7 Answers7

27

A better way to do this is to actually use the bounding box on the sprite itself (which is a CGRect). In this sample code, I put all my sprites in a NSMutableArray and I simple check if the sprite touch is in the bounding box. Make sure you turn on touch detection in the init. If you notice I also accept/reject touches on the layer by returning YES(if I use the touch) or NO(if I don't)

- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event 
{
  CGPoint location = [self convertTouchToNodeSpace: touch];

  for (CCSprite *station in _objectList)
  {
    if (CGRectContainsPoint(station.boundingBox, location))
    {
      DLog(@"Found sprite");
      return YES;
    }
  }

  return NO;
}
Terence
  • 361
  • 4
  • 6
23

Following Jonas's instructions, and adding onto it a bit more ...

- (void)ccTouchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
   UITouch* touch = [touches anyObject];
   CGPoint location = [[[Director sharedDirector] convertCoordinate: touch.location];
   CGRect particularSpriteRect = CGMakeRect(particularSprite.position.x, particularSprite.position.y, particularSprite.contentSize.width, particularSprite.contentSize.height);
   if(CGRectContainsPoint(particularSpriteRect, location)) {
     // particularSprite touched
     return kEventHandled;
   }
}

You may need to adjust the x/y a little to account for the 'centered positioning' in Cocos

David Higgins
  • 1,401
  • 11
  • 21
  • 2
    +1 for teaching me that CGRectContainsPoint works in CocosLand. – Genericrich Apr 15 '09 at 01:29
  • Cocos2D, since 0.7.1 (or 0.7.2?) now uses CCP (CGPoint) instead of the CPV (Chipmunk Vector) for it's coordinates. They are interchangeable, however - afaik, they've always been since they are defined the same way. Most any of the CG* methods should work. – David Higgins Jun 23 '09 at 13:51
  • It doesn't seem like this will handle sprites that have been scaled since Sprite.contentSize is the entire contents unscaled... Though I haven't tried it yet. – Dad Dec 19 '09 at 03:17
  • 2
    I like CGRectContainsPoint; however, CGMakeRect should be CGRectMake instead, and besides that, I would just use: CGRect particularSpriteRect = [particularSprite boundingBox]; – Dream Lane Jun 23 '11 at 18:36
  • 2
    there are no convertCoordinate and touch.location in cocos2d – Gargo Jul 02 '12 at 13:33
16

In your layer that contains your sprite, you need to say:

self.isTouchEnabled = YES;

then you can use the same events that you would use in a UIView, but they're named a little differently:

- (void)ccTouchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
   UITouch* touch = [touches anyObject];
  //in your touchesEnded event, you would want to see if you touched
  //down and then up inside the same place, and do your logic there.
}
Jonas
  • 4,454
  • 3
  • 37
  • 45
7

@david, your code has some typos for cocos 0.7.3 and 2.2.1, specifically CGRectMake instead of CGMakeRect and [touch location] is now [touch locationInView:touch.view].

here's what I did:

- (BOOL)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch * touch = [touches anyObject];

    CGPoint location = [[Director sharedDirector] convertCoordinate: [touch locationInView:touch.view]];
    CGRect myRect = CGRectMake(sprite.position.x, sprite.position.y, sprite.contentSize.width, sprite.contentSize.height);


    if(CGRectContainsPoint(myRect, location)) {
        // particularSprite touched
        return kEventHandled;
    }
}
John
  • 1,549
  • 1
  • 13
  • 15
  • Director does not exist. Should be CCDirector, but this code does not work anyway. Too old? (using cocos2d 2.x) – Jonny May 29 '13 at 02:41
  • Yeah, this worked in 2009 but I think a lot has changed. The thing you need in the location line is to convert the coordinate to a CGPoint, not sure what does that now. This looks like the up-to-date reference: http://www.cocos2d-x.org/projects/cocos2d-x/wiki/Coordinate_System – John May 30 '13 at 16:17
0

this is a good tutorial explaining the basic touch system http://ganbarugames.com/2010/12/detecting-touch-events-in-cocos2d-iphone/

first, write

self.isTouchEnabled = YES;

then, you need to implement the functions ccTouchesEnded, ccTouchesBegan, etc

from what I understood, you want to be able to 'match' two sprites that can be on different coordinates on the screen.

a method for doing this.. : (im sure theres many other methods)

consider having 2 global variables.

so everytime a touch touches a sprite, you use the CGRectContainsPoint function that is mentioned several times to find which sprite has been touched. then, you can save the 'tag' of that sprite in one of the global variables.

You do the same for the second touch, and then you compare the 2 global variables.

you should be able to figure out the rest but comment if you have problems.

penguinsource
  • 1,120
  • 3
  • 16
  • 40
0

Here's how it worked for me... Where spriteSize is obviously the sprite's size... :P

- (BOOL)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch * touch = [touches anyObject];

    CGPoint location = [[Director sharedDirector] convertCoordinate: [touch locationInView:touch.view]];
    CGRect myRect = CGRectMake(sprite.position.x-spriteSize/2, sprite.position.y-spriteSize/2, spriteSize, spriteSize);


    if(CGRectContainsPoint(myRect, location)) {
        // particularSprite touched
        return kEventHandled;
    }
}
agfa555
  • 950
  • 13
  • 19
0

@Genericrich: CGRectContainsPoint works in CocosLand because of the call 2 lines above:

[[Director sharedDirector] convertCoordinate:]

The Cocos2D objects will be using the OpenGL coordinate system, where 0,0 is the lower left, and UIKit coordinates (like where the touch happened) have 0,0 is upper left. convertCoordinate: is making the flip from UIKit to OpenGL for you.

BigSprocket
  • 166
  • 7
  • 1
    that is an inaccurate statement - it does not convert from OpenGL to UIKit ... but rather from OpenGL View Space to Screen Space as the unconverted coordinates have rather ridiculous values. Also, CocosNode objects are anchored in the center by default (0,0 == center of object) The value returned is simply a point on the screen, relative to Cocos2D Space. convertCoordinate is written as: int newY = openGLView_.frame.size.height - p.y; int newX = openGLView_.frame.size.width - p.x; CGPoint ret; switch(deviceOrientation_) { // various cases to swap around for orientation reasons } return ret; – David Higgins Jun 23 '09 at 13:45