What am I doing wrong? Savegame

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Rhynn
:warning: Old Version Published before Godot 3 was released.

For my first project, I’ve started making a Flappy Bird-type game, following the excellent tutorials by Edward (AngegaStudios on Youtube). I’ve worked ahead a little bit though because I’m eager to get this project finished, and I’ve got everything working as intended now… except saving the best score in a savegame, so it’s still there after closing the game.

The two relevant files:

First, game.gd, which is a global script:

#script: game

extends Node

const GROUP_PIPES = "pipes"
const GROUP_GROUNDS = "grounds"
const GROUP_BIRDS = "birds"

var score_best = 0 setget _set_score_best
var score_current = 0 setget _set_score_current

var savegame = File.new() #file
var save_path = "user://savegame.save" #place of the file
var save_data = {"highscore": 0} #variable to store data. Should it be 0, or should it be score_best?

signal score_best_changed
signal score_current_changed

func _ready():
	if not savegame.file_exists(save_path): #if the save game doesn't exist...
		create_save() #...create it! Function down below...
	read_savegame() #load (read) the savegame when the game starts
	stage_manager.connect("stage_changed", self, "_on_stage_changed")
	pass

func create_save(): #The function to create the savegame
	savegame.open(save_path, File.WRITE) #open file to write
	savegame.store_var(save_data) #store the content of the save_data variable
	savegame.close() #close the savegame

func save(score_best): #The function to save the game; I want it to save the score_best variable contents
	save_data["highscore"] = score_best #data to save 
	savegame.open(save_path, File.WRITE) #open file to write
	savegame.store_var(save_data) #store the data
	savegame.close() #close the file

func read_savegame(): #The function to load the game
	savegame.open(save_path, File.READ) #open the file
	save_data = savegame.get_var() #get the value
	savegame.close() #close the file
	return save_data["highscore"] #return the value

func _on_stage_changed():
	score_current = 0
	pass

func _set_score_best(new_value):
	if new_value > score_best:
		score_best = new_value
		emit_signal("score_best_changed")
	pass

func _set_score_current(new_value):
	score_current = new_value
	emit_signal("score_current_changed")
	pass

Next, a snippet from hbox_score_best, where I try to save the game whenever the best score has changed:

func _on_score_best_changed(): #when the best score has changed...
	set_number(game.score_best) #...first change the score_best variable in game.gd...
	game.save(game.score_best) #...and then save the game

I’m honestly not sure if that last line is even correct. I followed this post which is the only way I’ve found to save that doesn’t crash my game… as long as I pass an argument in that last function call, which I just can’t really figure out why. If I don’t pass an argument, I receive the following error:
“Invalid call to function ‘save’ in base ‘Node (game.gd)’. Expected 1 arguments.”
And if I do pass an argument, the game runs fine, but it doesn’t get saved. At all.

So… yeah. I need a bit of help here :slight_smile: I’m so close to finishing my project, but this has been frustrating me for a while now!

:bust_in_silhouette: Reply From: aozasori

I fiddled with this code a bit and it’s definitely saving.

I noticed that you don’t appear to be setting score_best after loading the data. In read_savegame, you return save_data["highscore"], but you don’t appear to catch/use the returned value anywhere. Perhaps that’s the problem?

func read_savegame():
    savegame.open(save_path, File.READ)
    save_data = savegame.get_var()
    savegame.close()
    return save_data["highscore"] ## here

Also, save is giving an error if you don’t pass it an argument because:

func save(score_best): ## you are asking for one when you define the function
    ...

If you want to use score_best, which already exists as a member variable, you don’t need to declare it as an argument.

func save(): ## this will work
    save_data["highscore"] = score_best
    ...

One small suggestion…
The create_save function is unnecessary. You can simply check if a save exists and only call read_savegame if it does.

func _ready():
    if savegame.file_exists(save_path):
        read_savegame()

Or check for it in read_savegame like so:

func read_savegame():
    if savegame.file_exists(save_path):
        savegame.open(save_path, File.READ)
        save_data = savegame.get_var()
        savegame.close()
    return save_data["highscore"]

Thank you very much! My problem is solved now :slight_smile:

Rhynn | 2016-10-01 23:01