检测 SKSpriteNodes 上的触摸事件
Detecting touch events on SKSpriteNodes
所以这里有一些类似的问题,但它们并没有真正回答我遇到的 questions/problem。
以下对我的项目的解释可能有帮助也可能没有帮助,我在这里添加它以防万一...
我正在尝试构建我的第一个 iOS 游戏,并且我已经使用场景编辑器构建了一个场景。该场景包含一个名为 "World" 的 SKNode。然后有一个背景节点和一个前景节点,它们是世界节点的子节点。现在场景中的所有内容,所有 SKSpriteNode,都是背景节点的子节点。
在我的 GameScene.swift 文件中,我将变量附加到背景和前景节点,以便我可以在游戏进行时将子节点添加到这些节点。
希望到目前为止这是清楚的...
现在我已将另外 5 个 *.sks 文件添加到我的项目中。这些文件包含我制作的场景,这些场景将通过我的 GameScene.swift 文件中的代码添加为前景节点的子节点。这些场景文件中的 SKSpriteNodes 被放置在前景中,但它们的 z 位置小于其中一个背景子节点的 z 位置。这是因为我想让一个盒子出现在光束后面(光束与背景分开,盒子被添加到前景)。这是一张图片,以防我造成任何混淆
我的问题是...
我想使用手势识别器点击屏幕,这样当我点击框时我就可以做一些事情。问题是,由于光束具有更大的 z 位置(导致我想要的效果),每次我使用 atPoint(_ p: CGPoint) -> SKNode 方法来确定我点击的节点时,我都会返回光梁节点而不是框节点。
如何只点击方框?我已经尝试将灯的 isUserInteractionEnabled 属性 更改为 false,并且我已经尝试使用 touchesBegan,如对类似问题的许多其他答复所示。我也试过阅读 Apple 提供的 swift 开发者文档,但我无法理解这一点。
我的手势识别器的代码如下:
//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()
}
}
希望这对你们来说足够了...如果您需要我提供更多代码,或者需要我澄清任何事情,请告诉我
请阅读代码中的注释。你可以在 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{ [=10=].name == name}
}
您想使用 nodesAtPoint
进行命中测试并获取与该点关联的所有节点。然后筛选列表以找到您要查找的框。
如果你有很多图层,你可能还想在你的图形顶部添加一个不可见的图层来处理被触摸的节点
您的另一个选择是关闭 isUserInteractionEnabled
除框以外的所有内容,然后覆盖框的触摸事件,但这意味着您不能像现在这样使用手势。
所以这里有一些类似的问题,但它们并没有真正回答我遇到的 questions/problem。
以下对我的项目的解释可能有帮助也可能没有帮助,我在这里添加它以防万一...
我正在尝试构建我的第一个 iOS 游戏,并且我已经使用场景编辑器构建了一个场景。该场景包含一个名为 "World" 的 SKNode。然后有一个背景节点和一个前景节点,它们是世界节点的子节点。现在场景中的所有内容,所有 SKSpriteNode,都是背景节点的子节点。
在我的 GameScene.swift 文件中,我将变量附加到背景和前景节点,以便我可以在游戏进行时将子节点添加到这些节点。
希望到目前为止这是清楚的...
现在我已将另外 5 个 *.sks 文件添加到我的项目中。这些文件包含我制作的场景,这些场景将通过我的 GameScene.swift 文件中的代码添加为前景节点的子节点。这些场景文件中的 SKSpriteNodes 被放置在前景中,但它们的 z 位置小于其中一个背景子节点的 z 位置。这是因为我想让一个盒子出现在光束后面(光束与背景分开,盒子被添加到前景)。这是一张图片,以防我造成任何混淆
我的问题是... 我想使用手势识别器点击屏幕,这样当我点击框时我就可以做一些事情。问题是,由于光束具有更大的 z 位置(导致我想要的效果),每次我使用 atPoint(_ p: CGPoint) -> SKNode 方法来确定我点击的节点时,我都会返回光梁节点而不是框节点。
如何只点击方框?我已经尝试将灯的 isUserInteractionEnabled 属性 更改为 false,并且我已经尝试使用 touchesBegan,如对类似问题的许多其他答复所示。我也试过阅读 Apple 提供的 swift 开发者文档,但我无法理解这一点。
我的手势识别器的代码如下:
//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()
}
}
希望这对你们来说足够了...如果您需要我提供更多代码,或者需要我澄清任何事情,请告诉我
请阅读代码中的注释。你可以在 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{ [=10=].name == name}
}
您想使用 nodesAtPoint
进行命中测试并获取与该点关联的所有节点。然后筛选列表以找到您要查找的框。
如果你有很多图层,你可能还想在你的图形顶部添加一个不可见的图层来处理被触摸的节点
您的另一个选择是关闭 isUserInteractionEnabled
除框以外的所有内容,然后覆盖框的触摸事件,但这意味着您不能像现在这样使用手势。