Kevin
Kevin

Reputation: 185

SpriteKit Touches - containsPoint

I'm having an issue where, within my touchesBegan method, I'm not getting back what I think I should.

I'm testing for a hit within a specific node. I've tried several methods, and none work. I've created a work-around, but would love to know if this is a bug or if I'm doing something wrong.

Here's the code:

Standard touchesBegan method:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    /* Called when a touch begins */
    SKSpriteNode *infoPanelNode = (SKSpriteNode *)[self childNodeWithName:@"infoPanelNode"];

    UITouch *touch = [touches anyObject];
    if(touch){
        //e.g.  infoPanelNode position:{508, 23} size:{446, 265.5}  (also of note - infoPanelNode is a child of self)

        //This solution works
        CGPoint location = [touch locationInNode:self];
        //location == (x=77, y=170)
        bool withinInfoPanelNode = [self myPtInNode:infoPanelNode inPoint:location];
        // withinInfoPanelNode == false  (CORRECT)

        //This one doesn't return the same result - returns true when hit is not in the cell
        CGPoint infoLocation = [touch locationInNode:infoPanelNode];
        //infoLocation == (x=-862, y=294)
        bool withinInfoPanelNodeBuiltInResult = [infoPanelNode containsPoint:infoLocation];
        // withinInfoPanelNodeBuiltInResult == true (WRONG)

// This one doesn't work either - returns an array with the infoPanelNode in it, even though the hit point and node location are the same shown above
//        NSArray *nodes = [self nodesAtPoint:location];
//        for (SKNode *node in nodes) {
//            if(node==infoPanelNode)
//                withinInfoPanelNode = true;
//        }
//   

        //Code omitted - doing something with the withinInfoPanelNode now
}

My custom hit test code:

-(bool) myPtInNode:(SKSpriteNode *)node inPoint:(CGPoint)inPoint {
    if(node.position.x < inPoint.x && (node.position.x+node.size.width) > inPoint.x){
        if(node.position.y < inPoint.y && (node.position.y+node.size.height) > inPoint.y){
            return true;
        }
    }
    return false;
}

Anyone see what's going wrong here?

Thanks, kg

Upvotes: 0

Views: 1639

Answers (2)

Loktar
Loktar

Reputation: 546

I'm not sure exactly how SKCropNode will work, but in general, in order for containsPoint: to detect touches within it you need to give it a point relative to its parent node. The following code should work. Note the addition of .parent when calling locationInNode:

CGPoint infoLocation = [touch locationInNode:infoPanelNode.parent];
BOOL withinInfoPanelNodeBuiltInResult = [infoPanelNode containsPoint:infoLocation];

Upvotes: 2

Kevin
Kevin

Reputation: 185

Solved this problem and wanted to update everyone.

It turns out that with this specific infoPanelNode (an SKSpriteNode), I have a child node within it that is an SKCropNode. This node then crops out a much larger node (obviously it's a child of the crop node) so only a small portion is viewable (allowing for scrolling to portions of that node). Unfortunately, the call to containsPoint apparently combines the boundaries of all child nodes with the receiving node's boundaries to use as the boundary test rect. This would be understandable if it would respect the SKCropNode's boundaries of IT'S children, but apparently, it doesn't so you have to roll your own if you have this type of setup.

Upvotes: 1

Related Questions