Texture Won't Gradually Fade In

The environment in my game is composed of several overlays, and each overlay gradually fades in and out over time. I was using transition.to() to handle the fading until I tested it on a device; it absolutely kills the framerate (I have a total of 72 items fading in and out simultaneously).

So I decided to write my own fading logic based off of the enterFrame event. I’m hoping that performance won’t be an issue anymore. But I can’t seem to get my objects to fade in properly.

Here’s the relevant code:

-- (transitionTime = 600 and I'm running it at 60 FPS)   
  
function overlay:Update()  
 if self.delay \> 0 then  
 self.delay = self.delay - 1  
 return  
 end  
  
 if self.fadingIn then  
 self.texture.alpha = self.texture.alpha + (1 / self.transitionTime)  
 else  
 self.texture.alpha = self.texture.alpha - (1 / self.transitionTime)  
 end  
  
 if self.texture.alpha \<= 0 or self.texture.alpha \>= 1.0 then  
 self.delay = math.random( 30, 120 )  
 self.fadingIn = not self.fadingIn  
  
 if self.fadingIn then self.texture.alpha = 0.0 else self.texture.alpha = 1.0 end  
 end  
end  

What’s weird is that my objects fade out perfectly. They just refuse to fade in! This is the line of code that’s causing the problem:

if self.fadingIn then  
 self.texture.alpha = self.texture.alpha + (1 / self.transitionTime)  

I can’t seem to assign alpha a value here for some reason, even though it works fine when I’m fading out. If I print out alpha before and after this assignment, alpha’s value doesn’t change.

Is my syntax messed up? I must be missing something really obvious…

Thanks for the help! :slight_smile:

(Here’s the whole file in case that’s useful)

local overlay = {}  
local overlay\_mt = { \_\_index = overlay }  
  
function overlay.new( texture, group )  
 local newOverlay = {}  
 newOverlay.texture = texture   
 newOverlay.texture.alpha = 0.1  
 newOverlay.fadingIn = true  
 newOverlay.delay = math.random( 30, 120 )  
 newOverlay.transitionTime = 600  
  
 if group then group:insert( newOverlay.texture ) end  
  
 return setmetatable( newOverlay, overlay\_mt )  
end  
  
function overlay:Update()  
 if self.delay \> 0 then  
 self.delay = self.delay - 1  
 return  
 end  
  
 if self.fadingIn then  
 self.texture.alpha = self.texture.alpha + (1 / self.transitionTime)  
 else  
 self.texture.alpha = self.texture.alpha - (1 / self.transitionTime)  
 end  
  
 if self.texture.alpha \<= 0 or self.texture.alpha \>= 1.0 then  
 self.delay = math.random( 30, 120 )  
 self.fadingIn = not self.fadingIn  
  
 if self.fadingIn then self.texture.alpha = 0.0 else self.texture.alpha = 1.0 end  
 end  
end  
  
return overlay  

[import]uid: 82003 topic_id: 20674 reply_id: 320674[/import]

I’m getting the feeling that this is due to some sort of rounding error. I’m trying to increase alpha by 0.0016666666666667 every frame, but this must be getting rounded down to 0. If I try increasing alpha by 0.005 everything works just fine.

Why, then, does the fading out code work? I’m decrementing alpha by the same value of 0.0016666666666667. Why isn’t *that* getting rounded down to 0?

EDIT: It must be some kind of weird rounding error that only applies to addition. Decrementing alpha by such a tiny amount works fine, but I can’t increase alpha by anything smaller than 0.004. [import]uid: 82003 topic_id: 20674 reply_id: 81154[/import]

Can you record the start time then just set the alpha each time based on that instead of basing it on its past value. E.g.
1-(currentTime-startTime)/totalTime

and to fade in would just be
(currentTime-startTime)/totalTime [import]uid: 62193 topic_id: 20674 reply_id: 81207[/import]

Mmmm, I’ll give that a shot! Thanks dmoore! [import]uid: 82003 topic_id: 20674 reply_id: 81317[/import]

That way it’s not based on framerate either, in case the device slows down, it will still fade-in and out the same pace [import]uid: 62193 topic_id: 20674 reply_id: 81325[/import]

Hmm…I’m still getting that very weird rounding problem where I can’t reassign alpha when alpha = 0 and the increment is very small.

Here’s my code based off of your suggestion:

if (self.fadingIn and self.texture.alpha \<= 0) or (not self.fadingIn and self.texture.alpha \>= 1) then  
 self.startingTime = system.getTimer()  
 end  
  
 if self.fadingIn then  
 local newAlpha = ( system.getTimer() - self.startingTime ) / ( self.transitionTime )  
  
 if newAlpha \> 1 then  
 self.texture.alpha = 1  
 else  
 self.texture.alpha = newAlpha  
 end  
 else  
 local newAlpha = 1 - (( system.getTimer() - self.startingTime ) / ( self.transitionTime ))  
  
 if newAlpha \< 0 then  
 self.texture.alpha = 0  
 else  
 self.texture.alpha = newAlpha  
 end  
 end  

Again, fading out works just fine. But the fading in logic won’t work at all. I can’t set alpha to a new value when alpha = 0 and newAlpha = a very small number… [import]uid: 82003 topic_id: 20674 reply_id: 81329[/import]

Ok, I think I know the problem. As you suggested, the initial 0.0016 value or whatever is rounding down to 0. So because it does so, you keep resetting the start time. Instead, reset the start time only once by re-organizing the code a bit:

[code]
if self.fadingIn then
local newAlpha = ( system.getTimer() - self.startingTime ) / ( self.transitionTime )

if newAlpha > 1 then
self.texture.alpha = 1
–this part is different
self.startingTime = system.getTimer()
self.fadingIn = false
else
self.texture.alpha = newAlpha
end
else
local newAlpha = 1 - (( system.getTimer() - self.startingTime ) / ( self.transitionTime ))

if newAlpha < 0 then
self.texture.alpha = 0
–this part is different
self.startingTime = system.getTimer()
self.fadingIn = true
else
self.texture.alpha = newAlpha
end
end
[/code] [import]uid: 62193 topic_id: 20674 reply_id: 81339[/import]

Ahh! That works beautifully! And it’s organized much more elegantly, too :slight_smile: Thanks for taking the time to help me out with this, dmoore. Much appreciated :slight_smile: [import]uid: 82003 topic_id: 20674 reply_id: 81400[/import]