Search code examples
cocos2d-iphonelabelccspritetouches

Registering touches on CCSprite characters of a CCLabelBMFont label


The problem I encounter is that the positions of the CCLabelBMFont label and the one of the CCSprite characters composing that label seem to be different so I cannot manage the touch events...

To test more in details this issue I tried this :

    -(id)init
    {
      if ((self = [super init])
      {
        CCLabelBMFont *label = [CCLabelBMFont labelWithString:"welcome" fntFile:@"Arial.fnt"];
        CGSize size = [[CCDirector sharedDirector] winSize];
        label.position =  ccp(size.width/2, size.height/2);
        [self addChild: self.label];

        self.isTouchEnabled = YES;
      }
    return self;
    }

    -(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
      UITouch *touch = [touches anyObject];
      CGPoint touchLocation = [touch locationInView:[touch view]];
      touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
      NSLog(@"point touched: x:%f, y:%f", touchLocation.x, touchLocation.y);

      for (CCSprite *character in [label children])
      {
        if (CGRectContainsPoint([character boundingBox], touchLocation))
        {
          [character setColor:ccRED];
        }
      }
    }

And whatever the letter of the label I touch it didn't turn red as it should.

And the reason why I think the position of the sprites composing the CCLabelBMFont and the label itself are different is that when I insert :

NSLog(@"character position: x:%f y: %f", character.position.x, character.position.y);

in the ccTouchesBegan touch handling, the position of the sprites are listed to be on the lower left corner of the screen.

So maybe I'm missing something simple but is there a way to convert the sprites position to be at the same place as the label to enable the recognition of the touches on the letters of a label?

Thanks in advance.


Solution

  • The position of child nodes is relative to their parent. You have to use the sprite's convertToNodeSpace or convertToWorldSpace methods to convert the position accordingly. In this case you would have to use convertToNodeSpace with touchLocation as input with each sprite before using it to test bounding box collisions.

    This should fix it:

    for (CCSprite *character in [label children])
    {
       CGPoint touchLocationNodeSpace = [character convertToNodeSpace:touchLocation];
       if (CGRectContainsPoint([character boundingBox], touchLocationNodeSpace))
       {
          [character setColor:ccRED];
       }
    }