Lampros Tzanetos
Lampros Tzanetos

Reputation: 323

Tap gesture to NOT occur when touching a specific location - SpriteKit

I have used touchesBegan to provide functionality for my UIButtons and have used a tapped gesture to provide functionality for my main player SKSpriteNode making it jump when triggered.

//Code regarding the UIButton touch

  override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
  //touches began is only used for GUI buttons -> not to affect player

    for touch: AnyObject in touches {
        //We get location of the touch
        let locationOfTouch = touch.location(in: self)

        if muteButton.contains(locationOfTouch) {  //mute the game  
            timer.invalidate()
            audioPlayer.volume = 0
        }

//Code regarding the tap

 let tap = UITapGestureRecognizer(target: self, action: #selector(GameScene.tapped(gesture:)))
    tap.cancelsTouchesInView = false

    self.view!.addGestureRecognizer(tap)

......

func tapped(gesture: UIGestureRecognizer) {  //used to make the player jump      
            player.physicsBody!.applyImpulse(CGVector(dx: 0, dy: 60))
            player.physicsBody!.affectedByGravity = true */

            }

My problem is that when I press on the restartButton the tap gesture is also activated later when the touch ends. Is there anything I can do?

Upvotes: 1

Views: 864

Answers (1)

nathangitter
nathangitter

Reputation: 9777

The main issue is that the two separate systems for detecting touches (using gesture recognizers and using the touchesBegan/Moved/Ended methods) are in conflict.

One solution is to enable and disable the gesture recognizer if the touch is inside one of the buttons.

In the touchesBegan method, if the touch is inside a button, disable the tap gesture recognizer:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch: AnyObject in touches {
        let locationOfTouch = touch.location(in: self)
        if muteButton.contains(locationOfTouch) { 
            // mute action
            tap.isEnabled = false
        }
    }
}

Then in touchesEnded and touchesCancelled, re-enable the gesture recognizer:

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    tap.isEnabled = true
}

override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
    tap.isEnabled = true
}

This way, if the touch is inside a button, the tap gesture recognizer will not fire. Whenever any touch is complete, we always re-enable the gesture recognizer in case the next touch is meant to make the player jump.

I have tested this out in an empty project, and it works.

Hopefully that helps! Good luck with your game.

Upvotes: 3

Related Questions