Steven
Steven

Reputation: 11

cocos2d for iPhone - Touch no longer works correctly after scale

I am rather new to using Cocos2d for iPhone and I am having an issue with touch locations. At the moment I am simply trying to touch and move a sprite on the screen, this works fine when the layer is unmoved as well as when I translate the layer (changing self.position in X direction in my case) however, when I scale my layer (example: self.scale = .5) the touch no longer moves the sprite. I have done a lot of forum searching/google searching and I think my issue has to do with my coordinate transforms (node space/world space etc.) But I am not 100% sure. I did notice that when I scale, if I click the location where the sprite would be without the scale, then I could move the sprite. This leads me to believe that my transforms are not taking the scale into account.

Here is the coordinate transform code I am currently using to get touch locations:

- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *myTouch = [touches anyObject];
    CGPoint location = [myTouch locationInView:[myTouch view]];
    location = [self convertToNodeSpace:location];
    location = [[CCDirector sharedDirector] convertToGL:location];
}

Here is the code that is checking if the location (same location variable as above) is touching a sprite, although I feel much more confident that this code is correct, who knows!

for (CCSprite *sprite in movableSprites) {
    if (CGRectContainsPoint(sprite.boundingBox, touchLocation)) {
        NSLog(@"Woohoo, you touched a sprite!");
        break;
    }
}

Let me know if you need anymore information and thanks for reading!

Upvotes: 1

Views: 575

Answers (2)

Guru
Guru

Reputation: 22042

Use this function to get sprite rect.

-(CGRect)getSpriteRect:(CCNode *)inSprite
{
    CGRect sprRect = CGRectMake(
                                inSprite.position.x - inSprite.contentSize.width*inSprite.anchorPoint.x,
                                inSprite.position.y - inSprite.contentSize.height*inSprite.anchorPoint.y,
                                inSprite.contentSize.width, 
                                inSprite.contentSize.height
                                ); 

    return sprRect;
}



- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *myTouch = [touches anyObject];
    CGPoint location = [myTouch locationInView:[myTouch view]];
    location = [[CCDirector sharedDirector] convertToGL:location];

    for (CCSprite *sprite in movableSprites) 
    {
       CGRect rect = [self getSpriteRect:sprite];
       if (CGRectContainsPoint(rect, location)) 
       {
           NSLog(@"Woohoo, you touched a sprite!");
           break;
       }
   }
}

Upvotes: 0

Super Class
Super Class

Reputation: 66

I think you should double the bounding box with the scale

   for (CCSprite *sprite in movableSprites) {
    if (CGRectContainsPoint(sprite.boundingBox*sprite.scale, touchLocation)) {
       //touch sprite action
    }
}

About converting the point, if I need an absolut screen point I always use:

convertToWorldSpace:CGPointZero. 

I'm not really sure why you need this on your touch location, I would usually do this on sprites when I need to disregard their position in a parent node.

Other then that, If your game is not real multi-touch game you better use ccTouchBegan and not ccTouchesBegan.

Upvotes: 1

Related Questions