Storyboard/Composer question

This should fix the error you gave me in your last post…

local composer = require("composer") local widget =require ("widget") local function godeckbuilder( event ) if ("ended" == event.phase) then composer.gotoScene( "deckbuilder" ) end end local deckbuilderbtn = widget.newButton { width = 100, height = 50, defaultFile = "icon.png", overFile = "icon.png", label = "deck builder", onEvent = godeckbuilder, } deckbuilderbtn.x = 10 deckbuilderbtn.y = 10

As for your other questions …

When you add an object to the sceneGroup like this

sceneGroup:insert(object)

Then when you change scenes the object removes itself…

But i dont know if this is a bug or what not but adding a newText to scene group to doesnt remove the obejct when changing scenes…

So i just do 

display.remove(object)

Now for canceling timers all you do is 

timer.cancel(timerVariable)

… 

You should look at “SCOPE” tuts for corona sdk… They are a little complicated i guess but it helps…

And like i mentioned before! You can always add me on Skype and id be glad to help out with any questions you might have!

Good Luck!

Hi, thanks for all your help so far and I’ve managed to get the first button working but the second button (returning to the menu) doesn’t seem to work and as far as i’m aware im using the same code except with different names for variables and functions.

here’s my code so far

Main.lua

display.setStatusBar( display.HiddenStatusBar )      

local composer = require(“composer”)

local widget =require (“widget”)

local function godeckbuilder( event )

if (“ended” == event.phase) then

composer.gotoScene( “deckbuilder” )

end

end

local deckbuilderbtn = widget.newButton

{

width = 100,

height = 50,

defaultFile = “icon.png”,

overFile = “icon.png”,

label = “deck builder”,

onEvent = godeckbuilder,

}

deckbuilderbtn.x = 10

deckbuilderbtn.y = 10

deckbuilder.lua

display.setStatusBar( display.HiddenStatusBar )      

local composer = require (“composer”)

local widget = require (“widget”)

local function gomenu( event )

if (“ended” == event.phase) then

composer.gotoScene( “main” )

end

end

local menubtn = widget.newButton

{

width = 100,

height = 50,

defaultFile = “icon.png”,

overFile = “icon.png”,

label = “menu”,

onEvent = gomenu,

}

menubtn.x = 10

menubtn.y = 10

and the error it gives me is

attempt to concatenate global ‘scenename’ (a nil value)

Hello again! I’m on mobile right now as I’m at work so sorry if I get something wrong… But what I think is wrong is This composer.gotoScene( “main” ) Has to be this composer.gotoScene( “Main” ) Because the file name is “Main.lua”… Lua is a very very case sensitive language. Good Luck!

I tried making that correction but it hasnt fixed the issue, also my “Deckbuilder” file has a capital d whereas the code for it does not so i dont think thats the issue. The rest of the code is copy pasted from the working one as i said its just the variable names changed.

Thanks for all the help its been very useful.

Can you please repost the code? But this time in the editor press the “<>” and add it in there…

Thanks!

I think i know the problem… After you require composer you have to add

local scene = composer.newScene()

In every file.

No luck so far with the local scene = composer.newscene()

the error appears as soon as it switches to the second scene, but before i click the button(i.e as soon as i press the first button and it loads the second scene (second button shows up)).

main.lua

display.setStatusBar( display.HiddenStatusBar ) local composer = require("composer") local widget =require ("widget") local function godeckbuilder( event ) if ("ended" == event.phase) then composer.gotoScene( "blank" ) end end local deckbuilderbtn = widget.newButton { width = 100, height = 50, defaultFile = "icon.png", overFile = "icon.png", label = "deck builder", onEvent = godeckbuilder, } deckbuilderbtn.x = 10 deckbuilderbtn.y = 10

deckbuilder.lua

display.setStatusBar( display.HiddenStatusBar ) local composer = require ("composer") local widget = require ("widget") local function gomenu( event ) if ("ended" == event.phase) then composer.gotoScene( "Main" ) end end local menubtn = widget.newButton { width = 100, height = 50, defaultFile = "icon.png", overFile = "icon.png", label = "menu", onEvent = gomenu, } menubtn.x = 10 menubtn.y = 10

On what line is it saying the error is in? And where is that line?

?:0: attempt to concatenate global ‘scenename’ (a nil value)

stack traceback:

?: in function ‘gotoScene’

main.lua:7 in function ‘_onEvent’

?: in function ‘?’

?: in function <?:677>

?: in function <?:221>

Is the error, it gives this after i press the first button and it loads the second scene (deckbuilder), but before i press the second button

I think this means the error is in main.lua but i think at this point it has left main.lua

Ok so since you are using composer you need to use the scenes… And you are making a game right? So if you dont use the scenes then you will have big problem later on when you start adding more code…

So here is a file of your problem(FIXED) 

Download it and unzip it and check out what i did…

http://www.mediafire.com/download/6y8b8z90xjj9q86/HELP.zip

Now ONLY use main.lua for stuff like loading files and stuff like that… And of course going to your first scene…

Corona does this…

main.lua --> Next Scene --> Next Scene and so on… 

Good Luck!

Can I recommend a few things to improve use of Composer?  Composer is best when you do things in the right place and understand scope. In one of the code blocks agive, things are being created in “scene:show()” that are best done in “scene:create()” The techinque above appears to be done to avoid scope issues.  First I’ll post the original code, adding some comments, then I’ll present what I recommend for the code.

local composer = require( "composer" ) local scene = composer.newScene() local widget = require("widget") function scene:create( event ) local sceneGroup = self.view local BG = display.newRect(display.contentCenterX, display.contentCenterY, 1080, 1920) BG:setFillColor(0, 0, 1) sceneGroup:insert( BG ) end function scene:show( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "did" ) then local counter = 100 --\<---- should be local to the whole scene local counterTimer --\<---- should be local to the whole scene -- these next three lines should be in ":create()" but counterText should be forward declared at the top local counterText = display.newText( "100", display.contentCenterX, display.contentCenterX, native.systemFontBold, 70) counterText:setFillColor( 1, 0, 0 ) sceneGroup:insert(counterText) -- best placed outside of this funciton to avoid nested functions. local function updateCounter(event) counter = counter - 1 counterText.text = string.format("%d", counter ) end local counterTimer = timer.performWithDelay( 1000, updateCounter, -1 ) -- again move out side. local function GotoMenu(event) if event.phase == "ended" then timer.cancel(counterTimer) display.remove(counterText) composer.gotoScene( "Menu", { time = 1000, effect = crossFade }) end end -- should be in :create() local btn = widget.newButton { top = display.contentCenterY, left = display.contentCenterX - 80, width = 84, height = 105, font = native.systemFontBold, id = "button1", label = "Press To Go To Menu", onEvent = GotoMenu } sceneGroup:insert(btn) end end scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) return scene

This is what I would do:

local composer = require( "composer" ) local scene = composer.newScene() local widget = require("widget") -- forward declarations local counter = 100 local counterTimer local counterText local function updateCounter(event) counter = counter - 1 counterText.text = string.format("%d", counter ) end local function gotoMenu(event) --\<---- try and maintain camel case variables if event.phase == "ended" then timer.cancel(counterTimer) display.remove(counterText) composer.gotoScene( "menu", { time = 1000, effect = crossFade }) end end function scene:create( event ) local sceneGroup = self.view local BG = display.newRect(display.contentCenterX, display.contentCenterY, 1080, 1920) BG:setFillColor(0, 0, 1) sceneGroup:insert( BG ) counterText = display.newText( "100", display.contentCenterX, display.contentCenterX, native.systemFontBold, 70) counterText:setFillColor( 1, 0, 0 ) sceneGroup:insert(counterText) local btn = widget.newButton { top = display.contentCenterY, left = display.contentCenterX - 80, width = 84, height = 105, font = native.systemFontBold, id = "button1", label = "Press To Go To Menu", onEvent = gotoMenu --\<------ camel case variable/function names } sceneGroup:insert(btn) end function scene:show( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "did" ) then counterTimer = timer.performWithDelay( 1000, updateCounter, -1 ) elseif ( phase == "will" ) then -- initialize things here that need to be reset each time the scene loads. counter = 100 end end function scene:hide( event ) local phase = event.phase if ( phase == "will" ) then if counterTimer then timer.cancel( counterTimer ) counterTimer = nil end end end scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) return scene

Let me explain a few things.  Composer is designed to create a scene once, and as long as you don’t hit a low memory situtation, the next time you access the scene it should not have to be re-created. Static things like displaying the counter and the button don’t change each time the scene loads. Anything like this should be created in scene:create(). 

The only thing scene:show() should do is reset any values that may change during the scene’s run that need reset back to their beginning values (in this case “counter”) during the “will” phase and then during the “did” phase start up anything that needs to start after the scene is on the screen. This includes physics, timers, transitions. You would hate for objects to already be falling before the scene comes fully on the screen. In this case, you have a timer.

scene:show() will always be paird with a scene:hide(). You are guarenteed to get these every time a scene loads and a scene exits. This is why you do these “starting” things here. And anything you start, you should attempt to top in scene:hide().  The scene:create() event is not guarenteed to fire each time the scene is entered (since it’s supposidly already created when you re-enter the scene). You can’t depend on it to start things.

Scope is important when working with composer.  In this case, you create things inside of scene:create(), but scene:show() may need to access the object. Other functions may need to as well. When this is the case you declare the variable/function at the highest code block where it’s visible to all other functions that needs it. This is why I moved counter, counterTimer, counterText and such to the main chunk of the scene. Now any composer event can access them.

Nested functions (functions inside of other functions, or functions inside of if statements inside of functions) are harder to trouble shoot. It’s like programming yourself into a box (literally) where all you can see is the inside of the box. In some cases this makes sense, but in most cases like this, they don’t make sense to bury inside of an if statement inside of scene:show(). I’ve moved these functions to the main chunk. Now everything is visible where it’s needed.

Finally a couple of minor nit picks. Most people prefer camelCase where the first letter is lower case, and subsequent word is capitalized. Of course you can code your variables in any style you want, but more Lua developers use camelCase. But in this case, many things are camelCase, but the one variable was not. Consistancy matters.

This leads into the final thing, it’s best to keep filenames all lower case where possible.  You should avoid Menu.lua and use menu.lua where you can. Devices are case sensitive and the simulator is not. It’s too easy to get into the “it works on the simulator but not on the device” when scene names and filenames don’t maintain a predicable standard, which for most people, its using lower case file names.

Sorry to hijack the main thread, but it’s good when we can all have consistant usage.  Now back to the real issue.

Rob

Thanks for the input @Rob!!! You are so much better at tutoring then me haha. I tend to like to sit there and do things quietly and just know what i’m doing in my head.

Thanks!

Hope Rob’s post helps you!!!

Good Luck!

Thanks a lot you guys I’ll check out the code and get back to you with the results

Just a quick question though as if I have this right

Does this just set the background? also, what goes in “put background in here”? just the PNG file?

function scene:create( event )

    local sceneGroup = self.view  

    --Put background in here

end

function scene:show( event )

    local sceneGroup = self.view

    local phase = event.phase

    if ( phase == “did” ) then

(code goes here)

    end

end

Is that the part that actually runs the scene? And all the buttons/objects/counters all go in there as they would normally?

What do these two lines do?

scene:addEventListener( “create”, scene )

scene:addEventListener( “show”, scene )

Thanks!

Hello! Once again… Next time can you post your code in the editor? Thanks!

Ok so in the background… You can add any images you need to display… Just nothing anything that you’ll need to access like btns etc…

And the “(code goes here)” you put all the stuff you said the timers objects counters…

And those last 2 lines are listener’s to initiate the scene…

Good Luck!

Thanks a lot for all the help guys, I’ll go try the things you’ve suggested soon I just have a few what i hope are simpler (maybe stupid) questions.

function scene:create( event ) local sceneGroup = self.view --Put background in here end&nbsp;

All the above does is set the background, right? also what goes in “–put background here”? is it just the “XXXX.PNG”?

Also, what does self.view do?

function scene:show( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "did" ) the (insert code here) end end

Is the above code what actually runs/happens in the scene? all code such as buttons, images, text displayed in the scene goes there?

sceneGroup:insert(deckbuilderbtn)

Does this add the function to the ‘local sceneGroup’? is this so that it disappears when you leave the scene?

Also, i’ve been curious for a while what the following three lines of code do and it would be great if someone could tell me what they do  individually (i like to understand what each command does rather than learning blocks of code to copy/paste)

Thanks!

scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) return scene

Hey again, I’m at an appointment atm… If no one helps you I’ll be back soon!

What @SonicX278 meant by “–Put background in here” is you create any objects that you need to display there, such as:

local background = display.newImageRect(“background.png”, 570, 360)

background.x = display.contentCenterX

background.y = display.contentCenterY

local scoreLabel = display.newText(“Score:”, 50, 25, native.systemFontBold, 18)

local btn = widget.newButton({

})

(using code examples above).

Then when he writes:  (insert code here)

he’s saying to put other code you need (we don’t know what you need) in here. There is however only some code you should put there. Only put things that start things in motion:  Physics, Timers, Transitions, Audio Playing, Runtime listeners, etc.

Rob

Thanks a lot guys its working now, you’ve been very helpful

Thanks @Rob for explaining! Didn’t have the time to do it.

@lazarfn, Your welcome! Hope your game comes together! Good Luck!

New question sorry…

but i cant seem to solve the error im getting here

Local function addCardOne( event ) if ("ended" == event.phase) then deck.insert( {(cardIndex[one])} ) end end

it says the error is on line 110 and it expects an ‘=’ near ‘function’

just to clarify im trying to insert a row from one table ( {…=…, …=… etc}) into another table where cardIndex is the first table and i want row ‘one’, and deck is the second table.

‘one’ is a local variable im using to keep track of cards as a new set is dealt each time a button is pressed. Basically it is some number, not necessarily one.

edit: nevermind, turns out i’d capitalized Local which meant it wasnt a command anymore

Edit2:

I’ve run into another problem

local cardIndex = ( { cat = a, subcat = a, cardType = a, name = a, def = a, atk = a, effect = a, pic = "jack1.png" , exist = 1 } { cat = a, subcat = a, cardType = a, name = , def = a, atk = a, effect = a, pic = "jack2.png" , exist = 1 } { cat = a, subcat = a, cardType = a, name = , def = a, atk = a, effect = a, pic = "jack3.png" , exist = 1 } { cat = a, subcat = a, cardType = a, name = , def = a, atk = a, effect = a, pic = "jack4.png" , exist = 1 } { cat = a, subcat = a, cardType = a, name = , def = a, atk = a, effect = a, pic = "jack5.png" , exist = 1 } { cat = a, subcat = a, cardType = a, name = , def = a, atk = a, effect = a, pic = "jack6.png" , exist = 1 } { cat = a, subcat = a, cardType = a, name = , def = a, atk = a, effect = a, pic = "jack7.png" , exist = 1 } { cat = a, subcat = a, cardType = a, name = , def = a, atk = a, effect = a, pic = a, exist = 0 } { cat = a, subcat = a, cardType = a, name = , def = a, atk = a, effect = a, pic = a, exist = 0 } { cat = a, subcat = a, cardType = a, name = , def = a, atk = a, effect = a, pic = a, exist = 0 } { cat = a, subcat = a, cardType = a, name = , def = a, atk = a, effect = a, pic = a, exist = 0 } ) return cardIndex

for the moment all im using is the ‘pic’ part of the table to test part of my app, it gives an error saying an error at line 3 where it expects ) to close the ( from line one beside ‘{’