Saving level /settings/ high score in between force quits

Hello guys, 

I have been testing a game on Android with a nexus 7. I can save scores/ high scores and other info in

between suspended app sessions. (i.e when I press the home button and exit the app and do other stuff or

play other games). However, if I remove the app from task manager/task list OR force quit the app, everyhing

goes back to 0 or default value. I was wondering is this normal? If it is, does iOS have something similar where

if an app is force quit, all associated data is erased? 

What method do you guys recommend to save scores so that it is not erased in the event of a force quit? 

Thank you. 

If you just have a couple of fields that you need to save such as high score I would just create a file in system.DocumentsDirectory and store the data there.

If you are planning on storing more information I would implement a database:

https://docs.coronalabs.com/daily/api/library/sqlite3/index.html

Hi Tomas,

I am sorry I forgot to mention that I actually am using a file in System.DocumentsDirectory to save scores. 

The code I am using is 

local M = {} -- Create the local module table (this will hold our functions and data) M.score = 0 M.filename = "score.txt" function M.set( value ) M.score = value M.scoreText = string.format( "% 6d", M.score ) end function M.get() return M.score end function M.add( amount ) M.score = M.score + amount M.scoreText = string.format( "% 6d" , M.score ) end function M.save() local path = system.pathForFile( M.filename, system.DocumentsDirectory ) local file = io.open(path, "w") if ( file ) then local contents = tostring( M.score ) file:write( contents ) io.close( file ) return true else print( "Error: could not read ", M.filename, "." ) return false end end function M.load() local path = system.pathForFile( M.filename, system.DocumentsDirectory ) local contents = "" local file = io.open( path, "r" ) if ( file ) then -- Read all contents of file into a string local contents = file:read( "\*a" ) local score = tonumber(contents); io.close( file ) return score else print( "Error: could not read scores from ", M.filename, "." ) end return nil end return M

That is the code provided in the tutorial. However, force quitting the app using task manager or ‘Force Stop’ in settings takes the scores back to 0, as if the app has been launched for very first time. 

So I was wondering what method could be implemented so scores aren’t lost in the event of a forced stop.

Thank you.

I use the code posted above in my gameover scene to compare and save scores by requiring score.lua.

Force quitting an app will not call any event listener so you need to deal with saving the score during the game.

For example:

  1. Load score

  2. The user plays

  3. The level ends

  4. Save score

  5. 2 - 3 is repeated until the user closes the application

Now you’ll always have the latest score but if the user force quits the application in the middle of a level that is lost data and nothing you can do about it. The only thing you can do is try to save as the necessary information when applicable.

Here is a link telling that force quitting doesn’t call any event listener:

https://forums.coronalabs.com/topic/56064-eventtype-guide-question-force-quit-an-application/

 In my app I do not have a pause button. But if I press home button and leave, when I come back the app just starts from exactly where it left of. So in this case, when I press the home button and leave the app does it fire “applicationSuspend” or “applicationExit” ?  Is pressing the home button ‘closing’ the application? 

When I said force quitting and losing scores, I meant force quitting after leaving the app by pressing the home button. In this case, it does not matter whether the user left while the level was being played or whether he exited from the menus. 

Home button and then returns calls applicationSuspend and then applicationResume.

applicationExit is a little bit more tricky. I think it’s called when it’s a planned shut down which on Android is pressing the back-button two times.

When it comes to IOS I don’t think it’s never called except when you code something like os.exit().

Even on the tutorial page they say that you should not rely on applicationExit for important application logic:

https://coronalabs.com/blog/2012/05/15/handling-corona-system-events/

Ok so if I understand from your answer, the reason the game stays in the same state is because exiting the app by pressing home button puts it in suspend mode? And once you come back it resumes? In that case if a user force quits after exiting the app by pressing home button it would make sense for saved data to be lost, is that correct? 

Thanks.

You are correct, when the user presses the “Home” button it goes into a “Application Suspend” state which keeps values of the variables (for example score = 2).

It would be a good idea to save the score when the user presses the “Home” button but for example on Android the user might press the “Back” button to exit the application (not suspend).

The best thing, I think, is to save the score when an update has been done and the score will not be updated anymore (i.e. when the level ends).

See that’s where my problem is. The user, (in this case me) plays a session, and makes a high score of 100 and  loses (score’s already saved and no more updates) and  goes to menu screen. By now the scores are already saved. However,  if he exits and force quits now, that 100 high score is gone and it’s back to 0.

So I am not sure what’s going wrong. Would it be because the app is in suspended mode and since it’s being force quit the OS gets rid of the system.Documents files? But then again if I go to app data on settings, I see that the temp and documents files are there and occupying memory.

Can you post the code where you load and save the score?

I actually tried your code before and it worked for me fine in the simulator:

score.lua

local M = {} -- Create the local module table (this will hold our functions and data) M.score = 0 M.filename = "score.txt" function M.set( value ) M.score = value M.scoreText = string.format( "% 6d", M.score ) end function M.get() return M.score end function M.add( amount ) M.score = M.score + amount M.scoreText = string.format( "% 6d" , M.score ) end function M.save() local path = system.pathForFile( M.filename, system.DocumentsDirectory ) local file = io.open(path, "w") if ( file ) then local contents = tostring( M.score ) file:write( contents ) io.close( file ) return true else print( "Error: could not read ", M.filename, "." ) return false end end function M.load() local path = system.pathForFile( M.filename, system.DocumentsDirectory ) local contents = "" local file = io.open( path, "r" ) if ( file ) then -- Read all contents of file into a string local contents = file:read( "\*a" ) local score = tonumber(contents); io.close( file ) return score else print( "Error: could not read scores from ", M.filename, "." ) end return nil end return M

main.lua

----------------------------------------------------------------------------------------- -- -- main.lua -- ----------------------------------------------------------------------------------------- -- Your code here local score = require("score") local function saveScore() score.set( 2 ) score.save() end local function loadScore() local s = score.load() score.set( s ) print("Current score: ", score.get() ) end -- Call this on your first try to set and save the score: -- saveScore() -- Call this on your second try to load the score: -- loadScore()

Ahhhh…I think I see the problem, it wasn’t the score.lua rather the saving in game. I use set and save every time. But I never load the score. So if it got force quit, I was using get instead of load, which was returning me a 0, since force quitting set everything back to 0. I wasn’t using load, so I never got the saved score returned. 

Thank you very much Tomas for your help. Really appreciate it :smiley:

If you just have a couple of fields that you need to save such as high score I would just create a file in system.DocumentsDirectory and store the data there.

If you are planning on storing more information I would implement a database:

https://docs.coronalabs.com/daily/api/library/sqlite3/index.html

Hi Tomas,

I am sorry I forgot to mention that I actually am using a file in System.DocumentsDirectory to save scores. 

The code I am using is 

local M = {} -- Create the local module table (this will hold our functions and data) M.score = 0 M.filename = "score.txt" function M.set( value ) M.score = value M.scoreText = string.format( "% 6d", M.score ) end function M.get() return M.score end function M.add( amount ) M.score = M.score + amount M.scoreText = string.format( "% 6d" , M.score ) end function M.save() local path = system.pathForFile( M.filename, system.DocumentsDirectory ) local file = io.open(path, "w") if ( file ) then local contents = tostring( M.score ) file:write( contents ) io.close( file ) return true else print( "Error: could not read ", M.filename, "." ) return false end end function M.load() local path = system.pathForFile( M.filename, system.DocumentsDirectory ) local contents = "" local file = io.open( path, "r" ) if ( file ) then -- Read all contents of file into a string local contents = file:read( "\*a" ) local score = tonumber(contents); io.close( file ) return score else print( "Error: could not read scores from ", M.filename, "." ) end return nil end return M

That is the code provided in the tutorial. However, force quitting the app using task manager or ‘Force Stop’ in settings takes the scores back to 0, as if the app has been launched for very first time. 

So I was wondering what method could be implemented so scores aren’t lost in the event of a forced stop.

Thank you.

I use the code posted above in my gameover scene to compare and save scores by requiring score.lua.

Force quitting an app will not call any event listener so you need to deal with saving the score during the game.

For example:

  1. Load score

  2. The user plays

  3. The level ends

  4. Save score

  5. 2 - 3 is repeated until the user closes the application

Now you’ll always have the latest score but if the user force quits the application in the middle of a level that is lost data and nothing you can do about it. The only thing you can do is try to save as the necessary information when applicable.

Here is a link telling that force quitting doesn’t call any event listener:

https://forums.coronalabs.com/topic/56064-eventtype-guide-question-force-quit-an-application/

 In my app I do not have a pause button. But if I press home button and leave, when I come back the app just starts from exactly where it left of. So in this case, when I press the home button and leave the app does it fire “applicationSuspend” or “applicationExit” ?  Is pressing the home button ‘closing’ the application? 

When I said force quitting and losing scores, I meant force quitting after leaving the app by pressing the home button. In this case, it does not matter whether the user left while the level was being played or whether he exited from the menus. 

Home button and then returns calls applicationSuspend and then applicationResume.

applicationExit is a little bit more tricky. I think it’s called when it’s a planned shut down which on Android is pressing the back-button two times.

When it comes to IOS I don’t think it’s never called except when you code something like os.exit().

Even on the tutorial page they say that you should not rely on applicationExit for important application logic:

https://coronalabs.com/blog/2012/05/15/handling-corona-system-events/

Ok so if I understand from your answer, the reason the game stays in the same state is because exiting the app by pressing home button puts it in suspend mode? And once you come back it resumes? In that case if a user force quits after exiting the app by pressing home button it would make sense for saved data to be lost, is that correct? 

Thanks.

You are correct, when the user presses the “Home” button it goes into a “Application Suspend” state which keeps values of the variables (for example score = 2).

It would be a good idea to save the score when the user presses the “Home” button but for example on Android the user might press the “Back” button to exit the application (not suspend).

The best thing, I think, is to save the score when an update has been done and the score will not be updated anymore (i.e. when the level ends).