Level Navigation

I’m using the http://www.newnams.com/corona-level-selection-tutorial

I’m unclear on how I would call a level using this. Say I have Level1.lua
How would I call that level if I select World 1 - Level 1 ?
Or if I had let’s say level21.lua for World 2 - Level 1 ?
My game is slowly getting there and I can’t wait to share it with everyone.
Thanks for any help.
-Cheers [import]uid: 72845 topic_id: 34149 reply_id: 334149[/import]

Based on what I see in the tutorial, you know the world…

"world #" = storyboard.world

And the button itself carries the level number.

"level #" == event.target.id

So when you use gotoScene…

storyboard.gotoScene( storyboard.world..event.target.id )

I appreciate the response. I’m still new to coding so I’m still a bit confused.

for

"level #" == event.target.id

would I change it to "level 1" == event.target.id

and

storyboard.gotoScene( storyboard.world..event.target.id )

would I keep that as is and just replace

 local worldText = display.newText("World Selected: "..storyboard.world,20,100,system.defaultFont,30)  
 local levelText = display.newText("Level Selected: "..storyboard.level,20,150,system.defaultFont,30)  

In the play.lua?

Thanks again for the help, I know I have a long way to go. [import]uid: 72845 topic_id: 34149 reply_id: 135768[/import]

“…” is concatenation. It works like this:

local cool = 1 local cat = "meow" print(cat..cool) -- "meow1"

Concatenation works for scene names too:

local world = 2 local level = 1 storyboard.gotoScene("level"..world.."-"..level) -- "level2-1"

So having looked more closely at that page code, you should do this:

-- inside the touch listener "buttonRelease", add this line inside the "if event.phase == "ended"" statement storyboard.level = event.target.id

-- then use the storyboard command storyboard.gotoLevel( "level"..storyboard.world..storyboard.level )

When you touch an object, inside of the touch event the object is called “event.target”, so “event.target.id” should be the level number too, it just looks like it’s easier to call storyboard.level since you are setting it already. [import]uid: 41884 topic_id: 34149 reply_id: 135777[/import]

So in the levels.lua it should be

local function buttonRelease(event)  
 storyboard.level = event.target.id  
 -- go to levels scene  
 storyboard.gotoLevel( "level"..storyboard.world..storyboard.level )  
  
 return true -- indicates successful touch  
end  

?
And if yes, when I click the world 1 level 1 button nothing happens : (
Is that because of my .lua name? do I have to name it world1level1.lua?

I really really appreciate your help with this. This is one of a few major hurdles I’m dealing with at the moment. [import]uid: 72845 topic_id: 34149 reply_id: 135782[/import]

What’s the FileName of your level? That’s what it has to match. [import]uid: 41884 topic_id: 34149 reply_id: 135785[/import]

World1Level1.lua [import]uid: 72845 topic_id: 34149 reply_id: 135789[/import]

When you use gotoScene, you need the exact name of the scene you’re going to. That scene name is always the name of the lua file. So if the scene name is “World1Level1.lua”, the scene name must be “World1Level1”. So let’s take a look at the concatenation:

storyboard.gotoScene( "World"..storyboard.world.."Level"..storyboard.level )

You have to get the case perfectly right, or corona can’t find the file. so I usually recommend lowercase only for lua files. :wink:

It’s also okay to use variables, btw

local where = "World"..storyboard.world.."Level"..storyboard.level storyboard.gotoScene(where) [import]uid: 41884 topic_id: 34149 reply_id: 135792[/import]

I’m pretty sure I understand now but for some reason it’s still not working.
I changed the .lua file name so it is now lowercase (world1level1.lua)

Here’s what my levels.lua looks like:

-----------------------------------------------------------------------------------------  
--  
-- levels.lua  
--  
-----------------------------------------------------------------------------------------  
  
local storyboard = require( "storyboard" )  
local widget = require "widget"  
  
local scene = storyboard.newScene()  
  
-- Table to hold level buttons  
local levels = {}  
  
-- 'onRelease' event listener for playBtn  
local function buttonRelease(event)  
 storyboard.level = event.target.id  
 -- go to levels scene  
storyboard.gotoScene( "world"..storyboard.world.."level"..storyboard.level )  
  
--^^^ Part that matters^^^---  
  
 return true -- indicates successful touch  
end  
-- Called when the scene's view does not exist:  
function scene:createScene( event )  
 local group = self.view  
  
 local background = display.newImageRect("background.png",480,320)  
 background.x = 240; background.y = 160  
 group:insert(background)  
  
 -- create 20 buttons to choose the level   
 for i=0,3 do  
 for j=1,5 do  
 current = i\*5 + j -- This calculates the current position in the table  
 levels[current] = widget.newButton{  
 label=current,  
 id=current,  
 default = "button.png",  
 width=64, height=64,  
 onRelease = buttonRelease -- event listener function  
 }  
 levels[current].x = 45 + (j\*65)  
 levels[current].y = 60+ (i\*65)  
  
 -- If you are using the last publicly available version of Corona, you may  
 -- need to replace the following line with:  
 -- group:insert( levels[current].view )  
 group:insert( levels[current] )  
  
 end  
 end  
  
end  
  
-- Called immediately after scene has moved onscreen:  
function scene:enterScene( event )  
 local group = self.view  
  
 -- INSERT code here (e.g. start timers, load audio, start listeners, etc.)  
  
end  
  
-- Called when scene is about to move offscreen:  
function scene:exitScene( event )  
 local group = self.view  
  
 -- INSERT code here (e.g. stop timers, remove listenets, unload sounds, etc.)  
  
end  
  
-- If scene's view is removed, scene:destroyScene() will be called just prior to:  
function scene:destroyScene( event )  
 local group = self.view  
  
 for i=#levels,1,-1 do  
 if levels[i] then  
 levels[i]:removeSelf() -- widgets must be manually removed  
 levels[i] = nil  
 end  
 end  
end  
  
-----------------------------------------------------------------------------------------  
-- END OF YOUR IMPLEMENTATION  
-----------------------------------------------------------------------------------------  
  
-- "createScene" event is dispatched if scene's view does not exist  
scene:addEventListener( "createScene", scene )  
  
-- "enterScene" event is dispatched whenever scene transition has finished  
scene:addEventListener( "enterScene", scene )  
  
-- "exitScene" event is dispatched whenever before next scene's transition begins  
scene:addEventListener( "exitScene", scene )  
  
-- "destroyScene" event is dispatched before view is unloaded, which can be  
-- automatically unloaded in low memory situations, or explicitly via a call to  
-- storyboard.purgeScene() or storyboard.removeScene().  
scene:addEventListener( "destroyScene", scene )  
  
-----------------------------------------------------------------------------------------  
  
return scene  

I have my world1level1.lua along with all the files needed to run it in the same folder as this tutorials files.

I’ve also tried to use a variable

local function buttonRelease(event)  
 storyboard.level = event.target.id  
 -- go to levels scene  
local where = "world"..storyboard.world.."level"..storyboard.level  
storyboard.gotoScene(where)  
   
--^^^ Part that matters^^^---  
  
 return true -- indicates successful touch  
end  

I feel like I’m missing something simple.
Again, thanks A LOT for your help. [import]uid: 72845 topic_id: 34149 reply_id: 135801[/import]

Variables in this case are just if you want to make your code easier to read or handle.

I feel like this should work at a glance but now what you need to do is troubleshoot. What you’re looking for is the shell to tell you what the error line is (the first error line it gives is usually what you’re looking for, or thereabouts) What error does it tell you? That the scene doesn’t exist?

So what you want to do is test the variables. Make buttonRelease look like this:

[code]local function buttonRelease(event)
storyboard.level = event.target.id

print(“storyboard.level is…”, storyboard.level)
print(“storyboard.world is…”, storyboard.world)

– go to levels scene
storyboard.gotoScene( “world”…storyboard.world…“level”…storyboard.level )

return true – indicates successful touch
end[/code]

If those numbers come out wrong then we need to fix something else. [import]uid: 41884 topic_id: 34149 reply_id: 135804[/import]

This is what it say in Terminal

2012-12-19 16:21:53.965 Corona Simulator[16861:903] storyboard.level is… 1
2012-12-19 16:21:53.966 Corona Simulator[16861:903] storyboard.world is… 1
2012-12-19 16:21:54.051 Corona Simulator[16861:903] Runtime error
?:0: attempt to call method ‘dispatchEvent’ (a nil value)
[import]uid: 72845 topic_id: 34149 reply_id: 135807[/import]

Yeah but what else shows up? Usually dispatchEvent is talking about something else further down [import]uid: 41884 topic_id: 34149 reply_id: 135808[/import]

2012-12-19 16:34:18.906 Corona Simulator[16906:903] storyboard.level is… 1
2012-12-19 16:34:18.906 Corona Simulator[16906:903] storyboard.world is… 1
2012-12-19 16:34:18.906 Corona Simulator[16906:903] Runtime error
?:0: attempt to call method ‘dispatchEvent’ (a nil value)
stack traceback:
[C]: in function ‘dispatchEvent’
?: in function ‘reloadScene’
?: in function ‘gotoScene’
…focuslab/Desktop/Level Select Beta/levels.lua:23: in function ‘onRelease’
?: in function <?:3>
?: in function <?:229>
[import]uid: 72845 topic_id: 34149 reply_id: 135809[/import]

  1. add storyboard.isDebug = true to main.lua, after you require storyboard. This should give you warning messages if a scene can’t be found or has a problem in it.
  2. make sure the level scene (world1level1) is in the root folder along with main.lua

Is there a new message if you try it that way? [import]uid: 41884 topic_id: 34149 reply_id: 135813[/import]

after adding

storyboard.isDebug = true  

to the main.lua I get:

2012-12-19 17:01:20.354 Corona Simulator[16906:903]
Copyright © 2009-2012 C o r o n a L a b s I n c .
2012-12-19 17:01:20.354 Corona Simulator[16906:903] Version: 2.0.0
2012-12-19 17:01:20.354 Corona Simulator[16906:903] Build: 2012.971
2012-12-19 17:01:20.355 Corona Simulator[16906:903] The file sandbox for this project is located at the following folder:
(/Users/focuslab/Library/Application Support/Corona Simulator/Level Select Beta-99EAA31164CE3DBB365EDA023A4733F6)
2012-12-19 17:01:20.357 Corona Simulator[16906:903] WARNING: display.setStatusBarMode() not supported in the simulator for the current device
2012-12-19 17:01:26.420 Corona Simulator[16906:903] storyboard.level is… 1
2012-12-19 17:01:26.420 Corona Simulator[16906:903] storyboard.world is… 1
2012-12-19 17:01:26.421 Corona Simulator[16906:903] Runtime error
?:0: attempt to call method ‘dispatchEvent’ (a nil value)
stack traceback:
[C]: in function ‘dispatchEvent’
?: in function ‘gotoScene’
…focuslab/Desktop/Level Select Beta/levels.lua:23: in function ‘onRelease’
?: in function <?:3>
?: in function <?:229>

This is the terminal log from the time I run the game until I press World 1 then Level 1

world1level1.lua is in the root folder [import]uid: 72845 topic_id: 34149 reply_id: 135815[/import]

I agree that there is probably something simple being missed but from a forum glance I’m not sure. I’ll run the code tonight when I get home. The dispatchEvent part makes me think there is a typo in the scene construction, but it could also be widget related. [import]uid: 41884 topic_id: 34149 reply_id: 135818[/import]

It sounds to me like the world name isn’t be constructed correctly. In other words a nil is getting passed in somewhere, which the only thing being passed in is scene name.

Try doing this:

 local world = "world"..storyboard.world.."level"..storyboard.level  
 print(world)   
 storyboard.gotoScene(world)   

and see if something is amis.
[import]uid: 199310 topic_id: 34149 reply_id: 135843[/import]

No clue why its not working : /
Anyone have an example of this working where you actually start a level not just posting text? [import]uid: 72845 topic_id: 34149 reply_id: 135849[/import]

Alright, sorry for the delay (family waits for no man). I loaded your code in, made a fake background.png, made a fake button.png…and the file loads perfectly.There’s a warning if I press on a button that the scene isn’t there, but that’s a far cry from your current situation.

(incidentally, the way you troubleshoot this stuff is to use --[[and --]] to encapsulate chunks of code that you think might be the problem. If you encapsulate and there are no errors, you know where the problem is lurking!)

( --[[–]] is the block version of just --, the latter of which has to be every line.)

The only exception I had to make was to hardcode storyboard.world = 1, but you’ve already shown that storyboard.world is being set…and you would get a concatenate error if it wasn’t.

Anyway, what I would do first is just – out the onRelease line from your button constructor. Does it still have an error? (We’re trying to narrow it down) I think Rob’s idea is also smart.

Let us know how it goes. [import]uid: 41884 topic_id: 34149 reply_id: 135853[/import]

 -- onRelease = buttonRelease   

No error [import]uid: 72845 topic_id: 34149 reply_id: 135855[/import]