【问题标题】:How do I detect which SKSpriteNode has been touched如何检测已触摸哪个 SKSpriteNode
【发布时间】:2016-04-07 01:57:37
【问题描述】:

我找到了similar question,但我正在尝试检测和识别用户触摸了哪个 Sprite,但我不知道该怎么做。这是我的变量:

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

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

【问题讨论】:

  • 您好! 0.0 @rakeshbs
  • 首先,不要创建这样的精灵。你必须设置他们的名字。稍后,在 touchesBegan 中,您可以使用 nodeAtPointnodesAtPoint 检查哪个节点被touched,并根据它们的名称采取适当的行动。如果您需要一些代码,请告知...
  • 实际上,rakeshbs 在该链接中发布的答案是您应该如何做。所以你必须创建按钮,命名它们,将它们添加到矩阵中(如果你喜欢的话)并使用他发布的代码。
  • 是的,这就是我正在尝试的。你知道使用 rakeshbs 的代码获取用户触摸的精灵名称的方法吗?我的意思是,将名称从类 touchesprite 发送到我的场景以更改精灵的颜色,因为我做不到。谢谢! @旋风
  • 那里都有解释。他展示了两种方法:1)在游戏场景中处理触摸检测。 2) 触摸检测在 touchesBegan 内部直接在 SKNode 的子类中处理。您正在尝试实施这两个示例中的哪一个?

标签: swift matrix sprite-kit touch skspritenode


【解决方案1】:

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

要实现这一点,首先您必须定义一个名为ButtonDelegate 的协议。该协议定义了一个要求,即任何符合要求的类都必须实现一个名为 printButtonsName(_:) 的方法:

protocol ButtonDelegate:class {

   func printButtonsName(name:String?)
}

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

接下来是按钮类本身。 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)
    }  
}

这里重要的是userInteractionEnabled = true,这意味着按钮将接受触摸。另一个重要的事情是delegate 属性。如前所述,按钮将场景设置为它们的代表。稍后我们会在创建一些按钮时将场景设置为按钮的委托...一个场景)为他做点什么(打印他的名字)。

好的,让我们确保场景符合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)
    }
}

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

【讨论】:

  • 哇!!!谢谢!你不知道我是多么感谢你的帮助!你太棒了!谢谢! :D
  • 为什么需要在委托中调用函数?为什么按钮在意识到它被触摸的那一刻就不能自己执行所需的活动?
  • @confused 你可以,但这真的取决于按下按钮时会发生什么。您可能想要在场景中添加/删除节点或进行转换。或者从场景中移除节点,所以在这些情况下,委托会很有用。您可以使用块,并将代码块传递给按钮实例,但我更喜欢这种委派责任的方式。你还没有真正定义 how 按钮应该“自己做活动”是什么意思,所以我真的不能评论更多。
  • “自己做活动”意味着在按钮的代码中覆盖 touchesBegan 函数。
  • 我同意委托,因为在问题中它指出“这个想法是识别 spriteNode,然后将其替换为其他 sprite 或更改颜色,”如果您想更改 sprite,委托会这样做调用不触摸的精灵。他没有说改变质地。
【解决方案2】:

首先,您需要另一种方法来创建精灵,这里有一种方法:

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

现在我们需要为精灵设置一个名称,以便我们知道稍后点击哪个节点。要为精灵添加名称,只需这样做:

spriteNode.name = "name of the sprite"

把这段代码放在上面的例子中会是这样的:

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

要检测触摸,请将其放入您的 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
}

targetNode 是您点击的节点。

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

【讨论】:

    猜你喜欢
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-06
    • 1970-01-01
    相关资源
    最近更新 更多