0
\$\begingroup\$

I've been trying to create a white-screen fade effect for my libgdx game.

When I run the following code with fadeOut = false, nothing happens (white-screen does not appear because alpha is 0). When fadeOut = true, it works (fades out) until the actors alpha is down to 0.5f, then it rebounds and starts fading in. No clue why.

    if(fadeOut){
        map.setColor(new Color(1, 1, 1, 1));
        addAction(Actions.fadeOut(duration));
    }else{
        map.setColor(new Color(1, 1, 1, 0));
        addAction(Actions.fadeIn(duration));
    }

When I run the exact same code but switch the starting alpha's like this:

if(fadeOut){
        map.setColor(new Color(1, 1, 1, 0)); //notice this is 0 now
        addAction(Actions.fadeOut(duration));
    }else{
        map.setColor(new Color(1, 1, 1, 1)); // notice this is 1 now
        addAction(Actions.fadeIn(duration));
    }

When I run this code with fadeOut = false, nothing happens (screen is all white though, because starting alpha is 1). When fadeOut = true, it actually fades in. sigh...


Here's the draw method i'm running, but I doubt there's an issue there.

@Override
public void draw(Batch batch, float parentAlpha){
    batch.draw(texture, 0, 0);

    //Get the current color of the actor
    batch.setColor(getColor());

    act(Gdx.graphics.getDeltaTime());

}

I really don't know why this is happening, any insight would be valuable.

Thanks!


Edit: Here's the full code I'm using to call the fades:

I have a "StartScreen" object that gets initialized (and contains the stage), and this piece of code is in it's constructor:

fade = new Fade((int)GdxGame.getWidth(), (int)GdxGame.getWidth(), Color.WHITE, fadeOut, duration);
stage.addActor(fade);

In the same StartScreen class, I have the following code to draw the stage:

@Override
public void render() {
    super.render();
    stage.draw();
}//end render

The following code then calls the "Fade" objects constructor which has the code mentioned above:

public Fade(int width, int height, Color color, boolean fadeOut, float duration){

    this.fadeIn = fadeOut;
    this.duration = duration;

    Pixmap map = new Pixmap(width, height, Pixmap.Format.RGBA8888);

    if(fadeOut){
        map.setColor(new Color(1, 1, 1, 1));
        addAction(Actions.fadeOut(duration));
    }else{
        map.setColor(new Color(1, 1, 1, 0));
        addAction(Actions.fadeIn(duration));
    }

    map.fillRectangle(0, 0, width, height);

    texture = new Texture(map);

    map.dispose();
}

Update: Changing the alpha with this line:

map.setColor(new Color(1, 1, 1, alpha)); to 0.2f or 0.7f works fine. Though that's because it's changing the alpha of the pixmap (and later becomes the texture)- which leads me into investigation of whether fadeOut or fadeIn change the texture's alpha or something else...

\$\endgroup\$
2
  • \$\begingroup\$ Can you show how you're calling the piece of code that starts the fade in/out? Is it possible it is being invoked multiple times? \$\endgroup\$
    – John
    Dec 26, 2016 at 16:25
  • \$\begingroup\$ Updated. The fades actually get called only once. Also, sorry the response was so late, I was a bit busy. \$\endgroup\$
    – Eric
    Dec 26, 2016 at 21:23

1 Answer 1

0
\$\begingroup\$

Big Edit: The reason the above didn't work was because I was changing the Alpha of the pixmap, and not the texture. Huge mistake, should work after creating a texture with the pixmap.


After a while of playing around, I arrived at a conclusion that fadeIn and fadeOut are defective. I was able to solve this issue (more below), but without using Actions. This solution below creates a new thread and starts a fade animation over time.

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.scenes.scene2d.Actor;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

public class Fade extends Actor {

public enum FadeType{
    FADE_IN,
    FADE_OUT
}

private Texture texture;

private Color color;
private AtomicFloat alpha = new AtomicFloat(); //I actually use a custom made AtomicFloat class
private final AtomicInteger duration;

private FadeType fade;

private AtomicBoolean isFading = new AtomicBoolean(false);


public Fade(int width, int height, Color color, FadeType fade, int duration){

    this.color = color;
    this.fade = fade;
    this.duration = new AtomicInteger(duration);

    Pixmap map = new Pixmap(width, height, Pixmap.Format.RGBA8888);
    map.setColor(new Color(color.r, color.g, color.b, alpha.get()));
    map.fillRectangle(0, 0, width, height);

    texture = new Texture(map);

    map.dispose();
}

public void startFade(){
    isFading.set(true);

    new Thread(new Runnable() {
        @Override
        public void run() {

            final int start = (int)System.currentTimeMillis();

            int current;
            float delta;

            do{
                current = (int)System.currentTimeMillis();

                delta = current - start;

                alpha.set( (fade == FadeType.FADE_OUT) ? delta/duration.get() : 1 - delta/duration.get() );

            }while (delta < duration.get());

            isFading.set(false);
        }
    }).start();

}//startFade

@Override
public void draw(Batch batch, float parentAlpha){

    if (isFading.get())
        batch.setColor(new Color(color.r, color.g, color.b, alpha.get()));

    batch.draw(texture, 0, 0);
}

}//Fade

You would use this code like so:

//create a new face object
Fade fade = new Fade(screenWidth, screenHeight, Color.WHITE, Fade.FadeType.FADE_IN, 3000);

//add the fade object to the stage (fade extends actor)
stage.addActor(fade);

//then call this method where ever needed
fade.startFade();

After battling this issue for a while, I hope this helps someone out.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .