Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

saveLocalData(), string, number or nil only?

edited February 2012 in Questions Posts: 25

Now that I managed to get the input from the user about his name and getting the score from my game I was thinking about combining these data into a highscore / player name list and store it as local data in a table or a data structure. But Codea told me, that I can store only numbers, strings or nil with saveLocalData(). Is that True? Is there a workaround or is it a question of more general io routines to come? Thanks!

Comments

  • The workaround is to store seperately.

    There has been some discussion on how to open file.io in a way that would be safe.

  • JohnJohn Admin Mod
    Posts: 579

    @Absche you can store a string that contains both the bits of data you want.

    player = "bob"
    score = 200
    
    combined = string.format("return {%s, %d}", player, score)
    saveLocalData("highScore", combined)
    
    -- get score back
    f = loadstring(readLocalData("highScore"))
    combined = f()
    print("player: ", combined[0])
    print("score: ", combined[1]) 
    

    Load string will just execute a string and return a function that will execute that code. In this code your string reconstructs a table containing both your player name and score. You can make more elaborate tables, and there is plenty of code on the net showing how to serialise arbitrary tables fairly easily using this method.

  • Posts: 25

    Oh yes, Thank you both for your replies. As I plan to save only the Top 5 or 10 Players I will go for your straight forward solution, John using two different separators for colums and lines.

  • Posts: 563

    @John - I'm playing around with the best way of providing high score functionality so I can add it to my next tutorial. I quite like the Chipmunk JSON parser but it seems like overkill.

    I tried your approach above but Codea prints out nil for both values. I haven't played with the loadString functionality much so let me have a go at explaining what is going on and you can tell me if I have got it wrong.

    combined is initialised with a string which looks like: "return {bob, 200}" and is saved locally with the key "highScore". So far so good.

    As I understand it loadString will return to f, a function which executes return {bob, 200}. So the line:

    combined = f()

    will now create a table in combined, initialised with bob and 200 as the elements. Now things start getting hazy. I would have thought that bob was at index 1 not index 0? And 200 would be at index 2 not 1?

    Also bob is being treated like a variable and not a string, which would explain why nil is returned as bob is not initialised. I would have expected the table constructor to look more like:

    return {"bob", 200}

    So if I make these tweaks, you get:

    player = "bob"
    score = 200
    
    combinedString = string.format("return {\"%s\", %d}", player, score)
    saveLocalData("highScore", combinedString)
    
    -- get score back
    
    f = loadstring(readLocalData("highScore"))
    combinedTable = f()
    
    print("player: ", combinedTable[1])
    print("score: ", combinedTable[2])
    

    Which seems to work and as a side effect I think I understand loadstring better (which is a very cool function BTW).

  • edited December 2012 Posts: 58

    @john- Although I like your method better after looking at it, this is the way that I came up with for saving the top ten high scores (it's part of a bigger project)-

    HighScores = class()
    
    function HighScores:init()
        self.updated = false
        self.timesUpdated = 0
        self:load()
    end
    
    function HighScores:draw()
        pushStyle()
            textMode(CENTER)
            fill(255, 255, 255, 255)
            fontSize(50)
            --self:update()
            for i, highScore in ipairs(self.scores) do
                text(i..": "..highScore["score"].." by "..highScore["name"], self.x, self.topY - (50 * i)) 
            end
        popStyle()
    end
    
    function HighScores:load()
        --self:clear()
        self.scores = {}
        for i=1, 10 do
            local highScoreTable = {
            score = readProjectData("highScore#"..tostring(i).."score", 0),
            name = readProjectData("highScore#"..tostring(i).."name", "Not yet accquired")
            }
            table.insert(self.scores, highScoreTable)
        end
        self.x = WIDTH/2
        self.topY = HEIGHT - 225
    end
    
    function HighScores:updatePosition(myPosition, checkPosition)
        local score = game.player.moolahEarned
        if score > readProjectData("highScore#"..tostring(checkPosition).."score", 0) then
            return myPosition - 1
        else
            return myPosition
        end
    end 
    
    function HighScores:saveAtPosition(position)
        local score = game.player.score
    
            saveProjectData("highScore#"..tostring(position).."score",
             readProjectData("highScore#"..tostring(tonumber(position - 1)).."score", 0))
    
            saveProjectData("highScore#"..tostring(position).."name",
             readProjectData("highScore#"..tostring(tonumber(position - 1)).."name", "Not yet accquired"))
    end
    
    function HighScores:update()
        print("updating high scores")
        self.updated = true
        local score = game.player.score
        local position  = 11
        for i=0, 9 do
            position = self:updatePosition(position, tonumber(10 - i))
        end
    
        local savePosition = 10
        for i=position, 10 do
            self:saveAtPosition(savePosition)
            savePosition = savePosition - 1
        end
            saveProjectData("highScore#"..tostring(position).."score", score)
            saveProjectData("highScore#"..tostring(position).."name", game.player.name)
        self:load()
    end
    
Sign In or Register to comment.