Как перейти от UIViewController к SKView и наоборот? - PullRequest
0 голосов
/ 10 сентября 2018

Моя идея - показать карту за несколько секунд до перехода на игровую сцену, и иерархия игровых экранов выглядит следующим образом:

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

Я сталкиваюсь с проблемой при переходе от MapController к GamePlayGround, чтобы иметь возможность сначала перейти от контроллера к сцене. Я изменил класс представления контроллеров на SKView из Storyboard, затем добавил следующий код ⬇️. После того, как метод 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 голосов
/ 11 сентября 2018

Решение с удалением всех подпредставлений из представления и последующим представлением 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

        }
    }
}

Не забудьте изменить UIViewController view class с "SKView":

  1. Выберите вид из Раскадровки -> Инспектор идентификации -> Пользовательский класс.

  2. 2.Выберите SKView из раскрывающегося списка Класс.

0 голосов
/ 10 сентября 2018

Легко исправить. Я скопировал и вставил код в тестовый проект и выяснил, что вы сделали неправильно. Вы не ссылаетесь на сцену, которая будет представлена. Вы не передаете конкретный 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
    }
}

Проверено и работает.

...