5

When using SpriteKit in watchOS 3, how do you handle the touch events? I am porting the SpriteKit games from iOS and the codes below won't work. Or you have to control the WKInterfaceController somehow?

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?)  {}

override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?)  {}
Lim Thye Chean
  • 8,704
  • 9
  • 49
  • 88

3 Answers3

8

After a lot of frustration with the same issue, I wound up using gesture recognizers, and calculating the position from there.

@IBAction func handleSingleTap(tapGesture: WKTapGestureRecognizer) {
    let location = tapGesture.locationInObject()
    if yourSpriteNodeRect.contains(location) {
        //do stuff
    }
}

One tip though: A strange bug I found though when creating the method to handle the gesture recognizer was that the gesture wasn't being passed by default into the method. I had to ctrl + drag to create the method, and then modify the signature to contain the gesture. If I created the method with the gesture in the signature, Xcode wouldn't allow me to attach the gesture recognizer to it.

It would seem that there would be a better way to detect the touches, but that's the workaround I found for now.

LMVogel
  • 779
  • 7
  • 28
  • You can do what you did my modifying the signature, or you can keep it and add a guard statement: @IBAction func panRecognized(_ sender: AnyObject) { guard let panGesture = sender as? WKPanGestureRecognizer else { return } – Ben Morrow Aug 11 '16 at 14:57
  • True, but the documentation (https://developer.apple.com/reference/watchkit/wkgesturerecognizer) allows for both types of signatures. The guard statement should be necessary. IBAction func handleGesture() / IBAction func handleGesture(gestureRecognizer : WKGestureRecognizer) – LMVogel Aug 14 '16 at 11:32
  • It is very annoying that the recognizer adds a delay to the touch. Depends on the type of game – matthiaswitt Nov 13 '16 at 16:00
0

To get something close to touch down events use a WKLongPressGestureRecognizer with super-short duration (0.001). The IBAction connected to this recognizer will get touch down events pretty much right away. The location is found in the locationInObject property of the recognizer. If the goal is to get moving touches then use the pan recognizer.

property settings in Interface Builder

photogrammer
  • 401
  • 4
  • 7
0

So to do this I first hooked up a gesture recognizer in the watch storyboard. Created an IBAction, then called a method on the SpriteKit Scene passing in gesture.locationInObject(). Then within the scene method for the conversion, here's some code.

let screenBounds = WKInterfaceDevice.current().screenBounds
let newX = ((location.x / screenBounds.width) * self.size.width) - (self.size.width / 2)
let newY = -(((location.y / screenBounds.height) * self.size.height) - (self.size.height / 2))

The newX and newY are the touch coordinates in the scene.

CodyMace
  • 646
  • 1
  • 8
  • 19