`SKScene.nodes()`为触摸位置提供了太多节点

时间:2017-01-21 04:44:41

标签: swift sprite-kit

我正在尝试将节点放在触摸位置,但遇到.nodes()返回父节点和同一“位置的其他节点的问题。

我尝试了十几种不同的代码配置,但似乎无法找到使用SKScene.convert()SKScene.convertPoint()和其他人的正确顺序....

基本上,我有一个垂直节点的分层树...顶部是父节点,下面每个节点都是直接在顶部的子节点...(见下图)

问题:

当我点击最底部节点时,我在我的场景中运行.nodes()获得了多次点击...我正在尝试仅在我点击的确切位置获取节点...当我点击某个地方我不希望父节点或其他节点在同一个“位置”或相同的“.position”打印...我只是试图获得我触摸的确切位置的节点... < / p>

以下是我正在使用的图片...当您点击/点按屏幕时,它会打印出哪些节点位于触摸位置:

enter image description here

这是我的点击代码(请记住,每个节点都是从上到下的父/子,而SKNode.name只是一个数字作为标识符):

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
  let allNodes = nodes(at: touches.first!.location(in: self))
  for node in allNodes { print( node.name! ) }
}

我已经尝试了十几种不同的方式将触摸点转换为UIViewSKNode坐标等等。我无法正确...这是我点击时的输出右下角的节点:

(同样,数字只是创建顺序中节点的名称......):

  

8
  7
  5
  4
  2
  1

当我点击右下方的节点时,应该只打印1-2个节点,而是我打印了6个节点......这是因为他们.postion是“相同的”我相信SK的混乱坐标系统有时= /

解决方法:

所以,我的解决方法是创建一个基于Y值工作的过滤器...换句话说,只有我点击的一般区域周围的节点才会被打印...但是我的操作已经很密集了,所以我试图不必为这个列表创建一个过滤器......

我真的认为有一种方法可以在我点击的地方获取节点

但是我无法找到.nodes().location(in:)的正确组合来做到这一点。

我尝试过玩.atPoint并使用.position,但没有运气......

我现在迷路了,不想创建一个文件管理器:{

1 个答案:

答案 0 :(得分:3)

如果我在您的项目中了解您的节点,每个节点都有不同的父节点。当您点击屏幕时,您触摸了一个特定的点,但在当前场景中检测到这一点&#39; self&#39; (你所在的班级touchesBegan)所以当你触摸关系父母/孩子中最深的节点时,触摸的节点也会显示他的父母。

但是你只想要触点可见区域中涉及的节点/节点,所以我认为你在这种情况下可以做的是获取转换到当前类(self)的每个节点的帧并检查触点是否包含在此框架中。

在下面的这个例子中,我使用了4个节点:

import SpriteKit
class GameScene: SKScene {
    var node5:SKSpriteNode!
    var node6:SKSpriteNode!
    var node7:SKSpriteNode!
    var node8:SKSpriteNode!
    override func didMove(to view: SKView) {
        let startPos = CGPoint(x:self.frame.midX,y:self.frame.midY)
        node5 = SKSpriteNode.init(color: .yellow, size: CGSize(width:50,height:60))
        self.addChild(node5)
        node5.name = "5"
        node5.position = CGPoint(x:startPos.x+35,y:startPos.y-180)
        node6 = SKSpriteNode.init(color: .blue, size: CGSize(width:50,height:60))
        node5.addChild(node6)
        node6.name = "6"
        node6.position = CGPoint(x:60,y:0)
        node7 = SKSpriteNode.init(color: .green, size: CGSize(width:80,height:60))
        node6.addChild(node7)
        node7.name = "7"
        node7.position = CGPoint(x:60,y:10)
        node8 = SKSpriteNode.init(color: .red, size: CGSize(width:80,height:60))
        node7.addChild(node8)
        node8.name = "8"
        node8.position = CGPoint(x:-10,y:20)
    }
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first
        let positionInScene = touch!.location(in: self)
        let allNodes = nodes(at: positionInScene)
        for node in allNodes {
            let nodePositionConverted = self.convert(node.position, from: node)
            let nodeFrameConverted = CGRect(origin: CGPoint(x:nodePositionConverted.x-node.frame.maxX,y:nodePositionConverted.y-node.frame.maxY),size:node.frame.size)
            if nodeFrameConverted.contains(positionInScene), let n = node.name {print(n)}
        }
    }
}

<强>输出

此输出显示不同的水龙头。第一次点击涉及3个节点,红色8,绿色7和蓝色6.确实你需要调试控制台:

enter image description here

第二次点击只涉及绿色7和蓝色6:

enter image description here

第三和第四次点击仅涉及蓝色和黄色节点,因此您只分别触及每个节点的数量。

最后一次点击涉及红色8和蓝色6,所以你有:

enter image description here

希望这对你的触摸有所帮助。

enter image description here