Saving and loading in Godot

YouTube: Saving and loading in Godot
YouTube: Saving and loading Godot

I figured it was time to tackle some kind of saving and loading system for my game.

Thankfully, Godot makes this, like most things, super easy.

Saving to a file is as simple as opening a file handle and writing a string to it. That string is a json representation of my GameState object that keeps track of all of the flags/locks in the game.

There are a few special paths when defining a filename. I used "user://" to save to default user location.

Something else I wanted to do when saving was to take a quick screenshot so that I can use it as part of the loading prompt.

That turned out to be simple too - you can get the current rendered screen as an image with get_viewport().get_texture().get_data().

So, my save method ended up looking something like this:

var file = File.new()
file.open(get_file_name(slot), File.WRITE)

# Take a screenshot to show on the load screen
var photo_file_name = "user://%d.png" % slot
var img = get_viewport().get_texture().get_data()
img.flip_y()
img.save_png(photo_file_name)

var save_data: Dictionary = {
    "photo": photo_file_name,
    "location": location,
    "state": {}
}
# Serialise our GameState
for name in get_unique_properties(GameState):
    save_data["state"][name] = GameState.get(name)

# Store our save data as JSON
file.store_string(to_json(save_data))
file.close()

Loading is basically the same thing, just in reverse.

First up we need to read in that image we saved. You can do that by loading it as an ImageTexture and passing it to a Sprite. Something like this:

var img = ImageTexture.new()
img.load(save_data.get("photo"))
slot_photo.sprite.texture = img

Once we've picked a save file to load we open the file handle, read the json back out, and give it to the GameState object.

var data: Dictionary = {}

var file_name = get_file_name(from_slot)
var file = File.new()
if file.file_exists(file_name):
    file.open(file_name, File.READ)
    data = parse_json(file.get_as_text())
    file.close()

# Put our values back into GameState
var state = data.get("state", {})
for name in get_unique_properties(GameState):
    if state.has(name):
        GameState.set(name, state.get(name))

Now that I had the code worked out I turned to the art side of things.

One thing I've always liked about Final Fantasy 9 is the moogle saving system. I love that the moogles are characters in the game but they are also a meta element that handles saving.

I wanted something like that for my game so I've decided to use owls.

I feel like having your save points as actual characters presents a bunch of story (and maybe puzzle) potential.

Once I had the first "save point" hooked up it looked like this:

Coco can save by talking to owls.

And that's it.

If you want to follow along as this game is being made then subscribe to my Game Dev YouTube channel.