检测 SKSpriteNodes 上的触摸事件

Posted

技术标签:

【中文标题】检测 SKSpriteNodes 上的触摸事件【英文标题】:Detecting touch events on SKSpriteNodes 【发布时间】:2018-09-24 00:08:57 【问题描述】:

所以这里有一些类似的问题,但他们并没有真正回答我遇到的问题。

以下对我的项目的解释可能有帮助,也可能没有帮助,我在这里添加以防万一......

我正在尝试构建我的第一个 ios 游戏,并且我已经使用场景编辑器构建了一个场景。该场景包含一个名为“World”的 SKNode。然后有一个 backgroundNode 和一个foregroundNode,它们是世界节点的子节点。现在场景中的所有东西,所有 SKSpriteNode,都是 backgroundNode 的子节点。

在我的 GameScene.swift 文件中,我将变量附加到背景和前景节点,以便我可以在游戏进行时将子节点添加到这些节点。

希望到目前为止这很清楚......

现在我在我的项目中添加了 5 个其他 *.sks 文件。这些文件包含我制作的场景,这些场景将通过我的 GameScene.swift 文件中的代码添加为前景节点的子节点。这些场景文件中的 SKSpriteNodes 放置在前景中,但它们的 z 位置小于背景子节点之一的 z 位置。这是因为我想让一个盒子出现在光束后面(光束是背景的一部分,盒子被添加到前景中)。这是一张图片,以防我引起任何混乱

我的问题是... 我想使用手势识别器点击屏幕,这样当我点击框时我可以做一些事情。麻烦的是,由于光束具有更大的 z 位置(导致我想要的效果),每次我使用 atPoint(_ p: CGPoint) -> SKNode 方法来确定我点击的节点时,我都会返回光梁节点而不是盒子节点。

如何只点按该框?我已经尝试将灯的 isUserInteractionEnabled 属性更改为 false,并且我尝试使用 touchesBegan,如对类似问题的许多其他回复所示。我也尝试过阅读 Apple 提供的 swift developer 文档,但我无法弄清楚。

我的手势识别器的代码如下:

 //variables for gesture recognition
let tapGesture = UITapGestureRecognizer()
let swipeUpGesture = UISwipeGestureRecognizer()

//set up the tap gesture recognizer
tapGesture.addTarget(self, action: #selector(GameScene.tappedBox(_:)))
self.view!.addGestureRecognizer(tapGesture)
tapGesture.numberOfTapsRequired = 1
tapGesture.numberOfTouchesRequired = 1

//handles the tap event on the screen
@objc func tappedBox(_ recognizer: UITapGestureRecognizer) 

    //gets the location of the touch
    let touchLocation = recognizer.location(in: recognizer.view)
    if TESTING_TAP 
        print("The touched location is: \(touchLocation)")
    

    //enumerates through the scenes children to see if the box I am trying to tap on can be detected (It can be detected using this just don't know how to actually detect it by tapping on the box)
    enumerateChildNodes(withName: "//Box1", using:  node, _ in
        print("We have found a single box node")
    )

    //tells me what node is returned at the tapped location
    let touchedNode = atPoint(touchLocation)
    print("The node touched was: \(String(describing: touchedNode.name))")

    //chooses which animation to run based on the game and player states
    if gameState == .waitingForTap && playerState == .idle
        startRunning()              //starts the running animation
        unPauseAnimation()
    else if gameState == .waitingForTap && playerState == .running 
        standStill()                //makes the player stand still
        unPauseAnimation()
    

希望这对你们来说已经足够了......如果您需要我提供更多代码,或者需要我澄清任何事情,请告诉我

【问题讨论】:

使用 UITouch 识别精灵。 【参考方案1】:

请阅读代码中的注释。你可以在 spriteKit 中轻松获得你想要的东西。希望你能得到答案。

     @objc func tappedBox(_ recognizer: UITapGestureRecognizer) 

     let touchLocation = recognizer.location(in: recognizer.view)

  // Before you check the position, you need to convert the location from view to Scene. That's the right location.
     let point =  (recognizer.view as! SKView).convert(touchLocation, to: self)

      print ( getNodesatPoint(point, withName: "whatever Node name"  ) )
   

 // 2 : This function  gives you all nodes with the name you assign. If you node has a unique name, you got it.
 ///     You can change name to other properties and find out.

     private func   getNodesatPoint(_ point : CGPoint , withName name: String) -> [SKNode] 
           return self.nodes(at: point).filter $0.name == name
   

【讨论】:

【参考方案2】:

您想使用nodesAtPoint 进行命中测试并获取与该点关联的所有节点。然后过滤列表以找到您要查找的框。

如果您有很多图层,您可能还想在图形顶部添加一个不可见的图层来处理被触摸的节点

您的另一个选择是关闭除框以外的所有内容上的isUserInteractionEnabled,然后覆盖框的触摸事件,但这意味着您不能像现在这样使用手势。

【讨论】:

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

如何检测不同图像部分上的不同触摸事件

在 Monotouch 中的 UIPageViewController 中检测控件上的触摸事件

带有子节点的 CCNode 上的 Cocos2d-iphone v3 触摸事件检测

如何在android中检测禁用复选框上的触摸事件

jquery mobile - 在滑动事件上检测触摸数组

在带有触摸屏的 Windows 8 上检测 Chrome 中的触摸事件