如何检测是不是已触摸 SKSpriteNode

Posted

技术标签:

【中文标题】如何检测是不是已触摸 SKSpriteNode【英文标题】:How do I detect if an SKSpriteNode has been touched如何检测是否已触摸 SKSpriteNode 【发布时间】:2015-03-11 09:53:38 【问题描述】:

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

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

【问题讨论】:

这个问题可以作为例子:***.com/questions/21840042/… 【参考方案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")
        
    


【讨论】:

touches.first 不会错过一些当节点相互重叠为Florian mentions for another answer 的用例?【参考方案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 是的,如果您进行身份平等,似乎 === 是正确的。详情:***.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

【讨论】:

以上是关于如何检测是不是已触摸 SKSpriteNode的主要内容,如果未能解决你的问题,请参考以下文章

快速检测到 SKSpriteNode 触摸

未检测到 SKSpriteNode 触摸

在触摸时将动画添加到 SKSpriteNode (Swift)

无法点击 SKSpriteNode - 未检测到触摸 ios

如何拖动SKSpriteNode而不用Swift触摸它

SKSpriteNode 纹理 alpha 是不是影响触摸区域?