Working with modules in composer

In my app, I have a small circle image that pulses to let the user know what to tap next. I have this image on almost every page so thought it’d be best to modularise it. However, I can’t get the functions without the module to work properly. Here is my code:

scene1.lua


local composer = require( “composer” )

local tapIndicatorFunc = require(“tapIndicatorFunc”)

local scene = composer.newScene()



– “scene:create()”

function scene:create( event )

   local sceneGroup = self.view

    

   local backgroundOne = display.newImage(“Images/page2.png”, true)

    backgroundOne.x = display.contentWidth/2

    backgroundOne.y = display.contentHeight/2

    

   local tapIndicator = display.newImage(“Images/tapButton.png”, true)

   tapIndicator.x= display.contentWidth/2 - 250

   tapIndicator.y= display.contentHeight/2 + 125

   --tapIndicator.alpha = 0

    

    sceneGroup:insert(backgroundOne)

   sceneGroup:insert(tapIndicator)

end


-------------------------------------------------------------------------------- 

– “scene:show()”

function scene:show( event )

   local sceneGroup = self.view

   local phase = event.phase

   if ( phase == “will” ) then

   elseif ( phase == “did” ) then

   

  tapIndicatorFunc.startScale(tapIndicator)

   

       local previous =  composer.getSceneName( “previous” )

             if previous ~= “main” and previous then

                composer.removeScene(previous, false)   

            end

   end

end


-------------------------------------------------------------------------------- 

– “scene:hide()”

function scene:hide( event )

   local sceneGroup = self.view

   local phase = event.phase

   if ( phase == “will” ) then

         elseif ( phase == “did” ) then

   end

end



– “scene:destroy()”

function scene:destroy( event )

   local sceneGroup = self.view

  transition.cancel(scaleTrans)

end


– Listener setup

scene:addEventListener( “create”, scene )

scene:addEventListener( “show”, scene )

scene:addEventListener( “hide”, scene )

scene:addEventListener( “destroy”, scene )


return scene


tapIndicatorFunc.lua  --my module file


local functionTable = {}

function functionTable.startScale(tapIndicator)

    transition.to(tapIndicator, {time=9000, x = 100, alpha=1, onComplete = scaleUp})   

end   

    

    function functionTable.scaleUp()

        scaleTrans = transition.scaleTo( tapIndicator, { xScale=1.1, yScale=1.1, time=500, onComplete=scaleDown}  )

    end

   function functionTable.scaleDown()

        scaleTrans = transition.scaleTo( tapIndicator, { xScale=1.0, yScale=1.0, time=500, onComplete=scaleUp } )

    end

return functionTable


The startScale function gets called but doesn’t launch the transition and doesn’t move to the onComplete function. Anyone got any idea where I’m going wrong?

Hi @amy.laura.b,

I’m almost certain that it’s just not recognizing your functions because they’re not specified properly. For example:

[lua]

transition.to( tapIndicator, { time=9000, x=100, alpha=1, onComplete=scaleUp } )

[/lua]

But what is “scaleUp” in your “onComplete”? It should probably be “functionTable.scaleUp”, since you added the function to that table.

Brent

Hi Brent,

I’ve actually tried that approach as well. As is : onComplete=functionTable.scaleUp etc but that makes no difference to the outcome. I added a print function to the startScale function and it prints but no transition happens and the other functions are never called.

Hi @amy.laura.b,

May I suggest that you just simplify this entire process into one function that handles all 3 possibilities? It would be more efficient and reliable in my opinion.

Brent

Thanks! That solved the problem. I’m now using this function:

function functionTable.pulsateFunction(tapIndicator)

    if tapIndicator.xScale == 1 then

        scaleTrans = transition.scaleTo( tapIndicator, { xScale=1.1, yScale=1.1, alpha=1, time=500, onComplete=functionTable.pulsateFunction } )

    else

        scaleTrans = transition.scaleTo( tapIndicator, { xScale=1.0, yScale=1.0, time=500, onComplete=functionTable.pulsateFunction})

    end

end

One problem I continue to have though, is that the function is being called immediately on loading the page even though I have called it with a delay in the show:did phase: 

timer.performWithDelay(10000, tapIndicatorFunc.pulsateFunction(tapIndicator)).

Does requiring the module automatically call the function or something?

The way you have it set up, it shouldn’t be called immediately. Are you 100% sure you’re not making some call to it from elsewhere?

Yeah I’ve double checked, no calls from elsewhere. It definitely launches as soon as the show:did phase is called and ignores any timer delay… Strange 

Also, if I’m going to be using the tapIndicator image on numerous pages but in different positions, am I better off creating it as a new display image on each page or once within the module? 

Well it’s true that code is executed when a module is require(d), but the code within module functions should not be called unless you explicitly do so (same as any function really). So, there must be something calling it… it can’t just execute itself.

Could the problem lie with how I am passing in the parameter?

      timer.performWithDelay(1000, tapIndicatorFunc.pulsateFunction(tapIndicator))

Found the issue! It was a problem with how I was passing in the parameter after all. I used a closure instead and now its working fine. 

Thanks for all your help Brent!

Hi @amy.laura.b,

I’m almost certain that it’s just not recognizing your functions because they’re not specified properly. For example:

[lua]

transition.to( tapIndicator, { time=9000, x=100, alpha=1, onComplete=scaleUp } )

[/lua]

But what is “scaleUp” in your “onComplete”? It should probably be “functionTable.scaleUp”, since you added the function to that table.

Brent

Hi Brent,

I’ve actually tried that approach as well. As is : onComplete=functionTable.scaleUp etc but that makes no difference to the outcome. I added a print function to the startScale function and it prints but no transition happens and the other functions are never called.

Hi @amy.laura.b,

May I suggest that you just simplify this entire process into one function that handles all 3 possibilities? It would be more efficient and reliable in my opinion.

Brent

Thanks! That solved the problem. I’m now using this function:

function functionTable.pulsateFunction(tapIndicator)

    if tapIndicator.xScale == 1 then

        scaleTrans = transition.scaleTo( tapIndicator, { xScale=1.1, yScale=1.1, alpha=1, time=500, onComplete=functionTable.pulsateFunction } )

    else

        scaleTrans = transition.scaleTo( tapIndicator, { xScale=1.0, yScale=1.0, time=500, onComplete=functionTable.pulsateFunction})

    end

end

One problem I continue to have though, is that the function is being called immediately on loading the page even though I have called it with a delay in the show:did phase: 

timer.performWithDelay(10000, tapIndicatorFunc.pulsateFunction(tapIndicator)).

Does requiring the module automatically call the function or something?

The way you have it set up, it shouldn’t be called immediately. Are you 100% sure you’re not making some call to it from elsewhere?

Yeah I’ve double checked, no calls from elsewhere. It definitely launches as soon as the show:did phase is called and ignores any timer delay… Strange 

Also, if I’m going to be using the tapIndicator image on numerous pages but in different positions, am I better off creating it as a new display image on each page or once within the module? 

Well it’s true that code is executed when a module is require(d), but the code within module functions should not be called unless you explicitly do so (same as any function really). So, there must be something calling it… it can’t just execute itself.

Could the problem lie with how I am passing in the parameter?

      timer.performWithDelay(1000, tapIndicatorFunc.pulsateFunction(tapIndicator))