如何从UIViewController移至SKView,反之亦然?

时间:2018-09-10 14:36:20

标签: ios swift sprite-kit skview

我的想法是在移动到游戏场景之前先显示地图几秒钟,然后游戏屏幕的层次结构如下所示:

GameViewController( UIViewController )-> EntryToGameScene( SKView )-> MapController( UIViewController )-> GamePlayGround( SKView

当我从MapController移到GamePlayGround时遇到一个问题,为了能够首先从控制器移到场景,我将控制器视图类从Storyboard更改为SKView,然后添加了以下代码⬇️。handleDelay()之后方法正在运行,游戏场景didMove()方法有效,但屏幕卡在了旧视图(MapController)上!我确定游戏场景didMove()方法有效,因为背景音乐开始播放。但是为什么屏幕没有变化?

我的代码如下:

override func viewDidLoad() {
    super.viewDidLoad()
    // Wait for three sec. then move to game scene
    self.perform(#selector(handleDelay), with: nil, afterDelay: 3.0)
}

@objc fileprivate func handleDelay() {

    view.layoutIfNeeded()

    if let view = self.view as! SKView? {
        // Load the SKScene
        let scene = GameScene(size: sceneSize)

        // Set the scale mode
        scene.scaleMode = .aspectFill
        scene.delegate = self
        // Present the scene
        view.presentScene(scene)

        view.ignoresSiblingOrder = true
        view.showsFPS = false
        view.showsNodeCount = false
        view.showsPhysics = false
    }
}

所有答案都可以接受。

2 个答案:

答案 0 :(得分:2)

从视图中删除所有子视图然后显示SKScene的解决方案。

注意:我知道它不是最好的解决方案,但目前没有其他选择,所以我像这样更改了代码:

override func viewDidLoad() {
    super.viewDidLoad()

    self.perform(#selector(handleDelay), with: nil, afterDelay: 3.0)

}

@objc fileprivate func handleDelay() {

    self.view.subviews.forEach {$0.removeFromSuperview()}

    if let view = self.view as! SKView? {
        // Load the SKScene from 'GameScene.swift' and should set it's size
        let scene = SecondGameScene(size: self.view.frame.size)
        // Set the scale mode to scale to fit the window
        scene.scaleMode = .aspectFill

        // Present the scene
        view.presentScene(scene)

        view.ignoresSiblingOrder = true

        view.showsFPS = false
        view.showsNodeCount = false
    }

}

更新: 最终,我找到了从SKScene和UIView Controller迁移的正确方法,反之亦然。

例如(从 SKScene 移至 UIViewController ):

fileprivate func moveToUIViewController(storyBoardId: String) {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let vc = storyboard.instantiateViewController(withIdentifier: storyBoardId)
    vc.view.frame = self.frame
    vc.view.layoutIfNeeded()        

    self.view?.window?.rootViewController?.present(vc, animated: true, completion: nil)
}

(从 UIViewController 移至 SKScene ):

fileprivate func returnToSKScene() {

    for element in self.view.subviews {
        element.removeFromSuperview()
    }
    self.dismiss(animated: true) {
        if let view = self.view as! SKView? {
            // Load the SKScene
            var scene: SKScene
            scene = AboutScene(size: sceneSize)

            // Set the scale mode
            scene.scaleMode = .aspectFill
            let transition = SKTransition.moveIn(with: .up, duration: 0.2)

            // Present the scene
            view.presentScene(scene, transition: transition)

            view.ignoresSiblingOrder = true
            view.showsFPS = false
            view.showsNodeCount = false
            view.showsPhysics = false

        }
    }
}

别忘了用“ SKView”更改UIViewController view 类:

  1. 从情节提要->身份检查器->自定义类中选择视图。

  2. 2。从“类”下拉列表中选择 SKView

答案 1 :(得分:0)

轻松修复。我将代码复制并粘贴到测试项目中,然后弄清楚您做错了什么。您没有引用要呈现的场景。您没有传递要显示的特定SKView。您正在呈现一个通用的SKView类。

此代码:

override func viewDidLoad() {
    super.viewDidLoad()
    // Wait for three sec. then move to game scene
    self.perform(#selector(handleDelay), with: nil, afterDelay: 3.0)
}

@objc fileprivate func handleDelay() {

    view.layoutIfNeeded()

    if let view = self.view as! SKView? {
        // Load the SKScene
        let scene = GameScene(size: sceneSize)

        // Set the scale mode
        scene.scaleMode = .aspectFill
        scene.delegate = self
        // Present the scene
        view.presentScene(scene)

        view.ignoresSiblingOrder = true
        view.showsFPS = false
        view.showsNodeCount = false
        view.showsPhysics = false
    }
}

应如下所示:

override func viewDidLoad() {
    super.viewDidLoad()
    // Wait for three sec. then move to game scene
    self.perform(#selector(handleDelay), with: nil, afterDelay: 3.0)
}

@objc fileprivate func handleDelay() {

    view.layoutIfNeeded()

    // Load the view as an SKView to prepare for an SKScene
    if let view = self.view as! SKView? {
        // Load the SKScene from the GameScene file
        let scene = GameScene()
        // Set the scale mode to scale to fit the window
        scene.scaleMode = .aspectFill

        // Present the scene
        view.presentScene(scene)

        view.ignoresSiblingOrder = true

        view.showsFPS = true
        view.showsNodeCount = true
    }
}

经过测试,可以正常工作。