Saving Game Data in Love2D

Dec. 05 2020

If you're creating a game that will take your players multiple sessions to complete you'll more than likely want a way to persist said player's session. Not only will your player want to save his/her game state before exiting the game, but other times may arise where you'll want to save snippets of information (i.e. checkpoints, updates to the player's inventory, or the game unexpectedly crashes). I'd like to share my approach I've been using lately in my last couple games.

Saving Data

First, The Love2D Filesystem...

A common topic you'll find in Love2D Forums is confusion surrounding how to use the love.filesystem library (sometimes argued). You aren't given much access, in fact you're only allow access to one directory. This is fine though since we're looking to save one to many .txt documents.

You can read more on this page for your Operating System's folder location. Since love.filesystem can only interact with this location we aren't really concerned with it. Just know that these files exist and you can find them on your computer.

Furthermore, setting the identity property of Love2D's conf table will name the subfolder where your files will be stored. And finally we'll be giving our save files each a name (referenced as {filename}).

For example, on a Mac your path may look something like this:

/Users/{username}/Library/Application Support/LOVE/{identity}/{filename}.txt

Now, onto actually saving this {filename}.txt file.

Save Module

Below is a simple module for loading and saving game data. With the help of Binser, a lua serializer, we can serialize our save data.

Usage

Our game data will be saved within a lua table, for example:

{
  player = {
    attr = { hp = 50, hpMax = 100, ... },
    weapons = { ... },
    items = { ... }
  },
  checkpoint = { map = A1, row = 3, col = 4 },
  ...
}

Now, let's set up some convienence functions to quickly save data.

function newGame(name)
    SAVE = Saver:save(name, {
       -- initial data
       player = {...},
       checkpoint = {...},
       ...
    })
end

function loadGame(name)
    if Saver:exists(name) then
        SAVE = Saver:load(name)
    else
        newGame(name)
    end
end

function saveGame(name, data)
    SAVE = Saver:save(name, data)
end

New Game

Remember how we said we would be saving to a {filename}.txt file? You are able to save multiple files for the same game. We've included a parameter in functions to name each save file. For example, when you first load your game:

function love.load()
    loadGame('game-a')
end

The path to your save file will thus be:

/Users/{username}/Library/Application Support/LOVE/{identity}/game-a.txt

Save Game

When you want to save data, we'll pull the entire table, edit what we need, and then call our saveGame function. Example, if we wanted to update our player's hp attribute:

-- save on the global variable
SAVE.player.attr.hp = 100

-- save time
saveGame(SAVE)

And that's it! Next time you return the game the player's hp attributes will show the updated value.