Timer won't start in a function

I’m trying run a timer in a function that’s called by an event listener, but it’s not getting set. When I print the variable I assigned the timer to, it only shows “nil”. Any idea what I’m doing wrong here?  Here my code:

local composer = require( "composer" ) local scene = composer.newScene() local physics = require("physics") physics.start() local upTimeTimer local counter local platform local ball -- ----------------------------------------------------------------------------- -- Scene functions -- ----------------------------------------------------------------------------- local function pushBall() upTimeTimer = timer.performWithDelay(10, upTimeCounter, 0) print(upTimeTimer) end local function upTimeCounter() counter = counter + 1 upTime.text = counter end -- create() function scene:create( event ) local sceneGroup = self.view platform = display.newRect(\_centerX,(\_height - 10),\_width,10) platform:setFillColor(0.3,0.3,0.6) platform.myName = "platform" ball = display.newCircle(100, 100, 50) ball.x = \_centerX ball.y = \_centerY ball:setFillColor(0.9,0.2,0.2) ball.alpha = 0.8 physics.addBody( platform, "static") physics.addBody( ball, "dynamic", {radius=50, bounce=0.5} ) upTime = display.newText( 0, 10, 20, native.systemFont, 40 ) upTime.anchorX = 0 upTime:setFillColor(0.8) sceneGroup:insert(platform) sceneGroup:insert(ball) sceneGroup:insert(upTime) end function scene:show( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then elseif ( phase == "did" ) then ball:addEventListener("tap", pushBall) ball.collision = onPlatformCollision ball:addEventListener("collision", ball) end end function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then elseif ( phase == "did" ) then end end function scene:destroy( event ) local sceneGroup = self.view end -- ----------------------------------------------------------------------------- -- Scene function listeners -- ----------------------------------------------------------------------------- scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) -- ----------------------------------------------------------------------------- return scene

Thanks!

You’re running into a scope issue. Corona is a one pass compiler (well interpreter). When this line executes:

upTimeTimer = timer.performWithDelay(10, upTimeCounter, 0)

upTimeCounter doesn’t exist, so Lua makes a new global variable for it and assigns the value nil. When this function eventually runs, the timer has nil as a value passed for it.  A few lines down you define the function:

local function upTimeCounter()

Now you have a new local variable that points to your function, that temporarily overrides the global for the rest of the module. But the timer is still holding the nil function.

The fix is to either move upTimeCounter() before pushBall() or declare upTimeCounter() at the top as a local (like you’ve done with several variables) and then change the function declaration to the anonymous format:

local ball local upTimeCounter -- ----------------------------------------------------------------------------- -- Scene functions -- ----------------------------------------------------------------------------- local function pushBall()     upTimeTimer = timer.performWithDelay(10, upTimeCounter, 0)     print(upTimeTimer) end upTimeCounter = function ()     counter = counter + 1     upTime.text = counter end

Personally I would do the first option. It’s pretty easy to reorder those two functions.

Thanks Rob! 

You’re running into a scope issue. Corona is a one pass compiler (well interpreter). When this line executes:

upTimeTimer = timer.performWithDelay(10, upTimeCounter, 0)

upTimeCounter doesn’t exist, so Lua makes a new global variable for it and assigns the value nil. When this function eventually runs, the timer has nil as a value passed for it.  A few lines down you define the function:

local function upTimeCounter()

Now you have a new local variable that points to your function, that temporarily overrides the global for the rest of the module. But the timer is still holding the nil function.

The fix is to either move upTimeCounter() before pushBall() or declare upTimeCounter() at the top as a local (like you’ve done with several variables) and then change the function declaration to the anonymous format:

local ball local upTimeCounter -- ----------------------------------------------------------------------------- -- Scene functions -- ----------------------------------------------------------------------------- local function pushBall()     upTimeTimer = timer.performWithDelay(10, upTimeCounter, 0)     print(upTimeTimer) end upTimeCounter = function ()     counter = counter + 1     upTime.text = counter end

Personally I would do the first option. It’s pretty easy to reorder those two functions.

Thanks Rob!