Storyboard and Game Loops, Timed Life Objects

Hi fellow devs,

I have a few questions regarding storyboard as i am not sure if this is the correct way to do it. I will show my codes below.

Please let me know if i am understanding storyboard correctly. If i am wrong, let me know where i did wrong too. Thanks in advance for your time.

  1. createScene is where i create the objects/images that are going to be display initially on the screen on first load.

  2. enterScene is when the scene is ready for use. Do i put my gameloop and other functions for the game inside or outside enterScene?

function scene:enterScene( event )  
 local group = self.view  
  
 local function gameloop( event )  
 -- my game codes here  
 end  
 Runtime:addEventListener( "enterFrame", gameloop )  
  
 -- Some other codes   
end  
  1. Do i need a local for scene’s functions? Example:
local function scene....  
  
or  
  
function scene...  
  1. Do i need to insert objects that have a timed life into a group? For example a time bomb that will explode in 5minutes. If yes (which is what i am currently doing), how do i make sure it is removed from the group since i am removing the object itself when it is destroyed.
    [import]uid: 74723 topic_id: 25977 reply_id: 325977[/import]
  1. Yes, that’s what createScene() is for.

  2. That is perfectly valid. I personally code all functions like gameLoop() outside of createScene() and enterScene() (putting them right above createScene() in my code if it’s not specifically for enterScene or createScene only. Thus my structure might look like:

  
local function gameLoop()  
...  
end  
  
local function createScene()  
...  
end  
  
local function enterScene()  
 Runtime:addEventListener("enterFrame", gameLoop)  
end  
  
local function exitScene()  
 Runtime:removeEventListener("enterFrame", gameLoop)  
end  

The reason I prefer it this way is it avoids scope problems. If you put the gameLoop inside enterScene, it can only be seen in that function and in this case, exitScene doesn’t know what gameLoop is. But if you remove the listener inside of enterScene then you would be fine.

Either way is valid.

  1. You should probably make createScene, enterScene, etc. Local to that function. Other scenes use the same scene names and making them global will cause them to stomp on each other.

  2. Yes everything created in the scene should be added to the group so that when you switch scenes it’s removed properly. Any thing not added specifically to “group” (the scene’s view group) will sit above the scene and be visible all the time. When an object is removed like your bombs when they blow up, they are removed from their parent group automatically as part of the :removeSelf or :remove calls. Likewise when a group is removed, all of its children members are likewise properly destroyed and removed for you. By making sure everything is put in group, when the scene is destroyed all that memory is freed up properly without you having to manually track everything.
    [import]uid: 19626 topic_id: 25977 reply_id: 105120[/import]

Thanks for the detail reply with examples! These are the answers i am looking for. [:

A few more questions:

  1. If i create my game functions outside of enterScene like what you showed in that example. How do i insert objects created from those external functions to the scene’s group?

  2. As of the newest version daily build, do i still need to remove widgets on destroyScene?

  3. I am getting an error from the below code:
    “WARNING: Cannot transition to a scene that does not exist. If you called storyboard.removeScene() on a scene that is NOT represented by a module, the scene must be recreated before transitioning back to it.”

The scene doesn’t go to menu.lua because there’s some error in menu.lua. I looked through a few times and i can’t find any syntax error or anything obvious. I am using daily build 799.

-----------------------------------------------------------------------------------------  
--  
-- main.lua  
--  
-----------------------------------------------------------------------------------------  
  
-- hide the status bar (battery)  
display.setStatusBar( display.HiddenStatusBar )  
  
-- require module  
local storyboard = require( "storyboard" ) -- Scene Manager  
  
-- load main menu  
storyboard.gotoScene( "menu" )  
-----------------------------------------------------------------------------------------  
--  
-- menu.lua  
--  
-----------------------------------------------------------------------------------------  
  
-- require module  
local storyboard = require( "storyboard" ) -- Scene Manager  
  
local widget = require( "widget" ) -- Button/UI Class  
  
-- Create Menu Scene  
local scene = storyboard.newScene()  
  
-- Helpful Locals  
local screenWidth = display.contentWidth  
local screenHeight = display.contentHeight  
  
-- Locals  
local btn\_play, btn\_load, btn\_grave  
  
-----------------------------------------------------------------------------------------  
-- BEGINNING OF YOUR IMPLEMENTATION  
-----------------------------------------------------------------------------------------  
  
-----------------------------------------------------------------------------------------  
--  
-- Menu Functions  
--  
-----------------------------------------------------------------------------------------  
  
-- btn\_play event listener (onRelease)  
local function startGame()  
 -- Go to creation screen  
 -- storyboard.gotoScene( "creation" )  
 print( "Going to creation screen!" )  
  
 return true -- indicates successful touch  
end  
  
-----------------------------------------------------------------------------------------  
--  
-- Story Board Functions  
--  
-----------------------------------------------------------------------------------------  
  
-- Called when the scene's view does not exist:  
local function scene:createScene( event )  
 local group = self.view  
  
 -----------------------------------------------------------------------------  
 --  
 -- CREATE display objects and add them to 'group' here.  
 --  
 -----------------------------------------------------------------------------  
  
 -- Background Image  
  
 -- Title  
  
 -- Buttons  
 btn\_play = widget.newButton{ label = "Play",  
 default = "art/menu/btn\_play.png",  
 over = "art/menu/btn\_play\_over.png",  
 width = 100,  
 height = 40,  
 onRelease = startGame  
 }  
  
 -- Set positions for images, texts, buttons  
 btn\_play.x = screenWidth / 2  
 btn\_play.y = screenHeight / 2  
  
  
 -- Insert objects created (Z order = Higher z-order for later insertion)  
 -- Insert Background  
 -- Insert Title  
 -- Insert Button  
 group:insert( btn\_play )  
  
end  
  
-- Called immediately after scene has moved onscreen:  
local 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:  
local function scene:exitScene( event )  
 -- local group = self.view  
  
 -----------------------------------------------------------------------------  
 --  
 -- INSERT code here (e.g. stop timers, remove listeners, unload sounds, etc.)  
 --  
 -----------------------------------------------------------------------------  
  
end  
-- Called prior to the removal of scene's "view" (display group)  
local function scene:destroyScene( event )  
 -- local group = self.view  
  
 -----------------------------------------------------------------------------  
  
 -- INSERT code here (e.g. remove listeners, widgets, save state, etc.)  
  
 -----------------------------------------------------------------------------  
  
 -- Widget  
 display.remove( btn\_play )  
  
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  

[import]uid: 74723 topic_id: 25977 reply_id: 105137[/import]

1. If i create my game functions outside of enterScene like what you showed in that example. How do i insert objects created from those external functions to the scene’s group?

You can either use the group:

scene.view

which is the group (see the line: local group = self.view, and self is “scene”)

Or create a local variable called “myGroup” at the top of the scene file and in :createScene(event) do a:

 local group = self.view  
 myScene = group  

Then you can access myScene anywhere in the module. I tend to do the latter because I don’t want to think about scene.view.

2. As of the newest version daily build, do i still need to remove widgets on destroyScene?

I don’t remember seeing anything about that. I know that in some later builds, the idea of widget.view went away for most widgets and that they can be safely removed by removing the group they are part of and don’t need specific removal calls. But that’s been true since January or February. Maybe that’s what your talking about. I do think one of the widgets may still need to be manually removed.

**3. I am getting an error from the below code:
“WARNING: Cannot transition to a scene that does not exist. If you called storyboard.removeScene() on a scene that is NOT represented by a module, the scene must be recreated before transitioning back to it.”

The scene doesn’t go to menu.lua because there’s some error in menu.lua. I looked through a few times and i can’t find any syntax error or anything obvious. I am using daily build 799.**

One of the things fixed in 805 was the ability to see the error in the scene that is being loaded. Starting with 797 (I think), there were storyboard fixes to messaging and it hid the errors from us. They were returned in 805.

There are several techniques to see the error prior to 805, which includes using a syntax checking IDE like CIDR or CoronaComplete whose editors try to show you problems as you code, or you can just do a require on the module itself:

local testscene = require(“menu”)

And that will show the errors so you can track them down.

Mind you 805 and 806 seem to have a bug that prevents builds from working, but things are fine in the simulator. And it also seems to have changed using dots for directory names in Lua files in sub-directories to using slashes like it should have the whole time. This has created some pretty big issues for people who are trying to use the last two daily builds.

[import]uid: 19626 topic_id: 25977 reply_id: 105166[/import]

Thank you, guys, for sharing the Q&A. Very helpful.

Edit: BTW, I did a real quick test project, and it looks like when I add local to scene functions, it brings up the WARNING: Cannot transition to a scene that does not exist. I looked at the Storyboard SampleCode that comes with Corona SDK, and it doesn’t have local in front of scene functions. Maybe scene functions are not intended to be localized for Storyboard API to work properly?

Naomi [import]uid: 67217 topic_id: 25977 reply_id: 105175[/import]

@Naomi, staring around build 797, there was a storyboard fix that changed the messages output when there is an error. That fix was fixed in build 805. However 805 has other issues.

Basically the scene you’re going to has errors.

[import]uid: 19626 topic_id: 25977 reply_id: 105189[/import]

@robmiracle, thank you for the note. I’m using 797, and a simple storyboard project that I put together works perfectly fine at the moment – but as soon as I add “local” in front of the scene function, it breaks. Perhaps I need to systematically add “local” (i.e., one function at a time) and see where it takes me.

Edit: I saw your comment here, and I now totally see why I shouldn’t add local in front of scene functions. Thank you, Rob @robmiracle. It may take a while for me to become fully familiar with Storyboard API (and learn to avoid silly errors), but so far, I’m liking the way Storyboard works.

Cheers,
Naomi [import]uid: 67217 topic_id: 25977 reply_id: 105192[/import]

@robmiracle
Thanks again for your help and tips. They are really helpful. For now i will stick with 799 until further daily builds.

@Naomi
Your question actually solved my problem (3), totally forgot that scene is already local. The error went away when locals are remove from the functions of scene and now i can see my button [:

Thanks all! Will post more questions when i am stuck and will learn as i go a long [: [import]uid: 74723 topic_id: 25977 reply_id: 105224[/import]