一尘不染

Swift:如何为我的游戏处理视图控制器

swift

我在开发基于SpriteKit的游戏时对视图控制器以及如何以一种干净的方式处理它们有一个一般性的问题。

我到目前为止所做的:

  • 仅将情节提要板用于定义视图控制器
  • SKScene在presentScene的每个视图控制器(Home,LevelSelection,Game)中都有显示
  • 在每个视图控制器中,我使用在视图控制器之间的情节 提要中 定义的标识符调用 performSegueWithIdentifier
  • 我在SKScene上使用SKSpritenode等以编程方式显示的所有内容
  • 在情节提要上,我仅具有定义了segue关系和标识符的视图控制器
  • 我在viewDidDisappear中所做的所有事情是因为这似乎是正确初始化我的SKScene的唯一方法

我的问题是:

  • 每当我选择另一个视图时,我的内存就会增加,因为视图控制器被重新初始化,所以旧的视图控制器一直停留在堆栈中
  • 我不清楚如何处理视图控制器之间的顺序,在某些教程页面上,我看到人们在使用导航控制器,其他人则在使用某些视图控制器的强大引用,并对视图控制器使用单例模式来决定初始化视图控制器或只显示它
  • 我的视图控制器没有取消初始化,我知道我的主视图无法启动,因为它是初始视图,但是由于ios无论如何都在重新初始化它,为什么不卸载它呢?

使用SpriteKit处理视图控制器的基于Swift的游戏的正确方法是什么?在下面,您可以看到我的初始视图控制器(主页),其中显示了一个带有简单播放按钮的SKScene,该按钮调用play()函数以选择关卡选择

import UIKit
import SpriteKit

class Home : UIViewController {
    private var scene : HomeScene!

    override func viewDidLoad() {
        print(self)
        super.viewDidLoad()
        self.scene = HomeScene(size: view.bounds.size)
        self.scene.scaleMode = .ResizeFill
        let skView = view as! SKView
        skView.showsFPS = true
        skView.showsNodeCount = true
        skView.ignoresSiblingOrder = true

        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(play), name: Constants.Events.Home.play, object: nil)

        skView.presentScene(self.scene)
    }

    override func viewDidDisappear(animated: Bool) {
        super.viewDidDisappear(animated)
        let v = view as! SKView
        self.scene.dispose()
        v.presentScene(nil)
        NSNotificationCenter.defaultCenter().removeObserver(self)
        self.scene = nil
        self.view = nil
        print("home did disappear")
    }

    func play() {
        self.performSegueWithIdentifier("home_to_levelselection", sender: nil)
    }

    deinit {
        print("Home_VC deinit")
    }
}

阅读 286

收藏
2020-07-07

共1个答案

一尘不染

要呈现3个场景,您的方法似乎非常复杂。它不是您应该为SpriteKit游戏做的,实际上只需要1个视图控制器(GameViewController)。

从GameViewController(例如HomeScene)加载您的第一个场景,仅此而已。直接在HomeScene中创建playButton和其他UI。将SpriteKit
API用于您的UI(SKLabelNodes,SKNodes,SKSpriteNodes等)。

您绝对不应在SpriteKit中真正使用UIKit(UIButtons,UILabels)。对此有一些例外,例如可能将UICollectionViews用于大量级别的选择菜单,但基本的UI应该使用SpriteKit
API完成。

Google上有很多教程,介绍如何创建Sprite
Kit按钮,如何使用SKLabelNodes等。Xcode具有SpriteKit级别编辑器,因此您可以在视觉上完成类似于故事板的所有操作。

从HomeScene过渡到LevelSelect场景,再到GameScene,反之亦然。它超级容易做到。

/// Home Scene
class HomeScene: SKScene {

  ...

   func loadLevelSelectScene() {

       // Way 1
       // code only, no XCode/SpriteKit visual level editor used
       let scene = LevelSelectScene(size: self.size) // same size as current scene

       // Way 2
       // with xCode/SpriteKit visual level editor
       // fileNamed is the LevelSelectScene.sks you need to create that goes with your LevelSelectScene class. 
       guard let scene = LevelSelectScene(fileNamed: "LevelSelectScene") else { return }


       let transition = SKTransition.SomeTransitionYouLike
       view?.presentScene(scene, withTransition: transition)
    }  
}

/// Level Select Scene
class LevelSelectScene: SKScene {
   ....

     func loadGameScene() {

        // Way 1
        // code only, no XCode/SpriteKit visual level editor used
        let scene = GameScene(size: self.size) // same size as current scene

        // Way 2
        // with xCode/SpriteKit visual level editor
        // fileNamed is the GameScene.sks you need to create that goes with your GameScene class. 
        guard let scene = GameScene(fileNamed: "GameScene") else { return }


       let transition = SKTransition.SomeTransitionYouLike
       view?.presentScene(scene, withTransition: transition)
    } 
}

/// Game Scene
class GameScene: SKScene {
   ....
}

我强烈建议您使用情节提要和ViewController方法,并仅使用不同的SKScenes和1个GameViewController。

希望这可以帮助

2020-07-07