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.
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
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With