Troubles with saving and loading

Im using storyboard and i would like to implement a feature that saves and loads the total amount of times the player has died as a stat that accumulates until the player has removed the game from device. The problem im having though is figuring out the logic behind doing this.

I run this in my main

-- load the JSON library. local json = require("json") -- Function to save a table. Since game settings need to be saved from session to session, we will -- use the Documents Directory function saveTable(t, filename) local path = system.pathForFile( filename, system.DocumentsDirectory) local file = io.open(path, "w") if file then local contents = json.encode(t) file:write( contents ) io.close( file ) return true else return false end end function loadTable(filename) local path = system.pathForFile( filename, system.DocumentsDirectory) local contents = "" local myTable = {} local file = io.open( path, "r" ) if file then -- read all contents of file into a string local contents = file:read( "\*a" ) myTable = json.decode(contents); io.close( file ) return myTable end return nil end

In my level i use this to create my file and save the amount of deaths that accured during that level

--Runtime Listener. local function saveData () myGameStats = {} myGameStats.totalDeaths = numberDeaths.text saveTable(myGameStats, "mygamestats.json") end

Function that handles incrementing the amount of deaths

--Check for collision with player and spikes. local function spikeDeath(event) if event.phase == "began" then if(event.object1.myName == "spike" and event.object2.myName == "player") then print ("You died from spikes") death = true end elseif event.phase == "ended" then if(event.object1.myName == "spike" and event.object2.myName == "player") then death = false numberDeaths.text = numberDeaths.text + 1 end end end

function scene:createScene( event )     local screenGroup = self.view numberDeaths = display.newText(0, 0, 0, native.systemFont, 32) numberDeaths.text = 0 numberDeaths.x = \_W - 248 numberDeaths.y = \_H - 66 numberDeaths:setFillColor(255,0,0) screenGroup:insert( numberDeaths ) end

My issue is that when i restart my game “myGameStats.totalDeaths” resets to 0 again. Im not sure how to handle this properly. Anyone think they can help with this?

I can see your function to save data, but I don’t see that you’ve called a similar function to load the data on startup, unless I’ve overlooked something?

You’ve got a loadTable function, but you never use it. I guess you just need to do this:

local myGameStats = loadTable("mygamestats.json")

and then change the code where you create your text object to this:

numberDeaths = display.newText(myGameStats.totalDeaths, 0, 0, native.systemFont, 32)

otherwise it will display 0 even if it has loaded the data.

This is what i ended up doing. I have a question though.

MAIN.LUA

-- load the JSON library. local json = require("json")   -- Function to save a table.  Since game settings need to be saved from session to session, we will -- use the Documents Directory   function saveTable(t, filename)     local path = system.pathForFile( filename, system.DocumentsDirectory)     local file = io.open(path, "w")     if file then         local contents = json.encode(t)         file:write( contents )         io.close( file )         return true     else         return false     end end   function loadTable(filename)     local path = system.pathForFile( filename, system.DocumentsDirectory)     local contents = ""     local myTable = {}     local file = io.open( path, "r" )     if file then          -- read all contents of file into a string          local contents = file:read( "\*a" )          myTable = json.decode(contents);          io.close( file )          return myTable          end          return nil end --This will return NIL if file does not exist myGameStats = loadTable("mygamestats.json") --This function will create my file if nil is returned function checkFile() if myGameStats == nil then myGameStats = {} myGameStats.totalDeaths = 0 saveTable(myGameStats, "mygamestats.json") end end checkFile()

Level_1.LUA Why does this come back with a error saying "Attempt to preform arithmethic on field totalDeaths a nil value "

--Save my data. This function is being listened to by Runtime local function saveData () myGameStats = {} myGameStats.totalDeaths = myGameStats.totalDeaths + numberDeaths.text saveTable(myGameStats, "mygamestats.json") end

If i do this everything works but i dont understand why the top does not also work.

local stats = myGameStats.totalDeaths local function saveData () myGameStats = {} myGameStats.totalDeaths = stats + numberDeaths.text saveTable(myGameStats, "mygamestats.json") end

It’s given you that message because it IS a nil value, since you reset your table immediately before trying to access one of it’s values:

local function saveData () --this line resets the myGameStats table to just a plain empty table myGameStats = {} --therefore myGameStats.totalDeaths does not exist yet --so you cannot add numberDeaths.text to it myGameStats.totalDeaths = myGameStats.totalDeaths + numberDeaths.text saveTable(myGameStats, "mygamestats.json") end

However here you store the value beforehand in a separate variable:

local stats = myGameStats.totalDeaths local function saveData () myGameStats = {} --so now you are accessing a variable "stats" that still exists myGameStats.totalDeaths = stats + numberDeaths.text saveTable(myGameStats, "mygamestats.json") end

Ahh I see now. That makes a ton of sense thanks.

I can see your function to save data, but I don’t see that you’ve called a similar function to load the data on startup, unless I’ve overlooked something?

You’ve got a loadTable function, but you never use it. I guess you just need to do this:

local myGameStats = loadTable("mygamestats.json")

and then change the code where you create your text object to this:

numberDeaths = display.newText(myGameStats.totalDeaths, 0, 0, native.systemFont, 32)

otherwise it will display 0 even if it has loaded the data.

This is what i ended up doing. I have a question though.

MAIN.LUA

-- load the JSON library. local json = require("json")   -- Function to save a table.  Since game settings need to be saved from session to session, we will -- use the Documents Directory   function saveTable(t, filename)     local path = system.pathForFile( filename, system.DocumentsDirectory)     local file = io.open(path, "w")     if file then         local contents = json.encode(t)         file:write( contents )         io.close( file )         return true     else         return false     end end   function loadTable(filename)     local path = system.pathForFile( filename, system.DocumentsDirectory)     local contents = ""     local myTable = {}     local file = io.open( path, "r" )     if file then          -- read all contents of file into a string          local contents = file:read( "\*a" )          myTable = json.decode(contents);          io.close( file )          return myTable          end          return nil end --This will return NIL if file does not exist myGameStats = loadTable("mygamestats.json") --This function will create my file if nil is returned function checkFile() if myGameStats == nil then myGameStats = {} myGameStats.totalDeaths = 0 saveTable(myGameStats, "mygamestats.json") end end checkFile()

Level_1.LUA Why does this come back with a error saying "Attempt to preform arithmethic on field totalDeaths a nil value "

--Save my data. This function is being listened to by Runtime local function saveData () myGameStats = {} myGameStats.totalDeaths = myGameStats.totalDeaths + numberDeaths.text saveTable(myGameStats, "mygamestats.json") end

If i do this everything works but i dont understand why the top does not also work.

local stats = myGameStats.totalDeaths local function saveData () myGameStats = {} myGameStats.totalDeaths = stats + numberDeaths.text saveTable(myGameStats, "mygamestats.json") end

It’s given you that message because it IS a nil value, since you reset your table immediately before trying to access one of it’s values:

local function saveData () --this line resets the myGameStats table to just a plain empty table myGameStats = {} --therefore myGameStats.totalDeaths does not exist yet --so you cannot add numberDeaths.text to it myGameStats.totalDeaths = myGameStats.totalDeaths + numberDeaths.text saveTable(myGameStats, "mygamestats.json") end

However here you store the value beforehand in a separate variable:

local stats = myGameStats.totalDeaths local function saveData () myGameStats = {} --so now you are accessing a variable "stats" that still exists myGameStats.totalDeaths = stats + numberDeaths.text saveTable(myGameStats, "mygamestats.json") end

Ahh I see now. That makes a ton of sense thanks.