![](/img/trans.png)
[英]How to detect collision between SKSpriteNode and SKView SpriteKit
[英]How to detect hidden SKSpriteNode by touching them in Spritekit?
我正在使用 Spritekit 创建棋盘游戏。 最初所有的部分(SKSpriteNode)都是隐藏的。 我触摸它们后它们应该出现吗? 但是由于它们被设置为隐藏,当我覆盖 touchBegan 函数时我无法访问它们。 我该怎么办?
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let location = touches.first!.locationInNode(self)
let touchedNode = self.nodeAtPoint(location)
if(touchedNode.name == "pieces"){
if(touchedNode.hidden == true){
touchedNode.hidden = false
}
}
}
您正在尝试的是在 iOS8 上工作。 但这已在 iOS9 中得到修复。 如果您在 iOS8 上尝试您的代码,您将看到它有效。 这是在 iOS8 上让我恼火的事情之一,因为您可以点击隐藏节点是没有意义的。 不过,您可以使用 alpha 0.0 的节点(也适用于 iOS8)会很好,但这在 iOS9 中也已修复。 因此将 alpha 设置为 0.0 将不起作用。
解决方案
您可以使用 SKNode 的containsPoint方法:
返回一个布尔值,指示一个点是否位于父坐标系内。
在您的情况下,父母将是您的精灵。 在此处阅读containsPoint
方法的工作原理。 基本上, containsPoint
并不关心节点是否可见,或者它是否有父节点。 它只是检查某个点( location
)是否位于父级( touchedNode
)坐标系内。 所以这里是你如何使用这种方法来做到这一点:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let location = touches.first!.locationInNode(self)
self.enumerateChildNodesWithName("pieces") { node, stop in
if node.containsPoint(location) && node.hidden == true {
node.hidden = false
stop.memory = true
}
}
}
在这里,您正在枚举所有部分(我假设 self 是它们的父节点),如果某个节点包含触摸位置并且它是隐藏的,则使其可见(并停止进一步的、不必要的搜索)。
提示:
还可以考虑在此处使用可选绑定:
if let touch = touches.first {
let location = touch.locationInNode(self)
//do your stuff here
}
使用可选绑定是个好习惯,因为它更安全。
到目前为止,我还有另一种方法似乎有效:
//如果必须轮流,可以用黑盘重复whitedisk for循环。 我正在使用 .name 来标识选择了哪个方块
func drawBoard() {
let numRows = 8
let numCols = 8
let x = scene?.size.width
xOffset = ((x)! - ((x)! / 9) * CGFloat(numCols))
squareSize = CGSizeMake(x!/9, x!/9)
diskSize = CGSizeMake(x!/11, x!/11)
// Draw the squares
for row in 0...numRows-1 {
for col in 0...numCols-1 {
square = SKSpriteNode(texture: SKTexture(imageNamed: "square.png"), size: squareSize!)
//row and column both start with zero, may want to start with 1 later
square!.name = "square \(col)-\(row)"
square!.userInteractionEnabled = false
square!.position = CGPointMake(CGFloat(col) * squareSize!.width + xOffset, CGFloat(row) * squareSize!.height + xOffset)
self.addChild(square!)
}
}
// Draw the White disks "hidden"
for row in 0...numRows-1 {
for col in 0...numCols-1 {
let gamePiece = SKSpriteNode(texture: SKTexture(imageNamed: "whitedisk.png"), size: diskSize!)
gamePiece.name = "whitedisk \(col)-\(row)"
gamePiece.userInteractionEnabled = false
//print("Disk Name: \(gamePiece.name)")
gamePiece.position = CGPointMake(CGFloat(col) * squareSize!.width + xOffset, CGFloat(row) * squareSize!.height + xOffset)
gamePiece.hidden = true
self.addChild(gamePiece)
}
}
}
// 磁盘变量是 whitedisk 或 blackdisk 取决于轮到谁 此函数在确定选择了哪个方块后显示游戏块
func placeDisk(name: String, disk: String) {
var myName = name
let theDisk = disk
myName = myName.stringByReplacingOccurrencesOfString("square", withString: theDisk)
let node = self.childNodeWithName(myName)
//print("Display: \(myName) - Node: \(String(node))")
node?.hidden = false
}
// 我对 touchesEND 函数过度使用,但你也可以使用 touches begin
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let positionInScene = touch.locationInNode(self)
let name = self.nodeAtPoint(positionInScene).name
if name != nil {
print("Touched: \(name)")
placeDisk(name!, disk: "whitedisk")
}
}
}
这是来自苹果的文档:
使用 Alpha 处理隐藏节点上的用户交互
半透明节点——那些 alpha 小于 1 但大于 0 的节点——仍然接收用户交互。 您可以将节点的 alpha 设置为
leastNonzeroMagnitude
以使其有效透明,但仍然对触摸或鼠标移动做出响应,尽管给它一个clear 颜色具有相同的效果。
在我的棋盘游戏中,我有一个带有clearcolor
的子对象。 它没有纹理,因此它变得不可见(如果你有纹理,我猜你可以使用leastNonzeroMagnitude
)。
我有一个 .sks 文件,我在这个屏幕截图中制作了清晰的颜色:
我选择一种自定义颜色并将其不透明度设置为 0。
我确实用以下代码检测到它:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let location = touch.location(in: self)
let touchedNodes = nodes(at: location)
let frontTouchedNode = atPoint(location).name
print(touchedNodes)
print(frontTouchedNode!)
}
有关更多信息,请访问 Apple 官方文章的链接: 控制节点上的用户交互
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.