Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent single tap from being called when double taps occurs in touchesBegan method

I have implemented both single and double tap. But whenever I double tap the screen the single tap code is also run. Please see code below:

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch = touches.first as UITouch!
    let touchLocation = touch?.location(in: self) 
    let touchedNode = self.atPoint(touchLocation!)

if touch?.tapCount == 1 {
        print("single tap")
        if let name = touchedNode.name        {
            if name == "enemySprite"
            {
                //handle single Tap
             }
         }
    }

if touch?.tapCount == 2 {
        print("double tap")
        if let name = touchedNode.name        {
            if name == "enemySprite"
            {
                //handle double Tap
             }
         }
    }
}

How can I make each of the tap counts mutually exclusive?

UPDATE

Based on Apurv’s answer and Whirlwind’s comment I thought the following code show work.

 override func didMove(to view: SKView) {

    var tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.view.sampleTapGestureTapped(recognizerMethod:)))
    self.view.addGestureRecognizer(tapGesture!)
    tapGesture.numberOfTapsRequired = 1;

    var tapGestureDouble = UITapGestureRecognizer(target: self, action: #selector(self.view.sampleTapGestureTapped(recognizerMethod2:)))
    self.view.addGestureRecognizer(tapGestureDouble!)
    tapGestureDouble.numberOfTapsRequired = 2;

    [tapGesture requireGestureRecognizerToFail : tapGestureDouble];

}

It doesn’t work and I get errors saying,

Value of type ’SKView?’ has no member ‘sampleTapGestureTapped(recognizerMethod:)’ and 
Value of type ’SKView?’ has no member ‘sampleTapGestureTapped(recognizerMethod2:)’

pointing to the declaration of the tap gesture variables

Also, I get the error

Expected expression in the container literal 

pointing to the last line in the above method.

I guess I’m missing something right here, I would really appreciate some help and clarifications on this.

like image 281
ItsMeAgain Avatar asked Mar 10 '17 12:03

ItsMeAgain


1 Answers

You don't have to access ViewController necessarily... You can handle taps inside you scene, like this:

import SpriteKit

class GameScene: SKScene {

    var recognizers:[UIGestureRecognizer] = []

    override func didMove(to view: SKView) {

        // Get label node from scene and store it for use later


        let single = UITapGestureRecognizer(target: self, action: #selector(GameScene.singleTapHandler(recognizer:)))
        view.addGestureRecognizer(single)
        single.numberOfTapsRequired = 1
        recognizers.append(single)

        let double = UITapGestureRecognizer(target: self, action: #selector(GameScene.doubleTapHandler(recognizer:)))
        view.addGestureRecognizer(double)
        double.numberOfTapsRequired = 2
        recognizers.append(double)

        single.require(toFail: double)

    }

    override func willMove(from view: SKView) {
        super.willMove(from: view)

        for recognizer in recognizers {
            self.view?.removeGestureRecognizer(recognizer)
        }
        recognizers.removeAll()
    }

    func singleTapHandler(recognizer:UITapGestureRecognizer){

        print("Single tap detected")
    }

    func doubleTapHandler(recognizer:UITapGestureRecognizer){
        print("Double tap detected")
    }

}

Of course calling some methods on ViewController can be done in a few ways (eg. delegation)... Still, based on your comments, I think that handling taps inside of a current scene is what you want to achieve.

EDIT:

To answer the question from your comment... You can grab the node which is touched by finding the touch location in view, converting it to the location in scene, and grabbing the node at that location:

func singleTapHandler(recognizer:UITapGestureRecognizer){

        print("Single tap detected")

        let locationInView = recognizer.location(in: self.view)

        let locationInScene = self.convertPoint(fromView: locationInView)

        print(locationInScene)

       let node = atPoint(locationInScene)

        if let nodeName = node.name {
            //do stuff
        }

        //or

        if let sprite = node as? SKSpriteNode {
            // node is an SKSpriteNode
        }
    }
like image 67
Whirlwind Avatar answered Sep 25 '22 23:09

Whirlwind