Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Help needed with Saving/Loading Data — Gideros Forum

Help needed with Saving/Loading Data

FaustoMFaustoM Member
edited May 2015 in Step by step tutorials
Hi. I am new to Gideros and Lua, so far everything was great, Lua was easy to learn and Gideros works nicely but now I am having troubles figuring how to save data and load. I am following the tutorial on the ebook Gideros Mobile Game Development but the autor asumes everything will work and does not give any hint or clue about common mistakes you can make. I can't find what I am doing wrong, I checked line by line and I have no error but when I try to save it crash. The author uses dataSaver (so do I) but I can't understand how it really works and can't find what I did wrong. Is there an easy way to save and load? I searched everywhere but everyone is using dataSaver as if it is the absolute solution and there is no troubleshooting or complex tutorial about it. Is there a tutorial?

I have an OptionsScene where you can input a name as your username, everything works well until I hit Accept, it then says I have a problem with a line of code but there is no mistake.

I do not know how to attach code nicely so I will just paste it.

OptionsScene.lua
OptionsScene = Core.class(Sprite)
 
function OptionsScene:init()
local optionsbg = Bitmap.new(Texture.new("images/cartoon_cat-800x600.jpg", true))
optionsbg:setAnchorPoint(0.5, 0.5)	
optionsbg:setPosition(conf.width/2, conf.height/2)
self:addChild(optionsbg)
 
local optionsHeading = TextField.new(conf.fontMedium, "Options")
optionsHeading:setPosition((conf.width - optionsHeading:getWidth())/2, 100)
optionsHeading:setTextColor(0xffff00)
self:addChild(optionsHeading)
 
local backText = TextField.new(conf.fontMedium, "Back")
backText:setTextColor(0xffff00)
local backButton = Button.new(backText)
backButton:setPosition((conf.width - backButton:getWidth())/2, conf.height - 50)
backButton:addEventListener("click", function() sceneManager1:changeScene("start", conf.transitionTime, conf.transition, conf.easing)
end)
self:addChild(backButton)
 
 
self:addEventListener(Event.KEY_DOWN, function(event)
if event.KeyCode == KeyCode.BACK then
sceneManager1:changeScene("start", conf.transitionTime, conf.transition, conf.easing)
end
end)
end
Settings.lua
Settings = Core.class()
 
function Settings:init()
 
--our Initial Settings
local settings = {
username = "Player",
}
 
--Check if Settings changed
self.isChanged = false
 
--loading settings if exist
self.sets = dataSaver.load("|D|settings")
if (not self.sets) then 
self.sets = {}
end
 
for key, val in pairs(settings) do 
if self.sets[key] == nil then 
self.sets[key] = val 
self.isChanged = true
end
end
 
end

Likes: Holonist

+1 -1 (+1 / -0 )Share on Facebook

Comments

  • ar2rsawseenar2rsawseen Maintainer
    Hello @FaustoM
    so where exactly does it crash? desktop or device?
    And are there any specific errors with crash?

    In your code I see settings initialization, but there is no saving part there

    Likes: FaustoM

    +1 -1 (+1 / -0 )Share on Facebook
  • FaustoMFaustoM Member
    My bad. I just noticed that I deleted the problematic code and then uploaded it here without it. I copied everything right from the ebook as I did before expecting the same error (to post it here as I should had before) but everything works fine now 8-|

    The code was something similar to this but I must had changed something without noticing because it is working now...

    OptionsScene.lua
    OptionsScene = Core.class(Sprite)
     
    function OptionsScene:init()
    local optionsbg = Bitmap.new(Texture.new("images/cartoon_cat-800x600.jpg", true))
    optionsbg:setAnchorPoint(0.5, 0.5)	
    optionsbg:setPosition(conf.width/2, conf.height/2)
    self:addChild(optionsbg)
     
    local optionsHeading = TextField.new(conf.fontMedium, "Options")
    optionsHeading:setPosition((conf.width - optionsHeading:getWidth())/2, 100)
    optionsHeading:setTextColor(0xffff00)
    self:addChild(optionsHeading)
     
    local backText = TextField.new(conf.fontMedium, "Back")
    backText:setTextColor(0xffff00)
    local backButton = Button.new(backText)
    backButton:setPosition((conf.width - backButton:getWidth())/2, conf.height - 50)
    backButton:addEventListener("click", function() sceneManager1:changeScene("start", conf.transitionTime, conf.transition, conf.easing)
    end)
    self:addChild(backButton)
     
     
    self:addEventListener(Event.KEY_DOWN, function(event)
    if event.KeyCode == KeyCode.BACK then
    sceneManager1:changeScene("start", conf.transitionTime, conf.transition, conf.easing)
    end
    end)
     
    local usernameText = TextField.new(conf.fontSmall, "Your usarname is: "..sets:get("username"))
    usernameText:setPosition(100, 200)
    usernameText:setTextColor(0xffff00)
    self:addChild(usernameText)
     
    local changeText = TextField.new(conf.fontSmall, "Change it")
    changeText:setTextColor(0x00ff00)
    local changeButton = Button.new(changeText)
    changeButton:setPosition(conf.width - changeButton:getWidth() - 100, 200)
    self:addChild(changeButton)
     
    changeButton:addEventListener("click", function()
    local textinputDialog = TextInputDialog.new("Change your username", "Enter your new username", sets:get("username"), "Cancel", "Save")
    textinputDialog:addEventListener(Event.COMPLETE, function(event)
    if event.buttonIndex ~= nil then
    sets:set("username", event.text, true)
    usernameText:setText("Your username is: "..sets:get("username"))
    end
    end)
    textinputDialog:show()
    end)
    end
    Settings.lua
    Settings = Core.class()
     
    function Settings:init()
     
    --our Initial Settings
    local settings = {
    username = "Player",
    }
     
    --Check if Settings changed
    self.isChanged = false
     
    --loading if exist
    self.sets = dataSaver.load("|D|settings")
    if (not self.sets) then 
    self.sets = {}
    end
     
    for key, val in pairs(settings) do 
    if self.sets[key] == nil then 
    self.sets[key] = val 
    self.isChanged = true
    end
    end
     
    --save settings
    function Settings:save()
    --check if anything changed
    if(self.isChanged) then
    self.isChanged = false
    dataSaver.save("|D|setttings", self.sets)
    end
    end
     
    --get value
    function Settings:get(key)
    return self.sets[key]
    end
     
    --set new value
    function Settings:set(key, value, autosave)
    if(self.sets[key] == nil or self.sets[key] ~= value) then
    self.sets[key] =  value
    self.isChanged = true
    end
    if autosave then
    self:save()
    end
    end
     
    end
    I guess I will never know what was wrong with my previous code... Is there any detailed tutorial on saving and loading? I always find the same structure with no explanation whatsoever. Until now I found Lua very easy to understand and simple to code but this saving/loading method escapes my understanding.

    I am testing with Gideros Player. Should the username remain when I restart or open a new Gideros Player windows? The username is always "Player". It retains the changes from scene to scene but when I restart or open it again it is gone :/

    Thanks a lot in advance. I really appreciate the time you are taking to read this wall of text and reply.
  • piepie Member
    Accepted Answer
    Hi, this should help:

    http://appcodingeasy.com/Gideros-Mobile/Save-and-load-data-module-for-Gideros-Mobile

    About the player name not updating between restarts, I think you have a typo:
    you're saving changes on "|D|setttings" but loading "|D|settings".
    :)

    Likes: Holonist

    +1 -1 (+1 / -0 )Share on Facebook
  • HolonistHolonist Member
    edited May 2015 Accepted Answer
    variant without dataSaver:
    require "json"
     
    player = {}
    player.name ="holo"
    player.str = 2
     
    --json.encode() converts your table to a string
    local serialPlayer = json.encode(player)
     
    --serialPlayer looks like this: ["name":"holo","str":2]
     
    --save your json string to a file
    local file = io.open("|D|player.txt", "w")
    file:write(serialPlayer)
    file:close()
     
    --load the json string from your file 
    local file = io.open("|D|player.txt", "r")
    local serialPlayer = file:read("*all")
    file:close()
     
    --convert the string back to a table with json.decode()
    player = json.decode(serialPlayer)
    In reality, you will want to load your data on game start, and save them in the end.
    Here you will have to check if the file exists first
     
    --if player.txt exists, load player. else create empty player table/object
    if isFile("|D|player.txt") then
    	local file = io.open("|D|player.txt", "r")
    	local serialPlayer = file:read("*all")
    	file:close()
     
    	player = json.decode(serialPlayer)
    else
    	player = {}
    	player.name = ""
    	player.str = 0
    end
     
    --the function we use above to check if our save file exists
    function isFile(fileName)
    	local file = io.open(fileName)
    	if file then
    		file:close()
    		return true
    	else
    		return false
    	end
    end
    That's basically how you save and load stuff.

    Unlike datasaver, here everytime we attempt to save/load something, the complete object gets read/overwritten, instead of single attributes. So here you have to decide between simplicity and speed. Though in my opinion, dataSaver never makes a noteable difference, unless you're working with HUGE tables (10k+ entries). And in the end, even datasaver has to rewrite the whole txt file anyway.

    If you want to encrypt your savegames with the same method, have a look at
    http://giderosmobile.com/forum/discussion/5625/simple-savegame-encryption#Item_1

    You can add me on Skype (theholonist) if you like
  • FaustoMFaustoM Member
    Hi @pie and @Holonist. After correcting that typo @pie mentioned everything works as it should. Thanks a lot. @Holonist, I will mess around with that other way of saving you posted, it looks cleaner in some parts. The encryption is also welcomed. Thanks a lot for both of your time. I really appreciate the help.
Sign In or Register to comment.