Reputation: 34513
SKNode A is a parent of SKNode B.
If touches begin inside of SKNode B, the touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?)
function gets called.
If, however, the touches begin outside of SKNode B but move into SKNode B, the touchesMoved
function never gets called.
One option is to handle all touch events inside SKNode A.
However, there are many nodes contained inside SKNode A. Ideally, we could push touch functionality into each child, as opposed to handling everything from SKNode A.
Is it possible to capture touch events that occur inside SKNode B even if they began outside of SKNode B?
Upvotes: 2
Views: 560
Reputation: 16827
When you hit your touchesBegan method, your touch is limited to the coordinate system of that node until the point it is ended. Moving onto another node will not change the coordinate system to the new node. If B is the only node that requires the touch, then you can add a child to cover the entire scene to ensure that B gets fired.
class TouchNode : SKSpriteNode
{
//if you need to override other inits do it here
convenience init(withSize size:CGSize)
{
self.init(color:UIColor(red:0,green:0,blue:0,alpha:0.1),size: size)
isUserInteractionEnabled = true
}
override func touchesBegan(touches: Set<UITouches>, withEvent event: UIEvent?) {
parent!.touchesBegan(touches:touches, withEvent:event)
}
override func touchesMoved(touches: Set<UITouches>, withEvent event: UIEvent?) {
parent!.touchesMoved(touches:touches, withEvent:event)
}
override func touchesEnded(touches: Set<UITouches>, withEvent event: UIEvent?) {
parent!.touchesEnded(touches:touches, withEvent:event)
}
override func touchesCancelled(touches: Set<UITouches>, withEvent event: UIEvent?) {
parent!.touchesCancelled(touches:touches, withEvent:event)
}
}
Then in your NodeB class:
required init(coder aDecoder:NSCoder)
{
super.init(coder:aDecoder)
DispatchQueue.main.async{
self.addChild(TouchNode(withSize:self.scene!.size))
}
}
override func touchesBegan(touches: Set<UITouches>, withEvent event: UIEvent?) {
//do stuff
}
override func touchesMoved(touches: Set<UITouches>, withEvent event: UIEvent?) {
//do stuff
}
override func touchesEnded(touches: Set<UITouches>, withEvent event: UIEvent?) {
//do stuff
}
override func touchesCancelled(touches: Set<UITouches>, withEvent event: UIEvent?) {
//do stuff
}
Edit: Misread question, but leaving the answer in case somebody else needs to go from inside the node to outside.
Think about it, you want to touch nodeB outside of nodeB, this does not make sense. It is like me poking the air and you crying that I am poking you. But if you absolutely need to go outside of the bounds, then add a child node to the sprite when you touch it that extends beyond the node itself, and be sure to transfer the touch back up to the parent
class TouchNode : SKSpriteNode
{
//if you need to override other inits do it here
convenience init(withSize size:CGSize)
{
self.init(color:UIColor(red:0,green:0,blue:0,alpha:0.1),size: size)
isUserInteractionEnabled = true
}
override func touchesBegan(touches: Set<UITouches>, withEvent event: UIEvent?) {
parent!.touchesBegan(touches:touches, withEvent:event)
}
override func touchesMoved(touches: Set<UITouches>, withEvent event: UIEvent?) {
parent!.touchesMoved(touches:touches, withEvent:event)
}
override func touchesEnded(touches: Set<UITouches>, withEvent event: UIEvent?) {
parent!.touchesEnded(touches:touches, withEvent:event)
}
override func touchesCancelled(touches: Set<UITouches>, withEvent event: UIEvent?) {
parent!.touchesCancelled(touches:touches, withEvent:event)
}
}
Then in your NodeB class:
lazy var touchNode = TouchNode(withSize:self.scene!.size)
override func touchesBegan(touches: Set<UITouches>, withEvent event: UIEvent?) {
addChild(touchNode)
//do other stuff
}
override func touchesEnded(touches: Set<UITouches>, withEvent event: UIEvent?) {
touchNode.removeFromParent()
//do other stuff
}
override func touchesCancelled(touches: Set<UITouches>, withEvent event: UIEvent?) {
touchNode.removeFromParent()
//do other stuff
}
Upvotes: 2