Json trouble saving highscore

So after reviewing https://docs.coronalabs.com/tutorial/data/jsonSaveLoad/index.html#savingloading-tables-to-json for awhile in order to come up with a way to save high score I came up with this code.

local newScore = { score } loadsave.saveTable( newScore, "NewScore.json" ) local scoreTable = { score } loadsave.saveTable( scoreTable, "scoreTable.json" ) local newScore2 = { score } if( loadsave.loadTable( scoreTable, "scoreTable.json" ) \> loadsave.loadTable( newScore, "NewScore.json" )) then loadsave.saveTable( newScore2, "NewScore2.json" ) end

In this, scoretable is essentially going to be the score, newscore = the previous score, and newscore2 = the final score.

The issue with this code is I cannot save a high score (newscore2) unless I compare scoretable (the score) to newscore (the previous score), but that brings me to the error “cannot compare two nil values.”

I’ve learned on here that to be nil means to not exist, but I am not sure how they don’t exist thus I am not sure how to make them exist.

I tried adding

local saveTable = loadsave.saveTable() local loadTable = loadsave.loadTable()

to the beginning of my game.lua, but to no avail.

And I also tried comparing them solely as

if( scoreTable \> newScore ) then loadsave.saveTable( newScore2, "NewScore2.json" ) end

but that gives me the error “attempt to compare two table values.”

So essentially my question is, am I going about saving my high score in the right way?

And how would I compare scoreTable and newScore?

Hi @ Davy1222, I think the first thing to address is your table structure.

It should look more like this

[lua]

local newScore = {

     score = 0

}

[/lua]

just “score” by itself doesn’t mean anything.  For a proper table you need a key (“score”) and a value ( 0 ).

The error you received is because you have asked for a comparison of two tables instead of the values inside the tables.

newScore should be a local value not a stored table value - I’m going to call it currentScore

[lua]

– create and save your initial high score which which is inside scoreTable

local scoreTable = {

     highScore = 0

}

– save scoreTable to JSON as scoreTable.json

loadsave.saveTable( scoreTable, “scoreTable.json” )

– create a current score variable

local currentScore = 0 – adjust this as it changes during the game

– load your saved scoreTable into a local table called “scores”

local scores = loadsave.loadTable( “scoreTable.json”)

– make your comparison - currentScore vs. the highScore which is inside the scores table (which was loaded from scoreTable.json)

if currentScore > scores.highScore then

    scores.highScore = currentScore

    – save scores to JSON as scoreTable.json

    loadsave.saveTable( scores, “scoreTable.json” )

end

– so your saved scores will always be in “scoreTable.json” but when we load them locally they are called scores

[/lua]

Give this a try, forgive any typos.

I tried this, and it does work. However it only works if I manually change the value of currentscore which does not update on its own.

The next step may be to make my score value not nil and use that instead of curentscore but I’m not sure how to do that when I’ve already defined it.

Or maybe theres a way to update the currentscore alongside the score without making it nil?

I have this at the top of game.lua

local score = 0 local score = require( "score" ) local scoreText = score.init( { fontSize = 40, x = 130, y = 130, maxDigits = 7, leadingZeros = false })

Yes, you would have to update the currentScore value in your game logic - which is normal.

I’m not sure what this is about (see below)

You are requiring a module called “score” but what does that do.  Please show the code for the score module

[lua]

local score = require( “score” )

local scoreText = score.init(

{

    fontSize = 40,

    x = 130,

    y = 130,

    maxDigits = 7,

    leadingZeros = false

})

[/lua]

Whatever variable you are using to track the score would be the currentScore or to update the currentScore variable in the sample I used, just add currentScore = score (score being whatever variable you use to track the current score) before you compare the currentScore to the high score

[lua]

currentScore = score – score being whatever variable you are using to track the current score

if currentScore > scores.highScore then

    scores.highScore = currentScore

    – save scores to JSON as scoreTable.json

    loadsave.saveTable( scores, “scoreTable.json” )

end

[/lua]

@ davy1222, Hey I think you should spend some time analyzing lua tables so you understand their structure more completely.  I think that would solve a bunch of your issues and also help you understand what is going on when you store lua tables as json files.

Try lua tables on lua.org

or

lua table in Corona Docs

I understand the tables better now and I’ve figured out where I went wrong.

I was supposed to set local currentScore = score.get() instead of just score, which is from my score.lua.(https://docs.coronalabs.com/tutorial/games/keepScores/index.html)

But the only problem is now is that the currentScore is saved no matter what instead of remaining the higher number.

You might be comparing the currentScore to something that is nil or not indexed correctly or a table instead of a value.  Can you show us the code?

in game.lua i have 

local composer = require( "composer" ) local loadsave = require( "loadsave" ) local score = require( "score" ) -- here you declare all your local variables: local score = 0 local highscore = 0 local scoreText = score.init( { fontSize = 40, x = 130, y = 130, maxDigits = 7, leadingZeros = false }) local function onCollision(event) if event.phase == "began" then print "collision happened" composer.gotoScene( "gameover",{ time=400, params=score } ) score.save() end -- here i have your code local scoreTable = { highScore = 0 } loadsave.saveTable( scoreTable, "scoreTable.json" ) local currentScore = score.get() local scorer = loadsave.loadTable( "scoreTable.json") if currentScore \> scorer.highScore then scorer.highScore = currentScore loadsave.saveTable( scorer, "scoreTable.json" ) end

and in score.lua i have

local M = {} M.score = 0 -- Set the score to 0 initially function M.init( options ) local customOptions = options or {} local opt = {} opt.fontSize = customOptions.fontSize or 24 opt.font = customOptions.font or native.systemFont opt.x = customOptions.x or display.contentCenterX opt.y = customOptions.y or opt.fontSize\*0.5 opt.maxDigits = customOptions.maxDigits or 6 opt.leadingZeros = customOptions.leadingZeros or false local prefix = "" if ( opt.leadingZeros ) then prefix = "0" end M.format = "%" .. prefix .. opt.maxDigits .. "d" -- Create the score display object M.scoreText = display.newText( string.format( M.format, 0 ), opt.x, opt.y, opt.font, opt.fontSize ) return M.scoreText end -- return M function M.set( value ) M.score = tonumber(value) M.scoreText.text = string.format( M.format, M.score ) end function M.get() return M.score end function M.add( amount ) M.score = M.score + tonumber(amount) M.scoreText.text = string.format( M.format, M.score ) end -- return M function M.save() local saved = system.setPreferences( "app", { currentScore=M.score } ) if ( saved == false ) then print( "ERROR: could not save score" ) end end function M.load() local score = system.getPreference( "app", "currentScore", "number" ) if ( score ) then return tonumber(score) else print( "ERROR: could not load score (score may not exist in storage)" ) end end return M

Could this may be because i have all this happening before scene:create,show,hide and destroy?

New Discovery: After tweaking a little, I find that moving your entire code before the collision  loads the previous value in the scoreTable.json. So what I’ve tried now is making your code into 3 parts.

 -- so here i have what saves the previous score local scoreTable1 = { Score = 0 } loadsave.saveTable( scoreTable1, "scoreTable1.json" ) local currentScore = score.get() local scorer1 = loadsave.loadTable( "scoreTable1.json") if currentScore \> scorer1.Score then scorer1.Score = currentScore loadsave.saveTable( scorer1, "scoreTable1.json" ) end local function onCollision(event) if event.phase == "began" then print "collision happened" composer.gotoScene( "gameover",{ time=400, params=score } ) score.save() end -- here I have what saves the current score local scoreTable2 = { Score = 0 } loadsave.saveTable( scoreTable2, "scoreTable2.json" ) local currentScore = score.get() local scorer2 = loadsave.loadTable( "scoreTable2.json") if currentScore \> scorer2.Score then scorer2.Score = currentScore -- save scores to JSON as scoreTable.json loadsave.saveTable( scorer2, "scoreTable2.json" ) end -- here is what determines the high score local scoreTable3 = { highScore = 0 } loadsave.saveTable( scoreTable3, "scoreTable3.json" ) local currentScore = score.get() local scorer3 = loadsave.loadTable( "scoreTable3.json") if scorer2.Score \> scorer1.Score then scorer3.highScore = scorer2.Score loadsave.saveTable( scorer3, "scoreTable3.json" ) elseif scorer2.Score \< scorer1.Score then scorer3.highScore = scorer1.Score loadsave.saveTable( scorer3, "scoreTable3.json" ) end

So this works but it only works for a few tries.

Say the score reads 3 first, then these will read

scorer1 = 0

scorer2 = 3

highscore = 3

now if I play again and the score reads 1

scorer1 = 3

scorer2 = 1

highscore = 3

now again and the score reads 2

scorer1 = 1

scorer2 = 2

highscore = 2

So should I try this method and it probably has something more that’s needed or needed to be taken away, or will it only ever be efficient for the first 2 games?

try checking the values to see what comes back

[lua]

print("current score = "…currentScore, "highScore = "…scorer.highScore)

[/lua]

try it in several places to find out what values you are getting

current score doesn’t print and highscore only prints every once in awhile

You overwrote your score variable

[lua]

local score = require( “score” )
– score can’t equal both the score module and your score
 

local score = 0

– now score = 0 so when you try score.get( ) there is no method to call on.

[/lua]

I think you should save everything in one table

[lua]

local scoreTable = {

     player1 = { highScore = 0, currentScore = 0 },

     player2 = { highScore = 0, currentScore = 0 },

     player3 = { highScore = 0, currentScore = 0 }

}

[/lua]

Keep all your scores local and only save them to the JSON file periodically instead of all the time.

Make all of your game logic and score comparisons local.  Get that working first, then add on the JSON storage.

Everything you are trying to achieve is doable, it’s just going to take some time to sort in all out and you’ll learn a lot on the way.

Also, in the beginning, use very descriptive variables like 

[lua]

local player1_HighScore = 0

local player1_CurrentScore = 0

local player2_HighScore = 0

local player2_CurrentScore = 0

local player3_HighScore = 0

local player3_CurrentScore = 0

[/lua]

later on, you can replace them with shorter variables but for now, they will help keep you on track