Repeating function call code question

I have an object I want to “grow” and then “scale” back endlessly with a changing glow effect and now I wonder if the following code is the best solution for this or if there is a better way to do it:

 local pulsin local pulsout pulsout =function (reactor,glow) transitionStash[#transitionStash+1]=transition.to(glow,{time=3800,delay=18,alpha=0.3,xScale=1,yScale=1,transition=easing.inOutQuad}) transitionStash[#transitionStash+1]=transition.to(reactor,{time=3800,delay=20,xScale=1,yScale=1,transition=easing.inOutQuad,onComplete=function() pulsin (reactor,glow) end}) end pulsin =function (reactor,glow) transitionStash[#transitionStash+1]=transition.to(glow,{time=3800,delay=18,alpha=0.1,xScale=0.9,yScale=0.9,transition=easing.inOutQuad}) transitionStash[#transitionStash+1]=transition.to(reactor,{time=3800,delay=20,xScale=0.9,yScale=0.9,transition=easing.inOutQuad,onComplete=function() pulsout (reactor,glow) end}) end pulsin(gfx.reactorcircle,gfx.reactorglow)

Any help welcome!

That is basically how I would approach this too. i.e. Two opposing transitions in functions used as the other transition’s onComplete.

Yeah, that’s how I do it too.

But there is one thing that might be interesting for you if you have several reactors and glows.

Imagine every reactor having the glow attached to the reactor object.

reactor.glow = glow

Now you can use the onComplete function without another anonymous function.

local pulsin local pulsout pulsout = function(reactor) transitionStash[#transitionStash+1]=transition.to(reactor.glow,{time=3800,delay=18,alpha=0.3,xScale=1,yScale=1,transition=easing.inOutQuad}) transitionStash[#transitionStash+1]=transition.to(reactor,{time=3800,delay=20,xScale=1,yScale=1,transition=easing.inOutQuad,onComplete=pulsin}) end pulsin =function (reactor) transitionStash[#transitionStash+1]=transition.to(reactor.glow,{time=3800,delay=18,alpha=0.1,xScale=0.9,yScale=0.9,transition=easing.inOutQuad}) transitionStash[#transitionStash+1]=transition.to(reactor,{time=3800,delay=20,xScale=0.9,yScale=0.9,transition=easing.inOutQuad,onComplete=pulsout}) end gfx.reactorcircle.glow = gfx.reactorglow pulsin(gfx.reactorcircle)

This works, because the onComplete function is called with the transitioning object as a parameter.

In time critical processes, this can give you a performance boost, as creating a lot of functions on the fly is somewhat performance heavy.

Thank you for your feedback! Much appreciated!

I have some questions regarding this:

  1. I’m searching for something counting up my memory… can it be the usage of this kind of anonymous functions causing this?

  2. How can reactor be known to the function when it is called more than once (when onComplete is calling it) without using parameters? It is called in onComplete without a parameter, so why is reactor still known then?

  3. Are the function()…end usage in onComplete very performance and memory “hungry”? Is there a way to get values to functions in onComplete without using a function()…end ?

Thx!

  1. It depends. Normally these functions are local and removed after the transition using finished. But you are using this “transitionStash” and as long as finished transitions stay there they will consume memory. So the question is, how and when do you clear the “transitionStash”?

  2. You use the reactor object in the transition.to function. After the completion the transition calls the “onComplete” function with the reactor as a parameter.

  3. As far as you are using the build in transition functions there is no other way.

Thx for the fast answers!

For 1. I only remove the transitionStash after I change a scene which means the functions are staying as long as the level is played and adding to the memory usage, right? What can be a better approach to handling a LOT of transitions (and timers) in a game scene then?

Than that coould be the problem.

If you stay with my example, you could do something like this:

local transitionStash = {} local pulsin local pulsout pulsout = function(reactor) if not tableIndexOf(transitionStash, reactor) then transitionStash[#transitionStash+1] = reactor end transition.to(reactor.glow,{time=3800,delay=18,alpha=0.3,xScale=1,yScale=1,transition=easing.inOutQuad}) transition.to(reactor,{time=3800,delay=20,xScale=1,yScale=1,transition=easing.inOutQuad,onComplete=pulsin}) end pulsin = function (reactor) if not tableIndexOf(transitionStash, reactor) then transitionStash[#transitionStash+1] = reactor end transition.to(reactor.glow,{time=3800,delay=18,alpha=0.1,xScale=0.9,yScale=0.9,transition=easing.inOutQuad}) transition.to(reactor,{time=3800,delay=20,xScale=0.9,yScale=0.9,transition=easing.inOutQuad,onComplete=pulsout}) end gfx.reactorcircle.glow = gfx.reactorglow pulsin(gfx.reactorcircle) local pauseTransitions = function() for i=1, #transitionStash do local reactor = transitionStash[i] transition.pause(reactor) transition.pause(reactor.glow) end end

So, what we are doing here is to insert the object in the transition stash and not the transition itself. (as a transition can also be paused on the transitioning object)

Every time the one of the two functions is executed, we check if the reactor has an index inside the transitionStash. If not, we define a new index for it. Now we call the transitions, without adding them to the stash.

If we want to pause all transition we loop through the stash and call transition.pause on evey object inside and on each reactor.glow as well.

This is great! Thank you so much!

I wonder how I can use anonymous function with this in the transitions? Is it okay then to use something like this: …onComplete=function() callFunc(var1,var2,var3) end

And how can I use this for my timers and the timerStash={} ? Because I have the same problem there.

The thing is, anonymous functions that are created over and over again might lead to performance issues. So your anonymous functions shoudl be as small as possible. To stay with the above example, it’s pretty easy to adjust.

Just use your anonymous functions as you did before.

local callFunc = function(var1, var2, var3) ... end transition.to(reactor,{time=3800,delay=20,xScale=0.9,yScale=0.9,transition=easing.inOutQuad,onComplete=function() callFunc(var1, var2, var3) end})

The important part the one about the transitionStash, the rest is up to you.

Thx for explaining this!

One more question regarding the memory clean up.

When using
gfx.reactorcircle.glow = gfx.reactorglow

from your example above… how do I have to remove the gfx.reactorglow from memory to really free the mem for this object correctly?

Is the handle gfx.reactorcircle.glow a reference to the object which also needs to be destroyed? Or is it destroyed automaticalle when the gfx.reactorcircle is removed and nilled?

If you nil all references to gfx.reactorcircle all references inside gfx.reactorcircle are removed as well.

So both of these have the same outcome:

local table1 = {} table1.value = 100 --this table1 = nil --has the same outcome like this table1.value = nil table1 = nil

That is basically how I would approach this too. i.e. Two opposing transitions in functions used as the other transition’s onComplete.

Yeah, that’s how I do it too.

But there is one thing that might be interesting for you if you have several reactors and glows.

Imagine every reactor having the glow attached to the reactor object.

reactor.glow = glow

Now you can use the onComplete function without another anonymous function.

local pulsin local pulsout pulsout = function(reactor) transitionStash[#transitionStash+1]=transition.to(reactor.glow,{time=3800,delay=18,alpha=0.3,xScale=1,yScale=1,transition=easing.inOutQuad}) transitionStash[#transitionStash+1]=transition.to(reactor,{time=3800,delay=20,xScale=1,yScale=1,transition=easing.inOutQuad,onComplete=pulsin}) end pulsin =function (reactor) transitionStash[#transitionStash+1]=transition.to(reactor.glow,{time=3800,delay=18,alpha=0.1,xScale=0.9,yScale=0.9,transition=easing.inOutQuad}) transitionStash[#transitionStash+1]=transition.to(reactor,{time=3800,delay=20,xScale=0.9,yScale=0.9,transition=easing.inOutQuad,onComplete=pulsout}) end gfx.reactorcircle.glow = gfx.reactorglow pulsin(gfx.reactorcircle)

This works, because the onComplete function is called with the transitioning object as a parameter.

In time critical processes, this can give you a performance boost, as creating a lot of functions on the fly is somewhat performance heavy.

Thank you for your feedback! Much appreciated!

I have some questions regarding this:

  1. I’m searching for something counting up my memory… can it be the usage of this kind of anonymous functions causing this?

  2. How can reactor be known to the function when it is called more than once (when onComplete is calling it) without using parameters? It is called in onComplete without a parameter, so why is reactor still known then?

  3. Are the function()…end usage in onComplete very performance and memory “hungry”? Is there a way to get values to functions in onComplete without using a function()…end ?

Thx!

  1. It depends. Normally these functions are local and removed after the transition using finished. But you are using this “transitionStash” and as long as finished transitions stay there they will consume memory. So the question is, how and when do you clear the “transitionStash”?

  2. You use the reactor object in the transition.to function. After the completion the transition calls the “onComplete” function with the reactor as a parameter.

  3. As far as you are using the build in transition functions there is no other way.

Thx for the fast answers!

For 1. I only remove the transitionStash after I change a scene which means the functions are staying as long as the level is played and adding to the memory usage, right? What can be a better approach to handling a LOT of transitions (and timers) in a game scene then?

Than that coould be the problem.

If you stay with my example, you could do something like this:

local transitionStash = {} local pulsin local pulsout pulsout = function(reactor) if not tableIndexOf(transitionStash, reactor) then transitionStash[#transitionStash+1] = reactor end transition.to(reactor.glow,{time=3800,delay=18,alpha=0.3,xScale=1,yScale=1,transition=easing.inOutQuad}) transition.to(reactor,{time=3800,delay=20,xScale=1,yScale=1,transition=easing.inOutQuad,onComplete=pulsin}) end pulsin = function (reactor) if not tableIndexOf(transitionStash, reactor) then transitionStash[#transitionStash+1] = reactor end transition.to(reactor.glow,{time=3800,delay=18,alpha=0.1,xScale=0.9,yScale=0.9,transition=easing.inOutQuad}) transition.to(reactor,{time=3800,delay=20,xScale=0.9,yScale=0.9,transition=easing.inOutQuad,onComplete=pulsout}) end gfx.reactorcircle.glow = gfx.reactorglow pulsin(gfx.reactorcircle) local pauseTransitions = function() for i=1, #transitionStash do local reactor = transitionStash[i] transition.pause(reactor) transition.pause(reactor.glow) end end

So, what we are doing here is to insert the object in the transition stash and not the transition itself. (as a transition can also be paused on the transitioning object)

Every time the one of the two functions is executed, we check if the reactor has an index inside the transitionStash. If not, we define a new index for it. Now we call the transitions, without adding them to the stash.

If we want to pause all transition we loop through the stash and call transition.pause on evey object inside and on each reactor.glow as well.

This is great! Thank you so much!

I wonder how I can use anonymous function with this in the transitions? Is it okay then to use something like this: …onComplete=function() callFunc(var1,var2,var3) end

And how can I use this for my timers and the timerStash={} ? Because I have the same problem there.

The thing is, anonymous functions that are created over and over again might lead to performance issues. So your anonymous functions shoudl be as small as possible. To stay with the above example, it’s pretty easy to adjust.

Just use your anonymous functions as you did before.

local callFunc = function(var1, var2, var3) ... end transition.to(reactor,{time=3800,delay=20,xScale=0.9,yScale=0.9,transition=easing.inOutQuad,onComplete=function() callFunc(var1, var2, var3) end})

The important part the one about the transitionStash, the rest is up to you.

Thx for explaining this!

One more question regarding the memory clean up.

When using
gfx.reactorcircle.glow = gfx.reactorglow

from your example above… how do I have to remove the gfx.reactorglow from memory to really free the mem for this object correctly?

Is the handle gfx.reactorcircle.glow a reference to the object which also needs to be destroyed? Or is it destroyed automaticalle when the gfx.reactorcircle is removed and nilled?