I have an SKSpriteNode
. This SKSpriteNode
has several children. How can I detect if it has been touched? Now, let me be clear, I already know to set up a button in SpriteKit and I tried using the same code I used to detect if the main parent node has been touched, but it didn't work. The button doesn't do anything. Is there a way to fix this? Also, I already tried to set user interaction to true for the child nodes.
Here is one way to track continuous touches (i.e.. directional arrows).
You need to keep track of the touches, in the SKScene node, or in the parent view controller:
var touches = Set<UITouch>()
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.touches.formUnion(touches)
self.updateTouches()
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
self.touches.formUnion(touches)
self.updateTouches()
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
self.touches.subtract(touches)
self.updateTouches()
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
self.touches.subtract(touches)
self.updateTouches()
}
For each touch, translate the coordinates to relative to the SKNode. Check if any of the touches is within the accumulated frame of the SKNode. The accumulated frame is the total bounding area of the node and all of its descendants.
private func isTouching(node: SKNode) -> Bool {
guard let parent = node.parent else {
return false
}
let frame = node.calculateAccumulatedFrame()
for touch in touches {
let coordinate = touch.location(in: parent)
if frame.contains(coordinate) {
return true
}
}
return false
}
For example:
override func update(_ currentTime: NSTimeInterval) {
let touchingJump = isTouching(node: jumpButtonNode)
if touchingJump {
print("jump")
}
}