2017-10-03 11 views
2

の全体の進行状況を保存する私はスウィフト、SpriteKitベース:どのシーン

import UIKit 
import SpriteKit 

class GameViewController: UIViewController { 


override func viewDidLoad() { 
    super.viewDidLoad() 


    if let scene = GameScene(fileNamed:"GameScene") { 
     // Configure the view. 
     let skView = self.view as! SKView 

     /* Set the scale mode to scale to fit the window */ 


     scene.scaleMode = .AspectFill 

     skView.presentScene(scene) 
     } 
    } 
} 

「GameViewController.swift」と迅速なゲームを構築していると私は「GameScene」と呼ばれるシーンがあります(これはデフォルトですスウィフトを開いて新しいスウィフトゲームを作成するときのゲームファイル)

import UIKit 
import SpriteKit 

class GameScene: SKScene{ 

var building = SKSpriteNode() 

override func didMoveToView(view: SKView) { 

    /* Setup your scene here */ 

} 

多くのことが起こっています。 (建物を置くことができ、いくつかの行動をトリガするなど)
しかし、あなたは、アプリケーションを終了するとすべての進捗状況が失われます。
この「GameScene」の進行状況をすべて保存して、最初に再読み込みするにはどうすればよいですか?

+0

クラスまたは構造体を使用してモデルを作成します。 –

答えて

2

SKSceneはNSCodingに準拠しているため、これを使用してシーンをアーカイブすることができます。ここで役立つチュートリアルがあります。 https://www.hackingwithswift.com/read/12/3/fixing-project-10-nscoding

基本的な考え方は、あなたのシーンのインスタンスを取り、そしてあなたがそれをアーカイブです:

NSKeyedArchiver.archivedData(withRootObject: scene)

その後、その後のことができます。これを取るし、それをディスクに保存したり、どこか別の場所

NSKeyedUnarchiver.unarchiveObject(with: scene) as! SKScene

と、後でそれを、アーカイブさカスタム・シーン・クラスを作成する場合は、作成する変数を必ず保存して、保存する必要があります。これは、人々が使用しない傾向がある厄介なイニシャライザが入ってくるところです。

基本的に、この初期化子を使用してカスタム変数をデコードします。

required init(coder aDecoder: NSCoder) { 
    player = aDecoder.decodeObject(forKey: "player") as! String 
} 

アーカイブに保存するには、(私が見つけたのチュートリアルに基づいて)シーンを保存するという目標を達成しようとするエンコード方法ここ

func encode(with aCoder: NSCoder) { 
    aCoder.encode(player, forKey: "player") 
} 
+0

あなたの答えをありがとう。これはこれを解決する方法の良い説明ですが、残念ながら私はこの作業を行うには十分な知能ではありませんが、私はこれを解決しようとします。 – frankibanki

0

をされて追加しますが、そのありませんワーキング。 ViewController.swiftため

import UIKit 
import SpriteKit 
class ViewController: UIViewController { 

override func viewDidLoad() { 
    super.viewDidLoad() 

    let skView = SKView(frame: view.frame) 

    var scene: MainScene? 

    if let savedSceneData =  NSUserDefaults.standardUserDefaults().objectForKey("currentScene") as? NSData, 
     let savedScene = NSKeyedUnarchiver.unarchiveObjectWithData(savedSceneData) as? MainScene { 
     print("loaded") 
     scene = savedScene 

     } 
     else if let url = NSBundle.mainBundle().URLForResource("MainScene", withExtension: "sks"), 
     let newSceneData = NSData(contentsOfURL: url), 
     let newScene = NSKeyedUnarchiver.unarchiveObjectWithData(newSceneData) as? MainScene { 
     print("saved") 
     scene = newScene 
     } 

    skView.presentScene(scene) 
    view.insertSubview(skView, atIndex: 0) 


} 




} 

とMainScene.Swift中:私はそれを構築する際

import UIKit 
import SpriteKit 
class MainScene: SKScene { 
var saved = false 


required init?(coder aDecoder: NSCoder) { 
    super.init(coder: aDecoder) 

    aDecoder.decodeBoolForKey("savingKey") 

} 

override func encodeWithCoder(aCoder: NSCoder) { 
    super.encodeWithCoder(aCoder) 


    aCoder.encodeBool(saved, forKey: "savingKey") 
} 

func saveScene() { 
    let sceneData = NSKeyedArchiver.archivedDataWithRootObject(self) 
    NSUserDefaults.standardUserDefaults().setObject(sceneData, forKey: "currentScene") 
} 


override func didMoveToView(view: SKView) { 
    super.didMoveToView(view) 

    size = view.frame.size 


} 




} 

は今、私は灰色の画面を取得します。それは何もロードしないか保存しません。 (チュートリアルと同じバージョンのSwiftと同じコピー/ペーストでも)

+0

あなたは 'saveScene'を呼び出しませんでした。通常、保存は 'ApplicationDidEnterBackground'で行います.'ApplicationDidEnterBackground'は' NotificationCenter'で購読できます。 –

1

applicationDidEnterBackground(_:)イベントでゲームの状態をアーカイブできます。通知を受けるにはNotificationCenterから登録してください。

class GameScene : SKScene { 
    required init?(coder decoder: NSCoder) { 
     super.init(coder: decoder) 

     NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterBackground), name: .UIApplicationDidEnterBackground, object: nil) 
    } 

    func applicationDidEnterBackground() { 
     // Save Scene 
     let sceneData = NSKeyedArchiver.archivedData(withRootObject: self) 
     UserDefaults.standard.set(sceneData, forKey: "currentScene") 
    } 

    class func loadScene() -> SKScene? { 
     var scene: GameScene? 

     if let savedSceneData = UserDefaults.standard.object(forKey: "currentScene") as? NSData, 
      let savedScene = NSKeyedUnarchiver.unarchiveObject(with: savedSceneData as Data) as? GameScene { 
      scene = savedScene 
     } else { 
      scene = nil 
     } 

     return scene 
    } 
} 

シーンのロードは最初以前にアーカイブのシーンを見つけるためにしようとか、何のアーカイブされたシーンが存在しない場合は、新しいシーンを作成することによって、viewDidLoadで起こります。

class GameViewController: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     if let view = self.view as! SKView? { 
      guard let scene = GameScene.loadScene() ?? SKScene(fileNamed: "GameScene") as? GameScene else { 
       fatalError("Scene not loaded") 
      } 

      scene.scaleMode = .resizeFill 

      view.presentScene(scene)    
      view.ignoresSiblingOrder = true 
     } 
    } 
} 

また、ゲームの要素NSCodingに準拠する必要があります(他の回答に記載されています)。

関連する問題