saving the current level the user leaves off at
You don't need to use encoding and decoding here. You can just save the name of the current scene in the user defaults. You don't even need the notification center. Just save the name of the scene in the user defaults like this:
class GameScene:SKScene {
let defaults = UserDefaults.standard
override func didMove(to view: SKView) {
defaults.set(currentLevel, forKey: "continuePoint")
}
}
Now in your GameViewController class check if there is a saved continuePoint. If this is the case, load the scene. If this is not the case, load your initial level:
class GameViewController: UIViewController{
let defaults = UserDefaults.standard
override func viewDidLoad(){
super.viewDidLoad()
//Switch this with the name of your first level.
var initialLevel = "initialLevelName"
if defaults.object(forKey: "continuePoint") != nil{
initialLevel = defaults.string(forKey: "continuePoint")!
}
if let view = self.view as! SKView? {
if let scene = GameScene(fileNamed: initialLevel) {
scene.scaleMode = .aspectFill
scene.currentLevel = initialLevel
view.presentScene(scene)
}
}
}
}
Unfortunately I can't test this at the moment, but something like this will definitely work, I use this in my game too.
EDIT:
I looked at your project and I see that you change your level in your mainMenu.swift to your firstLevel everytime. You can do something like this in your touchesBegan:
var levelName = ""
var nextLevel: SKScene?
if defaults.object(forKey: "continuePoint") != nil && defaults.string(forKey: "continuePoint") != ""{
levelName = defaults.string(forKey: "continuePoint")!
}
else{
levelName = "levelOne"
}
if levelName == "levelOne"{
nextLevel = levelOne(fileNamed: levelName)
}
else if levelName == "levelTwo"{
nextLevel = levelTwo(fileNamed: levelName)
}
nextLevel?.scaleMode = .aspectFill
self.view?.presentScene(nextLevel!, transition: SKTransition.fade(withDuration: 0.1))
}
But this is not the best way to do it. The problem is that you have a new subclass of SKScene for every level that is in the game. If you use a .plist file and set the properties for the specific levels there, you can parse it in your GameScene class and then you have only one SKScene class for all of your Scenes. Your Menu Scene should be in a seperate class though.
You sould find out how to use a plist file in your game to have a better structure. And btw: It is good to use source control like github or bitbucket in all of your projects. So when your project gets bigger and you build in new features and your code doesn't work as expected, you can easily set it back to an older state.
How do I save the user's level on my game?
save it with a string
UserDefaults.standard.set(StateOftheGame, forKey: "levelPass")
then on app delegate check if the user 'passLevel' when the game starts
in
didFinishLaunchingWithOptions -> add function passLevel()
func passLevel() {
if UserDefaults.standard.value(forKey: "levelPass") != nil
{
let VC = UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "YOURVIEWCONTROLLERWITHSAVESTATE")
let navVC = UINavigationController(rootViewController: VC)
let share = UIApplication.shared.delegate as? AppDelegate
share?.window?.rootViewController = navVC
share?.window?.makeKeyAndVisible()
}
}
Saving and Getting Level Number
Use Shared Preferences like so:
Create these methods for use, or just use the content inside of the methods whenever you want:
public int getLevel()
{
SharedPreferences sp = getSharedPreferences("prefName", 0);
int level = sp.getInt("levelReference", 1);
return level;
}
public void setLevel(String level)
{
SharedPreferences.Editor editor = getSharedPreferences("prefName", 0).edit();
editor.putInt("levelReference", level);
editor.commit();
}
The 1
in sp.getInt("levelReference", 1);
means that the method will return 1
if the preference is not found, so the default level is 1.
You can call them like this:
int level = getLevel(); // level is now the level that the user is on
setLevel(4); // user is now on level 4
How to store current MKCoordinateRegion or zoom level?
Unlike the JavaScript Google Maps api, the MKMapView doesn't have a readily available "zoom level" property (it isn't really necessary for your purpose).
Work with the center and span values in the region property.
This question gives an example of how to save/load the region to NSUserDefaults.
Related Topics
What Does the Underscore in a Function Declaration Do
Swift Cannot Output When Using Nstimer
Swift: Casting a Floatingpoint Conforming Value to Double
Use Huge Numbers in Apple Swift
How to Move a Model and Generate Its Collision Shape at the Same Time
Contacts Not Recognized When Body Is Changed from Circle to Rectangle
Nsmanagedobject Subclasses Duplicate Declaration
Core Data Update in Swift While Selecting Any Row in List Table View Not Working
Ibeacon: Get Advertisement Package Faster
Toggle Selectedrange Attributes in Uitextview
Decoding Dynamic JSON Structure in Swift 4
How to Pass a Local Function to Another Object During Init
How to Change Uitextfield Keyboard Type to Email in Swift
Apple Vision Framework - Text Extraction from Image
Swiftui - Mapkit - Binding Mapkit and Show View on Annotation Callout Buttons