0 votes

Hi, I'm making a simple 2D platform game, I've set up a main menu (with New Game and Continue buttons) and a pause screen while in game (with Save, Resume and Menu) buttons.

My problem is: I can get my 'Save' button to produce a .DAT file in the required user folder stating 'World 1' in text but I'm not sure how to get this to then load the game from this point when I press the 'Continue' button on the main menu. I want the game to continue when I press the 'Continue' button from the scene I was at when I saved the game in the pause menu.

This is my 'main.gd' where my save/load scripts are stored (I have this set to autoload in project settings):

    extends Node

var level = 1
var pause = false

func _ready():
    _load()

func _save():
    var data = ""
    data += "World_ " + str (level)
    var new_file = File.new()
    new_file.open("user://save.dat", File.WRITE)
    new_file.store_line(data)
    new_file.close()

func _load():
    var new_file = File.new()
    if not new_file.file_exists("user://save.dat"):
        _save()
        return
    new_file.open("user://save.dat", File.READ)
    var data = new_file.get_as_text()
    new_file.close()
    data = data.split("\n")
    for line in data:
        if line.begins_with("level"):
            level = int(line.split(" ")[1])

This is my MainMenu scene where my 'New Game' and 'Continue' buttons are:

 extends Control

var main = load("res://main.gd").new()

func _on_PlayButton_pressed():
    get_tree().change_scene("res://World_1.tscn")


func _on_ContinueButton_pressed():
    main._load()

I've been through all the guides and documentation and I can't get any further.. Help would be much appreciated as I've been really struggling to get it to work! Thanks!

Godot version 3.2.3
in Engine by (16 points)
edited by

1 Answer

0 votes

Your code has some oddities like why are you saving in the _load function?
The line that causes your issue would be data += "World_ " + str (level) so that when you call if line.begins_with("level"): the line would actually be World_ 1

Not that looping your save file line by line is wrong but you'll find better usability using a Dictionary with JSON. that being said i've took the leeway of adjusting your code as its not a true 'dat'

var save_data = {
    "level": 1,
    "power": 0,
    "vitality": 6, 
    "dexterity": 40
}

func _save():
    var new_file = File.new()
    var error = new_file.open_encrypted_with_pass(
        "user://save.dat", File.WRITE, OS.get_unique_id()
    )
    assert(not error, "Could not create save file")
    new_file.store_line(to_json(save_data))
    new_file.close()

func _load():
    var new_file = File.new()

    var error = new_file.open_encrypted_with_pass(
        "res://save.dat", File.READ, OS.get_unique_id()
    )
    if error:
        print("Failed to load save file")
        return

    var data = parse_json(new_file.get_as_text())
    if typeof(data) != TYPE_DICTIONARY:
            print("Save data corrupt")
        return

    save_data = data
    file.close()

For testing purposes you can use new_file.open() but the final product should use new_file.open_encrypted_with_pass() additionally the benefit of using a Dictionary is to easily store and access your variables like save_data.level = 200

by (4,304 points)
edited by

Thank you for your response, using this I'm now able to save as a real .DAT file in the project data folder.

My confusion is how do I save the game in a particular scene ("World1", "World2", "World3" e.t.c) (*with World being the names of my level scenes*) and then when reloading the game upon pressing the 'Continue' button I'm returned to the scene where I saved at?
At the moment I save the game, it sends a file to the project data folder but this doesn't mean I can continue from where I progressed to previously.

Depends on how your code is structured. Lets say your _save _load functions are in a Singleton which they should be

if your "Worlds" are being instanced by code you can do

func _ready():
    save_data.level = filename

func _on_ContinueButton_pressed():
    var level = load(save_data.level)
    replace_by(level.instance())

If your "Worlds" are Nodes in the tree that are just hidden / shown

func _ready():
    save_data.level = get_path()

func _on_ContinueButton_pressed():
    hide()
    get_node(save_data.level).show()

and in the Singleton call your save load functions like this:

func _notification(what):
    match what:
        NOTIFICATION_READY:
            _load()
        NOTIFICATION_WM_QUIT_REQUEST, NOTIFICATION_CRASH:
            _save()

Thank you for your help Wakatta. Honestly I've been trying with your help to get this working however I just can't get the Continue button to load the game from where it was previously, when pressed it just does nothing all I can get it to do is print text to the console.. It's down to my limited coding knowledge as I've only been using Godot for a few weeks without previous experience, I think the only way I'll be able to get it working for my game is through a screen share zoom call or sending my script on GitHub but I do appreciate your help and I'm definitely closer to getting it working :)

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.