Android 按下后退按钮后打开应用程序时,Libgdx纹理都很奇怪?

Android 按下后退按钮后打开应用程序时,Libgdx纹理都很奇怪?,android,libgdx,scene2d,Android,Libgdx,Scene2d,这就是我的困境,我真的快要在游戏商店上发布我的游戏了 在设备上测试应用程序时,我意识到当单击home按钮时,然后再次打开应用程序。一切都处理得很好 然而,当按下后退按钮并再次打开应用程序时,我游戏中的纹理会变得很奇怪,就像真的很奇怪一样 下面是屏幕截图,显示了应该是什么样子,不应该是什么样子 这是一个链接,显示了应该是什么样子 这是一个在按下后退按钮后加载的 经过一段时间的测试,我认为问题在于当点击后退按钮时,它会触发一个“退出”类型的函数,该函数应该退出应用程序。然而,由于某些原因,该应用程

这就是我的困境,我真的快要在游戏商店上发布我的游戏了

在设备上测试应用程序时,我意识到当单击home按钮时,然后再次打开应用程序。一切都处理得很好

然而,当按下后退按钮并再次打开应用程序时,我游戏中的纹理会变得很奇怪,就像真的很奇怪一样

下面是屏幕截图,显示了应该是什么样子,不应该是什么样子

这是一个链接,显示了应该是什么样子

这是一个在按下后退按钮后加载的

经过一段时间的测试,我认为问题在于当点击后退按钮时,它会触发一个“退出”类型的函数,该函数应该退出应用程序。然而,由于某些原因,该应用程序仍然存在于手机的背景中,这导致在单击“后退”按钮后加载奇怪的纹理。如果我是正确的,我需要做什么来处理这种行为

public class MainMenuScreen implements Screen{
    private static final int FLOOR_Y_OFFSET = -150;
    private static final int FOREGROUND_Y_OFFSET = -150;

    private FishyDash game;
    private OrthographicCamera cam;

    private Texture background;
    private Texture foreground;
    private Vector2 foregroundPos1, foregroundPos2;
    private Texture floor;
    private Vector2 floorPos1, floorPos2;
    private Fish fishy;

    //TABLE STUFF
    private Table table;
    private Table buttonTable;
    private Stage stage;

    private Image game_title;
    private Skin skin;
    private TextureAtlas buttonAtlas;
    private TextButton buttonPlay, buttonRate;
    private Viewport gamePort;

    public BitmapFont font;

    //Load all the sounds needed
    public Sound jumpSound;
    public Sound buttonClicked;
    public Music backgroundMusic;

    GameState gameState;

    //On Pause stuff
    public static Vector2 fish_pause_pos;

    public MainMenuScreen(FishyDash game) {
        this.game = game;
        gameState = GameState.READY;

        System.out.println("first");
    }


    @Override
    public void show() {
        System.out.println("second");
        //Initialize all the sounds
        jumpSound = Assets.manager.get(Assets.jumpSound, Sound.class);
        buttonClicked = Assets.manager.get(Assets.buttonClicked, Sound.class);
        backgroundMusic = Assets.manager.get(Assets.backgroundMusic, Music.class);
        backgroundMusic.setLooping(true);
        backgroundMusic.setVolume(.5f);
        backgroundMusic.play();

        //Initialize the textures needed in the MainMenuScreen class
        background = Assets.manager.get(Assets.background, Texture.class);
        floor = Assets.manager.get(Assets.floor, Texture.class);
        foreground = Assets.manager.get(Assets.foreground, Texture.class);

        fishy = new Fish();
        fishy.setPos(80, foreground.getHeight() + FOREGROUND_Y_OFFSET - 150);
        fishy.setMOVEMENT_X(200);
        fishy.setGRAVITY(-40);

        cam = new OrthographicCamera();
        cam.setToOrtho(false, background.getWidth(), background.getHeight());

        foregroundPos1 = new Vector2(cam.position.x - (cam.viewportWidth / 2), 0);
        foregroundPos2 = new Vector2(cam.position.x - (cam.viewportWidth / 2) + foreground.getWidth(), 0);

        floorPos1 = new Vector2(cam.position.x - (cam.viewportWidth / 2), 0);
        floorPos2 = new Vector2(cam.position.x - (cam.viewportWidth / 2) + floor.getWidth(), 0);

        createTable();

//        Gdx.input.setCatchBackKey(true);
//        game.getAdsController().showBannerAd();
    }

    public void createTable() {
        gamePort = new StretchViewport(FishyDash.V_WIDTH, FishyDash.V_HEIGHT, cam);
        stage = new Stage(gamePort, game.batch);
        stage.getViewport().setCamera(cam);

        table = new Table();
        table.setFillParent(true);
        table.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

        buttonTable = new Table();
        buttonTable.setFillParent(true);
        buttonTable.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

        game_title = new Image(new Texture("game_title.png"));
        font = Assets.manager.get(Assets.font, BitmapFont.class);
        buttonAtlas = Assets.manager.get(Assets.buttonAtlas, TextureAtlas.class);
        skin = new Skin(buttonAtlas);

        //Creating the TextStyle for the playButton
        TextButton.TextButtonStyle playButtonStyle = new TextButton.TextButtonStyle();
        playButtonStyle.up = skin.getDrawable("button_up");
        playButtonStyle.down = skin.getDrawable("button_down");
        playButtonStyle.pressedOffsetX = 1;
        playButtonStyle.pressedOffsetY = -1;
        playButtonStyle.font = font;

        //Creating the TextStyle for the rateButton
        TextButton.TextButtonStyle rateButtonStyle = new TextButton.TextButtonStyle();
        rateButtonStyle.up = skin.getDrawable("button_up");
        rateButtonStyle.down = skin.getDrawable("button_down");
        rateButtonStyle.pressedOffsetX = 1;
        rateButtonStyle.pressedOffsetY = -1;
        rateButtonStyle.font = font;

        //Setting the style and text for the playButton
        buttonPlay = new TextButton("PlAY", playButtonStyle);
        buttonPlay.pad(10);

        //Setting the style and text for the rateButton
        buttonRate = new TextButton("RATE", rateButtonStyle);
        buttonRate.pad(10);

        table.top();
        table.add(game_title).padTop(175).expandX();

        buttonTable.bottom().padBottom(200);
        buttonTable.add(buttonPlay).expandX().padLeft(30);
        buttonTable.add(buttonRate).expandX().padRight(30);

//        table.debug();
        stage.addActor(table);
        stage.addActor(buttonTable);

        buttonPlay.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event, float x, float y) {
                buttonClicked.play();
                dispose();
                game.setScreen(new GameScreen(game));
            }
        });

        buttonRate.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event, float x, float y) {
                buttonClicked.play();
                System.out.println("Nothing happens Yet");
            }
        });
    }

    public void updateWorld(float delta) {

        switch (gameState) {
            case READY:

                fishy.update(delta);

                if (fishy.getPosition().y < foreground.getHeight() + FOREGROUND_Y_OFFSET - 35) {
                    fishy.setMOVEMENT_X(100);
                }

                if (fishy.getPosition().y < floor.getHeight() + FLOOR_Y_OFFSET + 150) {
                    fishy.setMOVEMENT_X(100);
                    fishy.normalJump();
                    jumpSound.stop();
                }

                updateForeground();
                updateFloor();

                cam.position.x = fishy.getPosition().x + (cam.viewportWidth / 2) - 80;
                cam.update();

                table.setPosition(cam.position.x - cam.viewportWidth / 2, 0);
                buttonTable.setPosition(cam.position.x - cam.viewportWidth / 2, 0);

                Gdx.input.setInputProcessor(stage);
                break;

            case PAUSED:
                gameState = GameState.READY;
                break;
        }
    }

    public void drawWorld() {
        game.batch.setProjectionMatrix(cam.combined);
        switch (gameState) {

            case READY:
                game.batch.begin();

                game.batch.draw(background, cam.position.x - cam.viewportWidth / 2, 0);

                game.batch.draw(foreground, foregroundPos1.x, foregroundPos1.y + FOREGROUND_Y_OFFSET);
                game.batch.draw(foreground, foregroundPos2.x, foregroundPos2.y + FOREGROUND_Y_OFFSET);

                game.batch.draw(floor, floorPos1.x, floorPos1.y + FLOOR_Y_OFFSET);
                game.batch.draw(floor, floorPos2.x, floorPos2.y + FLOOR_Y_OFFSET);

                game.batch.draw(fishy.getAnimation().getKeyFrame(fishy.timePassed, true),
                        fishy.getPosition().x, fishy.getPosition().y);

                game.batch.end();

                stage.act();
                stage.draw();
                break;

            case PAUSED:
                break;
        }
    }

    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(1, 1, 1, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        updateWorld(delta);
        drawWorld();
    }

    @Override
    public void dispose() {
        System.out.println("Main Menu Dispose Called");

        fishy.dispose();
        stage.dispose();
    }

    public void updateForeground() {
        if(cam.position.x - (cam.viewportWidth / 2) > foregroundPos1.x + foreground.getWidth())
            foregroundPos1.add(foreground.getWidth() * 2, 0);
        if(cam.position.x - (cam.viewportWidth / 2) > foregroundPos2.x + foreground.getWidth())
            foregroundPos2.add(foreground.getWidth() * 2, 0);
    }

    public void updateFloor() {
        if(cam.position.x - (cam.viewportWidth / 2) > floorPos1.x + floor.getWidth())
            floorPos1.add(floor.getWidth() * 2, 0);
        if(cam.position.x - (cam.viewportWidth / 2) > floorPos2.x + floor.getWidth())
            floorPos2.add(floor.getWidth() * 2, 0);
    }

    @Override
    public void resize(int width, int height) {
        stage.getViewport().update(width, height, true);
    }

    @Override
    public void pause() {
        System.out.println("pause");
        gameState = GameState.PAUSED;
    }

    @Override
    public void resume() {
        System.out.println("resume");
    }

    @Override
    public void hide() {
        System.out.println("hide");
    }

    public enum GameState {
        READY, PAUSED;
    }
}

即使关闭应用程序,背景中存在的对象的静态实例也存在问题

当应用程序打开assets Manager的所有实例时,请确保您正在将其作为新实例进行处理、置零和创建

使用


另外,如果您使用了一些,请处理蒙皮,如果您将一些用作单音,请将处理程序设置为null,例如,您应该避免静态资产引用。当Android活动退出时,应用程序保持活动状态,因此静态引用的对象也保持活动状态,直到下次从启动器启动游戏(新活动实例)为止

从技术上讲,您可以对资产进行静态引用,但如果您这样做,您需要确切地知道您在做什么,而且很容易出错。(您必须绝对确保在活动关闭时处理完所有内容,将静态引用清除为null,并确保在游戏再次启动时加载新实例。)最安全的做法是避免对任何实现
一次性
的对象进行静态引用

您需要阅读Java的类对象(不是类,不是对象,而是“类对象”),以便了解这里发生了什么。
static
方法无法对非
static
成员变量进行操作,因此您还需要从
load
方法中删除
static
关键字

然后,要访问资产管理器,需要创建资产类的实例,并通过标准成员变量进行访问:

public class FishyDash extends Game {

    Assets assets;

    public void create(){
        assets = new Assets();
        assets.load();
        //....
    }

}

public class MainMenuScreen implements Screen{

    //...

    public void show() {
        System.out.println("second");

        jumpSound = game.assets.manager.get(Assets.jumpSound, Sound.class);
        //...
    }

    //...

}

这是一个更危险的答案。只有当您完全了解Android生命周期、Libgdx生命周期和Java的类对象时,我才建议您这样做

您可以保留静态资产引用,但必须确保它们在游戏结束时被处理掉

public class Assets {

    //Safer to keep this private and use below public method for access
    private static AssetManager manager; //do not instantiate here

    public static AssetManager manager(){
        if (manager == null) load();
        return manager;
    }

    public static void load (){
        if (manager == null) manager = new AssetManager();

        //your existing load code
    }

    public static void dispose() {
        if (manager != null){
            manager.dispose();
            manager = null;
       }
    }

}

public class FishyDash extends Game {

    //...

    @Override
    public void dispose() {
        Assets.dispose();
    }
}

public class MainMenuScreen implements Screen{

    //...

    public void show() {
        System.out.println("second");

        //NOTE THE PARENTHESES AFTER manager below
        jumpSound = Assets.manager().get(Assets.jumpSound, Sound.class);
        //...
    }

    //...

}

我不相信我在使用任何静态实例变量?然后检查您的资产管理器或其他您应该处理的对象-列表如下:好的,我使用的是这个公共静态最终资产管理器manager=new AssetManager();但现在我将其更改为这个AssetManager=new AssetManager();但是问题是,它给了我一个错误,非静态字段“manager”不能从静态上下文引用。我的马槽现在是红色的,有什么解决办法吗?你不需要让静态字段变成非静态的!如果您将它用作静态的,请保留它-只需确保在dispose方法上您正在处理它并将引用设置为null-这就是以前多次提出的所有问题。不要对AssetManager或纹理进行静态引用。退出Android活动不会退出整个应用程序,因此静态引用将保留。@Tenfour04我添加了我的资产代码,我希望您能对此有所启发。我在维基上读到,这是做事情的正确方法,但我似乎不能使用manager.load()?你能链接到维基上的哪个地方吗?从技术上讲,您可以对资产进行静态引用,但如果您这样做,您需要确切地知道您在做什么,而且很容易出错。初学者经常犯这样的错误,所以wiki应该清理一下。我还在想办法,但我不知道该怎么办。所以现在在我的资产类别的dispose方法中,我在处理了manager之后添加了manager=null。我尝试使用Gdx.input.setCatchBackKey(true),然后在其中处理assest,但它只会加载一个黑色屏幕,上面链接着:小心,并继续告诉您为什么不应该在assets.OMG中使用
static
关键字!我现在非常爱你,这绝对是我需要的信息,对不起,我不太理解你之前的评论。。但我知道我的错误,我完全忽略了我的加载方法是静态的,我不知道怎么做,但我做到了。我只是没有把二和二放在一起。但这就是解决办法!非常感谢你!
public class FishyDash extends Game {

    Assets assets;

    public void create(){
        assets = new Assets();
        assets.load();
        //....
    }

}

public class MainMenuScreen implements Screen{

    //...

    public void show() {
        System.out.println("second");

        jumpSound = game.assets.manager.get(Assets.jumpSound, Sound.class);
        //...
    }

    //...

}
public class Assets {

    //Safer to keep this private and use below public method for access
    private static AssetManager manager; //do not instantiate here

    public static AssetManager manager(){
        if (manager == null) load();
        return manager;
    }

    public static void load (){
        if (manager == null) manager = new AssetManager();

        //your existing load code
    }

    public static void dispose() {
        if (manager != null){
            manager.dispose();
            manager = null;
       }
    }

}

public class FishyDash extends Game {

    //...

    @Override
    public void dispose() {
        Assets.dispose();
    }
}

public class MainMenuScreen implements Screen{

    //...

    public void show() {
        System.out.println("second");

        //NOTE THE PARENTHESES AFTER manager below
        jumpSound = Assets.manager().get(Assets.jumpSound, Sound.class);
        //...
    }

    //...

}