说我有一个闪屏。此屏幕仅在游戏开始时加载,之后我不使用它。 是否可以根据需要配置此屏幕?
我尝试在启动后设置屏幕后立即处理它,并尝试在dispose()
方法上调用hide()
。
两个尝试都在异常中呈现。
如何根据需要配置此屏幕?我有相当沉重的纹理,并希望尽快释放记忆。
示例:
// SplashScreen class
class SplashScreen implements Screen {
private boolean renderingEnabled = true;
private Object lock = new Object();
@Override
public void render(float delta) {
synchronized(lock) {
if (!renderingEnabled) {
return;
}
spriteBatch.begin();
// here render the animations
spriteBatch.end();
}
}
@Override
public void dispose() {
synchronized(lock) {
renderingEnabled = false;
// here come the disposing of SpriteBatch and TextureAtlas
atlas.dispose();
atlas = null;
spriteBatch.dispose();
spriteBatch = null;
}
}
}
// The usage
game.setScreen(splashScreen);
...
// now when the splash screen animation is finished, I am calling the following from the controller:
splashScreen.dispose();
game.setScreen(mainMenuScreen);
我得到以下异常:
FATAL EXCEPTION: GLThread 398
java.lang.NullPointerException
at mypackage.SplashScreen.render(SplashScreen.java:85)
at com.badlogic.gdx.Game.render(Game.java:46)
at mypackage.Game.render(MyGame.java:33)
at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:414)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1522)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
当我有以下配置模式(在显示mainMenuScreen
之后处置)
// The usage
game.setScreen(splashScreen);
...
// now when the splash screen animation is finished, I am calling the following from the controller:
game.setScreen(mainMenuScreen);
splashScreen.dispose();
我得到了同样的例外。
例外是在render方法中的spriteBatch.end()
行。 spriteBatch
成员变为null。真的很混乱,因为我对render
和dispose
方法有互斥锁。
答案 0 :(得分:0)
我想到的是,LibGDX在一个线程中工作。
会发生什么是以下情况。当调用game.setScreen(mainMenuScreen)
,并且程序位于启动屏幕的render
方法的中间时,线程被中断,并且用于设置 mainMenuScreen 的代码是执行(在Game
类中),然后返回以继续启动画面的渲染方法。很奇怪,对吗?设置新屏幕后仍然显示旧屏幕?
无论如何,我做的是以下内容:
作为Game.setScreen(Screen screen)
方法的一部分,在旧屏幕上调用Screen.hide()
方法。
所以我做了什么,我在启动画面内的hideCalled
事件中引入了一个标志hide()
并将其设置为 true 。
在启动画面的render
方法中,我在方法的开头和结尾处检查此标志。如果标志是 true - 我会丢弃屏幕。
答案 1 :(得分:0)
我只是想着AssetManager,也许它会以更清洁的方式帮助你解决这个问题。 看看here。 我看到它异步加载资产所以也许你所描述的这个问题不会再发生了。
仅仅为了一些知识共享,我用另一种方法改变了屏幕: 我使用了附加到图像的动作,这些动作按照添加的顺序执行。首先我创建了一个加载图像的动作,然后,当第一个动作完成时,我添加了另一个切换屏幕的动作。 这是我的代码:
@Override
public void show() {
stage.addActor(splashImage);
splashImage.addAction(Actions.sequence(Actions.alpha(0), Actions.run(new Runnable() {
@Override
public void run() {
Assets.load();
}
}), Actions.fadeIn(0.5f), Actions.delay(1), Actions.fadeOut(0.5f), Actions.run(new Runnable() {
@Override
public void run() {
Utils.changeGameScreen(new GameScreen());
// ((Game) Gdx.app.getApplicationListener()).setScreen(new
// GameScreen());
}
})));
}