I have an isometric tile based dungeon crawling RPG and need to provide a "save/load" game function. I'm thinking about the best way to do that.
I suppose I can save as a single text file or mulitple text files. I can use a DB database (done that before). The game is in prototyping stage so the it will change. My chosen technique will need to be scalable and flexible without being overkill.
I'm thinking a DB falls into the overkill category. I like the neatness of different text files. My 'data' will be like any other rpg:
- map (tiles - 2D array
- character data (health, position in the world) (array)
- inventory (2d array)
- object state within the world (2d array)
I'm thinking of just dumping each array/list/table to a file when saving and then just read them back in during load. The map file will likely be large but the others would be small.
Is there something else I should be considering?
What is your advice for saving game state?
What is your advice for saving game state?
Last project:
https://togfox.itch.io/hwarang
A card game that brings sword fighting to life.
Current project:
Turn-based PBEM horse stable (racing) management sim: https://togfox.itch.io/horse-stable-manager
https://discord.gg/HeHgwE5nsZ
https://togfox.itch.io/hwarang
A card game that brings sword fighting to life.
Current project:
Turn-based PBEM horse stable (racing) management sim: https://togfox.itch.io/horse-stable-manager
https://discord.gg/HeHgwE5nsZ
Re: What is your advice for saving game state?
I save some table data as table:
savefile.lua:
And the to load it.
savefile.lua:
Code: Select all
return {
player = {name = "Hero", health = 10, position = {x=4, y=8}},
enemies = {
{health = 8, position = {x=10, y=18}},
{health = 12, position = {x=12, y=20}, hidden = true},
}
}
Code: Select all
save = require ('savefile')
- Gunroar:Cannon()
- Party member
- Posts: 1141
- Joined: Thu Dec 10, 2020 1:57 am
Re: What is your advice for saving game state?
Maybe you could serialize all the classes that hold data into different filrs(kind if like your last suggestion), leaving out the class functions, then to load it you would have a class/function(for each?) like MapLoader, that makes a new map class, for example, then takes all the variables for that deserialized data and replace them. Or you could put in all the functions that the data doesn't have, that's how I do it.
But for a case where classes are inside classes (like Tile classes inside Map) I give each class instance a _class variable that holds the name of the class they belong to, and I store all the classes in tables.
But for a case where classes are inside classes (like Tile classes inside Map) I give each class instance a _class variable that holds the name of the class they belong to, and I store all the classes in tables.
Re: What is your advice for saving game state?
I use moonblob. Makes it easy to save/load any table from disk.
Code: Select all
local writer, reader = require("BlobWriter"), require("BlobReader")
local filesystem_identity = "68841bcfb1b0c875"
state = {}
function save_state()
love.filesystem.setIdentity(filesystem_identity)
local blob = writer()
blob:write(state)
assert(love.filesystem.write("state", blob:tostring()))
end
function maybe_load_state()
love.filesystem.setIdentity(filesystem_identity)
local fileinfo = love.filesystem.getInfo("state")
if not fileinfo then
return false
end
local data = assert(love.filesystem.read("state"))
local blob = reader(data)
state = blob:read()
return true
end
Re: What is your advice for saving game state?
I put all my saveable data into one table, and used a library called table_save to save and load it. It works fine, but could easily be swapped out for some other system if I wanted more security or whatever.
My inventory and level state data are in sub-tables inside the main savedata table.
The other thing I do, which I thought helped during development, is create a fresh savegame and then copy the loaded table over the top of it. That way if I add a new field (at some point there are going to be player stats, like STR, for instance), it will be added to the loaded file without me having to start my game from scratch. I also (belatedly) added a version number so I can update or invalidate out-of-date saves.
I also have a slot-based system so i don't need to worry about filenames.
Edit: Just noticed my comment "Do some magic stuff". That was a placeholder from before I implemented it
My inventory and level state data are in sub-tables inside the main savedata table.
The other thing I do, which I thought helped during development, is create a fresh savegame and then copy the loaded table over the top of it. That way if I add a new field (at some point there are going to be player stats, like STR, for instance), it will be added to the loaded file without me having to start my game from scratch. I also (belatedly) added a version number so I can update or invalidate out-of-date saves.
I also have a slot-based system so i don't need to worry about filenames.
Code: Select all
require("lib/table_save")
-- globals
selectedSlot = 1
-- save data
player = {}
function loadGame(slot)
slot = slot or selectedSlot -- allow quickload from current slot
if (slotIsFull(slot)) then
-- do some magic stuff
local fileName = "slot" .. slot .. ".sav"
local loaded = table.load(fileName)
-- clone the table into player (this means we keep whatever is in player now
-- that doesn't exist in loaded, so it will have new fields we added since the
-- save, as long as they aren't subfields)
player = newSaveData()
for k, v in pairs(loaded) do
player[k] = v
end
-- make sure flags and automap are created
if (player.levelflags[player.area] == nil) then player.levelflags[player.area] = {} end
if (player.levelmaps[player.area] == nil) then player.levelmaps[player.area] = {} end
selectedSlot = slot
level.loadLevel(player.area)
return true
end
return false
end
function saveGame(slot)
slot = slot or selectedSlot -- allow us to call with no slot (bit hacky)
local fileName = "slot" .. slot .. ".sav"
table.save(player, fileName)
end
function newSaveData()
local saveData = {}
saveData.version = 1
saveData.x = 1
saveData.y = 1
saveData.facing = 2
saveData.area = 1
saveData.hp = 100
saveData.maxhp = saveData.hp
saveData.xp = 0
saveData.level = 1
-- event tracking
saveData.globalflags = {}
saveData.levelflags = {}
-- automaps
saveData.levelmaps = {}
-- inventory
saveData.inventory = {
{ "fist", -1 },
{ "knife", 10 },
{ "heal", 5 },
}
-- make sure flags and automap are created
if (saveData.levelflags[saveData.area] == nil) then saveData.levelflags[saveData.area] = {} end
if (saveData.levelmaps[saveData.area] == nil) then saveData.levelmaps[saveData.area] = {} end
return saveData
end
Re: What is your advice for saving game state?
Thanks for all the replies. I eventually found this on github:
https://github.com/BroccoliRaab/SaveData
It is very simple and pretty much does what everyone here is saying but it is neatly encapsulated so you just need savedata.save and savedata.load. I thought that was worth posting here.
https://github.com/BroccoliRaab/SaveData
It is very simple and pretty much does what everyone here is saying but it is neatly encapsulated so you just need savedata.save and savedata.load. I thought that was worth posting here.
Last project:
https://togfox.itch.io/hwarang
A card game that brings sword fighting to life.
Current project:
Turn-based PBEM horse stable (racing) management sim: https://togfox.itch.io/horse-stable-manager
https://discord.gg/HeHgwE5nsZ
https://togfox.itch.io/hwarang
A card game that brings sword fighting to life.
Current project:
Turn-based PBEM horse stable (racing) management sim: https://togfox.itch.io/horse-stable-manager
https://discord.gg/HeHgwE5nsZ
Re: What is your advice for saving game state?
Who is online
Users browsing this forum: No registered users and 0 guests