Best way to structure code?

Hi,

I’m doing a small iPad project and are constantly running into issues where I can’t reach local function variables and tables. I feel that the way I have structured my functions and my code is the main issue here.

I started with the “game” template in Corona and so in my level1.lua I’ve put some code in the scene:createScene functions and some of it outside - for example a tap listener function.

What is the best way of structuring things like these? Keep everything in the main createScene function or just the display objects? And if separate how do I access the different functions?

Below is the structure I use. Declare things you will need throughout the scene at the top of the file.  For example you can set up an table for local variables and graphics objects, which can then be accessed or added to later.

[lua]

local v = {}

v.currentScore = 0

v.difficulty = 3

local gfx = {}

gfx.bg = display.newImageRect(“bg.png”, 480, 320) – within create scene

[/lua]

You could then say hide the background in a function later on with gfx.bg.alpha = 0.

SCENE TEMPLATE:

[lua]


– LIBRARIES


local storyboard = require(“storyboard”)


– DISPLAY GROUPS


local group = display.newGroup()


– LOCAL VARIABLES


local scene = storyboard.newScene()


– OBJECT DECLARATIONS



– MY SCENE FUNCTIONS



– STORYBOARD FUNCTIONS


– Called when the scene’s view does not exist:

function scene:createScene(event)

    group = self.view

end

– Called BEFORE scene has moved onscreen:

function scene:willEnterScene(event)

    group = self.view

end

– Called immediately after scene has moved onscreen:

function scene:enterScene(event)

    group = self.view

end

– Called when scene is about to move offscreen:

function scene:exitScene(event)

    group = self.view

end

– Called AFTER scene has finished moving offscreen:

function scene:didExitScene(event)

    group = self.view

end

– Called prior to the removal of scene’s “view” (display group)

function scene:destroyScene(event)

    group = self.view

end

– Called if/when overlay scene is displayed via storyboard.showOverlay()

function scene:overlayBegan(event)

    group = self.view

    local overlay_scene = event.sceneName – overlay scene name

end

– Called if/when overlay scene is hidden/removed via storyboard.hideOverlay()

function scene:overlayEnded(event)

    group = self.view

    local overlay_scene = event.sceneName – overlay scene name

end


– END OF YOUR IMPLEMENTATION


scene:addEventListener(“createScene”, scene)

scene:addEventListener(“willEnterScene”, scene)

scene:addEventListener(“enterScene”, scene)

scene:addEventListener(“exitScene”, scene)

scene:addEventListener(“didExitScene”, scene)

scene:addEventListener(“destroyScene”, scene)

scene:addEventListener(“overlayBegan”, scene)

scene:addEventListener(“overlayEnded”, scene)


return scene

[/lua]

Ahh, great template - big thanks for that! I’ve transferred my prev scene into that one and cleaned it up loads just from that new structure. I’ve moved most of the functions up under “My scene functions” and are calling them from my scene:createScene function now instead.

In one spot I’m still running into this (i’m sure very simple) problem where I can’t reach a variable. In my tap listener I want to check if the tapped object is the correct one but I can’t reach variable “rightOne”. I though I could do it with theOne.rightOne but apparently not.

-- Set random shape as "The one!" local function theOne(shapes) local rightOne = math.random( 1, 3) print( "Correct: ".. rightOne .. " - " .. shapes[rightOne] ) -- Debug return rightOne end -- Check for tap and do things local function myTapListener( event ) if ( event.target.name == shapes[rightOne]) then print( "Right you are son!" ) print( event.target.name ) else print( "Noop!" ) print( event.target.name ) -- Debug print( shapes[rightOne] ) -- Debug print( rightOne) -- Debug end print( "Tap event on: " .. event.target.name ) -- Debug return true end

You seem to be creating rghtOne as a local variable within the theOne function, so it will only be accessible to that function. I see that you return the value but I can’t see what to.

The key thing to remember is that any local variable created within a function is deleted as soon as the function has completed, unless you store it in another variable with a wider scope, either directly or by returning it from the function.

At the top of your file in the local variables section you could have:

[lua]

local rightOne – this will declare rightOne as a variable that the whole scene has access to

[/lua]

Then when you call theOne do:

[lua]

rightOne = theOne(shapes)

[/lua]

This will assign a value of between 1-3 to the variable rightOne, which can now be accessed by the tap listener.

Yes, I think it’s in the scope of the functions I’m confusing myself. I thought by returning the the local variable it would become usable to other functions. But alas no.

I’ve deleted function theOne now and instead made it part of an above shuffle function when I understood that Lua can return multiple values. I cannot call the function in the tap listener as it would randomize the correct answer again (it should only be done once per play round). 

The shuffle function is run once when the level is loaded and then again when the player has found the correct answer (thus starting a new round). The tap listener should check every tap and see if the correct (randomzied) object has been tapped.

Here is the full function code. I call it when creating the scene by: shuffle(shapes)

------------------------------------------------------------------ -- LOCAL VARIABLES ------------------------------------------------------------------ local scene = storyboard.newScene() local screenW, screenH, halfW = display.contentWidth, display.contentHeight, display.contentWidth\*0.5 -- Create an array/table with the scene shapes local shapes = {"triangel.png", "kvadrat.png", "cirkel.png"} local newShapes local rightOne ------------------------------------------------------------------ -- OBJECT DECLARATIONS ------------------------------------------------------------------ ------------------------------------------------------------------ -- MY SCENE FUNCTIONS ------------------------------------------------------------------ -- Randomize the shapes to display local function shuffle(shapes) local n = #shapes while n \> 2 do local k = math.random(n) shapes[n], shapes[k] = shapes[k], shapes[n] n = n - 1 end -- Set random at correct local rightOne = math.random( 1, 3) print( "Correct: ".. rightOne .. " - " .. shapes[rightOne] ) -- Debug return newShapes, rightOne end -- Check for tap and do things local function myTapListener(event) newShapes = shuffle(shapes) rightOne = shuffle(shapes) if ( event.target.name == shapes[rightOne] ) then print( "Right you are son!" ) print( event.target.name ) else print( "Noop!" ) print( event.target.name ) -- Debug print( shapes[rightOne] ) -- Debug print( rightOne) -- Debug end print( "Tap event on: " .. event.target.name ) -- Debug return true end

Perhaps I’ve gone about this the wrong way somehow? It seems it shouldn’t be hard or require any type of work around?

Below is the structure I use. Declare things you will need throughout the scene at the top of the file.  For example you can set up an table for local variables and graphics objects, which can then be accessed or added to later.

[lua]

local v = {}

v.currentScore = 0

v.difficulty = 3

local gfx = {}

gfx.bg = display.newImageRect(“bg.png”, 480, 320) – within create scene

[/lua]

You could then say hide the background in a function later on with gfx.bg.alpha = 0.

SCENE TEMPLATE:

[lua]


– LIBRARIES


local storyboard = require(“storyboard”)


– DISPLAY GROUPS


local group = display.newGroup()


– LOCAL VARIABLES


local scene = storyboard.newScene()


– OBJECT DECLARATIONS



– MY SCENE FUNCTIONS



– STORYBOARD FUNCTIONS


– Called when the scene’s view does not exist:

function scene:createScene(event)

    group = self.view

end

– Called BEFORE scene has moved onscreen:

function scene:willEnterScene(event)

    group = self.view

end

– Called immediately after scene has moved onscreen:

function scene:enterScene(event)

    group = self.view

end

– Called when scene is about to move offscreen:

function scene:exitScene(event)

    group = self.view

end

– Called AFTER scene has finished moving offscreen:

function scene:didExitScene(event)

    group = self.view

end

– Called prior to the removal of scene’s “view” (display group)

function scene:destroyScene(event)

    group = self.view

end

– Called if/when overlay scene is displayed via storyboard.showOverlay()

function scene:overlayBegan(event)

    group = self.view

    local overlay_scene = event.sceneName – overlay scene name

end

– Called if/when overlay scene is hidden/removed via storyboard.hideOverlay()

function scene:overlayEnded(event)

    group = self.view

    local overlay_scene = event.sceneName – overlay scene name

end


– END OF YOUR IMPLEMENTATION


scene:addEventListener(“createScene”, scene)

scene:addEventListener(“willEnterScene”, scene)

scene:addEventListener(“enterScene”, scene)

scene:addEventListener(“exitScene”, scene)

scene:addEventListener(“didExitScene”, scene)

scene:addEventListener(“destroyScene”, scene)

scene:addEventListener(“overlayBegan”, scene)

scene:addEventListener(“overlayEnded”, scene)


return scene

[/lua]

Ahh, great template - big thanks for that! I’ve transferred my prev scene into that one and cleaned it up loads just from that new structure. I’ve moved most of the functions up under “My scene functions” and are calling them from my scene:createScene function now instead.

In one spot I’m still running into this (i’m sure very simple) problem where I can’t reach a variable. In my tap listener I want to check if the tapped object is the correct one but I can’t reach variable “rightOne”. I though I could do it with theOne.rightOne but apparently not.

-- Set random shape as "The one!" local function theOne(shapes) local rightOne = math.random( 1, 3) print( "Correct: ".. rightOne .. " - " .. shapes[rightOne] ) -- Debug return rightOne end -- Check for tap and do things local function myTapListener( event ) if ( event.target.name == shapes[rightOne]) then print( "Right you are son!" ) print( event.target.name ) else print( "Noop!" ) print( event.target.name ) -- Debug print( shapes[rightOne] ) -- Debug print( rightOne) -- Debug end print( "Tap event on: " .. event.target.name ) -- Debug return true end

You seem to be creating rghtOne as a local variable within the theOne function, so it will only be accessible to that function. I see that you return the value but I can’t see what to.

The key thing to remember is that any local variable created within a function is deleted as soon as the function has completed, unless you store it in another variable with a wider scope, either directly or by returning it from the function.

At the top of your file in the local variables section you could have:

[lua]

local rightOne – this will declare rightOne as a variable that the whole scene has access to

[/lua]

Then when you call theOne do:

[lua]

rightOne = theOne(shapes)

[/lua]

This will assign a value of between 1-3 to the variable rightOne, which can now be accessed by the tap listener.

Yes, I think it’s in the scope of the functions I’m confusing myself. I thought by returning the the local variable it would become usable to other functions. But alas no.

I’ve deleted function theOne now and instead made it part of an above shuffle function when I understood that Lua can return multiple values. I cannot call the function in the tap listener as it would randomize the correct answer again (it should only be done once per play round). 

The shuffle function is run once when the level is loaded and then again when the player has found the correct answer (thus starting a new round). The tap listener should check every tap and see if the correct (randomzied) object has been tapped.

Here is the full function code. I call it when creating the scene by: shuffle(shapes)

------------------------------------------------------------------ -- LOCAL VARIABLES ------------------------------------------------------------------ local scene = storyboard.newScene() local screenW, screenH, halfW = display.contentWidth, display.contentHeight, display.contentWidth\*0.5 -- Create an array/table with the scene shapes local shapes = {"triangel.png", "kvadrat.png", "cirkel.png"} local newShapes local rightOne ------------------------------------------------------------------ -- OBJECT DECLARATIONS ------------------------------------------------------------------ ------------------------------------------------------------------ -- MY SCENE FUNCTIONS ------------------------------------------------------------------ -- Randomize the shapes to display local function shuffle(shapes) local n = #shapes while n \> 2 do local k = math.random(n) shapes[n], shapes[k] = shapes[k], shapes[n] n = n - 1 end -- Set random at correct local rightOne = math.random( 1, 3) print( "Correct: ".. rightOne .. " - " .. shapes[rightOne] ) -- Debug return newShapes, rightOne end -- Check for tap and do things local function myTapListener(event) newShapes = shuffle(shapes) rightOne = shuffle(shapes) if ( event.target.name == shapes[rightOne] ) then print( "Right you are son!" ) print( event.target.name ) else print( "Noop!" ) print( event.target.name ) -- Debug print( shapes[rightOne] ) -- Debug print( rightOne) -- Debug end print( "Tap event on: " .. event.target.name ) -- Debug return true end

Perhaps I’ve gone about this the wrong way somehow? It seems it shouldn’t be hard or require any type of work around?