Cancelling Timers & Releasing Objects?

Hi All,

I’m brand new to Corona…probably why I’m posting in the newbies section and was hoping for a little input.

I’m not new to app development, I have a number of apps already on the App Store but I developed them all in Xcode and Objective-C. The reason I started looking elsewhere for a development platform were for 2 main reasons, firstly and most importantly I wanted to be able to deal with motion and physics handling and had no idea where to start and secondly, I’d kind of like to speed up the coding process!

The second reason is kind of ironic because at this current moment in time I could code something faster in Objective-C than I could in Corona purely for the fact I have never programmed anything in Lua but I’m hoping that it will benefit me once I can get my head around Lua.

I have a couple of questions I was hoping someone could answer for me:

Memory management is obviously important as with any programming language and I want to ensure I get this right from the outset. Currently I have set up an app with 2 screens or in fact 2 scenes (using storyboard), the first scene I add a bunch of objects (12 images) and when I tap a button the new scene loads.

What I’ve done is set up a function (on the tap of a button) that tells all the objects to remove themselves and nil out…like this:

[code]
playButton:removeSelf()
playButton = nil

homeBGImage:removeSelf()
homeBGImage = nil[/code]

Obviously I’ve done that for all 12 images…is this the right way to do things to release them all from memory or is there a better way?

Secondly I understand that I need to cancel my timers but they seem to continue, here’s how I’ve been trying to cancel my timers:

 timer.cancel(moveCloudTimer)  
 moveCloudTimer = nil  

The strange thing is I have a cloud that moves across the screen and once it disappears off the screen to the left I have it reset to the right hand side of the screen, yet when I cancel its timer the cloud still continues to move.

Why would the cloud continue to move even though I cancelled its timer?

Thanks for any help and apologies for the longish post, I didn’t intend to write so much!! [import]uid: 107915 topic_id: 34468 reply_id: 334468[/import]

Hi, welcome to Corona! I hope you find it enjoyable to develop in, even though Lua can seem “odd” at first, especially for some devs coming from languages like Obj-C.

For Q1, you have the correct method… always remember to nil something out to allow the Lua garbage collector to clean up properly and free the memory. Also remember that you need to clear out “holding tables” and other things that might contain references to other objects. For example, if you create X enemies and then add them to a table like “onScreenEnemies” (so you can easily reference them and loop through them if you need), be sure to clear that table out going in reverse order, before you remove them from the scene in any other manner. If you just remove them from the display, Lua sees that there are still references to them elsewhere and it can’t clean them up fully.

For Q2, that is the correct way to cancel and clear a timer. But you say you’re moving the cloud. How so, via a transition? Physics? A runtime position update? A timer can’t move anything by itself, so I’d have to see your code to figure this out, which I can certainly do (please just post code within <code> tags so its easier to read).

Best regards,
Brent Sorrentino [import]uid: 200026 topic_id: 34468 reply_id: 137073[/import]

I also just noticed this thread that Rob responded to, pertaining to some memory handling and cleanup issues. This should help too!

http://developer.coronalabs.com/forum/2013/01/01/need-clarity-about-memory-handling [import]uid: 200026 topic_id: 34468 reply_id: 137074[/import]

Thanks for the reply, that’s good news that I seem to be dealing with memory allocation and removal correctly. I did read somewhere that you also need to manually empty the garbage collector with collectgarbage(“collect”), however there does see to be conflicting information depending how new or old the information is. From what I can gather you no longer need to manually add collectgarbage(“collect”)?

Also is there an easy way to add some code that allows me to see how much memory is being used? I’d like to physically see it rising a dropping when I create and release objects.

As for the movement of the cloud I am using a transition, the code I set up is:

local function moveLargeCloud()  
moveCloudTimer = transition.to( largeCloud, { time=21000, delay=600, x=-70})  
end  
  
local function moveCloudToLeft()  
transition.to( largeCloud, { time=0, delay=0, y=math.random(200, 265), x=380})  
moveCloudToLeftTimer = timer.performWithDelay(0, moveLargeCloud, 1)  
end  
  
local function checkCloudPosition()  
if (largeCloud.x == -70) then  
checkCloudPositionTimer = timer.performWithDelay(500, moveCloudToLeft, 1)  
end  
end  
  
cloudPositionTimer = timer.performWithDelay(500, checkCloudPosition, 0)  
  

Thanks again. [import]uid: 107915 topic_id: 34468 reply_id: 137095[/import]

Hi Chris,
Happy to help! To answer your recent questions:

  1. Typically, you don’t need to outright call the garbage collector function. It runs behind the scenes and does its job well. The rare exception might be if you want to instantly clear out (from memory) items that are “awaiting” garbage collection, but you need it to happen immediately. This is useful when switching Storyboard scenes, but Storyboard does that for you, so no need to worry about adding it yourself.

  2. Here’s a function and timer for checking memory usage (both system memory and texture memory). Note that it runs on a repeating timer (the “0” parameter for endless repeat) of 1000 ms. You can decrease this time if you want, but I find 1000 ms is fine. This will only print the values to the Terminal, but you can easily add an updating screen text display for the value(s) if you prefer.

local function memPrinting()  
 collectgarbage("collect")  
 local memUsage\_str = string.format( "MEMORY = %.3f KB", collectgarbage( "count" ) )  
 print( memUsage\_str, "TEXTURE = "..(system.getInfo("textureMemoryUsed")/1000000) )  
 print( memUsage\_str )  
end  
timer.performWithDelay( 1000, memPrinting, 0 )  
  1. For moving your clouds, I suggest you avoid the timers and use transition “onComplete” calls instead. Like this:
local largeCloud = display.newImage() --however you defined it  
  
local function moveLargeCloud()  
 if ( largeCloud.moveTransition ) then transition.cancel( largeCloud.moveTransition ) end  
 largeCloud.x = 200  
 largeCloud.y = math.random(200, 400)  
 largeCloud.moveTransition = transition.to( largeCloud, { time=2000, delay=60, x=70, onComplete=moveLargeCloud })  
end  
  
local function stopCloud( event )  
 local thisCloud = event.source.cloudToStop --event.source is the handle of the timer  
 if ( thisCloud.moveTransition ) then transition.cancel( thisCloud.moveTransition ) end  
end  
local t = timer.performWithDelay( 5000, stopCloud, 1 ) ; t.cloudToStop = largeCloud  
  
moveLargeCloud() --just call the function; you don't need a timer necessarily  

This just runs a function with a transition that calls the same function on completion, resetting the cloud to the starting x position and a random y position. I also show how you can “attach” a variable or object reference to a timer, and then access it on the timer’s completion using event.source.[reference]. This is a useful method for building a stop function that handles several clouds, not just one in specific.

Finally, I recently viewed a comprehensive video tutorial series which you might find useful, as it discusses many things I believe you’re hoping to tackle: physics, transitions, Storyboard, scrolling/repeating background, etc. It’s a fairly long video (14 parts!) but give it a whirl.
http://www.youtube.com/watch?v=0GtUxdSeWzk

Best of luck!
Brent [import]uid: 200026 topic_id: 34468 reply_id: 137107[/import]

**UPDATE ON POST BELOW**

Okay, so I decided to carry on using storyboard but create my objects outside of the function ‘scene:createScene( event )’

I decided that this way I can get rid of them anytime I choose and know they have been destroyed. What I also did was add all my objects into a reload() function and then add reload() to ‘function scene:enterScene( event )’, this way it reloads the entire scene so everything starts from the beginning.

**END OF UPDATE**

Thanks Brent. It’s good to be able to see the memory in use, that definitely helps me to see if I’m releasing objects.

I thought there would likely be a better way to move the clouds rather than with all the timers I had…thanks.

Strange you should mention those videos as I was watching the 7th one when I looked at your message!

There is one thing I am really struggling with though and it’s incredibly frustrating because I would never expect to spend nearly 2 days on trying to figure out what happens to objects when a change of scene takes place!

Initially I had a project that had just 2 scenes, the first scene had a bit of animation going on (the clouds moving) a couple of other images, some music playing and a button that when tapped went to scene 2 which literally just had a background image and a button that went back to scene 1.

As it was so simple, I didn’t really think it was possible for it to go wrong…famous last words. After spending hours and hours on it I noticed a couple of things. Firstly this is how I thought scenes worked:

Scene 1 loads and shows necessary objects etc, on button press to go to scene 2, transition takes place and once scene 2 is on the screen, Scene 1 is automatically deleted (all objects, tables etc etc). Exactly the same thing happens when the button on Scene 2 is pressed but in reverse. So essentially when going to any seen irrelevant of whether it’s been shown before it should load back into memory completely fresh.

I’m obviously wrong with the above because as I said earlier I noticed a couple of things. Firstly I added your memory code to allow me to see what was happening with my scene 1 objects or at least to see if they were removed once scene 2 was showing and to my surprise the memory usage stayed exactly the same as did texture. So I decided to remove some objects manually from scene 1 using a timer of 1 second so that when the button was pressed to goto scene 2 the timer would fire a function to remove about 4 graphical items. Once I did this I could see that this time the memory and texture was reduced as I expected.

I also noticed that when I went to scene 1 from scene 2, the music I had set to play in scene 1 never started again after going to scene 2?! It plays when I first launch the app and stops as I requested when going to scene 2 but as soon as I go back the music is not playing.

So with all the above in mind I decided to create a really simple 2 scene project. Scene 1 has a background, music playing and a button which takes me to scene 2. Scene 2 has nothing but a background and a button which takes me to scene 1. Using the scene templates this is how my code looks but still scene 1 never seems to unload and the music never starts again on going back to scene 1 from scene 2?

Main.lua

local storyboard = require "storyboard"  
  
-- load scenetemplate.lua  
storyboard.gotoScene( "scene1", "fade", 800 )  

Scene1.lua

----------------------------------------------------------------------------------  
--  
-- scenetemplate.lua  
--  
----------------------------------------------------------------------------------  
  
local storyboard = require( "storyboard" )  
local widget = require "widget"  
local scene = storyboard.newScene()  
local bgImage, playButton, homeScreenMusicChannel  
----------------------------------------------------------------------------------  
  
local function gotoScene2()  
storyboard.gotoScene( "Scene2", "crossFade", 800 )  
end  
  
---------------------------------------------------------------------------------  
-- BEGINNING OF YOUR IMPLEMENTATION  
---------------------------------------------------------------------------------  
  
-- Called when the scene's view does not exist:  
function scene:createScene( event )  
 local group = self.view  
  
bgImage = display.newImageRect( "Home-Page-BG.png", 320, 568 )  
bgImage:setReferencePoint( display.CenterReferencePoint )  
bgImage.x = display.contentCenterX  
bgImage.y = display.contentCenterY  
group:insert( bgImage )  
  
playButton = widget.newButton{  
default = "Play-Button.png",  
over = "Play-Button.png",  
onPress = playButtonPress,  
onEvent = buttonHandler,  
id = "playButton",  
width = 198,  
height = 69.5  
}  
playButton.x = 160; playButton.y = 250  
group:insert( playButton )  
  
function playButton:tap( event )  
audio.fadeOut({channel=1, time=1400})   
timer.performWithDelay(1400, removeAudio, 1)  
gotoHomeScreenTimer = timer.performWithDelay(1000, gotoScene2, 1)  
end  
end  
-- Called immediately after scene has moved onscreen:  
function scene:enterScene( event )  
 local group = self.view  
  
 playButton:addEventListener( "tap", button )  
  
 homeScreenMusicChannel = audio.loadStream( "Home Screen Music.mp3" )  
 homeScreenMusicChannel = audio.play( homeScreenMusicChannel, { channel=1} )  
  
end  
-- Called when scene is about to move offscreen:  
function scene:exitScene( event )  
 local group = self.view  
  
 --function removeAudio (event)   
 audio.dispose( homeScreenMusicChannel )  
 homeScreenMusicChannel = nil  
 -----------------------------------------------------------------------------  
  
 -- INSERT code here (e.g. stop timers, remove listeners, unload sounds, etc.)  
  
 -----------------------------------------------------------------------------  
  
end  
-- Called prior to the removal of scene's "view" (display group)  
function scene:destroyScene( event )  
 local group = self.view  
  
 display.remove( playButton )  
 playButton = nil  
 -----------------------------------------------------------------------------  
  
 -- INSERT code here (e.g. remove listeners, widgets, save state, etc.)  
  
 -----------------------------------------------------------------------------  
  
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 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  

Scene2.lua

[code]


– scenetemplate.lua


local storyboard = require( “storyboard” )
local widget = require “widget”
local scene = storyboard.newScene()
local bgImage, playButton

local function gotoScene1()
storyboard.gotoScene( “Scene1”, “crossFade”, 800 )
end


– BEGINNING OF YOUR IMPLEMENTATION

– Called when the scene’s view does not exist:
function scene:createScene( event )
local group = self.view

bgImage = display.newImageRect( “Home-Page-BG.png”, 320, 568 )
bgImage:setReferencePoint( display.CenterReferencePoint )
bgImage.x = 160
bgImage.y = 200
group:insert( bgImage )

playButton = widget.newButton{
default = “Play-Button.png”,
over = “Play-Button.png”,
onPress = gotoScene1,
onEvent = buttonHandler,
id = “playButton”,
width = 198,
height = 69.5
}

playButton.x = 160; playButton.y = 400
group:insert( playButton )

end
– Called immediately after scene has moved onscreen:
function scene:enterScene( event )
local group = self.view

storyboard.removeScene( “Scene1” )

– 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 listeners, unload sounds, etc.)


end
– Called prior to the removal of scene’s “view” (display group)
function scene:destroyScene( event )
local group = self.view


– INSERT code here (e.g. remove listeners, widgets, save state, etc.)


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 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
[/code] [import]uid: 107915 topic_id: 34468 reply_id: 137202[/import]

Hi Chris,
Storyboard can control things nicely, but it takes some practice to learn where you place and create things, and in what “phase” you clean them up (or don’t, if they should be scene-persistent).

You might get some use from my responses to this other thread about Storyboard:
https://developer.coronalabs.com/forum/2013/01/01/sprite-group

Brent [import]uid: 200026 topic_id: 34468 reply_id: 137218[/import]

Thanks for your help with this Brent, everything is finally starting to click into place, although I still have a long way to go I’m finally starting to understand how things work in Lua, it’s been hard trying to rewire my brain from Objective-C but I feel that I will reap the rewards with the Corona SDK now I’m getting used to it. [import]uid: 107915 topic_id: 34468 reply_id: 137285[/import]

Sincerely happy to help. I hope your current apps are succeeding, and that you find equal success using Corona. If you need any other assistance, please post to the forums or drop an e-mail at my Corona account.

Take care, and happy 2013!
Brent [import]uid: 200026 topic_id: 34468 reply_id: 137295[/import]

Hi, welcome to Corona! I hope you find it enjoyable to develop in, even though Lua can seem “odd” at first, especially for some devs coming from languages like Obj-C.

For Q1, you have the correct method… always remember to nil something out to allow the Lua garbage collector to clean up properly and free the memory. Also remember that you need to clear out “holding tables” and other things that might contain references to other objects. For example, if you create X enemies and then add them to a table like “onScreenEnemies” (so you can easily reference them and loop through them if you need), be sure to clear that table out going in reverse order, before you remove them from the scene in any other manner. If you just remove them from the display, Lua sees that there are still references to them elsewhere and it can’t clean them up fully.

For Q2, that is the correct way to cancel and clear a timer. But you say you’re moving the cloud. How so, via a transition? Physics? A runtime position update? A timer can’t move anything by itself, so I’d have to see your code to figure this out, which I can certainly do (please just post code within <code> tags so its easier to read).

Best regards,
Brent Sorrentino [import]uid: 200026 topic_id: 34468 reply_id: 137073[/import]

I also just noticed this thread that Rob responded to, pertaining to some memory handling and cleanup issues. This should help too!

http://developer.coronalabs.com/forum/2013/01/01/need-clarity-about-memory-handling [import]uid: 200026 topic_id: 34468 reply_id: 137074[/import]

Thanks for the reply, that’s good news that I seem to be dealing with memory allocation and removal correctly. I did read somewhere that you also need to manually empty the garbage collector with collectgarbage(“collect”), however there does see to be conflicting information depending how new or old the information is. From what I can gather you no longer need to manually add collectgarbage(“collect”)?

Also is there an easy way to add some code that allows me to see how much memory is being used? I’d like to physically see it rising a dropping when I create and release objects.

As for the movement of the cloud I am using a transition, the code I set up is:

local function moveLargeCloud()  
moveCloudTimer = transition.to( largeCloud, { time=21000, delay=600, x=-70})  
end  
  
local function moveCloudToLeft()  
transition.to( largeCloud, { time=0, delay=0, y=math.random(200, 265), x=380})  
moveCloudToLeftTimer = timer.performWithDelay(0, moveLargeCloud, 1)  
end  
  
local function checkCloudPosition()  
if (largeCloud.x == -70) then  
checkCloudPositionTimer = timer.performWithDelay(500, moveCloudToLeft, 1)  
end  
end  
  
cloudPositionTimer = timer.performWithDelay(500, checkCloudPosition, 0)  
  

Thanks again. [import]uid: 107915 topic_id: 34468 reply_id: 137095[/import]

Hi Chris,
Happy to help! To answer your recent questions:

  1. Typically, you don’t need to outright call the garbage collector function. It runs behind the scenes and does its job well. The rare exception might be if you want to instantly clear out (from memory) items that are “awaiting” garbage collection, but you need it to happen immediately. This is useful when switching Storyboard scenes, but Storyboard does that for you, so no need to worry about adding it yourself.

  2. Here’s a function and timer for checking memory usage (both system memory and texture memory). Note that it runs on a repeating timer (the “0” parameter for endless repeat) of 1000 ms. You can decrease this time if you want, but I find 1000 ms is fine. This will only print the values to the Terminal, but you can easily add an updating screen text display for the value(s) if you prefer.

local function memPrinting()  
 collectgarbage("collect")  
 local memUsage\_str = string.format( "MEMORY = %.3f KB", collectgarbage( "count" ) )  
 print( memUsage\_str, "TEXTURE = "..(system.getInfo("textureMemoryUsed")/1000000) )  
 print( memUsage\_str )  
end  
timer.performWithDelay( 1000, memPrinting, 0 )  
  1. For moving your clouds, I suggest you avoid the timers and use transition “onComplete” calls instead. Like this:
local largeCloud = display.newImage() --however you defined it  
  
local function moveLargeCloud()  
 if ( largeCloud.moveTransition ) then transition.cancel( largeCloud.moveTransition ) end  
 largeCloud.x = 200  
 largeCloud.y = math.random(200, 400)  
 largeCloud.moveTransition = transition.to( largeCloud, { time=2000, delay=60, x=70, onComplete=moveLargeCloud })  
end  
  
local function stopCloud( event )  
 local thisCloud = event.source.cloudToStop --event.source is the handle of the timer  
 if ( thisCloud.moveTransition ) then transition.cancel( thisCloud.moveTransition ) end  
end  
local t = timer.performWithDelay( 5000, stopCloud, 1 ) ; t.cloudToStop = largeCloud  
  
moveLargeCloud() --just call the function; you don't need a timer necessarily  

This just runs a function with a transition that calls the same function on completion, resetting the cloud to the starting x position and a random y position. I also show how you can “attach” a variable or object reference to a timer, and then access it on the timer’s completion using event.source.[reference]. This is a useful method for building a stop function that handles several clouds, not just one in specific.

Finally, I recently viewed a comprehensive video tutorial series which you might find useful, as it discusses many things I believe you’re hoping to tackle: physics, transitions, Storyboard, scrolling/repeating background, etc. It’s a fairly long video (14 parts!) but give it a whirl.
http://www.youtube.com/watch?v=0GtUxdSeWzk

Best of luck!
Brent [import]uid: 200026 topic_id: 34468 reply_id: 137107[/import]

**UPDATE ON POST BELOW**

Okay, so I decided to carry on using storyboard but create my objects outside of the function ‘scene:createScene( event )’

I decided that this way I can get rid of them anytime I choose and know they have been destroyed. What I also did was add all my objects into a reload() function and then add reload() to ‘function scene:enterScene( event )’, this way it reloads the entire scene so everything starts from the beginning.

**END OF UPDATE**

Thanks Brent. It’s good to be able to see the memory in use, that definitely helps me to see if I’m releasing objects.

I thought there would likely be a better way to move the clouds rather than with all the timers I had…thanks.

Strange you should mention those videos as I was watching the 7th one when I looked at your message!

There is one thing I am really struggling with though and it’s incredibly frustrating because I would never expect to spend nearly 2 days on trying to figure out what happens to objects when a change of scene takes place!

Initially I had a project that had just 2 scenes, the first scene had a bit of animation going on (the clouds moving) a couple of other images, some music playing and a button that when tapped went to scene 2 which literally just had a background image and a button that went back to scene 1.

As it was so simple, I didn’t really think it was possible for it to go wrong…famous last words. After spending hours and hours on it I noticed a couple of things. Firstly this is how I thought scenes worked:

Scene 1 loads and shows necessary objects etc, on button press to go to scene 2, transition takes place and once scene 2 is on the screen, Scene 1 is automatically deleted (all objects, tables etc etc). Exactly the same thing happens when the button on Scene 2 is pressed but in reverse. So essentially when going to any seen irrelevant of whether it’s been shown before it should load back into memory completely fresh.

I’m obviously wrong with the above because as I said earlier I noticed a couple of things. Firstly I added your memory code to allow me to see what was happening with my scene 1 objects or at least to see if they were removed once scene 2 was showing and to my surprise the memory usage stayed exactly the same as did texture. So I decided to remove some objects manually from scene 1 using a timer of 1 second so that when the button was pressed to goto scene 2 the timer would fire a function to remove about 4 graphical items. Once I did this I could see that this time the memory and texture was reduced as I expected.

I also noticed that when I went to scene 1 from scene 2, the music I had set to play in scene 1 never started again after going to scene 2?! It plays when I first launch the app and stops as I requested when going to scene 2 but as soon as I go back the music is not playing.

So with all the above in mind I decided to create a really simple 2 scene project. Scene 1 has a background, music playing and a button which takes me to scene 2. Scene 2 has nothing but a background and a button which takes me to scene 1. Using the scene templates this is how my code looks but still scene 1 never seems to unload and the music never starts again on going back to scene 1 from scene 2?

Main.lua

local storyboard = require "storyboard"  
  
-- load scenetemplate.lua  
storyboard.gotoScene( "scene1", "fade", 800 )  

Scene1.lua

----------------------------------------------------------------------------------  
--  
-- scenetemplate.lua  
--  
----------------------------------------------------------------------------------  
  
local storyboard = require( "storyboard" )  
local widget = require "widget"  
local scene = storyboard.newScene()  
local bgImage, playButton, homeScreenMusicChannel  
----------------------------------------------------------------------------------  
  
local function gotoScene2()  
storyboard.gotoScene( "Scene2", "crossFade", 800 )  
end  
  
---------------------------------------------------------------------------------  
-- BEGINNING OF YOUR IMPLEMENTATION  
---------------------------------------------------------------------------------  
  
-- Called when the scene's view does not exist:  
function scene:createScene( event )  
 local group = self.view  
  
bgImage = display.newImageRect( "Home-Page-BG.png", 320, 568 )  
bgImage:setReferencePoint( display.CenterReferencePoint )  
bgImage.x = display.contentCenterX  
bgImage.y = display.contentCenterY  
group:insert( bgImage )  
  
playButton = widget.newButton{  
default = "Play-Button.png",  
over = "Play-Button.png",  
onPress = playButtonPress,  
onEvent = buttonHandler,  
id = "playButton",  
width = 198,  
height = 69.5  
}  
playButton.x = 160; playButton.y = 250  
group:insert( playButton )  
  
function playButton:tap( event )  
audio.fadeOut({channel=1, time=1400})   
timer.performWithDelay(1400, removeAudio, 1)  
gotoHomeScreenTimer = timer.performWithDelay(1000, gotoScene2, 1)  
end  
end  
-- Called immediately after scene has moved onscreen:  
function scene:enterScene( event )  
 local group = self.view  
  
 playButton:addEventListener( "tap", button )  
  
 homeScreenMusicChannel = audio.loadStream( "Home Screen Music.mp3" )  
 homeScreenMusicChannel = audio.play( homeScreenMusicChannel, { channel=1} )  
  
end  
-- Called when scene is about to move offscreen:  
function scene:exitScene( event )  
 local group = self.view  
  
 --function removeAudio (event)   
 audio.dispose( homeScreenMusicChannel )  
 homeScreenMusicChannel = nil  
 -----------------------------------------------------------------------------  
  
 -- INSERT code here (e.g. stop timers, remove listeners, unload sounds, etc.)  
  
 -----------------------------------------------------------------------------  
  
end  
-- Called prior to the removal of scene's "view" (display group)  
function scene:destroyScene( event )  
 local group = self.view  
  
 display.remove( playButton )  
 playButton = nil  
 -----------------------------------------------------------------------------  
  
 -- INSERT code here (e.g. remove listeners, widgets, save state, etc.)  
  
 -----------------------------------------------------------------------------  
  
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 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  

Scene2.lua

[code]


– scenetemplate.lua


local storyboard = require( “storyboard” )
local widget = require “widget”
local scene = storyboard.newScene()
local bgImage, playButton

local function gotoScene1()
storyboard.gotoScene( “Scene1”, “crossFade”, 800 )
end


– BEGINNING OF YOUR IMPLEMENTATION

– Called when the scene’s view does not exist:
function scene:createScene( event )
local group = self.view

bgImage = display.newImageRect( “Home-Page-BG.png”, 320, 568 )
bgImage:setReferencePoint( display.CenterReferencePoint )
bgImage.x = 160
bgImage.y = 200
group:insert( bgImage )

playButton = widget.newButton{
default = “Play-Button.png”,
over = “Play-Button.png”,
onPress = gotoScene1,
onEvent = buttonHandler,
id = “playButton”,
width = 198,
height = 69.5
}

playButton.x = 160; playButton.y = 400
group:insert( playButton )

end
– Called immediately after scene has moved onscreen:
function scene:enterScene( event )
local group = self.view

storyboard.removeScene( “Scene1” )

– 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 listeners, unload sounds, etc.)


end
– Called prior to the removal of scene’s “view” (display group)
function scene:destroyScene( event )
local group = self.view


– INSERT code here (e.g. remove listeners, widgets, save state, etc.)


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 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
[/code] [import]uid: 107915 topic_id: 34468 reply_id: 137202[/import]

Hi Chris,
Storyboard can control things nicely, but it takes some practice to learn where you place and create things, and in what “phase” you clean them up (or don’t, if they should be scene-persistent).

You might get some use from my responses to this other thread about Storyboard:
https://developer.coronalabs.com/forum/2013/01/01/sprite-group

Brent [import]uid: 200026 topic_id: 34468 reply_id: 137218[/import]

Thanks for your help with this Brent, everything is finally starting to click into place, although I still have a long way to go I’m finally starting to understand how things work in Lua, it’s been hard trying to rewire my brain from Objective-C but I feel that I will reap the rewards with the Corona SDK now I’m getting used to it. [import]uid: 107915 topic_id: 34468 reply_id: 137285[/import]

Sincerely happy to help. I hope your current apps are succeeding, and that you find equal success using Corona. If you need any other assistance, please post to the forums or drop an e-mail at my Corona account.

Take care, and happy 2013!
Brent [import]uid: 200026 topic_id: 34468 reply_id: 137295[/import]