Hi
I posted this over on the game development forum, but i think it might be better placed here as im using director
My game currently has a main menu and multiple levels. Each level is on a new screen.
After each level is completed i would like it to save (either auto save or maybe user saves manually once level is complete with a pop up save button).
I would then like the user to be able to load this from the main menu.
I have tried looking at all the samples and older forum post but its getting really confusing.
From what i can gather from these examples is that i need to create a database, have each level write to this database and have a load from database function in my main menu.
Please could someone help by making a really easy to use guide for implementing this.
Just a bit more detail on what i would like to be saved and loaded.
Once the level is complete, save this. When user chooses load from main menu The next level (screen) will be loaded.
I have read that using screens for levels isn’t the best way to go about creating games, however i feel comfortable using them at the moment as a beginner
All help is appreciated.
[import]uid: 24981 topic_id: 5884 reply_id: 305884[/import]
Actually this is not a Director’s issue but I’ll try to help you.
I have a file called settings.lua where I have functions to get and set global variables and load and save functions to use the SQLite database. You can use the save and load for what you want:
[code]
module(…, package.seeall)
– DATABASE
require “sqlite3”
local dbPath = system.pathForFile(“settings.db”, system.DocumentsDirectory)
local db = sqlite3.open( dbPath )
db:exec [[CREATE TABLE IF NOT EXISTS tb_settings (
name VARCHAR(50) PRIMARY KEY,
type VARCHAR(1),
value_string TEXT,
value_number NUMBER);]]
local function onSystemEvent( event )
if( event.type == “applicationExit” ) then
db:close()
end
end
– VARIABLES
local tabVars = {}
tabVars[“numPlayers”] = 2
– FUNCTIONS
– GET
function settings:getVar ( pVarName )
return tabVars[pVarName]
end
– SET
function settings:setVar ( pVarName, pVarValue )
tabVars[pVarName] = pVarValue
end
– LOAD
function settings:loadVar( pVarName )
for row in db:nrows(“SELECT * FROM tb_settings WHERE name = '” … string.upper(pVarName) … “’”) do
if row.type == “N” then
return tonumber(row.value_number)
else
return tostring(row.value_string)
end
end
return nil
end
– SAVE
function settings:saveVar( pVarName, pVarValue )
if type(pVarValue) == “nil” then
pVarValue = tabVars[pVarName]
else
settings:setVar ( pVarName, pVarValue )
end
local vVarType
if type(pVarValue) == “number” then
vVarType = ‘N’
elseif type(pVarValue) == “string” then
vVarType = ‘C’
else
return true
end
for row in db:nrows(“SELECT count(*) as cont FROM tb_settings WHERE name = '” … string.upper(pVarName) … “’”) do
if row.cont > 0 then
if vVarType == “N” then
db:exec (“UPDATE tb_settings SET type = ‘N’, value_number = " … pVarValue … " WHERE name = '” … string.upper(pVarName) … “’;”)
else
db:exec (“UPDATE tb_settings SET type = ‘C’, value_string = '” … pVarValue … “’ WHERE name = '” … string.upper(pVarName) … “’;”)
end
else
if vVarType == “N” then
db:exec (“INSERT INTO tb_settings ( name, type, value_number) VALUES (’” … string.upper(pVarName) … “’,‘N’,” … pVarValue … “);”)
else
db:exec (“INSERT INTO tb_settings ( name, type, value_string) VALUES (’” … string.upper(pVarName) … “’,‘C’,’” … pVarValue … “’);”)
end
end
end
end
[/code] [import]uid: 8556 topic_id: 5884 reply_id: 20176[/import]
Thanks for the quick reply Ricardo
Where would i insert this code and how would i implement this into my levels and menu.
Sorry for asking such novice questions, im still a beginner 
[import]uid: 24981 topic_id: 5884 reply_id: 20178[/import]
hey Ricardo! I would also love some additional information on how to implement this code. I’m using your Director library heavily (Thank you by the way!) and I think this is a great way to transfer things back and forth between pages. [import]uid: 13801 topic_id: 5884 reply_id: 20284[/import]
That’s easy, you only need to put it like this:
settings:setVar ( "myVar", 1 )
print("result: " .. settings:getVar ( "myVar" ) )
And at the main.lua file you put this:
local settings = require("settings")
[import]uid: 8556 topic_id: 5884 reply_id: 20295[/import]
Ace! Thanks so much! [import]uid: 13801 topic_id: 5884 reply_id: 20296[/import]
Hey Ricardo
So iv created the settings.lua file and inserted the other parts of the code into my level and main.lua files. What would i do next.
It would be great if you could create a video explaining all this like you did with director class as that was very helpful
[import]uid: 24981 topic_id: 5884 reply_id: 20346[/import]
Iv brushed up on my SQL skills and im understanding it a lot better now. Thanks for the help [import]uid: 24981 topic_id: 5884 reply_id: 20434[/import]
Using database for storing variables is an easy way to save states and progress but to customize it you need some knowledge in SQL. [import]uid: 8556 topic_id: 5884 reply_id: 20499[/import]
Can you help me out by explaining what variables this is saving and what I should be editing for my application? I am trying to create locked levels and only unlock them when the user beats the previous level.
This is the function to decifer if the level is playable, but i’m not sure what to save and how to save it.
if lastLevelUnlocked == levelNumber then
levelPlayable=true
elseif lastLeveunlocked \> levelNumber then
levelPlayable=true
elseif lastLevelUnlocked \< levelNumber then
levelPlayable=false
end
[import]uid: 32061 topic_id: 5884 reply_id: 22876[/import]
Ok, let’s go step-by-step.
1 - Create a file called settings.lua with the code that I put on the comment #1.
2 - At the main.lua file, you have to require it, like this:
local settings = require("settings")
3 - When you start the game, you want to load the stored variable so you have to do it at the main.lua file:
-- Test if it exists. If false then create it with a 0 value
if type(settings:loadVar("lastLevelUnlocked")) == "nil" then
settings:saveVar( "lastLevelUnlocked", 0 )
else
settings:setVar( "lastLevelUnlocked", settings:loadVar("lastLevelUnlocked") )
end
4 - Change your test to decipher if the level is playable:
if settings:getVar("lastLevelUnlocked") \>= levelNumber then
levelPlayable=true
else
levelPlayable=false
end
5 - Finally, when the player beats the level, you just need to save the state:
settings:saveVar( "lastLevelUnlocked", settings:getVar("lastLevelUnlocked") + 1 )
[import]uid: 8556 topic_id: 5884 reply_id: 22924[/import]
Wow. Thanks for the help!
My Main file now looks like this.
local settings = require("settings")
-- Test if it exists. If false then create it with a 0 value
if type(settings:loadVar("lastLevelUnlocked")) == "nil" then
settings:saveVar( "lastLevelUnlocked", 0 )
else
settings:setVar( "lastLevelUnlocked", settings:loadVar("lastLevelUnlocked") )
end
if settings:getVar("lastLevelUnlocked") \>= levelNumber then
levelPlayable=true
else
levelPlayable=false
end
settings:saveVar( "lastLevelUnlocked", settings:getVar("lastLevelUnlocked") + 1 )
-- Import director class
local director = require("director")
-- Create a main group
local mainGroup = display.newGroup()
-- Main function
local function main()
-- Add the group from director class
mainGroup:insert(director.directorView)
-- Change scene without effects
-- This sends user to the main menu
director:changeScene("screen1")
return true
end
-- Begin
main()
And my Settings.lua file looks like this.
module(..., package.seeall)
---------------------------------------------------------
-- DATABASE
---------------------------------------------------------
require "sqlite3"
--
local dbPath = system.pathForFile("settings.db", system.DocumentsDirectory)
local db = sqlite3.open( dbPath )
--
db:exec [[CREATE TABLE IF NOT EXISTS tb\_settings (
name VARCHAR(50) PRIMARY KEY,
type VARCHAR(1),
value\_string TEXT,
value\_number NUMBER);]]
--
local function onSystemEvent( event )
if( event.type == "applicationExit" ) then
db:close()
end
end
---------------------------------------------------------
-- VARIABLES
---------------------------------------------------------
local tabVars = {}
--
tabVars["numPlayers"] = 2
---------------------------------------------------------
-- FUNCTIONS
---------------------------------------------------------
-- GET
function settings:getVar ( pVarName )
return tabVars[pVarName]
end
-- SET
function settings:setVar ( pVarName, pVarValue )
tabVars[pVarName] = pVarValue
end
-- LOAD
function settings:loadVar( pVarName )
for row in db:nrows("SELECT \* FROM tb\_settings WHERE name = '" .. string.upper(pVarName) .. "'") do
if row.type == "N" then
return tonumber(row.value\_number)
else
return tostring(row.value\_string)
end
end
return nil
end
-- SAVE
function settings:saveVar( pVarName, pVarValue )
--
if type(pVarValue) == "nil" then
pVarValue = tabVars[pVarName]
else
settings:setVar ( pVarName, pVarValue )
end
--
local vVarType
--
if type(pVarValue) == "number" then
vVarType = 'N'
elseif type(pVarValue) == "string" then
vVarType = 'C'
else
return true
end
--
for row in db:nrows("SELECT count(\*) as cont FROM tb\_settings WHERE name = '" .. string.upper(pVarName) .. "'") do
if row.cont \> 0 then
if vVarType == "N" then
db:exec ("UPDATE tb\_settings SET type = 'N', value\_number = " .. pVarValue .. " WHERE name = '" .. string.upper(pVarName) .. "';")
else
db:exec ("UPDATE tb\_settings SET type = 'C', value\_string = '" .. pVarValue .. "' WHERE name = '" .. string.upper(pVarName) .. "';")
end
else
if vVarType == "N" then
db:exec ("INSERT INTO tb\_settings ( name, type, value\_number) VALUES ('" .. string.upper(pVarName) .. "','N'," .. pVarValue .. ");")
else
db:exec ("INSERT INTO tb\_settings ( name, type, value\_string) VALUES ('" .. string.upper(pVarName) .. "','C','" .. pVarValue .. "');")
end
end
end
end
Where do I enter the function that states when something happens, the level is completed, thus unlocking the next level?
Also, where do I put the list of levels or do I need to? [import]uid: 32061 topic_id: 5884 reply_id: 22965[/import]
I am working on the same issue right now. From above, do I used this code at the end of the level?
settings:saveVar( “lastLevelUnlocked”, settings:getVar(“lastLevelUnlocked”) + 1
[import]uid: 33363 topic_id: 5884 reply_id: 22982[/import]
Guys,
It depends on how you structured the game. If you are using a table to put all your levels then you just need to put the commands with the table. If you are using a bunch of objects to represent each level then you have to test on each.
Think like Cut The Rope, if you have equal or more then 250 stars, you can play the Cosmic Box levels. You don’t need to create a single variable for all your levels. Use the settings:getVar(“lastLevelUnlocked”) to store the “star count” like Cut The Rope then put a test on level 5 (example) to check if the lastLevelUnlocked is more or equal to 5, something like that.
Before going coding, stop for a moment to create a structure to your software. [import]uid: 8556 topic_id: 5884 reply_id: 22986[/import]
My game is structured using director obviously and each level is a different lua file. level1.lua level2.lua etc…
I have a single goal at the end of each level, to touch a crate with an object, so a collision.
My confusion is, do I need to list out each level and mark them as locked or unlocked? or does the setting.lua file take care of that with variables?
Thanks again for your help. [import]uid: 32061 topic_id: 5884 reply_id: 22988[/import]
@4d32petersc
This settings.lua file that I put here is only to make easier the way you use variables between scenes and load/save them into a database. How do you will organize your levels on the screen it’s up to you. If you want to save them all or just a token is your choice. Also, this file doesn’t work with display objects, only data.
My advice is to create movieclips with 2 frames (locked/unlocked) and test the lastLevelUnlocked variable. Each movieclip can be a button to one level and can be changed to go to the level or not.
[code]
local level01button = movieclip.newAnim{“levelLocked.png”,“levelUnlocked.png”}
localGroup:insert(level01button)
local function level01touch ( event )
if event.phase == “ended” then
if settings:getVar(“lastLevelUnlocked”) >= 1 then
director:changeScene(“level1”,“fade”)
end
end
end
level01button:addEventListener( “touch” , level01touch )
if settings:getVar(“lastLevelUnlocked”) >= 1 then
level01button:stopAtFrame(2)
end
[/code] [import]uid: 8556 topic_id: 5884 reply_id: 22991[/import]
That makes sense. The issue I can’t figure out is where the data is stored for each level?
So each level is shown as locked until an event changes it to unlocked, and then the game references that file whenever it is opened. [import]uid: 32061 topic_id: 5884 reply_id: 23016[/import]
Yes, if you use the saveVar function then the variable will be saved at SQLite database. If you use only the setVar function then the variable will stay at the memory inside the tabVars table at settings.lua file. [import]uid: 8556 topic_id: 5884 reply_id: 23090[/import]
Hello Ricardo, I read through this to try and figure out how to do this, and I kind of got an idea but I’m not sure…
as an example, could you show me how the code could be used with ghosts vs monsters sample code so I could get an idea how it would look?
I’m recently new to lua so I’m still learning
Thanks [import]uid: 14940 topic_id: 5884 reply_id: 23336[/import]
any help? =[[import]uid: 14940 topic_id: 5884 reply_id: 23799[/import]