1
\$\begingroup\$

How can i create a fade out in libgdx? I have a class "Menu" and with a fade, i want to change class to "Game".

This is how i change class, from "Menu" to "Game":

if (Gdx.input.isTouched()){  
                this.dispose();
                game.setScreen(new Game(game));
}
\$\endgroup\$
2
  • \$\begingroup\$ What have you tried based on your research to date, and published tutorials/Q&A you've reviewed? \$\endgroup\$
    – DMGregory
    May 12, 2022 at 18:31
  • \$\begingroup\$ I only found one way with "stage" \$\endgroup\$
    – witsel
    May 12, 2022 at 18:36

1 Answer 1

1
\$\begingroup\$

There are many different ways of achieving this depending on how much control you need over what the fade looks like.

If you need very fine-grained control then an option is to render each Screen to a FrameBuffer and then write a custom fragement shader that takes both FrameBuffer's as input and blends them according to some logic.

If what you want is a simple "fade out screen one and then fade in screen two" kind of behaviour then you can get this by creating a Screen that renders a square over your screen (for example using a ShareRenderer) and alter the opacity depending on how far along the fade you are.

The example below (which has two different screens, a red and a green) uses a FadeScreen class that is a Screen that can take another Screen as input and then either fade to a solid color or from a solid color. And by chaining two of these FadeScreens a fade-out-fade-in effect can be acieved.

fading between screens

Essentially the FadeScreen class works by first calling render on the Screen you want to fade from or to, and then render a blended rect ontop using the ShapeRenderer:

private void renderFade() {
    Gdx.gl.glEnable(GL20.GL_BLEND);
    Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
    float f = Math.min(1.0f, elapsed / fade.duration);
    float opacity = fade.type == FadeType.OUT ? fade.interpolation.apply(f) : 1.0f - fade.interpolation.apply(f);

    shapeRenderer.setProjectionMatrix(camera.combined);
    shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
    shapeRenderer.setColor(fade.color.r, fade.color.g, fade.color.b, opacity);
    shapeRenderer.rect(0, 0, camera.viewportWidth, camera.viewportHeight);
    shapeRenderer.end();
    Gdx.gl.glDisable(GL20.GL_BLEND);
}

The opacity is calculated as an interpolation based on the elapsed time, and the amount is either increasing for a fade out or decreasing for a fade in.

Again this method doesn't blend one screen into another, but rather one screen into a color, and then that color into the next screen.

The fade is setup by creating a definition for the fade out and for the fade in, and then setting the current Screen to an instance of a FadeScreen that fades from screenA to another FadeScreen that fades into screenB.

        FadeScreen.FadeInfo fadeOut = new FadeScreen.FadeInfo(FadeScreen.FadeType.OUT, Color.WHITE, Interpolation.smoother, 2.0f);
        FadeScreen.FadeInfo fadeIn = new FadeScreen.FadeInfo(FadeScreen.FadeType.IN, Color.WHITE, Interpolation.smoother, 2.0f);

        fadeScreen = new FadeScreen(this, fadeOut, screenA, new FadeScreen(this, fadeIn, screenB, null));
        setScreen(fadeScreen);

Full source code for the FadeScreen class:

import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.ScreenAdapter;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Interpolation;

public class FadeScreen extends ScreenAdapter {
    public enum FadeType { IN, OUT }

    public static class FadeInfo {
        public final FadeType type;
        public final Color color;
        public final Interpolation interpolation;
        public final float duration;

        public FadeInfo(FadeType type, Color color, Interpolation interpolation, float duration) {
            this.type = type;
            this.color = color;
            this.interpolation = interpolation;
            this.duration = duration;
        }
    }

    private final FadeInfo fade;
    private Screen screen;
    private Screen next;
    private final Game game;
    private final ShapeRenderer shapeRenderer;
    private final Camera camera;
    private float elapsed;

    public FadeScreen(Game game, FadeInfo fade, Screen screen, Screen next) {
        this.game = game;
        this.fade = fade;
        this.screen = screen;
        this.next = next;
        shapeRenderer = new ShapeRenderer();
        camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        camera.position.set(camera.viewportWidth / 2.0f, camera.viewportHeight / 2.0f, 0.0f);
        camera.update();
    }

    private void renderFade() {
        Gdx.gl.glEnable(GL20.GL_BLEND);
        Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
        float f = Math.min(1.0f, elapsed / fade.duration);
        float opacity = fade.type == FadeType.OUT ? fade.interpolation.apply(f) : 1.0f - fade.interpolation.apply(f);

        shapeRenderer.setProjectionMatrix(camera.combined);
        shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
        shapeRenderer.setColor(fade.color.r, fade.color.g, fade.color.b, opacity);
        shapeRenderer.rect(0, 0, camera.viewportWidth, camera.viewportHeight);
        shapeRenderer.end();
        Gdx.gl.glDisable(GL20.GL_BLEND);
    }

    public void render(float delta) {
        if (screen != null) {
            elapsed += delta;
            if (elapsed >= fade.duration) {
                if (next != null) {
                    game.setScreen(next);
                    screen.dispose();
                    screen = null;
                } else
                    game.setScreen(screen);
            }
        }

        Gdx.gl.glClearColor(0, 0, 0, 0);
        if (screen != null)
            screen.render(delta);
        renderFade();
    }
}
\$\endgroup\$
3
  • \$\begingroup\$ Thank you, but is there an easier way? Maybe by creating a simple stage? \$\endgroup\$
    – witsel
    May 13, 2022 at 8:57
  • \$\begingroup\$ Easier how? Fewer lines of code? \$\endgroup\$
    – bornander
    May 13, 2022 at 10:25
  • \$\begingroup\$ Fewer lines for my code. I understand your lesson but I can't implement it, so i started to use stage for a fadeIn, but doesn't work. Now post the code \$\endgroup\$
    – witsel
    May 13, 2022 at 10:27

You must log in to answer this question.

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