由于我在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?
}
}
答案 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
你应该阅读这篇文章
观看2016年苹果主题演讲" SpriteKit中的新功能"他们谈到它的一半。
希望这有帮助