SpriteKit:如何检测从节点外部开始的节点上的触摸

Posted

技术标签:

【中文标题】SpriteKit:如何检测从节点外部开始的节点上的触摸【英文标题】:SpriteKit: How to detect touches on node that began outside of node 【发布时间】:2017-11-29 09:45:36 【问题描述】:

SKNode A 是 SKNode B 的父节点。

如果触摸在 SKNode B 内部开始,则调用 touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) 函数。

但是,如果触摸开始于 SKNode B 之外但移动到 SKNode B,则永远不会调用 touchesMoved 函数。

一种选择是处理 SKNode A 内的所有触摸事件。

但是,SKNode A 中包含许多节点。理想情况下,我们可以将触摸功能推送到每个子节点,而不是处理来自 SKNode A 的所有内容。

是否有可能捕获发生在 SKNode B 内部的触摸事件,即使它们开始于 SKNode B 之外?

【问题讨论】:

你要覆盖 NodeB 内部的 touchesBegan 吗? @ThrowingSpoon 是的 【参考方案1】:

当您点击 touchesBegan 方法时,您的触摸将被限制在该节点的坐标系中,直到它结束为止。移动到另一个节点不会将坐标系更改为新节点。如果 B 是唯一需要触摸的节点,那么您可以添加一个子节点来覆盖整个场景以确保 B 被触发。

class TouchNode : SKSpriteNode

    //if you need to override other inits do it here
    convenience init(withSize size:CGSize)
    
       self.init(color:UIColor(red:0,green:0,blue:0,alpha:0.1),size: size)
       isUserInteractionEnabled = true

    

    override func touchesBegan(touches: Set<UITouches>, withEvent event: UIEvent?)  
        parent!.touchesBegan(touches:touches, withEvent:event)
     

    override func touchesMoved(touches: Set<UITouches>, withEvent event: UIEvent?)  
        parent!.touchesMoved(touches:touches, withEvent:event)
     

    override func touchesEnded(touches: Set<UITouches>, withEvent event: UIEvent?)  
        parent!.touchesEnded(touches:touches, withEvent:event)
     

    override func touchesCancelled(touches: Set<UITouches>, withEvent event: UIEvent?)  
        parent!.touchesCancelled(touches:touches, withEvent:event)
     


然后在你的 NodeB 类中:

required init(coder aDecoder:NSCoder)

    super.init(coder:aDecoder)
    DispatchQueue.main.async
        self.addChild(TouchNode(withSize:self.scene!.size))
    

override func touchesBegan(touches: Set<UITouches>, withEvent event: UIEvent?)  
    //do stuff
 

override func touchesMoved(touches: Set<UITouches>, withEvent event: UIEvent?)  
    //do stuff
 

override func touchesEnded(touches: Set<UITouches>, withEvent event: UIEvent?)  
    //do stuff
 

override func touchesCancelled(touches: Set<UITouches>, withEvent event: UIEvent?)  
    //do stuff
 

编辑:误读问题,但留下答案以防其他人需要从节点内部到外部。

想一想,你想在nodeB之外触摸nodeB,这没有意义。就像我在戳空气,你在哭,我在戳你。但是,如果您绝对需要超出范围,则在触摸精灵时将其添加到超出节点本身的子节点,并确保将触摸转移回父节点

class TouchNode : SKSpriteNode

    //if you need to override other inits do it here
    convenience init(withSize size:CGSize)
    
       self.init(color:UIColor(red:0,green:0,blue:0,alpha:0.1),size: size)
       isUserInteractionEnabled = true

    

    override func touchesBegan(touches: Set<UITouches>, withEvent event: UIEvent?)  
        parent!.touchesBegan(touches:touches, withEvent:event)
     

    override func touchesMoved(touches: Set<UITouches>, withEvent event: UIEvent?)  
        parent!.touchesMoved(touches:touches, withEvent:event)
     

    override func touchesEnded(touches: Set<UITouches>, withEvent event: UIEvent?)  
        parent!.touchesEnded(touches:touches, withEvent:event)
     

    override func touchesCancelled(touches: Set<UITouches>, withEvent event: UIEvent?)  
        parent!.touchesCancelled(touches:touches, withEvent:event)
     


然后在你的 NodeB 类中:

lazy var touchNode = TouchNode(withSize:self.scene!.size)

override func touchesBegan(touches: Set<UITouches>, withEvent event: UIEvent?)  
    addChild(touchNode)
    //do other stuff
 
override func touchesEnded(touches: Set<UITouches>, withEvent event: UIEvent?)  
    touchNode.removeFromParent()
    //do other stuff
 

override func touchesCancelled(touches: Set<UITouches>, withEvent event: UIEvent?)  
    touchNode.removeFromParent()
    //do other stuff
 

【讨论】:

谢谢!澄清一下,我同意你的看法,但这不是目标。 :) 目标是在节点 B 内部捕获事件。问题是如果触摸在 B 内部,如果它们在 B 外部开始 将被忽略(即,从 C 开始,然后转到 B)。 哦,我读错了问题,当然节点 B 内部的 touchesMoved 不会被调用,没有 touchesBegan 就不能使用 touchesMoved。你需要做与这个答案相反的事情,在你的 touchesmoved 上,检查你的孩子被触摸并传递信息 我需要检查,但我很确定如果您从节点内部开始并移动到外部,touchesMoved 也不会在外部调用,它仅限于节点的坐标系被触摸 如果 nodeB 是唯一需要触摸的节点,则此答案适用于修改(只需在 init 之后添加 touchNode [在初始化期间执行此操作将使场景为零] 并且永远不要删除它) 不是你的错,这意味着问题的措辞不够清楚。 :) 同意,正如问题中提到的,似乎唯一的选择是节点 A 处理所有接触并踢到节点 B。希望看看是否可以将所有内容放入节点 B 并保持节点 A 清洁(因为节点 A 需要处理很多其他的东西)。

以上是关于SpriteKit:如何检测从节点外部开始的节点上的触摸的主要内容,如果未能解决你的问题,请参考以下文章

SpriteKit如何检测节点是不是正在移动

如何使用 SpriteKit 检测节点是不是离开屏幕 [重复]

检测 SpriteKit 中节点特定区域的触摸

如何在 SpriteKit 中跟踪接触后的节点移动

SpriteKit:检测 UILongPressGestureRecognizer 是不是点击了子节点

spritekit 如何在两个不同的节点上转换两个 SKAction