Swift 3.0:SKSpriteNode作为Button在给定非SKView父级时不起作用?

时间:2017-01-15 16:36:41

标签: swift sprite-kit skspritenode skcameranode

关于如何在SpriteKit中创建按钮,例如Swift Spritekit Adding Button ProgramaticlySetting up buttons in SKScene,已经有一些问题。

无论哪种方式,解决方案是使public static String lengthAsString(String str) { int len = str.length(); return Integer.toString(len); } 为按钮设置纹理,然后在函数SKSpriteNode中,测试触摸是否属于按钮 - touchesEnded

然而,有趣的是,如果要让按钮成为孩子,例如SKSpriteNode或其他SKCameraNode,则此方法不再有效。

我的问题是为什么?以及如何克服这种困境。

更新

关于这里的帖子,这里有两个简单的GameScene.swift文件的备用版本。主要区别在于,在第一种情况下,SKSpriteNode不是相机的子项,而在版本2中则是。

注意:在GIF中,请注意在版本1上,单击紫色精灵(sprite2)会导致它打印"您点击了紫色精灵。",而它说" 34;蓝精灵"在第2版中。因此问题很清楚:

点击另一个SKNode的子节点注册为点击最上面的父节点,而不是实际点击的节点!

新问题:如何纠正这个问题。

附录:版本2 sprite2由于成为相机的孩子而改变了位置 - 因为它是M.W.E.它并没有影响这个演示,我选择不纠正它。

版本1

sprite2

enter image description here

版本2

class GameScene: SKScene {
    var cam: SKCameraNode!

    var sprite = SKSpriteNode(imageNamed: "sprite")
    var sprite2 = SKSpriteNode(imageNamed: "sprite2")


    override func didMove(to view: SKView) {
        backgroundColor = SKColor.white

        sprite.position = CGPoint(x: size.width/4,y: size.height/2)
        sprite2.position = CGPoint(x: size.width/4 * 3,y: size.height/2)

        sprite.anchorPoint = CGPoint(x:0.5, y:0.5)

        // Set up the camera
        cam = SKCameraNode()
        self.camera = cam
        cam.setScale(3.0)

        cam.position = CGPoint(x: size.width/4, y: 0)
        sprite.addChild(cam)



        addChild(sprite); addChild(sprite2)


    }


    func touchDown(atPoint pos : CGPoint) {

    }

    func touchMoved(toPoint pos : CGPoint) {

    }

    func touchUp(atPoint pos : CGPoint) {

    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        for t in touches { self.touchDown(atPoint: t.location(in: self)) }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        for t in touches { self.touchMoved(toPoint: t.location(in: self)) }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first
        let touchLocation = touch!.location(in: self)

        if sprite.contains(touchLocation) {
            print("You tapped the blue sprite")
        }

        if sprite2.contains(touchLocation) {
            print("You tapped the purple sprite")
        }

    }

    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        for t in touches { self.touchUp(atPoint: t.location(in: self)) }
    }


    override func update(_ currentTime: TimeInterval) {
        // Called before each frame is rendered
    }
}

enter image description here

1 个答案:

答案 0 :(得分:4)

我不认为你说的是​​真的。您可以检测来自子节点的触摸。为了演示,我只在我的一个SpriteKit项目中运行了一些测试代码,我在相机节点上检测到了触摸

var cameraNode = SKCameraNode()

然后在didMove(to:)

addChild(cameraNode)
camera = cameraNode
camera?.position = CGPoint(x: size.width/2, y: size.height/2)

使用cameraNode检测touchesEnded上的触摸:

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }

    let location = touch.location(in: cameraNode)

    print("LocationX: \(location.x), LocationY: \(location.y)")
}

这是我的打印出来的:

LocationX: -13.9129028320312, LocationY: 134.493041992188

要进一步说明,如果您添加了一个按钮作为cameraNode的子项,那么您将执行以下操作:

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }

    let location = touch.location(in: cameraNode)

    // Check if tap was within button frame (assuming your buttonNode is named button and a child of cameraNode)
    if button.frame.contains(location) {
        // Tap was within the frame of the button
        // Do whatever is necessary
    }
}

进一步修改

您的问题源自您请求触摸位置的节点。正如我在回答中提到的,您需要根据您检查精灵框架的节点来推断触摸位置。在您的修改中,您只能在self上检测到触摸,然后会为您提供相对于scene的坐标。如果要检测像摄像机节点这样的子视图上的触摸,则需要在摄像机节点内请求触摸位置。以下是我根据您添加的代码进行讨论的内容:

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }

    // This will give you touch location from the camera node 'cam' NOT 'self'
    let cameraLocation = touch.location(in: cam)

    // This will give you touch location from the scene itself
    let sceneLocation = touch.location(in: self)

    if sprite.contains(sceneLocation) {
        print("You tapped the blue sprite")
    }

    if sprite2.contains(cameraLocation) {
        print("You tapped the purple sprite")
    }

}

我刚试过这个,它对我来说很好。