Saving highscore after exiting app

After searching through forums I found a way to store the highscore… except the highscore goes back to zero after program exit.

 

highscore.txt has 0 in it 

 

in main lua:

 

local highScore

    _path = system.pathForFile( “highScore.txt”, system.ResourceDirectory )
    _file = io.open( _path, “r” )

    for line in _file:lines() do
     highScore = tonumber (line)
    end

    io.close( _file )
    _file = nil
    _path = nil

    _path = system.pathForFile( “highScore.txt”, system.DocumentsDirectory )
    _file = io.open( _path, “w” )
    _file:write( highScore )

    io.close( _file )
    _file = nil
    _path = nil

 

 

At the top of game lua

local highScore

    _path = system.pathForFile( “highScore.txt”, system.DocumentsDirectory )
    _file = io.open( _path, “r” )

    for line in _file:lines() do
     highScore = tonumber (line)
    end

    io.close( _file )
    _file = nil
    _path = nil

 

after game over:

 

if score > highScore then

highScore = score
_path = system.pathForFile( “highScore.txt”, system.DocumentsDirectory )
    _file = io.open( _path, “w” )
    _file:write( highScore )

    io.close( _file )
    _file = nil
    _path = nil
end

Unfortunately, I get bleary-eyed looking at other people’s code. But I will give you the code I use in some of my apps. Probably others can improve it, but last time I checked it does work. 

local json = require("json") local saveTable = nil local getValue = function(key) if not saveTable then local path = system.pathForFile("savedData.json", system.DocumentsDirectory) local file = io.open(path, "r") if file then saveTable = json.decode(file:read("\*a")) io.close(file) end end saveTable = saveTable or {} return saveTable[key] end local saveValue = function(key, value, operateSave) if saveTable == nil then local path = system.pathForFile("savedData.json", system.DocumentsDirectory) local file = io.open(path, "r") if file then M.saveTable = json.decode(file:read("\*a")) io.close(file) end end saveTable = saveTable or {} saveTable[key] = value if operateSave then local path = system.pathForFile("savedData.json", system.DocumentsDirectory) local file = io.open(path, "w+") file:write(json.encode(saveTable)) io.close(file) end return saveTable[key] end

Now to save the value you would use. Sending false to this function just updates the local table and does not write to the file system since it is expensive and you might want to delay it until you are doing nothing in the game:

saveValue("HighScore", 2324, true)

And to retrieve it:

getValue("HighScore")

Hopefully, it is helpful and at the very least you can use part of this code in your code.

I don’t know JSON so i just copied your code and it gives me an error saying attempted to index field ‘?’ (a nil value). Should I be creating a file or changing anything when using the code you provided?

Nope. Here is a sample project. Should work as is. 

SSK 2 (which is free) offers super EASY solutions to this kind of problem.  It provides two solutions that are suitable:

  • Table Extensions - It may be too hard for you, but SSK2 extends the table.* library by adding functions to save and load tables.  If you want to use this I’ll let you work it out.
  • SSK2 Persist Library - Specifically designed for maintaining persistent data (which is what your score keeping question is about).

Here is a full example of how to use this feature.

Setting Up SSK

https://roaminggamer.github.io/RGDocs/pages/SSK2/#installing-ssk2

Using Persist Library

main.lua

-- .. after loading and initializing SSK -- and before you start your game code ssk.persist.setDefault( "gamedata.json", "lastScore", 0 )

… later in any file you can read the score like this:

local lastScore = ssk.persist.get( "gamedata.json", "lastScore" ) print( lastScore )

… later in any file you can write the score like this:

-- Increment last score by 10 local lastScore = ssk.persist.get( "gamedata.json", "lastScore" ) ssk.persist.set( "gamedata.json", "lastScore", lastScore + 10 )

This score will be persistent across runs.

For anyone who is curious, Persist.* has three nice features:

  1. It caches the data in memory so get calls are fast and don’t require a file load each time you look at a saved data set.
  2. Writes are combined, so multiple set() calls in a short period of time only result in a single write.
  3. It is suspend aware and flushes outstanding writes if a suspend is detected.

Just as a quick observation.  You don’t need to know JSON to use JSON. You make a Lua table, JSON encode it, write it out to a file, read the file back in when needed and JSON decode it to a Lua table again.

However, Corona has other simple to use methods for saving data.  Look at system.setPreferences()  https://docs.coronalabs.com/api/library/system/setPreferences.html

Then you can use system.getPreferences() to retrieve the data.

Rob

Unfortunately, I get bleary-eyed looking at other people’s code. But I will give you the code I use in some of my apps. Probably others can improve it, but last time I checked it does work. 

local json = require("json") local saveTable = nil local getValue = function(key) if not saveTable then local path = system.pathForFile("savedData.json", system.DocumentsDirectory) local file = io.open(path, "r") if file then saveTable = json.decode(file:read("\*a")) io.close(file) end end saveTable = saveTable or {} return saveTable[key] end local saveValue = function(key, value, operateSave) if saveTable == nil then local path = system.pathForFile("savedData.json", system.DocumentsDirectory) local file = io.open(path, "r") if file then M.saveTable = json.decode(file:read("\*a")) io.close(file) end end saveTable = saveTable or {} saveTable[key] = value if operateSave then local path = system.pathForFile("savedData.json", system.DocumentsDirectory) local file = io.open(path, "w+") file:write(json.encode(saveTable)) io.close(file) end return saveTable[key] end

Now to save the value you would use. Sending false to this function just updates the local table and does not write to the file system since it is expensive and you might want to delay it until you are doing nothing in the game:

saveValue("HighScore", 2324, true)

And to retrieve it:

getValue("HighScore")

Hopefully, it is helpful and at the very least you can use part of this code in your code.

I don’t know JSON so i just copied your code and it gives me an error saying attempted to index field ‘?’ (a nil value). Should I be creating a file or changing anything when using the code you provided?

Nope. Here is a sample project. Should work as is. 

SSK 2 (which is free) offers super EASY solutions to this kind of problem.  It provides two solutions that are suitable:

  • Table Extensions - It may be too hard for you, but SSK2 extends the table.* library by adding functions to save and load tables.  If you want to use this I’ll let you work it out.
  • SSK2 Persist Library - Specifically designed for maintaining persistent data (which is what your score keeping question is about).

Here is a full example of how to use this feature.

Setting Up SSK

https://roaminggamer.github.io/RGDocs/pages/SSK2/#installing-ssk2

Using Persist Library

main.lua

-- .. after loading and initializing SSK -- and before you start your game code ssk.persist.setDefault( "gamedata.json", "lastScore", 0 )

… later in any file you can read the score like this:

local lastScore = ssk.persist.get( "gamedata.json", "lastScore" ) print( lastScore )

… later in any file you can write the score like this:

-- Increment last score by 10 local lastScore = ssk.persist.get( "gamedata.json", "lastScore" ) ssk.persist.set( "gamedata.json", "lastScore", lastScore + 10 )

This score will be persistent across runs.

For anyone who is curious, Persist.* has three nice features:

  1. It caches the data in memory so get calls are fast and don’t require a file load each time you look at a saved data set.
  2. Writes are combined, so multiple set() calls in a short period of time only result in a single write.
  3. It is suspend aware and flushes outstanding writes if a suspend is detected.

Just as a quick observation.  You don’t need to know JSON to use JSON. You make a Lua table, JSON encode it, write it out to a file, read the file back in when needed and JSON decode it to a Lua table again.

However, Corona has other simple to use methods for saving data.  Look at system.setPreferences()  https://docs.coronalabs.com/api/library/system/setPreferences.html

Then you can use system.getPreferences() to retrieve the data.

Rob