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\$
  • \$\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 '16 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 '16 at 21:23
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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.