Add fade out/in transition between screens

This commit is contained in:
Lonami Exo 2017-02-23 21:15:21 +01:00
parent a8dc942bc2
commit eeb43d5e4f
5 changed files with 160 additions and 12 deletions

View file

@ -4,12 +4,14 @@ import com.badlogic.gdx.Application;
import com.badlogic.gdx.Game; import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Preferences; import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.NinePatch; import com.badlogic.gdx.graphics.g2d.NinePatch;
import com.badlogic.gdx.scenes.scene2d.ui.Skin; import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import io.github.lonamiwebs.klooni.screens.MainMenuScreen; import io.github.lonamiwebs.klooni.screens.MainMenuScreen;
import io.github.lonamiwebs.klooni.screens.TransitionScreen;
public class Klooni extends Game { public class Klooni extends Game {
@ -82,6 +84,15 @@ public class Klooni extends Game {
super.render(); super.render();
} }
// TransitionScreen will also dispose by default the previous screen
public void transitionTo(Screen screen) {
transitionTo(screen, true);
}
public void transitionTo(Screen screen, boolean disposeAfter) {
setScreen(new TransitionScreen(this, getScreen(), screen, disposeAfter));
}
//endregion //endregion
//region Disposing //region Disposing

View file

@ -145,8 +145,7 @@ class CustomizeScreen implements Screen {
//region Private methods //region Private methods
private void goBack() { private void goBack() {
CustomizeScreen.this.game.setScreen(lastScreen); CustomizeScreen.this.game.transitionTo(lastScreen);
dispose();
} }
//endregion //endregion

View file

@ -46,9 +46,8 @@ public class MainMenuScreen extends InputListener implements Screen {
0, GameScreen.hasSavedData() ? "play_saved_texture" : "play_texture"); 0, GameScreen.hasSavedData() ? "play_saved_texture" : "play_texture");
playButton.addListener(new ChangeListener() { playButton.addListener(new ChangeListener() {
public void changed (ChangeEvent event, Actor actor) { public void changed (ChangeEvent event, Actor actor) {
MainMenuScreen.this.game.setScreen( MainMenuScreen.this.game.transitionTo(
new GameScreen(MainMenuScreen.this.game, GameScreen.GAME_MODE_SCORE)); new GameScreen(MainMenuScreen.this.game, GameScreen.GAME_MODE_SCORE));
dispose();
} }
}); });
table.add(playButton).colspan(3).fill().space(16); table.add(playButton).colspan(3).fill().space(16);
@ -70,9 +69,8 @@ public class MainMenuScreen extends InputListener implements Screen {
statsButton.addListener(new ChangeListener() { statsButton.addListener(new ChangeListener() {
@Override @Override
public void changed(ChangeEvent event, Actor actor) { public void changed(ChangeEvent event, Actor actor) {
MainMenuScreen.this.game.setScreen( MainMenuScreen.this.game.transitionTo(
new GameScreen(MainMenuScreen.this.game, GameScreen.GAME_MODE_TIME)); new GameScreen(MainMenuScreen.this.game, GameScreen.GAME_MODE_TIME));
dispose();
} }
}); });
table.add(statsButton).space(16); table.add(statsButton).space(16);
@ -81,8 +79,9 @@ public class MainMenuScreen extends InputListener implements Screen {
final SoftButton paletteButton = new SoftButton(3, "palette_texture"); final SoftButton paletteButton = new SoftButton(3, "palette_texture");
paletteButton.addListener(new ChangeListener() { paletteButton.addListener(new ChangeListener() {
public void changed (ChangeEvent event, Actor actor) { public void changed (ChangeEvent event, Actor actor) {
MainMenuScreen.this.game.setScreen(new CustomizeScreen(MainMenuScreen.this.game, MainMenuScreen.this.game.getScreen()));
// Don't dispose because then it needs to take us to the previous screen // Don't dispose because then it needs to take us to the previous screen
MainMenuScreen.this.game.transitionTo(new CustomizeScreen(
MainMenuScreen.this.game, MainMenuScreen.this.game.getScreen()), false);
} }
}); });
table.add(paletteButton).space(16); table.add(paletteButton).space(16);

View file

@ -59,8 +59,7 @@ class PauseMenuStage extends Stage {
homeButton.addListener(new ChangeListener() { homeButton.addListener(new ChangeListener() {
public void changed (ChangeEvent event, Actor actor) { public void changed (ChangeEvent event, Actor actor) {
game.setScreen(new MainMenuScreen(game)); game.transitionTo(new MainMenuScreen(game));
dispose();
} }
}); });
@ -72,8 +71,7 @@ class PauseMenuStage extends Stage {
@Override @Override
public void changed(ChangeEvent event, Actor actor) { public void changed(ChangeEvent event, Actor actor) {
// false, don't load the saved game state; we do want to replay // false, don't load the saved game state; we do want to replay
game.setScreen(new GameScreen(game, gameMode, false)); game.transitionTo(new GameScreen(game, gameMode, false));
dispose();
} }
}); });
@ -86,8 +84,8 @@ class PauseMenuStage extends Stage {
paletteButton.addListener(new ChangeListener() { paletteButton.addListener(new ChangeListener() {
@Override @Override
public void changed(ChangeEvent event, Actor actor) { public void changed(ChangeEvent event, Actor actor) {
game.setScreen(new CustomizeScreen(game, game.getScreen()));
// Don't dispose because then it needs to take us to the previous screen // Don't dispose because then it needs to take us to the previous screen
game.transitionTo(new CustomizeScreen(game, game.getScreen()), false);
} }
}); });

View file

@ -0,0 +1,141 @@
package io.github.lonamiwebs.klooni.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.FrameBuffer;
import io.github.lonamiwebs.klooni.Klooni;
public class TransitionScreen implements Screen {
//region Members
// Rendering
private FrameBuffer frameBuffer;
private TextureRegion bufferTexture;
private final SpriteBatch spriteBatch;
private float fadedElapsed;
private boolean fadingOut;
private int width, height;
// From, to, and game to change the screen after the transition finishes
private final Screen fromScreen, toScreen;
private final Klooni game;
// Should the previous screen be disposed afterwards? Not desirable
// if it was stored somewhere else, for example, to return to it later
private final boolean disposeAfter;
//endregion
//region Static variables
// Time it takes to fade out and in, 0.15s (0.3s total)
private static final float FADE_INVERSE_DELAY = 1f / 0.15f;
//endregion
//region Constructor
public TransitionScreen(Klooni game, Screen from, Screen to, boolean disposeAfter) {
this.disposeAfter = disposeAfter;
this.game = game;
fromScreen = from;
toScreen = to;
spriteBatch = new SpriteBatch();
}
//endregion
//region Rendering
@Override
public void show() {
fadedElapsed = 0f;
fadingOut = true;
}
@Override
public void render(float delta) {
// Black background since we're fading to black
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// Render on another buffer so then we can set its opacity. This
// second buffer also would allow us to do more stuff, since then
// we can use a texture, which we could move across the screen.
frameBuffer.begin();
float opacity;
if (fadingOut) {
fromScreen.render(delta);
opacity = 1 - Math.min(fadedElapsed * FADE_INVERSE_DELAY, 1);
if (opacity == 0) {
fadedElapsed = 0;
fadingOut = false;
}
}
else {
toScreen.render(delta);
opacity = Math.min(fadedElapsed * FADE_INVERSE_DELAY, 1);
}
frameBuffer.end();
// Render the faded texture
spriteBatch.begin();
spriteBatch.setColor(1, 1, 1, opacity);
spriteBatch.draw(bufferTexture, 0, 0, width, height);
spriteBatch.end();
fadedElapsed += delta;
// We might have finished fading if the opacity is full
if (opacity == 1 && !fadingOut) {
game.setScreen(toScreen);
dispose();
}
}
@Override
public void resize(int width, int height) {
this.width = width;
this.height = height;
if (frameBuffer != null)
frameBuffer.dispose();
frameBuffer = new FrameBuffer(Pixmap.Format.RGB565, width, height, false);
bufferTexture = new TextureRegion(frameBuffer.getColorBufferTexture());
bufferTexture.flip(false, true);
}
//endregion
//region Disposing
@Override
public void dispose() {
frameBuffer.dispose();
if (disposeAfter)
fromScreen.dispose();
}
//endregion
//region Unused methods
@Override
public void pause() { }
@Override
public void resume() { }
@Override
public void hide() { }
//endregion
}