如何检测触摸了SKSpriteNode

时间:2023-01-23 00:17:13

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:

我发现了一个类似的问题,但我正在尝试检测并识别用户触摸的哪个Sprite,而我不知道该怎么做。这是我的变量:

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.

想法是识别spriteNode,然后将其替换为其他精灵或更改颜色,但我不知道如何使用这个spriteNodes矩阵,我想第一步是识别精灵。

I really appreciate your help! Thanks!

我非常感谢你的帮助!谢谢!

2 个解决方案

#1


9  

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.

您尝试做的事情(即使我没有看到这个原因)也可以使用委托模式来完成。基本上,您将告诉您的代表(场景或您设置为委托的任何内容)为您做一些事情,您将直接从按钮的touchesBegan方法中执行此操作。此外,您将按钮的名称传递给场景。

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(_:):

要实现这一点,首先必须定义一个名为ButtonDelegate的协议。该协议定义了一个要求,该要求声明任何符合要求的类必须实现一个名为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.

这是将在您的GameSceneclass中实现的方法,但是从button的touchesBegan中调用。此外,此方法将用于将按钮的名称传递给其委托(场景),因此您将始终知道点击了哪个按钮。

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

接下来是按钮类本身。 Button可能如下所示:

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).

这里重要的是userInteractionEnabled = true,这意味着该按钮将接受触摸。另一个重要的事情是委托财产。如前所述,按钮将场景设置为其委托。当我们创建一些按钮时,将场景设置为按钮的代表...为了使您更容易,请将代表视为为老板工作的工作人员:)老板(按钮)告诉他的工作人员(一个场景)为他做点什么(打印他的名字)。

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 :)

好的,所以让我们确保场景符合ButtonDelegate协议......为什么这很重要?这很重要,因为工人(场景)必须遵循老板的命令(按钮)。通过遵守这个协议,工人正在与他的老板签订合同,确认他知道如何完成工作并遵循他的命令:)

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.

就是这样。当您点击播放按钮时,将调用按钮本身上的touchesBegan,然后该按钮将告诉其委托使用场景类中定义的方法打印其名称。

#2


0  

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:

要检测触摸,请将其放入SKScene子类中:

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.

targetNode是您点击的节点。

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

如果你想获得精灵的名字,你可以使用targetNode.name。

#1


9  

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.

您尝试做的事情(即使我没有看到这个原因)也可以使用委托模式来完成。基本上,您将告诉您的代表(场景或您设置为委托的任何内容)为您做一些事情,您将直接从按钮的touchesBegan方法中执行此操作。此外,您将按钮的名称传递给场景。

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(_:):

要实现这一点,首先必须定义一个名为ButtonDelegate的协议。该协议定义了一个要求,该要求声明任何符合要求的类必须实现一个名为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.

这是将在您的GameSceneclass中实现的方法,但是从button的touchesBegan中调用。此外,此方法将用于将按钮的名称传递给其委托(场景),因此您将始终知道点击了哪个按钮。

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

接下来是按钮类本身。 Button可能如下所示:

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).

这里重要的是userInteractionEnabled = true,这意味着该按钮将接受触摸。另一个重要的事情是委托财产。如前所述,按钮将场景设置为其委托。当我们创建一些按钮时,将场景设置为按钮的代表...为了使您更容易,请将代表视为为老板工作的工作人员:)老板(按钮)告诉他的工作人员(一个场景)为他做点什么(打印他的名字)。

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 :)

好的,所以让我们确保场景符合ButtonDelegate协议......为什么这很重要?这很重要,因为工人(场景)必须遵循老板的命令(按钮)。通过遵守这个协议,工人正在与他的老板签订合同,确认他知道如何完成工作并遵循他的命令:)

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.

就是这样。当您点击播放按钮时,将调用按钮本身上的touchesBegan,然后该按钮将告诉其委托使用场景类中定义的方法打印其名称。

#2


0  

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:

要检测触摸,请将其放入SKScene子类中:

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.

targetNode是您点击的节点。

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

如果你想获得精灵的名字,你可以使用targetNode.name。