How to detect hidden SKSpriteNode by touching them in Spritekit?

时间:2016-04-12 00:33:04

标签: ios swift sprite-kit

I'm creating a board game using Spritekit. Initially all the pieces (SKSpriteNode) are hidden. They are supposed to appear after I touch them? But since they are set hidden, I can't access them when I override the touchBegan function. What am I supposed to do?

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
        }
    }
}

3 个答案:

答案 0 :(得分:2)

您正在尝试使用的是iOS8。但这已在iOS9中修复。如果您在iOS8上试用代码,您会看到它的工作原理。这是让我在iOS8上烦恼的事情之一,因为你可以点击一个隐藏的节点是没有意义的。尽管如此,你可以点击一个带有alpha 0.0的节点(也可以在iOS8上运行),但这在iOS9中也已经修复。因此将alpha设置为0.0将无效。

解决方案

您可以使用SKNode的containsPoint方法:

  

返回一个布尔值,指示一个点是否位于   父母的坐标系。

您案例中的父母将是您的精灵。阅读here 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是他们的父级),如果某个节点包含触摸位置加上它是隐藏的,那么让它可见(并停止进一步的,不必要的搜索)。 / p>

<强>提示:

此外,请考虑使用可选绑定:

if let touch = touches.first {

    let location = touch.locationInNode(self)

    //do your stuff here
}

使用可选绑定是个好习惯,因为它更安全。

答案 1 :(得分:0)

到目前为止,我有另一种似乎有效的方法:

//如果你必须轮流,你可以用黑色磁盘重复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函数,但你也可以使用触摸

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")
            }
        }
    }

答案 2 :(得分:0)

这是来自苹果的文档:

<块引用>

使用 Alpha 处理隐藏节点上的用户交互

半透明节点——那些 alpha 小于 1 但大于 0 的节点——仍然接收用户交互。您可以将节点的 alpha 设置为 import 'package:flutter/material.dart'; typedef CustomCallBack = Widget Function(String name); class CustomWidget extends StatefulWidget { final CustomCallBack myWidget; CustomWidget({this.myWidget}); @override _CustomWidgetState createState() => _CustomWidgetState(); } class _CustomWidgetState extends State<CustomWidget> { @override Widget build(BuildContext context) { return Container( child: widget.myWidget( 'ASAD'), //I'm able to access the constructor here but now I get an error. ); } } class Profile extends StatefulWidget { final String name; Profile({this.name}); @override _ProfileState createState() => _ProfileState(); } class _ProfileState extends State<Profile> { @override Widget build(BuildContext context) { return Center( child: Text('${widget.name}'), ); } } class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( body: CustomWidget( myWidget: (name) => Profile( name: name, ), ) //I don't want to pass the argument here ); } } 以使其有效透明,但仍然可以响应触摸或鼠标移动,尽管给它一个透明色具有相同的效果。

在我的棋盘游戏中,我有一个带有 leastNonzeroMagnitude 的子对象。它没有纹理,因此它变得不可见(如果你的有纹理,你可以使用 clearcolor 我猜)。

我有一个 .sks 文件,我在这个屏幕截图中制作了清晰的颜色:

clear color

我选择了一种自定义颜色并将其不透明度设置为 0。

我确实用这个代码检测到它:

leastNonzeroMagnitude

有关更多信息,请访问 Apple 官方文章的链接:Controlling User Interaction on Nodes