I need to detect touches in a circular shape, the problem is that while the shape looks like a circle the touchable area is still rectangular. How do I detect touches only if the user touches my circle?
This is what I'm doing now:
// Here I add the Shape
_circle = [SKShapeNode node];
_circle.name = @"circle";
_circle.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
[_circle setPath:CGPathCreateWithRoundedRect(CGRectMake(-70, -70, 140, 140), 70, 70, nil)];
_circle.strokeColor = _circle.fillColor = [UIColor colorWithRed:255.0/255.0 green:0.0/255.0 blue:0.0/255.0 alpha:1.0];
[self addChild:_circle];
//...
// Listening to touches
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
if (CGRectContainsPoint(_circle.frame, location)) {
NSLog(@"Circle is touched");
}
}
If you are dealing with an actual circle, you can use math to get the result you want. You could just calculate the distance from the center of the circle to the touch point. If that distance is lower than radius of the circle, then you have a valid touch.
- (bool)pressed:(UITouch*) touch
{
CGPoint location = [touch locationInNode:self];
float hyp = sqrtf(powf(_button.position.x - location.x,2) + powf(_button.position.y - location.y,2));
if(hyp < _button.frame.size.width/2)
{
return true;
} else {
return false;
}
}
However, with a rounded rect, this solution will not work.
You could however take a different approach by using the physics of SpritKit. What you would do is create a transparent node with a physics body, and have it move to the touch location. That should give you a collision between your node and the button.
Of course your button would need a proper physics body as well.
Not the ideal solution I think you were hoping for, but at this point there is not a simple and performance friendly one for SpriteKit.
update
Wanted to add one more option, which again is not ideal, but can completely remove touches outside of the shape. However, it has kind of the inverse issue as some of the edges will not be touch reactive.
What you could do is create a secondary touch object that is a plain rectangle made to be as large as it can without extending outside your rounded rect, and use that to do your touch detection.
Like I said, you'd have the inverse issue as the outer areas your touch rect doesn't cover will not be touch reactive. This functionality may or may not be as desirable, depending on the case. Just figured I'd throw it out there and let you decide.