LibGDX FitViewport 可以正确调整大小,但在更换屏幕后会重置
LibGDX FitViewport resizes properly, but resets after changing screens
我在 LibGDX 中遇到 FitViewport
的问题。调整 window 大小时,一切正常。接下来我切换屏幕,一切都回到正常尺寸,图像被裁剪到左侧,而应用程序的尺寸保持调整大小。
调整大小后,FitViewport 工作正常:
但是,当我按下 to first screen
按钮时,会发生这种情况:
所以一切正常(按 to main screen
按钮将带您回到原始屏幕),除了按钮和图像的缩放和定位。
window 的尺寸保持不变,但图像恢复为原始大小(即 500x500)并放置在坐标 (0,0) 处。
关于如何解决这个问题有什么想法或建议吗?我正在为这个问题而烦恼,似乎无法正确处理...我希望它就像第一个屏幕一样。
这些是我的 class 文件:我使用抽象屏幕 class 来跟踪屏幕(以及稍后扩展)和屏幕管理器:
主要class:
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);
}
}
摘要屏幕Class:
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();
}
屏幕管理器Class:
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;
}
}
主屏幕Class:
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();
}
}
第一屏Class:
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();
}
}
(我知道我提供了很多classes,但我想详细解释一切......)
我猜这可能是一些小事,但我似乎做对了,这让我发疯了……
任何帮助或建议将不胜感激!
当您使用 ScreenManager 创建新屏幕时,您不会在新实例化的屏幕上调用 resize
。它是第一次工作,因为您是在 ApplicationListener 上调用 resize
之前创建第一个屏幕,而 ApplicationListener 又会在屏幕上调用 resize
。
顺便说一句,您还必须在这些屏幕超出范围之前调用 dispose
,否则会泄漏内存。 dispose
屏幕的 dispose
方法中的所有资产、批次等(任何实现 Disposable 的东西)。
你的问题在这里:
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);
每次检查当前 window 大小并创建 window 具有的大小的视口。解决方案是手动定义 window 大小并根据此值创建新的屏幕视口。
在您的 Main class 中创建静态 public 大小变量(您当然可以在您想要或不创建但直接写入值的任何地方创建它 -但由于未来的重构,这并不好)
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);
就这些了。
如果您不需要这个,也请考虑不要创建新相机 - 也许默认的 stage 相机对您来说足够了?想想看。
我在 LibGDX 中遇到 FitViewport
的问题。调整 window 大小时,一切正常。接下来我切换屏幕,一切都回到正常尺寸,图像被裁剪到左侧,而应用程序的尺寸保持调整大小。
调整大小后,FitViewport 工作正常:
但是,当我按下 to first screen
按钮时,会发生这种情况:
所以一切正常(按 to main screen
按钮将带您回到原始屏幕),除了按钮和图像的缩放和定位。
window 的尺寸保持不变,但图像恢复为原始大小(即 500x500)并放置在坐标 (0,0) 处。
关于如何解决这个问题有什么想法或建议吗?我正在为这个问题而烦恼,似乎无法正确处理...我希望它就像第一个屏幕一样。
这些是我的 class 文件:我使用抽象屏幕 class 来跟踪屏幕(以及稍后扩展)和屏幕管理器:
主要class:
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);
}
}
摘要屏幕Class:
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();
}
屏幕管理器Class:
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;
}
}
主屏幕Class:
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();
}
}
第一屏Class:
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();
}
}
(我知道我提供了很多classes,但我想详细解释一切......) 我猜这可能是一些小事,但我似乎做对了,这让我发疯了…… 任何帮助或建议将不胜感激!
当您使用 ScreenManager 创建新屏幕时,您不会在新实例化的屏幕上调用 resize
。它是第一次工作,因为您是在 ApplicationListener 上调用 resize
之前创建第一个屏幕,而 ApplicationListener 又会在屏幕上调用 resize
。
顺便说一句,您还必须在这些屏幕超出范围之前调用 dispose
,否则会泄漏内存。 dispose
屏幕的 dispose
方法中的所有资产、批次等(任何实现 Disposable 的东西)。
你的问题在这里:
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);
每次检查当前 window 大小并创建 window 具有的大小的视口。解决方案是手动定义 window 大小并根据此值创建新的屏幕视口。
在您的 Main class 中创建静态 public 大小变量(您当然可以在您想要或不创建但直接写入值的任何地方创建它 -但由于未来的重构,这并不好)
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);
就这些了。
如果您不需要这个,也请考虑不要创建新相机 - 也许默认的 stage 相机对您来说足够了?想想看。