How do I detect which SKSpriteNode has been touched

那年仲夏 提交于 2019-11-26 08:30:47

问题


I find a similar question, but I am trying to detect and identify which Sprite the user touch, and I don\'t know how to do that. This is my variable:

var sprites: [[SKSpriteNode]] = [[SKSpriteNode(imageNamed: \"a\"), SKSpriteNode(imageNamed: \"b\")], [SKSpriteNode(imageNamed: \"c\"),SKSpriteNode(imageNamed: \"d\")]]

The idea is identify the spriteNode and then replace it for other sprite or change the color, but I don´t know how to do it with this matrix of spriteNodes, I guess the first step it´s identify the sprite.


回答1:


What you are trying to do (even if I don't see a reason for this) can be accomplished using delegation pattern. Basically, you will tell your delegate (the scene, or whatever you set as a delegate) to do something for you, and you will do that directly from within the button's touchesBegan method. Also, you will pass the button's name to a scene.

To make this happen, first you have to define a protocol called ButtonDelegate. That protocol defines a requirement which states that any conforming class has to implement a method called printButtonsName(_:):

protocol ButtonDelegate:class {

   func printButtonsName(name:String?)
}

This is the method which will be implemented in your GameSceneclass, but called from within button's touchesBegan. Also, this method will be used to pass a button's name to its delegate (scene), so you will always know which button is tapped.

Next thing is button class itself. Button might look like this:

class Button : SKSpriteNode{

    weak var delegate:ButtonDelegate?

    init(name:String){
        super.init(texture: nil, color: .purpleColor(), size: CGSize(width: 50, height: 50))
        self.name = name
        self.userInteractionEnabled = true
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }


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

        delegate?.printButtonsName(self.name)
    }  
}

The important thing here is userInteractionEnabled = true, which means that button will accept touches. Another important thing is a delegate property. As already mentioned, buttons will have the scene set as their delegate. Setting a scene as delegate of buttons will be done later when we create some buttons... To make this easier for you, think of a delegate as a worker who works for his boss :) The boss (a button) tells his worker (a scene) to do something for him (to prints his name).

Okay, so lets make sure that scene conforms to a ButtonDelegate protocol...Why is this important? It is important because the worker (scene) must follow the orders of his boss (a button). By conforming to this protocol, the worker is making a contract with his boss where confirming that he knows how to do his job and will follow his orders :)

class GameScene: SKScene, ButtonDelegate {


    override func didMoveToView(view: SKView) {

        let play = Button(name:"play")
        play.delegate = self
        let stop = Button(name:"stop")
        stop.delegate = self

        play.position = CGPoint(x: frame.midX - 50.0, y: frame.midY)
        stop.position = CGPoint(x: frame.midX + 50.0, y: frame.midY)

        addChild(play)
        addChild(stop)
    }

    func printButtonsName(name: String?) {

        if let buttonName = name {
            print("Pressed button : \(buttonName) ")
        }

        //Use switch here to take appropriate actions based on button's name (if you like)
    }
}

And that's it. When you tap the play button, the touchesBegan on a button itself will be called, then the button will tell its delegate to print its name using the method defined inside of scene class.




回答2:


First, you need another way to create the sprite, here are a way:

let spriteA = SKSpriteNode(imageNamed: "a")
scene.addChild(spriteA)
let spriteB = SKSPriteNode(imageNamed: "b")
scene.addChild(spriteB)
...and so on...

Now we needs to set a name for the sprite so we can know which node is tapped later. To add a name for a sprite just do this:

spriteNode.name = "name of the sprite"

Putting this code in the above example will look something like this:

let spriteA = SKSpriteNode(imageNamed: "a")
spriteA.name = "a"
scene.addChild(spriteA)
let spriteB = SKSPriteNode(imageNamed: "b")
spriteB.name = "b"
scene.addChild(spriteB)
...and so on...

To detect touches put this into your SKScene subclass:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    let touch = touches.first as UITouch!
    let touchLocation = touch.locationInNode(self)
    let targetNode = nodeAtPoint(touchLocation) as! SKSpriteNode
}

The targetNode is the node you tapped.

If you wants to get the name of the sprite you can use targetNode.name.



来源:https://stackoverflow.com/questions/36465372/how-do-i-detect-which-skspritenode-has-been-touched

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!