Saving / Loading to / from a file
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
Saving / Loading to / from a file
Hello! I'm new to using love and I am curious on how to make a save / load system for my game. The player can edit the level in-game but I want to get it to save to a file where when the game is reopened the level is regenerated as after it was edited (for example, the level is completely blank but I place a gold block, and then close and reopen the game the golden block will still be there) If anyone knows the solution I would deeply appreciate it, thank you!
Re: Saving / Loading to / from a file
There is currently an active thread about reading/writing files:
viewtopic.php?f=3&t=94262
Read all posts, there are different approaches.
What is best depends on your game. Is it tile-based?
viewtopic.php?f=3&t=94262
Read all posts, there are different approaches.
What is best depends on your game. Is it tile-based?
-
- Party member
- Posts: 559
- Joined: Wed Oct 05, 2016 11:53 am
Re: Saving / Loading to / from a file
More or less, you save the necessary information about the game level via in its present state with love.filesystem.write, which will write a file to your game's save folder (location is OS dependent; see this page). However, you can't directly just take a typical lua table and save it with the afore-mentioned function, and instead need to serialize the level data somehow. Essentially, turning the lua table into a binary or string representation, that can be written into a file, and then read back to reconstruct the original table contents. To this end, there are many serialization libraries out there to use, each with their pros and cons - so pick the one you like the most. Personally, I use bitser.
After you've saved the file, you then simply load the file with something like love.filesystem.read, and then deserialize the contents (ie. reverse the serialization process, with the library you chose or otherwise).
This is basically the gist of the whole process, for everything from saving a level, to a more mundane save system that only tracks a few variables.
After you've saved the file, you then simply load the file with something like love.filesystem.read, and then deserialize the contents (ie. reverse the serialization process, with the library you chose or otherwise).
This is basically the gist of the whole process, for everything from saving a level, to a more mundane save system that only tracks a few variables.
Re: Saving / Loading to / from a file
I actually decided to search up how to read / write to file in lua and found io.open()MrFariator wrote: ↑Sun Feb 05, 2023 12:44 am More or less, you save the necessary information about the game level via in its present state with love.filesystem.write, which will write a file to your game's save folder (location is OS dependent; see this page). However, you can't directly just take a typical lua table and save it with the afore-mentioned function, and instead need to serialize the level data somehow. Essentially, turning the lua table into a binary or string representation, that can be written into a file, and then read back to reconstruct the original table contents. To this end, there are many serialization libraries out there to use, each with their pros and cons - so pick the one you like the most. Personally, I use bitser.
After you've saved the file, you then simply load the file with something like love.filesystem.read, and then deserialize the contents (ie. reverse the serialization process, with the library you chose or otherwise).
This is basically the gist of the whole process, for everything from saving a level, to a more mundane save system that only tracks a few variables.
Basically it opens a file for read / write or whatever you want and you can then write / read to / from file and close it and for me it works! So I highly appreciate the help but for me i am going to simply use io.open() as it is much simpler for me. Thank you though!
- BrotSagtMist
- Party member
- Posts: 659
- Joined: Fri Aug 06, 2021 10:30 pm
Re: Saving / Loading to / from a file
Please do not use io.open stuff in löve.
This is NOT compatible with other users, basically your program will only work for yourself then.
This is NOT compatible with other users, basically your program will only work for yourself then.
obey
Re: Saving / Loading to / from a file
Why is this? I don't see a compatibility issue, could you further explain?BrotSagtMist wrote: ↑Sun Feb 05, 2023 1:15 am Please do not use io.open stuff in löve.
This is NOT compatible with other users, basically your program will only work for yourself then.
Re: Saving / Loading to / from a file
If it can help you to write yours here is the first of my many backup scripts that I could write, it is far from being the most perfect (the first) but it is quick to use and quite easy to understand by compared to the others that I could have proposed:
It was before I wrote my own serialization script so it uses TSerial, to use it is really not a headache, you make a model of your save:
Then if you are only supposed to have one backup you can do:
This way you won't need to fill in the `save()` and `load()` parameters anymore, although you can still do it even afterwards. And you can load directly in stride, the table will not be modified if there is no save to load:
SaveMan.load()
And to save you only have to do:
The scripts uses Löve's functions to compress and encode the backup, which makes it less easily editable for cheats, there are of course other ways to optimize this.
I share this one with you as an example because I know that it is largely optimizable but offers a good idea of what it could look like, so I encourage you to write yours with your own features!
Otherwise for using the Lua I/O module this may not work for all users as it depends on the operating system and file access permissions. Löve you have already "chewed" the work on this question for not going into details,
Code: Select all
require("lib/TSerial")
local SM = {}
function SM.getDataTable(data)
if type(data) ~= "table" then
error("SM.getDataTable only takes a table as a parameter.")
else
SM.data = data
end
end
function SM.getSaveName(name)
if type(name) ~= "string" then
error("SM.getSaveName only takes a string as a parameter.")
else
SM.name = name
end
end
function SM.save(data, name)
if type(data) ~= "table" then
if type(SM.data) == "table" then
data = SM.data else return false
end
end
if type(name) ~= "string" then
if not SM.name then
error("SM.save has no name given as a parameter nor previously saved.")
else
name = SM.name
end
end
local temp = TSerial.pack(data)
temp = love.data.compress("string", "zlib", temp, 9)
temp = love.data.encode("string", "base64", temp)
love.filesystem.write(name, temp)
return true
end
function SM.load(name)
if type(name) ~= "string" then
if not SM.name then
error("SM.save has no name given as a parameter nor previously saved.")
else
name = SM.name
end
end
local data
if love.filesystem.getInfo(name) then
data = love.data.decode("string", "base64", love.filesystem.read(name))
data = love.data.decompress("string", "zlib", data)
data = TSerial.unpack(data)
else
return false
end
if SM.data then
for i,v in pairs(data) do
SM.data[i] = v
end
return true
end
return data
end
return SM
Code: Select all
Save = { score = 0 }
Code: Select all
SaveMan.getDataTable(Save)
SaveMan.getSaveName("save.dat")
SaveMan.load()
And to save you only have to do:
Code: Select all
SaveMan.save()
I share this one with you as an example because I know that it is largely optimizable but offers a good idea of what it could look like, so I encourage you to write yours with your own features!
Otherwise for using the Lua I/O module this may not work for all users as it depends on the operating system and file access permissions. Löve you have already "chewed" the work on this question for not going into details,
Re: Saving / Loading to / from a file
Alright, thanks for the explanation. This will really help with my game as I really needed this saving code. Thank you!
- BrotSagtMist
- Party member
- Posts: 659
- Joined: Fri Aug 06, 2021 10:30 pm
Re: Saving / Loading to / from a file
Cause this is absolute file system access.Pratix wrote: ↑Sun Feb 05, 2023 1:16 amWhy is this? I don't see a compatibility issue, could you further explain?BrotSagtMist wrote: ↑Sun Feb 05, 2023 1:15 am Please do not use io.open stuff in löve.
This is NOT compatible with other users, basically your program will only work for yourself then.
It requires every user to have the exact same hardrive setup as you. And even then it will break on different OS.
Thats why löve provides its own read and write which abstracts access to a _fitting_ place depending on what system the user uses.
obey
-
- Party member
- Posts: 559
- Joined: Wed Oct 05, 2016 11:53 am
Re: Saving / Loading to / from a file
Putting aside any file access, file locations or other issues with io.open, another issue is how the io library can often silently fail when dealing with large chunks of data, files containing utf8 strings, and other subtler issues. The issues got to a point that when I wanted to save to a location outside of LÖVE's save folder (for some debug/development purposes; nothing I'd put in a released game), I used love.filesystem.write to write a file to save folder, and then copy that file by executing an OS-dependent file copying command with lua's os.execute. Sounds very roundabout way of doing things, but it worked far better than any of the io.* functions.
To put it short, LÖVE's file system functions are far more robust (outside restricting you into saving files to the save folder; which is what you likely want to do anyway), and less error-prone. Use them to save a bit of your sanity.
To put it short, LÖVE's file system functions are far more robust (outside restricting you into saving files to the save folder; which is what you likely want to do anyway), and less error-prone. Use them to save a bit of your sanity.
Who is online
Users browsing this forum: No registered users and 5 guests