LibGDX FitViewport正确调整大小,但在更改屏幕后重置

时间:2015-09-11 17:26:47

标签: java libgdx viewport window-resize

我在LibGDX中遇到FitViewport问题。调整窗口大小时,一切正常。接下来我切换屏幕,一切都只是翻回到正常尺寸,图像被裁剪到左侧,同时应用程序的尺寸仍然调整大小。

调整大小后,FitViewport正常工作: Resized window, no problems

但是,当我按下to first screen按钮时,会发生这种情况:

Next screen, resizing fails

所以一切正常(按to main screen按钮将您带回原始屏幕),除了缩放按钮和图像的位置。

窗口的尺寸保持不变,但图像会恢复到原始尺寸(500x500)并放在坐标(0,0)处。

有关如何解决此问题的任何想法或建议?我对这个问题感到不满,似乎无法做到正确......我希望它就像第一个屏幕一样。

这些是我的类文件:我使用抽象的Screen类来跟踪屏幕(以及稍后进行扩展)和ScreenManager:

主要课程:

public class MainClass implements ApplicationListener {

    @Override
    public void create () {
        ScreenManager.setScreen(new MainScreen());
    }

    @Override
    public void render () {
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        if (ScreenManager.getCurrentScreen() != null) {
            ScreenManager.getCurrentScreen().render();
        }
    }

    @Override
    public void resize(int width, int height) {
        if (ScreenManager.getCurrentScreen() != null)
            ScreenManager.getCurrentScreen().resize(width, height);
    }
}

摘要屏幕类:

public abstract class Screen {

    public abstract void create();

    public abstract void render();

    public abstract void resize(int width, int height);

    public abstract void pause();

    public abstract void dispose();

    public abstract void resume();
}

屏幕管理员课程:

public class ScreenManager {

    private static Screen currentScreen;

    public static void setScreen(Screen screen) {
            if (currentScreen != null)
            currentScreen.dispose();
        currentScreen = screen;
        currentScreen.create();
    }

    public static Screen getCurrentScreen() {
        return currentScreen;
    }
}

主屏类:

public class MainScreen extends Screen {

    private Texture bg1;
    private Image bg1Image;
    private Skin skin;

    private Stage stage;
    private OrthographicCamera camera;
    private FitViewport fitViewport;

    @Override
    public void create() {
        camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        fitViewport = new FitViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), camera);

        bg1 = new Texture(Gdx.files.internal("background1.png"));
        bg1Image = new Image(bg1);
        skin = new Skin(Gdx.files.internal("uiskin.json"));

        TextButton nextButton = new TextButton("to first screen", skin);
        nextButton.setPosition(200, 200);
        nextButton.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event, float x, float y) {
                ScreenManager.setScreen(new FirstScreen());
                super.clicked(event, x, y);
            }
        });

        stage = new Stage(fitViewport);
        stage.addActor(bg1Image);
        stage.addActor(nextButton);

        Gdx.input.setInputProcessor(stage);
    }

    @Override
    public void render() {
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        stage.act(Gdx.graphics.getDeltaTime());

        fitViewport.apply();
        stage.draw();
    }

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

第一个屏幕类:

public class FirstScreen extends Screen {

    private Texture bg2;
    private Image bg2Image;
    private Skin skin;

    private Stage stage;
    private OrthographicCamera camera;
    private FitViewport fitViewport;

    @Override
    public void create() {
        camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        fitViewport = new FitViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), camera);

        bg2 = new Texture(Gdx.files.internal("background2.png"));
        bg2Image = new Image(bg2);
        skin = new Skin(Gdx.files.internal("uiskin.json"));

        TextButton prevButton = new TextButton("to main screen", skin);
        prevButton.setPosition(200, 200);
        prevButton.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event, float x, float y) {
                ScreenManager.setScreen(new MainScreen());
                super.clicked(event, x, y);
            }
        });

        stage = new Stage(fitViewport);
        stage.addActor(bg2Image);
        stage.addActor(prevButton);

        Gdx.input.setInputProcessor(stage);
    }

    @Override
    public void render() {
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        stage.act(Gdx.graphics.getDeltaTime());

        fitViewport.apply();
        stage.draw();
    }

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

(我知道我提供了很多课程,但我想详细解释一切......) 我猜这可能是次要的,但我似乎无法做到这一点,这让我疯狂...... 任何帮助或建议将不胜感激!

2 个答案:

答案 0 :(得分:0)

使用ScreenManager创建新屏幕时,您不会在新实例化的屏幕上调用resize。它是第一次运行,因为您在ApplicationListener上调用resize之前创建了第一个屏幕,然后在屏幕上调用resize

顺便说一下,你也必须在这些屏幕超出范围之前调用dispose,否则你会泄漏内存。 dispose屏幕'dispose方法中的所有资产,批次等(实施Disposable的任何内容)。

答案 1 :(得分:0)

你的问题在这里:

    camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    fitViewport = new FitViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), camera);

每次检查当前窗口大小并创建具有窗口大小的视口。解决方案是手动定义窗口大小并根据此值创建新的屏幕视口。

主类中创建静态公共大小变量(当然,您可以创建它,或者不创建,但可以直接写入值 - 但由于将来的重构,这不是很好)

    public static final float WIDTH = 800, HEIGHT = 600; //or any other values you need

然后只需创建您的视口和相机

    camera = new OrthographicCamera(Main.WIDTH, Main.HEIGHT);
    camera.setToOrtho(false, Main.WIDTH, Main.HEIGHT);
    fitViewport = new FitViewport(Main.WIDTH, Main.HEIGHT, camera);

就是这样。

如果您不需要,请考虑不要创建新相机 - 也许默认的舞台相机对您来说已经足够了?想一想。