java - libGDX - 屏幕之间的简单淡入淡出过渡?

标签 java android libgdx android-transitions

几天来我一直在寻找一种简单的方法来在实现 Screen 的游戏屏幕之间进行简单的淡出淡出转换。在执行某个操作后,我将调用 game.setScreen 方法,但我想要在两者之间进行转换。 我不使用舞台和 Actor 。

我应该制作阶段并使用actions进行转换还是有更简单的方法,例如TweenEngine?

如果我应该使用阶段,如何将我的正常渲染方法转换为stage.draw?将我所有的渲染方法转换为带有 actorsstage 会很困难吗?您可以将整个渲染方法放入 stage.draw 中以使用 actions 淡出 Screen 吗?只要解决方案有效,它是否愚蠢或低效并不重要。

谢谢

编辑:我完整的游戏类。这里可能有成千上万的奇怪的东西。请原谅我,因为这是我的第一个 libGDX 项目。

package com.samuel.kiwi;

import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.utils.viewport.ExtendViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.samuel.kiwi.states.MenuState;

public class Kiwi extends Game {

    private Sound point;
    private Sound select;
    private Sound die;
    private Music chirp;

    private Actor fadeActor = new Actor();
    private ShapeRenderer fadeRenderer;


    public SpriteBatch batch;
    public static BitmapFont font;
    public static final int WIDTH = 480;
    public static final int HEIGHT = 800;

    private int currentHighscore;
    private Preferences highscore;

    private int currentTotalScore;
    private Preferences totalScore;

    private int currentDeaths;
    private Preferences deaths;

    private boolean soundOn;
    private Preferences sound;


    Viewport viewport;
    Viewport viewportFont;

    private boolean currentTutMode;
    private Preferences tut;

    public static final String TITLE = "Kiwi";
    private OrthographicCamera cam;

    public static OrthographicCamera fontCam;

    private float aspectRatio;


    @Override
    public void create() {


        batch = new SpriteBatch();

        fontCam = new OrthographicCamera();

        aspectRatio = (float) Gdx.graphics.getHeight() / Gdx.graphics.getWidth();

        cam = new OrthographicCamera();

        viewport = new ExtendViewport((WIDTH / 4) * aspectRatio, HEIGHT / 2, cam);
        viewportFont = new ExtendViewport((WIDTH) * aspectRatio, HEIGHT * 2, fontCam);
        viewport.apply();
        viewportFont.apply();
        cam.position.set(WIDTH / 4, HEIGHT / 4, 0);
        fontCam.position.set(WIDTH, HEIGHT, 0);


        initFonts();

        highscore = Gdx.app.getPreferences("highscore"); //highscore preferencen
        currentHighscore = highscore.getInteger("currentHighscore", 0);

        totalScore = Gdx.app.getPreferences("total_score"); //total score
        currentTotalScore = totalScore.getInteger("totalScore", 0);

        deaths = Gdx.app.getPreferences("deaths");
        currentDeaths = deaths.getInteger("currentDeaths", 0);

        tut = Gdx.app.getPreferences("is tutorial on");
        currentTutMode = tut.getBoolean("currentTutMode", true);

        sound = Gdx.app.getPreferences("sound");
        soundOn = sound.getBoolean("currentSoundMode", true);

        point = Gdx.audio.newSound(Gdx.files.internal("sounds/point.wav"));
        select = Gdx.audio.newSound(Gdx.files.internal("sounds/select.wav"));
        die = Gdx.audio.newSound(Gdx.files.internal("sounds/die.wav"));


        Gdx.gl.glClearColor(0, 0, 0, 1);


        fadeRenderer = new ShapeRenderer(8);


        chirp = Gdx.audio.newMusic(Gdx.files.internal("sounds/chirp.wav"));
        chirp.setLooping(true);
        chirp.setVolume(0);
        chirp.play();
        setScreen(new MenuState(this, cam)); //ändra till splash
    }

    @Override
    public void render() {

        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        super.render();

        cam.update();
        fontCam.update();
        fadeActor.act(Gdx.graphics.getDeltaTime());
        float alpha = fadeActor.getColor().a;
        if (alpha != 0) {
            fadeRenderer.begin(ShapeRenderer.ShapeType.Filled);
            fadeRenderer.setColor(0, 0, 0, alpha);
            System.out.println("alpha: " + alpha); //shows the alpha becoming less and less and then more an more
            fadeRenderer.rect(-1, -1, 2, 2); //full screen rect w/ identity matrix
            fadeRenderer.end();
        }


    }

    @Override
    public void resize(int width, int height) {
        viewport.update(width, height);
        viewportFont.update(width, height);
        cam.position.set(WIDTH / 4, HEIGHT / 4, 0);
        fontCam.position.set(WIDTH, HEIGHT, 0);

    }


    public void initFonts() {

        FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/Minecraft.ttf"));
        FreeTypeFontGenerator.FreeTypeFontParameter params = new FreeTypeFontGenerator.FreeTypeFontParameter();
        params.characters = "0123456789-.";
        params.size = 80;
        params.color.set(254f / 255f, 208f / 255f, 0, 1f);
        params.shadowColor.set(0 / 255f, 0 / 255f, 0, 0.5f);
        params.shadowOffsetY = 8;
        font = generator.generateFont(params);

        generator.dispose();

    }

    @Override
    public void dispose() {
        super.dispose();
        batch.dispose();
        font.dispose();
        select.dispose();
        point.dispose();
        chirp.dispose();
        die.dispose();
        fadeRenderer.dispose();


    }


    public void setScreenWithFade(final Screen screen, float duration) {
        fadeActor.clearActions();
        fadeActor.setColor(Color.CLEAR);
        fadeActor.addAction(Actions.sequence(
                Actions.color(Color.BLACK, duration / 2f, Interpolation.fade),
                Actions.run(new Runnable() {
                    public void run() {
                        setScreen(screen);
                    }
                }),
                Actions.color(Color.CLEAR, duration / 2f, Interpolation.fade)
        ));
    }


    public void setCurrentHighscore(int currentHighscore) {
        this.currentHighscore = currentHighscore;
    }

    public Preferences getHighscore() {
        return highscore;
    }


    public void setCurrentTotalScore(int currentTotalScore) {
        this.currentTotalScore = currentTotalScore;
    }

    public Preferences getTotalScore() {
        return totalScore;
    }

    public boolean isCurrentTutMode() {
        return currentTutMode;
    }

    public void setCurrentTutMode(boolean currentTutMode) {
        this.currentTutMode = currentTutMode;
    }

    public Preferences getTut() {
        return tut;
    }


    public Sound getPoint() {
        return point;
    }

    public Sound getSelect() {
        return select;
    }

    public Sound getDie() {
        return die;
    }

    public Music getChirp() {
        return chirp;
    }

    public Preferences getDeaths() {
        return deaths;
    }

    public void setSoundOn(boolean soundOn) {

        sound.putBoolean("currentSoundMode", soundOn);
        sound.putBoolean("soundOn", soundOn);
        sound.flush();

    }

    public Preferences getSound() {
        return sound;
    }

    public boolean isSoundOn() {
        return sound.getBoolean("currentSoundMode", true);
    }

    public void setCurrentDeaths(int currentDeaths) {
        this.currentDeaths = currentDeaths;
    }
}

编辑 2:我的 MenuState 屏幕

package com.samuel.kiwi.states;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Vector3;
import com.samuel.kiwi.Kiwi;

/**
 * Created by Samuel on 10/2/2016.
 */

public class MenuState extends InputAdapter implements Screen {

    private Texture bg;
    private Texture playBtn;
    private Texture playBtnDown;

    private Texture gPlayBtn;
    private Texture gPlayBtnDown;

    private Texture settingsBtn;
    private Texture settingsBtnDown;

    private boolean updatePos;

    private Kiwi game;

    private Texture kiwiLogo;
    private Vector3 kiwiLogoPos;
    private Vector3 kiwiLogoVel;

    private Vector3 touchPos;

    private boolean isTouchPlay;
    private boolean isTouchReleased;

    private boolean isGDown;
    private boolean isGReleased;

    private boolean isSettingsDown;
    private boolean isSettingsReleased;

    private OrthographicCamera cam;
    private boolean handleInput;


    public MenuState(final Kiwi game, OrthographicCamera cam) {

        this.game = game;
        this.cam = cam;

        kiwiLogo = new Texture("pics/menu/kiwiLogo.png");
        bg = new Texture("pics/bg.png");
        playBtn = new Texture("pics/menu/play_button.png");
        playBtnDown = new Texture("pics/menu/play_button_down.png");

        gPlayBtn = new Texture("pics/menu/g_play_button.png");
        gPlayBtnDown = new Texture("pics/menu/g_play_button_down.png");

        settingsBtn = new Texture("pics/menu/settings_button.png");
        settingsBtnDown = new Texture("pics/menu/settings_button_down.png");
    }


    public void handleInput() {


        if (isTouchReleased && isTouchPlay) {

            Gdx.input.setInputProcessor(null);
            game.setScreenWithFade(new PlayState(game, cam), 5);
            handleInput = false;
        }

        if (isGReleased) {
            //glöm inte disposa... eller?
            //google playa dude


        }

        if (isSettingsReleased && isSettingsDown) {

            Gdx.input.setInputProcessor(null);
            game.setScreenWithFade(new SettingsState(game, cam), 5);
            handleInput = false;

        }


    }


    public void update(float delta) {
        if (handleInput)
            handleInput();
        if (updatePos) {
            if (kiwiLogoPos.y < cam.position.y + 30)
                kiwiLogoVel.add(0, 3, 0);
            else
                kiwiLogoVel.add(0, -3, 0);
            kiwiLogoVel.scl(delta);
            kiwiLogoPos.add(0, kiwiLogoVel.y, 0);

            kiwiLogoVel.scl(1 / delta);

        }
    }


    @Override
    public void show() {
        handleInput = true;
        updatePos = true;
        if (game.isSoundOn())
            game.getChirp().setVolume(1);
        else
            game.getChirp().setVolume(0);
        Gdx.input.setInputProcessor(this);
        kiwiLogoPos = new Vector3(cam.position.x - kiwiLogo.getWidth(), cam.position.y + 25, 0);
        kiwiLogoVel = new Vector3(0, 0, 0);

        isTouchPlay = false;
        touchPos = new Vector3();


    }

    @Override
    public void render(float delta) {
        update(delta);
        game.batch.begin();
        game.batch.setProjectionMatrix(cam.combined);

        game.batch.draw(bg, cam.position.x - cam.viewportWidth / 2, cam.position.y - cam.viewportHeight / 2, cam.viewportWidth, cam.viewportHeight);

        game.batch.draw(kiwiLogo, kiwiLogoPos.x, kiwiLogoPos.y, kiwiLogo.getWidth() * 2, kiwiLogo.getHeight() * 2);


        if (!isTouchPlay) {
            game.batch.draw(playBtn, cam.position.x - playBtn.getWidth(), cam.position.y - 100, playBtn.getWidth() * 2, playBtn.getHeight() * 2);
        } else {

            game.batch.draw(playBtnDown, cam.position.x - playBtn.getWidth(), cam.position.y - 100, playBtn.getWidth() * 2, playBtn.getHeight() * 2);
        }

        if (!isGDown) {

            game.batch.draw(gPlayBtn, cam.position.x - playBtn.getWidth(), cam.position.y - gPlayBtn.getHeight() * 2 - 112, gPlayBtn.getWidth() * 2, gPlayBtn.getHeight() * 2);
        } else {

            game.batch.draw(gPlayBtnDown, cam.position.x - playBtn.getWidth(), cam.position.y - gPlayBtn.getHeight() * 2 - 112, gPlayBtn.getWidth() * 2, gPlayBtn.getHeight() * 2);
        }
        if (!isSettingsDown) {

            game.batch.draw(settingsBtn, cam.position.x + playBtn.getWidth() - settingsBtn.getWidth() * 2, cam.position.y - gPlayBtn.getHeight() * 2 - 112, gPlayBtn.getWidth() * 2, gPlayBtn.getHeight() * 2);
        } else {

            game.batch.draw(settingsBtnDown, cam.position.x + playBtn.getWidth() - settingsBtn.getWidth() * 2, cam.position.y - gPlayBtn.getHeight() * 2 - 112, gPlayBtn.getWidth() * 2, gPlayBtn.getHeight() * 2);
        }

        game.batch.end();


    }

    @Override
    public void resize(int width, int height) {

    }

    @Override
    public void pause() {


    }

    @Override
    public void resume() {
    }

    @Override
    public void hide() {

        dispose();
    }

    @Override
    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
        cam.unproject(touchPos.set(screenX, screenY, 0));
        //gobutton
        if (touchPos.x > cam.position.x - playBtn.getWidth() && touchPos.x < cam.position.x + playBtn.getWidth()
                && touchPos.y < cam.position.y - 100 + playBtn.getHeight() * 2 && touchPos.y > cam.position.y - 100) {
            isTouchPlay = true;
            if (game.isSoundOn())
                game.getSelect().play();
        }
//gplay
        if (touchPos.x > cam.position.x - playBtn.getWidth() && touchPos.x < cam.position.x - playBtn.getWidth() + gPlayBtn.getWidth() * 2
                && touchPos.y < cam.position.y - 112 && touchPos.y > cam.position.y - gPlayBtn.getHeight() * 2 - 112) {
            isGDown = true;
            if (game.isSoundOn())
                game.getSelect().play();
        }
//settings
        if (touchPos.x > cam.position.x + playBtn.getWidth() - settingsBtn.getWidth() * 2 && touchPos.x < cam.position.x + playBtn.getWidth()
                && touchPos.y < cam.position.y - 112 && touchPos.y > cam.position.y - gPlayBtn.getHeight() * 2 - 112) {
            isSettingsDown = true;
            if (game.isSoundOn())
                game.getSelect().play();
        }


        return true;
    }

    @Override
    public boolean touchUp(int screenX, int screenY, int pointer, int button) {

        cam.unproject(touchPos.set(screenX, screenY, 0));
        //gobutton
        if (touchPos.x > cam.position.x - playBtn.getWidth() && touchPos.x < cam.position.x + playBtn.getWidth()
                && touchPos.y < cam.position.y - 100 + playBtn.getHeight() * 2 && touchPos.y > cam.position.y - 100 && isTouchPlay)
            isTouchReleased = true;
        else
            isTouchPlay = false;

        //gplay
        if (touchPos.x > cam.position.x - playBtn.getWidth() && touchPos.x < cam.position.x - playBtn.getWidth() + gPlayBtn.getWidth() * 2
                && touchPos.y < cam.position.y - 112 && touchPos.y > cam.position.y - gPlayBtn.getHeight() * 2 - 112)
            isGReleased = true;
        else
            isGDown = false;

//settings
        if (touchPos.x > cam.position.x + playBtn.getWidth() - settingsBtn.getWidth() * 2 && touchPos.x < cam.position.x + playBtn.getWidth()
                && touchPos.y < cam.position.y - 112 && touchPos.y > cam.position.y - gPlayBtn.getHeight() * 2 - 112)
            isSettingsReleased = true;
        else
            isSettingsDown = false;
        return true;
    }


    @Override
    public void dispose() {
        bg.dispose();
        playBtn.dispose();
        playBtnDown.dispose();
        gPlayBtn.dispose();
        gPlayBtnDown.dispose();
        settingsBtn.dispose();
        settingsBtnDown.dispose();
        kiwiLogo.dispose();
    }


}

最佳答案

您可以通过在 Actor 上放置 ColorAction(或 TemporalAction 的任何子类)来使用 Actor 作为补间引擎。那么您就不必浪费舞台和随之而来的开销。像这样的事情:

public class GameWithTransitions extends Game {

    private Actor fadeActor = new Actor();
    private ShapeRenderer fadeRenderer;

    public void create (){ 
        //...your create() code

        fadeRenderer = new ShapeRenderer(8);
    }

    public void setScreenWithFade (final Screen screen, float duration) {
        fadeActor.clearActions();
        fadeActor.setColor(Color.CLEAR);
        fadeActor.addAction(Actions.sequence(
            Actions.color(Color.BLACK, duration/2f, Interpolation.fade),
            Actions.run(new Runnable(){public void run(){setScreen(screen);}}),
            Actions.color(Color.CLEAR, duration/2f, Interpolation.fade)
        ));
    }

    @Override
    public void render (){
        super.render();

        fadeActor.act(Gdx.graphics.getDeltaTime());
        float alpha = fadeActor.getColor().a;
        if (alpha != 0){
            fadeRenderer.begin(ShapeType.Filled);
            fadeRenderer.setColor(0, 0, 0, alpha);
            fadeRenderer.rect(-1, -1, 2, 2); //full screen rect w/ identity matrix
            fadeRenderer.end();
        }
    }

}

注意:我还没有测试过上面的代码。

关于java - libGDX - 屏幕之间的简单淡入淡出过渡?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40159555/

相关文章:

java - Java 8 默认方法会破坏源代码兼容性吗?

java - 多线程方法

java - Java套接字聊天程序(聊天成员突然离开房间,没有错误)

java - 渲染和触摸输入之间的 libgdx 坐标系差异

java - 当它应该在 rt.jar 中时,为什么我没有这个类?

c# - xamarin.android 接收器出现 BOOT_COMPLETED 错误

Android 不同的屏幕尺寸和密度

android - Android中是否可以监控各个方法的CPU,内存使用情况

java - 将文件中的每一行设置为 java libgdx 中的 GlyphLayout

java - libgdx - 测量 Android 上的内存使用情况