Properly creating local variables and disposal with Storyboard

Hey Everyone,

First let me say that I love the Corona community so far and that I would definitely appreciate all of your opinions on the best practices here.

Being relatively new I’m sort of stumbling through some best techniques and I definitely want to practice performance optimization as much as I can. (I’ve read A LOT but this part still eludes me)

My question is about creating local variables, where to do so, and where to removeSelf()/nil them if applicable. I’ll sort-of split this into two different methods to make it a little easier to understand (I’ll also show code for both)… Is one better than the other? (Please see Method1 and Method2 below):

Method 1 (Game button still exists in scene:destroyScene):
Specifically, I’ve noticed that if I create local variables at the top of my file in a “Forward Declarations” section, say a UI button, initialize that button in the scene:createScene function and add it to the screen group, I have access to it and can removeSelf()/nil it in the scene:destroyScene function.

VERY Stripped down example of the code for Method 1 (I’ve left out irrelevant code/functions):

  
---------------------------------------------------------------------------------  
-- Forward Declarations  
---------------------------------------------------------------------------------  
  
local newGameButton;  
  
---------------------------------------------------------------------------------  
-- Main Menu functions  
---------------------------------------------------------------------------------  
  
-- These are the functions triggered by the buttons  
  
local function newGameButtonReleased( event )  
  
 if event.phase == "ended" then  
 storyboard.gotoScene( "nextscene", "slideLeft", 500 );  
 end  
  
 return true;  
end  
  
---------------------------------------------------------------------------------  
-- Storyboard functions  
---------------------------------------------------------------------------------  
  
function scene:createScene( event )  
 local screenGroup = self.view;   
  
 -- Create buttons  
 newGameButton = ui.newButton{  
 default = "images/redbutton.png",  
 over = "images/redbuttonover.png",  
 onRelease = newGameButtonReleased,  
 id = "newGameButton",  
 text = "New Game",  
 textColor = { 51, 51, 51, 255 },  
 size = 22,  
 emboss = true  
 }  
 screenGroup:insert( newGameButton );  
  
 newGameButton.x = display.contentWidth/2;   
 newGameButton.y = display.contentHeight/2 - 115;  
  
end  
  
function scene:destroyScene( event )  
  
 -- Remove display items: NOTICE newGameButton DOES exist in this way of doing it:  
  
 if newGameButton then newGameButton:removeSelf(); newGameButton=nil; end  
  
end  
  
... etc.  
  

Method 2 (Game button DOES NOT exist in scene:destroyScene):
On the otherhand, if I don’t create the local button in at the top of my file and assign it to a new button in the scene:createScene function but rather create and assign it in that function (and add to local screengroup) that I do not have access to it.

VERY Stripped down example of the code for Method 2 (I’ve left out irrelevant code/functions):

  
---------------------------------------------------------------------------------  
-- Main Menu functions  
---------------------------------------------------------------------------------  
  
-- These are the functions triggered by the buttons  
  
local function newGameButtonReleased( event )  
  
 if event.phase == "ended" then  
 storyboard.gotoScene( "nextscene", "slideLeft", 500 );  
 end  
  
 return true;  
end  
  
---------------------------------------------------------------------------------  
-- Storyboard functions  
---------------------------------------------------------------------------------  
  
function scene:createScene( event )  
 local screenGroup = self.view;   
  
 -- Create buttons  
 local newGameButton = ui.newButton{  
 default = "images/redbutton.png",  
 over = "images/redbuttonover.png",  
 onRelease = newGameButtonReleased,  
 id = "newGameButton",  
 text = "New Game",  
 textColor = { 51, 51, 51, 255 },  
 size = 22,  
 emboss = true  
 }  
 screenGroup:insert( newGameButton );  
  
 newGameButton.x = display.contentWidth/2;   
 newGameButton.y = display.contentHeight/2 - 115;  
  
end  
  
function scene:destroyScene( event )  
  
 -- Remove display items: NOTICE newGameButton DOES NOT exist in this way of doing it which makes checking and removing the newGameButton irrelevant:  
  
 -- if newGameButton then newGameButton:removeSelf(); newGameButton=nil; end  
  
end  
  
... etc.  
  

Thank you for any help you can provide you lovely Corona experts! :slight_smile: [import]uid: 141828 topic_id: 29249 reply_id: 329249[/import]

Hi there,

I would say that Method 1 is better.

In Method 2, your comment in line 43 isn’t quite right. Although it’s true that you can’t access newGameButton outside of the createScene function, it still most certainly exists (i.e., the button does still appear on screen). That’s a problem, because you have an object that exists, but you no longer have a variable to reference that object and, thereby, remove it.

Method 1 doesn’t suffer from this problem, because the scope of the newGameButton variable is the entire module, so both the createScene and destroyScene functions can access it.

It’s good that you’re focused on performance optimization. In general, though, whether you localize single variables like this in a function or in the entire module won’t make any noticeable difference. Where your choice of localization starts to matter more is variables that you access in your main game loop (i.e., in enterFrame events), or in other long loops within your code.

Hope this helps.

  • Andrew [import]uid: 109711 topic_id: 29249 reply_id: 117625[/import]

Thank you for the reply aukStudios!

I was leaning more toward Method 1 as it seemed like a good idea to have access to localized variables throughout the module and having the ability to dispose of them in the destroyScene function.

Would the same thing apply to other types of objects such as images/text? I noticed that most examples I see have these types of objects as local variables within their respective functions, such as:

  
function scene:createScene( event )  
 local screenGroup = self.view;   
  
 -- Set background image  
 local mainmenuBG = display.newImageRect( "images/genericbackground.jpg", 320, 480 );  
 mainmenuBG.x = display.contentWidth/2;   
 mainmenuBG.y = display.contentHeight/2;  
 screenGroup:insert( mainmenuBG );  
  
 -- Create header text  
 local headerText = display.newEmbossedText(screenGroup, "Test", 0, 0, "Font", 40);  
 headerText:setReferencePoint(display.CenterReferencePoint);  
 headerText.x = display.contentWidth/2;  
 headerText.y = 23;  
 headerText:setTextColor(42, 46, 231);  
 screenGroup:insert( headerText );  
  

Seems like they should follow the same process as my buttons in Method 1 by setting them up in my forward declarations etc …

Also, If you happen to have any good examples of best practices while working with game loops I would definitely appreciate it!

Thank you again for your help - It is tough to learn best practices when there are so many examples! [import]uid: 141828 topic_id: 29249 reply_id: 117629[/import]

Hi reliky,

Yep, you could take that same approach for images, text, or any other display object. However, you can imagine that this could get quickly out of hand if you have lots of display objects.

I don’t know what’s considered best practice, but in my case, I do the following. When I create any display object, I never add it directly to the stage (the default display group). Instead, I always add it somewhere in my hierarchy of display groups. Then, I wrote a recursive removeDisplayGroups function. When passed a display group, it first removes the display group’s children (by calling itself on each child) and then removes the display group itself. This way, I can clear the memory of all, or a portion of, my display group hierarchy at any time, and yet I don’t have to maintain references to the objects themselves outside of the block where they were created.

  • Andrew [import]uid: 109711 topic_id: 29249 reply_id: 117632[/import]

Excellent - Thank you so much Andrew for the excellent explanation and suggestion about how you manage your display groups. I have a much better understanding of how that could be very beneficial!

Also, if anyone else has any additional information about how they manage performance optimization for display objects/groups etc. I would definitely appreciate it - any tips are greatly appreciated since there are so many options! [import]uid: 141828 topic_id: 29249 reply_id: 117634[/import]