2016-09-26 59 views
2

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

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

回答

4

焦点导航只是现在支持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的子类,您将用于您游戏中的所有按钮。使用枚举并给它们不同的名称/标识符以在它们被按下时区分它们(结账Apples示例游戏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或其他用户界面。

如开始场景

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 

您还必须告诉你GameViewController当你之间转换,以更新其重点环境SKScenes(例如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”这里只讲了一半的方式通过。

希望这会有所帮助

+0

哇,谢谢你这么彻底的答复! – GarySabo

+0

不客气。我最近刚刚处理了这一切。再看看我的答案,我做了一些调整,避免你错过了一些东西。 – crashoverride777

+0

在我的游戏场景中添加了代码我得到了“Objective-C选择器'preferredFocuseEnvironments'的Getter'preferredFocuseEnvironments'与'getFocusEnvironments'的超类'SKNode具有相同Objective-C选择器的getter冲突 – GarySabo