How do I lock levels with storyboard

If you have a different scene file for each level in your game (probably a bad idea) then yes, you’ll have display.newText in each one of those.

But if you use one scene file for ALL the levels (the best way to do it, in general) then you only have to update that display object.

Jay
[import]uid: 9440 topic_id: 25923 reply_id: 107689[/import]

Jay,

i do have different scenes for each room in the game. i was thinking of setting up the score in the scene 1 and have the other scenes add to it.

so basically you start in scene 1 and then move into the next room scene2 and so forth. so they are not levels but rooms

how would i implement the score to a system like this?
[import]uid: 17701 topic_id: 25923 reply_id: 107693[/import]

Just use a global in main.lua called score and add to that in each level.

When you start a new level, show that score on the screen with display.newText. While you can pass stuff back and forth from level to level, why bother?

Globals are not evil and while there may be reasons not to use them in some cases, a score (I think) fits the bill for a good use.

As far as different scenes for different levels, maybe there’s a good reason to do that, but in a lot of cases when I see that I think it’s because the person is inexperienced. (Although like I posted earlier today, everybody start inexperienced and the final product is more important than how it happens, so I don’t mean that as a “bad” thing.)

In my game Roly-Polies HD I have 60 levels – but just one scene file (I used Director for that – it was pre-Storyboard). Unless every level you’re doing has a different game mechanic, you’re just dealing with the same data presented in different ways.

For example, in Angry Birds there are a bazillion levels, but I’ll bet you they have one routine for them all.

It’s like your kitchen – you don’t have one kitchen to make breakfast, a different one for lunch, and a third to make dinner. You have one kitchen, one set of pans/utensils (unless you’re kosher), but you can still make different meals.

In a game with 30 levels you’ll have 30 different “sets of data” but you don’t need (or want) 30 scene files. For one thing, if you fix a bug in one you’ll end up fixing the same bug in 29 other files. :slight_smile:

Jay

PS - This is a very different way of looking at things than you guys have been discussing, so feel free to ignore it. [import]uid: 9440 topic_id: 25923 reply_id: 107696[/import]

Robmiracle: thanks for your helpful insight on this thread. [import]uid: 76002 topic_id: 25923 reply_id: 107709[/import]

Jay,

well the scene 1 , scene 2 , scene 3 are all different rooms in the hotel. just imagine a point and click a venture game like grisly manor or lost city.

so there are no levels, just one huge entire game. and i would be moving from one door (scene) to the next. thats why i need to keep the score tracked along the way.

hope that clears the mix up.

i didn;t know its possible to create a point and click adventure game with just one scene. the logic you bring up makes a lot of scene, no need to have many copies of the same level.

i have different mechanics for the rooms. I’m assuming you have your scene setup with different function levels to load up on the screen?

i dont ignore ideas and suggestions, there are always different ways to solve a problem. which is always good :slight_smile:

thats true we all start out in experienced and gain skills along the way.

as you can see in post # 15 I’m stuck with my code to get the text box to update the score value and keep it displayed on the screen, on the other hand i have the score correctly adding up in the terminal via the print command. I’m just not able to get it refreshed while displayed.

i’ve tried getting a score setup using ice and no luck with that either.

thanks again for your insight

any suggestions ??

[import]uid: 17701 topic_id: 25923 reply_id: 107741[/import]

Okay, let’s say scene1 is the Lobby, scene2 is the Elevator, and scene3 is a hotel room.

If you were in a community theatre group putting on a play where the action happened in those three locations, in three different acts, you wouldn’t have three stages – you’d have just one that looks like a lobby when the audience comes in and watches the first act.

Then the stage lights dim and the crew scurries around and changes the scenery and when the lights come back on, the audience sees the act that happens in the elevator. (It’s a very moving scene!)

Then the stage lights go down again and there is more scurrying around and when the lights come on you see the interior of the hotel room.

Three rooms, one stage.

You can do the same thing with your game. Basically, you have a list of objects that need to go in each location, along with their coordinates. When you load scene1, you put the lobby background in place and then the front desk object, the chair and couch objects, etc. Whatever you need to have to make your scene look correct.

Your core code doesn’t change, only the objects that go in each scene need to be different.

However, depending on what you’re doing in each room you may need custom code for each – but do you need an entirely new storyboard scene for each, with duplicate code? Maybe, maybe not.

The main thing to remember is that if you have the same code in more than one file you probably want to make one function with that code and call it from multiple places.

I don’t think I gave you any “answers” exactly, but maybe some things to think about that may help you decide what to do. :slight_smile:

Jay
[import]uid: 9440 topic_id: 25923 reply_id: 107745[/import]

let me try and simply things a bit. First there is no magic to Storyboard. It’s just loading lua files and removing them with some transitions.
Your player’s score value is just an integer variable that you increment. There are several ways of making that variable available to each scene:

  1. Make it global… create it in main.lua and leave the “local” off of the front. i.e.
score = 0  

Then in any scene just access the variable score, i.e.

score = score + 1  
  1. Make it global, but part of the super global table _G… i.e.
\_G.score = 0  

to initialize it. Then in any scene:

\_G.score = \_G.score + 1  
  1. Use the fact that “storyboard” is already a global object and that you can extend it by adding variables and functions to it. This reduces the number of global variables and is considered cleaner:
storyboard.score = 0  

Then in any scene you simply:

storyboard.score = storyboard.score + 1  

Nothing magical here. Just a variable and Lua/Corona gives us multipe ways to manage it.

Now for displaying things, this is pretty simple too.

Any display object you created and DO NOT put into a scene’s view group (i.e. “group”) is be displayed ever where. Switching scenes will leave those objects on screen. Storyboard only removes things you explicitly put into “group”.

You can create a HUD (Heads up Display), with control panels, high scores, etc. that has to be in every scene by creating them for example in main.lua (main.lua doesn’t have a storyboard scene view or group).

The problem with this is you may have the items showing at times you don’t want them like on a help scene, credits scene or main menu.

You have two choices: Either create new display objects for each scene that show your HUD bits like the score and let storyboard kill them and create them as you move from scene to scene. This is probably the easiest, though you end up writing the code to display the score multiple times.

Or you can create your HUD elements in main.lua and I would recommend creating a display group to put them in and make that group global somehow. Then you can set the .isVisible flag on the group in scenes where you don’t want it to show, and true when you do.

For instance in main.lua:

\_G.highScore = 0  
\_G.hud = display.newGroup()  
\_G.highScoreText = display.newText(\_G.highScore, 0, 0, "Helvetica", 32)  
\_G.hud:insert(\_G.highScoreText)  
\_G.highScoreText.x = 500  
\_G.highScoreText.y = 25  
\_G.hud.isVisible = false  

Now we have the hud with our high score text in it and it’s invisible since I presume you’re going to a menu screen first.

Now in your scene file where you want the hud to appear, in the “enterFrame” function:

\_G.hud.isVisible = true  

and when you want to update the score:

\_G.highScore = \_G.highScore + 1  
\_G.highScoreText.text = \_G.highScore  

Now if you want to use storyboard to de-global this, simply change out the _G for storyboard.

[import]uid: 19626 topic_id: 25923 reply_id: 107771[/import]

Jay,

thats a good point with having too many different scene files when it could possibly done in one. i don’t know if storyboard works that way. by the way i have just over 40 scenes for the game,

the thing is I’ve already set up the game for separate files for each scene, are transitions only aviavle for scene events?

do you suggest setting each room as a module?

thanks for the options you provided.

Rob,

first of all thanks so much for trying to simplify things for me.

wow thats a lot of code samples and descriptions you provided.

I’m going to work on the sample code examples you provided, and get back to you with my results.

i hope the saving functions can work out for me.

i really like the idea of hiding the HUD when needed.

now i was also planning on have 3 different save slots for the game. now I’m worried about the complexities when saving data. lets say i choose to start with slot 2, now i assume i need to check which save slot i need to store my data, as it would be bad to start accessing the first slot and start adding new scores to it.

thank you so much for helping me along the way with this coding.

ill let you know tomorrow now it turned out.

have you ever thought about writing a Corona Development book to teach people ? i like the way you write and show the concepts.

thanks again.
[import]uid: 17701 topic_id: 25923 reply_id: 107854[/import]

Rob,

thanks for the code, i did get it working but i was wondering how to get it working with the saving and loading.

heres the code

-----------------------------------------------------------------------------------------  
-- main.lua  
-----------------------------------------------------------------------------------------  
display.setStatusBar( display.HiddenStatusBar )  
  
-- require controller module  
local storyboard = require( "storyboard" )  
local scene = storyboard.newScene()  
---------------------------------------------------------------------------------  
-- BEGINNING OF YOUR IMPLEMENTATION  
---------------------------------------------------------------------------------  
--[[ uncomment out below four lines to remove FPS status  
local fps = require("fps")  
local performance = fps.PerformanceOutput.new();  
performance.group.x, performance.group.y = 50, 0;  
performance.alpha = 0.2; -- So it doesn't get in the way of the rest of the scene  
--]]  
  
local json = require( "json" )  
   
function saveTable(t, filename)  
 local path = system.pathForFile( filename, system.DocumentsDirectory)  
 local file = io.open(path, "w")  
 if file then  
 local contents = json.encode(t)  
 file:write( contents )  
 io.close( file )  
 return true  
 else  
 return false  
 end  
end  
   
function loadTable(filename)  
 local path = system.pathForFile( filename, system.DocumentsDirectory)  
 local contents = ""  
 local myTable = {}  
 local file = io.open( path, "r" )  
 if file then  
 print("trying to read ", filename)  
 -- read all contents of file into a string  
 local contents = file:read( "\*a" )  
 myTable = json.decode(contents);  
 io.close( file )  
 print("Loaded file")  
 return myTable  
 end  
 print("file not found")  
 return nil  
end  
   
storyboard.loadTable = loadTable  
storyboard.saveTable = saveTable  
  
storyboard.settings = storyboard.loadTable("settings.json")  
if storyboard.settings == nil then -- didn't load the table  
 storyboard.settings = {}  
 storyboard.settings.musicOn = true  
 storyboard.settings.soundFX = true  
 storyboard.settings.highScore = 100  
 storyboard.saveTable(storyboard.settings, "settings.json")  
end  
  
--[[  
print ("Current HIGH SCORE:", storyboard.settings.highScore)  
storyboard.settings.highScore = storyboard.settings.highScore + 25  
storyboard.saveTable(storyboard.settings, "settings.json")  
print ("HIGH Score updated to:", storyboard.settings.highScore)  
--]]  
  
\_G.highScore = storyboard.settings.highScore  
\_G.hud = display.newGroup()  
\_G.highScoreText = display.newText(\_G.highScore, 0, 0, "Helvetica", 32)  
\_G.hud:insert(\_G.highScoreText)  
\_G.highScoreText.x = 440  
\_G.highScoreText.y = 20  
\_G.hud.isVisible = false  
  
--[[  
local highScoreText = display.newText(string.format("%03d", storyboard.settings.highScore), 0, 0, "Helvetica", 22)  
highScoreText.x = display.contentWidth - 50  
highScoreText.y = 300  
--group:insert(highScoreText)  
--]]  
  
-- load first screen  
storyboard.gotoScene( "intro", "fade", 1000 )  

in line 71 , i placed

\_G.highScore = storyboard.settings.highScore

i don’t know if thats really the best way to store the data, would it be better to use the settings to save to ??

[import]uid: 17701 topic_id: 25923 reply_id: 107986[/import]

in whatever scene you change the score and want to save it:

\_G.highScore = \_G.highScore + 1  
  
storyboard.settings.highScore = \_G.highScore  
storyboard.saveTable(storyboard.settings, "settings.json")  
  

[import]uid: 19626 topic_id: 25923 reply_id: 108152[/import]

Rob,

thanks for the info.

i added a print line to the code and it would update the score in terminal to 1, then in the next scene it was 2. but the output on screen was still 0. when i re launch the app the score gets set to 0 and acts as if nothing was saved.

\_G.highScore = \_G.highScore + 1  
storyboard.settings.highScore = \_G.highScore  
storyboard.saveTable(storyboard.settings, "settings.json")  
print ("intro score:", \_G.highScore )  

im not sure why this isn’t working out for me. it all sounds so simple.

do i need to require the previous data or do i need to load the table into every scene to save?

maybe i need to set up the score thats its set to 0 id new , and if not new then keep current score [import]uid: 17701 topic_id: 25923 reply_id: 108172[/import]

In your scene file, you also have to do:

_G.highScoreText.text = _G.highScore

So that the text field knows to update to the new value.
[import]uid: 19626 topic_id: 25923 reply_id: 108187[/import]

Rob,

that works i put that code below the previous lines of code.

\_G.highScore = \_G.highScore + 1  
storyboard.settings.highScore = \_G.highScore  
storyboard.saveTable(storyboard.settings, "settings.json")  
\_G.highScoreText.text = \_G.highScore  
print ("intro score:", \_G.highScore )  

only problem is thats its not being saved. after i relaunch the app the score goes back to zero

i think the problem stems from setting up the score as 0 in the main.lua files. is there a way to check if _G.highScore has a value instead of always writing it to zero on main.lua ??

here is the main.lua file – UPDATED–

-----------------------------------------------------------------------------------------  
-- main.lua  
-----------------------------------------------------------------------------------------  
display.setStatusBar( display.HiddenStatusBar )  
  
-- require controller module  
local storyboard = require( "storyboard" )  
local scene = storyboard.newScene()  
---------------------------------------------------------------------------------  
-- BEGINNING OF YOUR IMPLEMENTATION  
---------------------------------------------------------------------------------  
--[[ uncomment out below four lines to remove FPS status  
local fps = require("fps")  
local performance = fps.PerformanceOutput.new();  
performance.group.x, performance.group.y = 50, 0;  
performance.alpha = 0.2; -- So it doesn't get in the way of the rest of the scene  
--]]  
  
local json = require( "json" )  
   
function saveTable(t, filename)  
 local path = system.pathForFile( filename, system.DocumentsDirectory)  
 local file = io.open(path, "w")  
 if file then  
 local contents = json.encode(t)  
 file:write( contents )  
 io.close( file )  
 return true  
 else  
 return false  
 end  
end  
   
function loadTable(filename)  
 local path = system.pathForFile( filename, system.DocumentsDirectory)  
 local contents = ""  
 local myTable = {}  
 local file = io.open( path, "r" )  
 if file then  
 print("trying to read ", filename)  
 -- read all contents of file into a string  
 local contents = file:read( "\*a" )  
 myTable = json.decode(contents);  
 io.close( file )  
 print("Loaded file")  
 return myTable  
 end  
 print("file not found")  
 return nil  
end  
   
storyboard.loadTable = loadTable  
storyboard.saveTable = saveTable  
  
storyboard.settings = storyboard.loadTable("settings.json")  
if storyboard.settings == nil then -- didn't load the table  
 storyboard.settings = {}  
 storyboard.settings.musicOn = true  
 storyboard.settings.soundFX = true  
 storyboard.settings.highScore = 100  
 storyboard.saveTable(storyboard.settings, "settings.json")  
end  
  
--[[  
print ("Current HIGH SCORE:", storyboard.settings.highScore)  
storyboard.settings.highScore = storyboard.settings.highScore + 25  
storyboard.saveTable(storyboard.settings, "settings.json")  
print ("HIGH Score updated to:", storyboard.settings.highScore)  
--]]  
  
\_G.highScore = 0  
\_G.hud = display.newGroup()  
\_G.highScoreText = display.newText(\_G.highScore, 0, 0, "Helvetica", 32)  
\_G.hud:insert(\_G.highScoreText)  
\_G.highScoreText.x = 440  
\_G.highScoreText.y = 20  
\_G.hud.isVisible = true  
  
--[[  
local highScoreText = display.newText(string.format("%03d", storyboard.settings.highScore), 0, 0, "Helvetica", 22)  
highScoreText.x = display.contentWidth - 50  
highScoreText.y = 300  
--group:insert(highScoreText)  
--]]  
  
-- load first screen  
storyboard.gotoScene( "intro", "fade", 1000 )  

any ideas ?

by the way in line 60 I’m assigning the score to 100

 storyboard.settings.highScore = 100

would this be a issue as well ? [import]uid: 17701 topic_id: 25923 reply_id: 108191[/import]

Rob,

i was able to get the scoring working by adjusting the code like below

\_G.highScore = storyboard.settings.highScore  
\_G.hud = display.newGroup()  
\_G.highScoreText = display.newText(\_G.highScore, 0, 0, "Helvetica", 32)  
\_G.hud:insert(\_G.highScoreText)  
\_G.highScoreText.x = 440  
\_G.highScoreText.y = 20  
\_G.hud.isVisible = true  

as you can see the below code was

\_G.highScore = 0

and I’m assuming every time i entered into main.lua it would override the score to zero. which is not good.

am i also able to implement a locked / unlocked level data into this settings file? or should i create a new saving data ??

Thanks again [import]uid: 17701 topic_id: 25923 reply_id: 108192[/import]

First, I would like to apologize for not being responsive. I’m on a business trip in Biloxi, MS right now, and well the Roulette wheel has been stealing my time (I’m up $80… starting with $20… for the curious)

Secondly I’m glad you were able to solve that last problem on your own.

You have kind of a problem with your code and it may be leading you to some frustration. You’re mixing using _G and storyboard to hold your game’s information.

Let me try to break this down even finer:

storyboard is a table.
_G is a table.

We are trying to use them to pass information from one module to another because both tables are visible in your various storyboard scene files.

You can add new variables to either (or both) tables simply by saying:

storyboard.someVariableNameYouMakeUp = “fred”

or

_G.someVariableNameYouMakeUp = 12

They are of course different variables since they are in different tables, but either one will work to pass the variable’s data to another scene or be used later in this .lua file.

When I do:

storyboard.settings.highScore = 0

I’m adding a variable to a table called “settings”. It’s nothing more than a lua table… except that you can add tables to tables. So in effect I added a table called settings to the table called storyboard. Then I added a variable called highScore to the settings table.

You could very well add the settings table to the _G table if you wanted too and keep your game settings in that table rather than the storyboard table.

So if you imagine for a second that “storyboard” is a big box with lots of slots to hold things and you put another box named “settings” into one of “storyboard”'s boxes, and the “settings” box had slots to hold other things like your score.

Now you are using a function named “saveTable”, which for your convenience has also been added to the big storyboard box. That function expects to things to be passed to it… A table to save and a file name to save the table too.

So the code:

storyboard.saveTable(storyboard.settings, “settings.json”)

says to find the function saveTable in the “storyboard” box and run it. I want to take the box called “settings” which is also in the storyboard box and save that content to a file named “settings.json”.

The storyboard box also now has a loadTable function which will read in a specified filename and stick it into the box of your choice. So when we do:

storyboard.settings = storyboard.loadTable(“settings.json”)

We are looking in the storyboard box where we have conveniently put the loadTable function and we are saying get the contents of “settings.json” and put it in the box “settings” which happens to be in the box “storyboard”.

What you need to take away from this is that you can put any variable, be it a number, a string or another table and add it to “settings”, which you have “settings” added to “storyboard”.

When you code:

storyboard.settings.levelLocked = {false, true, true, true, true, true }

you are saying that level 1 is unlocked, level 2 is locked, level 3 is locked etc.

By doing this, you have added a new table “levelLocked” to your settings table and that levelLocked table holds true or false values for each level of your game.

That way, when you execute this line of code:

storyboard.saveSettings(storyboard.settings, “settings.json”)

Then you have saved your current level locked/unlocked status.

If you want to test if a levels is locked?

level = 1  
  
if storyboard.settings.levelLocked[level] == true then  
 -- the level is locked  
else  
 -- the level is unlocked  
end  

[import]uid: 19626 topic_id: 25923 reply_id: 108426[/import]

Rob,

no worries for the delay. how did you end up doing with the roulette wheel ? end up making more $$$ ? i was once up $ 100 from $ 20, i should of quit but i didn’t and ended up losing it all.

i see what you mean a problem with the code.

im assuming its much simple to just save the data onto one of the tables and just create a _G just for the hud display. i guess that should work.

it will save me lots of time and lots of lines of code.

ill take a look at the code and see if I’m able to just save to storyboard and not the global

good point in noticing that, thanks

now in my case for the levels locked, it will be doors to different rooms.

now in your example

storyboard.settings.levelLocked = {false, true, true, true, true, true }

now if i have 5 rooms (DOORS) locked it would look like

storyboard.settings.levelLocked = {true, true, true, true, true }

now i do plan on coding it for when i find the key, the first room will be unlocked and set and saved to false

then later on when i find the key to door two ill update the code to false and save and also unlock the door.

level = 1  
   
if storyboard.settings.levelLocked[level] == true then  
 -- the level is locked -- DISPLAY "DOOR is LOCKED , look for key"  
else  
 -- the level is unlocked -- Go to the NEXT Scene  
end   

im assuming the level = 1 means to look at the first value in the level locked settings. so then in level = 3 would look into the third value.

how to i go about unlocking a level ?

do i need to this ?

storyboard.settings.levelLocked = {false, true, true, false, true, true }

Thanks again for your help and advice.

UPDATE:

i figured that i just assign that values, but i had to enter all the info for all the doors.

local function gotoDeleteSlot1( self, event )  
 if event.phase == "began" then  
 \_G.highScore = 100  
 storyboard.settings.highScore = \_G.highScore  
 storyboard.settings.levelLocked = {true, true, true, true, true, true, true }  
 storyboard.saveTable(storyboard.settings, "settings.json")  
 \_G.highScoreText.text = \_G.highScore  
 print ("Deleted slot 1 Current Score is:", \_G.highScore )  
 return true  
 end  
end  

as you see from my code it resets the levels locked back to default on deleting the save file. and i use the below code to unlock a level

storyboard.settings.levelLocked[3] = false

as you can see I’m experimenting with save slots. so I’m assuming the best way is to create separate boxes for each settings file.

but how would i go about checking which saveslot I’m using in storyboard and knowing which file to save to ? [import]uid: 17701 topic_id: 25923 reply_id: 108520[/import]

do i need to this ?

storyboard.settings.levelLocked = {false, true, true, false, true, true }  

That line of code is the same as saying:

storyboard.settings.levelLocked = {} -- make it a table  
storyboard.settings.levelLocked[1] = false -- assume level 1 is unlocked  
storyboard.settings.levelLocked[2] = true  
storyboard.settings.levelLocked[3] = true  
storyboard.settings.levelLocked[4] = true  
storyboard.settings.levelLocked[5] = true  
storyboard.settings.levelLocked[6] = true  

Then consider this:

if storyboard.settings.levelLocked[1] == true then  
 -- do stuff for level 1 being locked  
else  
 -- do stuff for level 1 beig unlocked  
end  

is the exact same as:

currentLevel = 1  
  
if storyboard.settings.levelLocked[currentLevel] == true then  
 -- do stuff for level 1 being locked  
else  
 -- do stuff for level 1 beig unlocked  
end  

In the second case I use a variable to hold the variable so that you don’t have to hard code the tests to see if a level is locked or not. You just have to make sure that currentLevel holds the value of the level you want to work with. [import]uid: 19626 topic_id: 25923 reply_id: 108709[/import]

rob,

thanks for clearing that up. i find the first one to be more effective and less coding. which is always better.

funny thing is i used that code below last night as i revised the code you provided. and it turned out well.

if storyboard.settings.levelLocked[1] == true then  

would it be complex to create two addition settings boxes (one for each save file)
as I’m worried about how the scene would know which one to save to.

for example. select the game save two slot from the menu and once selected the scene1.lua would save and load to the second slot and not the first.

what are your thoughts ??

UPDATE:

so far its working out for me. i just encountered a error with my display text when you click on a locked door

text1 = display.newText( "Door is Locked, the key should be near by", 0, 245, native.systemFontBold, 20 )  
text1:setTextColor( 255 )   
transition.to(text1, {time=1000, onComplete = function() display.remove(text1) end})  

the above code is supposed to display the text and remove it, but if i double click it , it stays on and doesn’t remove itself.

have you had this issue ?? maybe i coded this wrong ? or is there a way to just display.newText with a timer and it then disappears

[import]uid: 17701 topic_id: 25923 reply_id: 108787[/import]

There isn’t enough code to show why double clicking the text would cause a problem. You have not setup any time of event handler in the code sample so I don’t know why a double click messes you up.

Now in your remove code, you do need to set:

text1 = nil

after you do your remove so that it will be garbage collected properly.
[import]uid: 19626 topic_id: 25923 reply_id: 108868[/import]

Rob,

the problem is that if i press it twice in a row it will stay on the screen. is there a way when displaying the display.newText to specify the time the writing will stay on the scene ?

ill look into adding the event handlers for the text

thanks [import]uid: 17701 topic_id: 25923 reply_id: 108894[/import]