Using a for loop as an improv particle generator?

Hi everyone,  

I’ve been trying to use a numerical for loop as a simple generator to trigger a few “flashes” to appear randomly on the screen, but the function only triggers the flash once (instead of three times). 

Here’s the message I get in the simulator console is…

"2015-04-19 11:27:16.306 Corona Simulator[29208:507] WARNING: Cannot set y-scale property of display object to zero.

2015-04-19 11:27:16.306 Corona Simulator[29208:507] WARNING: Cannot set x-scale property of display object to zero."

I gather that the console warning is referring to something not directly related to the for loop, but I can’t figure out what I’m doing wrong here. 

local function randomFlashes() for i = 1, 3 do display.remove(whiteFlash) local randomPosition = (math.random(1200)) whiteFlash = display.newImage("interface-elements/white-flash.png") whiteFlash.x = randomPosition whiteFlash.y = randomPosition whiteFlash:scale(0,0) whiteFlash.alpha = 0 transition.to(whiteFlash, {time=200, xScale=1, yScale=1, alpha=1}) transition.to(whiteFlash, {delay=200, time=200, xScale=0, yScale=0, alpha=0}) end end

First, you rock.  Thanks for formatting your code it looks good.

Second, transition.* functions are non -blocking. The code doesn’t stop there and wait.  It tells Corona, go do this after this delay and over this amount of time.

So it will seem as if ONLY the last ‘flash’ triggers’.

Why?  Think of it like this:

  1. Loop 1 (time 0) - Create object, randomly position it, start two transition.to() calls.
  2. Loop 2 (time 0 + 1 or 2 ms maybe even less) - Destroy object from loop 1, do all that again.
  3. Loop 3 (time 0 + 4 or 5 ms maybe even less) - Destroy object from loop 2, do all that again.

The object from loop3 is not destroyed and the transition.* calls actually execute.

Try this instead:

local function onComplete( self ) display.remove( self ) end local function randomFlashes() for i = 1, 3 do ---display.remove(whiteFlash) -- DO NOT DO THIS local randomPosition = (math.random(1200)) local whiteFlash = display.newImage("interface-elements/white-flash.png") -- CAHNGED TO LOCAL whiteFlash.x = randomPosition whiteFlash.y = randomPosition whiteFlash:scale(0,0) whiteFlash.alpha = 0 transition.to(whiteFlash, {time=200, xScale=1, yScale=1, alpha=1}) transition.to(whiteFlash, {delay=200, time=200, xScale=0, yScale=0, alpha=0, onComplete = onComplete}) end end

Thank you! It works perfectly. Very interesting… So using onComplete to forcibly kick the logic out of the same function does the trick. Is this because the jump to execute the second function, onComplete in this case, is considered a blocking action? Because the logic flow has left the same local function from whence it started? 

No.  onCompleteis an optional argument you can pass to transition.to().  It executes the function pointed to after the transition ends.

re: Blocking.  I don’t think you understood me.

In LUA, all code is blocking, in the sense that you can’t move onto the next line of code until the current line executes.  I said that transition.to() is non-blocking, because your question made it seem like you thought the transition action had to finish before the next line of code would execute:

-- I think you thought this: transition.to(whiteFlash, {time=200, xScale=1, yScale=1, alpha=1}) -- .. 200 ms, then next line transition.to(whiteFlash, {delay=200, time=200, xScale=0, yScale=0, alpha=0, onComplete = onComplete}) -- 200 ms, then next line

This is not how it works.  

The transition library allows you to schedule work to be done over time.  Then every frame, Corona does a little bit of that work.

What the above code really does:

-- Execute next two lined in order and immediately. transition.to(whiteFlash, {time=200, xScale=1, yScale=1, alpha=1}) transition.to(whiteFlash, {delay=200, time=200, xScale=0, yScale=0, alpha=0, onComplete = onComplete}) -- Now, two transitions have been scheduled to do this: -- -- First transition, Over 200 ms, transition: -- -- whiteFlash.xScale from 0 to 1 -- whiteFlash.yScale from 0 to 1 -- whiteFlash.alpha from 0 to 1 -- Second transition wait 200 ms, then start (actually on next avilable frame boundary): -- whiteFlash.xScale from 1 to 0 -- whiteFlash.yScale from 1 to 0 -- whiteFlash.alpha from 1 to 0 -- At the end of the second transition, call onComplete and pass in a reference to 'whiteFlash'

Yup, I’m confused. I definitely did think that at first, that the first transition.to had to finish executing before the next one in the sequence would execute. Now I see that it doesn’t. I get that part of it I think. 

In your example above with onComplete on the second transition.to, how does display.remove( self ) successfully remove the display object (self) when the object (whiteFlash) was declared as a local variable inside a different function? i thought that local variables and handles were only accessible from within their respective chunks? 

On a separate note, I thought I saw somewhere that you’ve been working with Corona for 3-4 years. Is that right? Out of curiosity, do you still consult on small and medium-sized projects? If you don’t mind my asking, where are you located? I live in Northern California in the US about 30 miles north of San Francisco. 

Thank you again, 

Chad

‘whiteFlash’ is local and falls out of scope, but… transition.to() knows about it since you pass the ‘handle’ to it.  So, when transtion.to() is done, it looks to see if you supplied an onComplete function.  If you did, it passes the handle for the object ‘whiteFlash’ to the onComplete function you supplied.

Yes, I’ve been using Corona since 2012, and Yes, I still consult.  I live near Portland OR.

Cheers (not I’m not British, just like to use this closing),

Ed

hi Roaminggamer,

it would be really nice if you could help me with my problem. This is roughly the same as this topic but I can not make my function can be called any time without bug in transitions.

https://forums.coronalabs.com/topic/56964-multiple-transition-on-the-same-time/

First, you rock.  Thanks for formatting your code it looks good.

Second, transition.* functions are non -blocking. The code doesn’t stop there and wait.  It tells Corona, go do this after this delay and over this amount of time.

So it will seem as if ONLY the last ‘flash’ triggers’.

Why?  Think of it like this:

  1. Loop 1 (time 0) - Create object, randomly position it, start two transition.to() calls.
  2. Loop 2 (time 0 + 1 or 2 ms maybe even less) - Destroy object from loop 1, do all that again.
  3. Loop 3 (time 0 + 4 or 5 ms maybe even less) - Destroy object from loop 2, do all that again.

The object from loop3 is not destroyed and the transition.* calls actually execute.

Try this instead:

local function onComplete( self ) display.remove( self ) end local function randomFlashes() for i = 1, 3 do ---display.remove(whiteFlash) -- DO NOT DO THIS local randomPosition = (math.random(1200)) local whiteFlash = display.newImage("interface-elements/white-flash.png") -- CAHNGED TO LOCAL whiteFlash.x = randomPosition whiteFlash.y = randomPosition whiteFlash:scale(0,0) whiteFlash.alpha = 0 transition.to(whiteFlash, {time=200, xScale=1, yScale=1, alpha=1}) transition.to(whiteFlash, {delay=200, time=200, xScale=0, yScale=0, alpha=0, onComplete = onComplete}) end end

Thank you! It works perfectly. Very interesting… So using onComplete to forcibly kick the logic out of the same function does the trick. Is this because the jump to execute the second function, onComplete in this case, is considered a blocking action? Because the logic flow has left the same local function from whence it started? 

No.  onCompleteis an optional argument you can pass to transition.to().  It executes the function pointed to after the transition ends.

re: Blocking.  I don’t think you understood me.

In LUA, all code is blocking, in the sense that you can’t move onto the next line of code until the current line executes.  I said that transition.to() is non-blocking, because your question made it seem like you thought the transition action had to finish before the next line of code would execute:

-- I think you thought this: transition.to(whiteFlash, {time=200, xScale=1, yScale=1, alpha=1}) -- .. 200 ms, then next line transition.to(whiteFlash, {delay=200, time=200, xScale=0, yScale=0, alpha=0, onComplete = onComplete}) -- 200 ms, then next line

This is not how it works.  

The transition library allows you to schedule work to be done over time.  Then every frame, Corona does a little bit of that work.

What the above code really does:

-- Execute next two lined in order and immediately. transition.to(whiteFlash, {time=200, xScale=1, yScale=1, alpha=1}) transition.to(whiteFlash, {delay=200, time=200, xScale=0, yScale=0, alpha=0, onComplete = onComplete}) -- Now, two transitions have been scheduled to do this: -- -- First transition, Over 200 ms, transition: -- -- whiteFlash.xScale from 0 to 1 -- whiteFlash.yScale from 0 to 1 -- whiteFlash.alpha from 0 to 1 -- Second transition wait 200 ms, then start (actually on next avilable frame boundary): -- whiteFlash.xScale from 1 to 0 -- whiteFlash.yScale from 1 to 0 -- whiteFlash.alpha from 1 to 0 -- At the end of the second transition, call onComplete and pass in a reference to 'whiteFlash'

Yup, I’m confused. I definitely did think that at first, that the first transition.to had to finish executing before the next one in the sequence would execute. Now I see that it doesn’t. I get that part of it I think. 

In your example above with onComplete on the second transition.to, how does display.remove( self ) successfully remove the display object (self) when the object (whiteFlash) was declared as a local variable inside a different function? i thought that local variables and handles were only accessible from within their respective chunks? 

On a separate note, I thought I saw somewhere that you’ve been working with Corona for 3-4 years. Is that right? Out of curiosity, do you still consult on small and medium-sized projects? If you don’t mind my asking, where are you located? I live in Northern California in the US about 30 miles north of San Francisco. 

Thank you again, 

Chad

‘whiteFlash’ is local and falls out of scope, but… transition.to() knows about it since you pass the ‘handle’ to it.  So, when transtion.to() is done, it looks to see if you supplied an onComplete function.  If you did, it passes the handle for the object ‘whiteFlash’ to the onComplete function you supplied.

Yes, I’ve been using Corona since 2012, and Yes, I still consult.  I live near Portland OR.

Cheers (not I’m not British, just like to use this closing),

Ed

hi Roaminggamer,

it would be really nice if you could help me with my problem. This is roughly the same as this topic but I can not make my function can be called any time without bug in transitions.

https://forums.coronalabs.com/topic/56964-multiple-transition-on-the-same-time/