【问题标题】:Detect SpriteKit button press overlay from SceneKit从 SceneKit 检测 SpriteKit 按钮按下覆盖
【发布时间】:2019-01-05 06:06:49
【问题描述】:

我有一个简单的 HUD,它是使用 sprite kit 构建的,它是我的 3d 场景套件游戏的叠加层。我有一个可见的“主菜单”按钮,但在我的一生中,我无法检测到它被按下了。

下面是叠加层的设置方式。

    sceneView = self.view as! GameSCNView
    scene = SCNScene(named: "art.scnassets/MainScene.scn")
    sceneView.scene = scene
    sceneView.overlaySKScene = OverlayScene(size: sceneView.bounds.size)
    overlayScene = sceneView.overlaySKScene as! OverlayScene
    overlayScene.isUserInteractionEnabled = false

现在这里是正在创建的叠加场景。

class OverlayScene : SKScene {

var timeLabel:SKLabelNode!
var mainMenu:SKSpriteNode!

override init(size: CGSize) {
    super.init(size: size)

    //setup the overlay scene
    self.anchorPoint = CGPoint(x: 0.5, y: 0.5)

    //automatically resize to fill the viewport

    let widthScale = size.width / 1024
    let heightScale = size.height / 768

    self.scaleMode = .resizeFill

    // Initialize the Score
    timeLabel = SKLabelNode(text: "Time: 0")
    timeLabel.position = CGPoint(x: -size.width * 0.35, y: size.height*0.45)
    timeLabel.fontName = "AmericanTypewriter-Bold"
    timeLabel.fontSize = 36 * widthScale
    timeLabel.fontColor = UIColor.white
    addChild(timeLabel)

    mainMenu = SKSpriteNode(imageNamed: "MainMenu_ButtonHighlighted-IpadMini.png")
    mainMenu.anchorPoint = CGPoint(x: 0, y: 0)
    mainMenu.xScale = widthScale
    mainMenu.yScale = heightScale
    mainMenu.position = CGPoint(x: -size.width * 0.35, y: size.height*0.45)
    mainMenu.isUserInteractionEnabled = false
    mainMenu.zPosition = 0
    addChild(mainMenu)
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

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

        let location = touch.location(in: self)

        if mainMenu.contains(location) {
            print("Main Menu Touch Began")
        }
    }
}


override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch: AnyObject in touches {

        let location = touch.location(in: self)

        if mainMenu.contains(location) {
            print("Main Menu Touch Ended")
        }
    }
}
}

我的预期输出是看到“主菜单触摸开始”和“主菜单触摸结束”,但我什么也没得到。任何帮助将不胜感激。

【问题讨论】:

  • 如果您将isUserInteractionEnabledmainMenuOverlayScene 都更改为true,会发生什么?
  • 什么都没有,而且我还发现将其设为 false 会使按钮触发,而 true 则不会。在我看来有点违反直觉。感谢您的评论!
  • 是的,这家伙似乎也想通了:stackoverflow.com/questions/33850541/…
  • 你能看到 touchesBegan 和 touchEnded 是否被调用,只是没有进入 if 语句吗?
  • 通过将打印放在 for 语句和 if 语句之外,我没有得到任何输出。因此,在按下按钮或 SKScene 的任何其他部分时不会调用它们

标签: ios swift sprite-kit scenekit


【解决方案1】:

1) 通过在您的叠加层上将 isUserInteractionEnabled 设置为 false,您的叠加层将永远不会接收触摸事件。

2) 手动缩放时,您可以打开自己的数学题。 SpriteKit 旨在为您处理缩放,这就是 scaleMode 存在的原因。在最后的过程中扩展一次,然后不断地扩展每一件小事,这更有意义。

进行以下更改,它应该适合您。

设置

overlayScene.isUserInteractionEnabled = true

为了让您的场景能够接收触摸,

然后清理你的代码:

class OverlayScene : SKScene {

    var timeLabel:SKLabelNode!
    var mainMenu:SKSpriteNode!
    override init(size: CGSize) {
        super.init(size:size)
    }
    convenience override init() {

        self.init(size: CGSize(width:1024,height:768))

            //setup the overlay scene
            self.anchorPoint = CGPoint(x: 0.5, y: 0.5)

            //automatically resize to fill the viewport



            self.scaleMode = .fill

            // Initialize the Score
            timeLabel = SKLabelNode(text: "Time: 0")
            timeLabel.position = CGPoint(x: size.width * 0.35, y: size.height*0.45)
            timeLabel.fontName = "AmericanTypewriter-Bold"
            timeLabel.fontSize = 36
            timeLabel.fontColor = UIColor.white
            addChild(timeLabel)

            mainMenu = SKSpriteNode(imageNamed: "MainMenu_ButtonHighlighted-IpadMini.png")
            mainMenu.anchorPoint = CGPoint(x: 0, y: 0)

            mainMenu.position = CGPoint(x: size.width * 0.35, y: size.height*0.45)
            mainMenu.isUserInteractionEnabled = false
            mainMenu.zPosition = 0
            addChild(mainMenu)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

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

            let location = touch.location(in: self)

            if mainMenu == self.atPoint(location) {
                print("Main Menu Touch Began")
            }
        }
    }


    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch: AnyObject in touches {

            let location = touch.location(in: self)

            if mainMenu == self.atPoint(location) {
                print("Main Menu Touch Ended")
            }
        }
    }
}

并使用:

sceneView.overlaySKScene = OverlayScene()

【讨论】:

  • 感谢您提供了一种更加可控的方式来缩放 HUD,但这些更改并没有解决问题。我逐字复制了您的代码并在self(size: CGSize(width:1024,height:768) 上收到错误我将其替换为super.init(size: CGSize(width:1024,height:768)) 这将缩放更改为简化形式,但sceneView.overlaySKScene = OverlayScene()overlayScene.isUserInteractionEnabled = true 对触摸开始功能没有影响。不过感谢您的尝试。
  • 你为什么要改变它?这是一个方便的初始化,它需要自我而不是超级
  • 我改了是因为你的代码报错:Cannot call value of non-function type 'OverlayScene'
  • 我为你修好了
  • 我想知道你为什么使用负宽度尺寸大声笑。您需要屏幕左侧的时间 您可以使用特定的数字将其放置在您想要的任何位置。我测试了我的代码并且它可以工作,所以如果你没有进入 touchesBegan 函数,那么你还有其他事情发生。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-12
  • 2021-03-03
  • 1970-01-01
相关资源
最近更新 更多