Search code examples
ioscocos2d-iphoneuitouchccsprite

If touch is in CCSprite bounds? Cocos2d v3


I am trying to create a simple helper method to detect whether a UITouch is within a CCSprite's bounds with this method:

- (BOOL)containsTouchLocation:(UITouch *)touch {
    CGPoint p = [self convertToNodeSpace:touch.locationInWorld];
    CGRect r = self.boundingBox;
    return CGRectContainsPoint(r, p);
}

It seems like it should work in retrospect but it just returns "NO" even though the touch is clearly in a sprite on the screen. Is there something I am doing wrong here? I am using Cocos2d v3.


Solution

  • What you are doing wrong is that boundingBox is the analog of frame and not bounds. Therefore r is in coordinate space of the parent of the node and p in coordinate space of the node itself.

    If you know that node has a parent you can calculate p in parents coordinate space:

    CGPoint p = [self.parent convertToNodeSpace:touch.locationInWorld];
    // You can also use a shorthand [touch locationInNode: self.parent];
    

    Or instead you could get r as the bounds rect instead of the frame

    // notice that it is `contentSizeInPoints` and not `contentSize`
    CGRect r = { .origin = CGPointZero, .size = self.contentSizeInPoints };
    

    But either way the CCNode now also has hitAreaExpansion which you might want to take into account:

    r = CGRectInset(r, -self.hitAreaExpansion);
    

    Or instead of doing all this you could use the hitTestWithWorldPos: method, default implementation of which tests whether given world location is within bounds of the node +/- hitAreaExpansion.