2017-10-03 6 views
2

ich ein schnelles Spiel mit einem „GameViewController.swift“Swift, SpriteKit: wie der ganzen Fortschritt einer Szene

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) 
     } 
    } 
} 

und ich habe eine Szene „GameScene“ genannt bauen speichern (es ist die Standardeinstellung Spiel-Datei, wenn Sie schnell öffnen und erstellen Sie ein neues schnelles Spiel)

eine Menge Dinge, die dort vor sich gehen. (Gebäude können platziert werden und das löst einige Aktionen aus und so weiter)
Aber alle Fortschritte gehen verloren, wenn Sie die App verlassen.
Wie kann man den gesamten Fortschritt dieser "GameScene" speichern und zu Beginn neu laden?

+0

Erstellen Sie ein Modell mit einer Klasse oder Struktur. –

Antwort

2

SKScene entspricht NSCoding, Sie können damit Ihre Szene archivieren. Hier ist ein Tutorial, das Ihnen helfen kann. https://www.hackingwithswift.com/read/12/3/fixing-project-10-nscoding

Die Grundidee ist, nehmen Sie die Instanz der Szene, und Sie archivieren mit:

NSKeyedArchiver.archivedData(withRootObject: scene)

Dann nehmen Sie diese und auf der Festplatte speichern oder woanders

Sie können dann dearchivieren es später mit

NSKeyedUnarchiver.unarchiveObject(with: scene) as! SKScene

Nun, wenn Wenn Sie eine benutzerdefinierte Szenenklasse erstellen, müssen Sie sicherstellen, dass alle von Ihnen erstellten Variablen, die Sie speichern möchten, einbezogen werden. Dies ist, wo dieser lästige required init(coder aDecoder:NSCoder) Initialisierer kommt, dass Menschen dazu neigen, nicht zu verwenden.

Sie verwenden diesen Initialisierer im Grunde, um Ihre benutzerdefinierten Variablen wie diese zu dekodieren.

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

Um es in das Archiv zu speichern, erhalten Sie eine Kodierungsverfahren

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

Vielen Dank für Ihre Antwort. Dies ist eine gute Erklärung für einen Weg, dies zu lösen, aber leider bin ich nicht intelligent genug, um dies zu tun, aber ich werde weiter versuchen, dies zu lösen. – frankibanki

0

hier einen Versuch fügen Sie das Ziel, das Speichern einer Szene zu erreichen (basierend auf einem tutorial i), aber es ist nicht Arbeiten.

für die 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) 


} 




} 

und in der MainScene.Swift: Jetzt

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 


} 




} 

, wenn ich es bauen, bekomme ich nur einen grauen Bildschirm. Es scheint, dass es nichts lädt oder speichert. (Auch mit der gleichen Kopie/Paste aus dem Tutorial und der gleichen Version von Swift)

+0

Sie haben 'saveScene' nicht aufgerufen. Normalerweise sollte das Speichern in 'applicationDidEnterBackground' erfolgen, das Sie über 'NotificationCenter' abonnieren können. –

1

Sie können Ihren Spielstatus im applicationDidEnterBackground(_:) Ereignis archivieren. Melden Sie sich unter NotificationCenter an, um benachrichtigt zu werden.

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 
    } 
} 

Szene Laden geschieht in viewDidLoad, indem zuerst eine zuvor archivierten Szene zu lokalisieren versucht, oder eine neue Szene zu schaffen, wenn keine archivierten Szene existiert.

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 
     } 
    } 
} 

Sie brauchen auch Spielelemente NSCoding konform zu machen, wie in anderen Antworten erwähnt.

Verwandte Themen