在SKSpriteNode上设置TVOS的首选焦点?

时间:2016-09-26 22:22:11

标签: ios swift tvos

由于我在SpriteKit工作,我的按钮是SKSpriteNodes ...但我发现自己处于需要通过覆盖viewController在我的preferredFocusedView中设置焦点的情况。有没有办法将SKSpriteNode转发为UIView?如果是这样的话,我还没弄清楚......还有其他选择吗?

        let playButton = SKSpriteNode(imageNamed: "PlayButton")
        playButton.position = CGPoint(x: scene.size.width * 0.25, y: scene.size.height * 0.25)
        playButton.zPosition = Layer.UI.rawValue
        scene.worldNode.addChild(playButton)

override var preferredFocusedView: UIView? {
    get {
        return //playButton how? 
    }
}

1 个答案:

答案 0 :(得分:6)

现在只有tvOS 10和SpriteKit支持焦点导航,在此之前你必须使用自己的焦点系统手动完成。因此,不推荐使用首选焦点视图,因为它仅支持UIViews。您现在应该使用首选焦点环境。

您要做的第一件事就是在GameViewController中为当前呈现的SKScene设置首选焦点环境。这实际上意味着您的SKScenes将处理首选焦点而不是GameViewController。在SpriteKit游戏中,SKScenes应该使用SpriteKit API(如SKLabelNodes,SKSpriteNodes等)来处理UI,例如按钮。因此,您需要将首选焦点传递给SKScene。

class GameViewController: UIViewController {

      override func viewDidLoad() {
           super.viewDidLoad()

           // default code to present your 1st SKScene.
      }
}

#if os(tvOS)
extension GameViewController {

      /// Tell GameViewController that the currently presented SKScene should always be the preferred focus environment
      override var preferredFocusEnvironments: [UIFocusEnvironment] {
           if let scene = (view as? SKView)?.scene {
               return [scene]
           } 
           return []
      }
 }
 #endif

您的playButton应该是SKSpriteNode的子类,您将用于游戏中的所有按钮。使用枚举并给它们不同的名称/标识符,以便在按下它们时区分它们(结帐苹果示例游戏DemoBots)。

 class Button: SKSpriteNode {

      var isFocusable = true // easy way to later turn off focus for your buttons e.g. when overlaying menus etc.

      /// Can become focused
      override var canBecomeFocused: Bool {
          return isFocusable
      }

      /// Did update focus
      override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {

          if context.previouslyFocusedItem === self {
              // SKAction to reset focus animation for unfocused button
          }

          if context.nextFocusedItem === self {
               // SKAction to run focus animation for focused button
          }
      }
 }

在SKScenes中,您可以将焦点环境设置为playButton或其他UI。

例如,开始场景

class StartScene: SKScene {
   ....
}

#if os(tvOS)
extension StartScene {
      override var preferredFocusEnvironments: [UIFocusEnvironment] {
          return [playButton]
     }
}
#endif

例如GameScene(例如在需要时将焦点转移到游戏菜单)

class GameScene: SKScene {
   ....
}

#if os(tvOS)
extension GameScene {

      override var preferredFocusEnvironments: [UIFocusEnvironment] {
         if isGameMenuShowing { // add some check like this
             return [gameMenuNode]
         }
         return []
     }    
}
#endif

当你在SKScenes之间转换时,你还必须告诉你的GameViewController更新它的焦点环境(例如StartScene - > GameScene)。如果你使用SKTransitions,这一点尤为重要,我花了一些时间来解决这个问题。如果您使用SKTransitions,而不是旧的和新的场景在转换期间处于活动状态,那么GameViewController将使用旧场景首选焦点环境而不是新场景,这意味着新场景将无法正确聚焦。

每当我在场景之间转换时,我就是这样做的。您将不得不稍微延迟使用,否则将无法正常工作。

 ...
 view?.presentScene(newScene, transition: ...)

 #if os(tvOS)
    newScene.run(SKAction.wait(forDuration: 0.1)) { // wont work without delay
               newScene.view?.window?.rootViewController?.setNeedsFocusUpdate()
            newScene.view?.window?.rootViewController?.updateFocusIfNeeded()
        }
    #endif

你应该阅读这篇文章

https://medium.com/folded-plane/tvos-10-getting-started-with-spritekit-and-focus-engine-53d8ef3b34f3#.x5zty39pc

观看2016年苹果主题演讲" SpriteKit中的新功能"他们谈到它的一半。

希望这有帮助