【问题标题】:How do I detect if an SKSpriteNode has been touched如何检测是否已触摸 SKSpriteNode
【发布时间】:2023-03-08 19:29:01
【问题描述】:

我正在尝试检测我的精灵节点是否已被触摸,但我不知道从哪里开始。

let Pineapple = SKSpriteNode(imageNamed: "Pineappleimg")
Pineapple.userInteractionEnabled = true
Pineapple.position = CGPoint(x: CGRectGetMidX(self.frame) - 200, y: CGRectGetMidY(self.frame));
self.addChild(Pineapple)

【问题讨论】:

标签: swift sprite-kit touch skspritenode touchesbegan


【解决方案1】:

首先将SKSpriteNodename属性设置为字符串。

pineapple.name = "pineapple"
pineapple.userInteractionEnabled = false

然后在touchesBegan函数中的Scene

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    let touch:UITouch = touches.anyObject()! as UITouch
    let positionInScene = touch.locationInNode(self)
    let touchedNode = self.nodeAtPoint(positionInScene)

    if let name = touchedNode.name
    {
        if name == "pineapple"
        {
            print("Touched")
        }
    }

}

这是一种方法。
您还可以继承 SKSpriteNode 并覆盖其中的 touchesBegan

class TouchableSpriteNode : SKSpriteNode
{
    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        print("touched")
    }
}

那就做吧

let pineapple = TouchableSpriteNode(imageNamed: "Pineappleimg")
pineapple.userInteractionEnabled = true
pineapple.position = CGPoint(x: CGRectGetMidX(self.frame) - 200, y: CGRectGetMidY(self.frame));
self.addChild(pineapple)

【讨论】:

  • 在 swift 3 中编译失败。
  • Swift4.1。覆盖 func touchesBegan(_ touches: Set, with event: UIEvent?) { let touch:UITouch = touches.first! as UITouch let positionInScene = touch.location(in: self) let touchNode = self.atPoint(positionInScene) if let name = touchNode.name { if name == "pineapple" { print("Touched") } } }
【解决方案2】:

如果您只寻找可以触摸的几个节点(例如,游戏 UI 中的“继续”或“退出”标签),这可能是一种替代但非常简单的解决方案:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    let touch = touches.first!
    if myNode.containsPoint(touch.locationInNode(self)) {
        print("touched")
    }
}

【讨论】:

  • 如何区分 Continue 和 Exit 标签?
  • 可能......也许......你建议这段代码在两个标签中,继续和退出,当 touchesBegun 信息发送给它时,其中一个将被调用。 . 因为它是通过覆盖 touchesBegun 为触摸信息注册的。是这样吗,还是我……
  • 当然这不适用于重叠或相交的标签,但 touchesBegan() 旨在为整个场景覆盖,而不是标签的方法。
  • 所以 touchesBegun() 只能存在于场景类中?
  • 其实它是由 UIResponder 继承的:developer.apple.com/reference/uikit/uiresponder/… ... 这是 UIView 的超类。 SKScene 包含一个继承自 UIView 的 SKView :)
【解决方案3】:

更新 Swift Swift 版本 3.0.2 (swiftlang-800.0.63 clang-800.0.42.1) 和 XCode 版本 8.2.1 (8C1002):

“Set”类型的值没有成员“anyObject

'locationInNode' 已重命名为 'location(in:)'

'nodeAtPoint' 已重命名为 'atPoint(_:)'

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch in touches {
        let location = touch.location(in: self)
        let node : SKNode = self.atPoint(location)
        if node.name == "myNodeName" {
            print("Hello")
        }
    }
}

【讨论】:

    【解决方案4】:

    这将在 Xcode 9.2 Swift 4.0

    中检测触摸
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
    {
        let touch:UITouch = touches.first!
        let positionInScene = touch.location(in: self)
        let touchedNode = self.atPoint(positionInScene)
    
        if let name = touchedNode.name
        {
            if name == "playLbl"
            {
                print("playLbl Touched")
            }
        }
    
    }
    

    【讨论】:

    【解决方案5】:

    实现在触摸开始时调用的touchesBegan 方法。或者,您也可以在 touchesEnded 中执行此操作。

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent)
    {
        let touch = touches.anyObject() as UITouch
        let location = touch.locationInNode(self)
        let nodes = self.nodesAtPoint(location)
    
        for node in nodes
        {
            if node.name == "youNodeName"
            {
                // Node tapped
                // Do something
    
                break
            }
        }
    }
    

    【讨论】:

      【解决方案6】:

      Swift 3 答案在SKSpriteNode 的子类中嵌入了触摸功能:

      class SpriteSub: SKSpriteNode {
      
          init() {
              super.init(texture: nil, color: UIColor.red, size: CGSize(width: 50, height: 50))
              isUserInteractionEnabled = true
          }
      
          required init?(coder aDecoder: NSCoder) {
              fatalError("init(coder:) has not been implemented")
          }
      
          ...
      
          override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
              print("touch!")
          }
      
      }
      

      【讨论】:

      • Crashalot 它仍然让我进入 NSCoder 初始化...我忘记了如何正确覆盖这个东西 x{
      • @Fluidity 是的,你也需要这个
      • @Fluidity 再次更新。您编辑的 UIColor.clear() 也不是 Swift 3 代码。
      • Crashalot 是的,我也抓住了这个问题
      • @Fluidity 没什么,因为 UIColor.clear 是透明的。试试 UIColor.red。
      【解决方案7】:

      swift 5更新

      override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
      
              for touch in touches {
                  let location = touch.location(in: self)
                  let touchedNode = self.nodes(at: location)
                  for node in touchedNode {
                      if node.name == "play_button" {
                          startGame()
                      }
                  }
              }
          }
      

      【讨论】:

        【解决方案8】:

        使用这段代码来检测 SKSpriteNode 上的触摸

        if(nodeAtPoint(location) == node){
        
        
        
        }
        

        【讨论】:

        • 有史以来最简单的答案!谢谢你:)
        • 这有效,但前提是所讨论的节点不与其他节点重叠,对吧?
        • 比较类,你不应该使用===而不是==吗?
        • @mogelbuster 是的,如果您进行身份平等,似乎 === 是正确的。详情:stackoverflow.com/a/44222407/144088
        【解决方案9】:

        Swift 3.0 和 XCode 7.3.1 的更新。我有一个 SKShapeNode 派生到一个新类并将其插入到场景中。当我想检测这个对象时,我检查如下:

        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        
            for touch in touches {
        
                let location = touch.locationInNode(self)
                let nodes = self.nodesAtPoint(location)
        
                for node in nodes
                {
                    if node is SKNodeDerivedNode
                    {
                        NSLog("Touch a SKNodeDerivedNode")
                        break
                    }
                }
            }
        }
        

        【讨论】:

          【解决方案10】:

          这是我在 Swift 4 中用于查找特定类型节点中是否存在触摸的方式:

          override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
              guard let touch = touches.first else {
                  return
              }
              let touchPosition = touch.location(in: self)
              let touchedNodes = nodes(at: touchPosition)
              for node in touchedNodes {
                  if let nodoTouched = node as? YourNodeType {
                      // touched!
                  }
              }
          }
          

          【讨论】:

            【解决方案11】:

            如果您在子类化SKSpriteNode 之后仍然没有让您的精灵工作,那么您很可能在初始化时忘记添加node.isUserInteractionEnabled = true

            这允许调用touchesBegan(_:with:),因为您现在可以与节点交互。


            例子:

            node = MySprite(texture: texture, size: size)
            node.isUserInteractionEnabled = true
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多