libgdx Screen 切换

我们一般在开发时,都会分成多个Screen去实现不同的功能,比如:

MenuScreen用于菜单界面显示,GameScreen主游戏界面,HelpScreen游戏帮助界面。

直接使用game.setScreen就可以完成场景的切换。不过这样略显生硬,另外,在内存占用方面有可能出现瞬时内存占用太大的问题,可能导致游戏退出什么的。

跟cocos2dx的道理一样,一个ScreenOne在切换的ScreenTwo时,是这样一个过程:

1. ScreenOne在运行中,它已加载资源。

2. 实例化ScreenTwo,加载ScreenTwo的资源(这时One和Two的资源都在内存中

3. 将显示切换到ScreenTwo,也就是game.setScreen(ScreenTwo)

4. ScreenOne销毁释放它的资源。

如果这两个Screen都加载很多资源的话,程序很容易出现问题。

比如iOS限定单个app最大10M内存(具体多少我忘了,我只是比方,请查文档),而ScreenOne和ScreenTwo分别占用8M,切换瞬间会有16M,这时就有问题啦。

 

以前在玩2dx的时候,哥们告诉我了一种方法,就是中间加个过渡的切换专用Screen,当然它的占用应该很小。

然后切换过程就变成了这样:

1. ScreenOne在运行中,它已加载资源。

2. 实例化TransScreen,加载TransScreen的资源,当然也可以不用资源,就是个黑屏

3. 将显示切换到TransScreen,也就是game.setScreen(TransScreen)

4. ScreenOne销毁释放它的资源。

5. 实例化ScreenTwo,加载ScreenTwo的资源

6. 将显示切换到ScreenTwo,也就是game.setScreen(ScreenTwo)

7. TransScreen销毁释放它的资源。

 

这样我们就把大量的资源占用错开了。

上代码

  1 public class ScreenTrans implements Screen {

  2     private ScreenType next;

  3     private Game game;//在需要切换场景的时候直接game.setScreen

  4     private Stage stage;

  5     private static final Logger LOGGER = new Logger(ScreenTrans.class.getName(), Application.LOG_DEBUG);

  6     private static final float DURATION=0.5f;

  7     private Texture logoTexture;

  8     private Skin skin;

  9     private ProgressBar bar;

 10     private GameTimer timer;

 11 

 12     public enum ScreenType{

 13         SCREEN_ONE,SCREEN_TWO

 14     }

 15 

 16     public ScreenTrans(Game game,ScreenType next) {

 17         LOGGER.debug("init");

 18         this.game = game;

 19         this.next = next;

 20 

 21         stage = new Stage();

 22         //Gdx.input.setInputProcessor(null);

 23 

 24         logoTexture = new Texture(Gdx.files.internal("badlogic.jpg"));

 25         Image logo = new Image(logoTexture);

 26         logo.setCenterPosition(Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2);

 27         stage.addActor(logo);

 28 

 29         skin = new Skin();

 30         Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888);

 31         pixmap.setColor(Color.WHITE);

 32         pixmap.fill();

 33         skin.add("white", new Texture(pixmap));

 34 

 35         ProgressBar.ProgressBarStyle style = new ProgressBar.ProgressBarStyle();

 36         style.knob = skin.newDrawable("white",Color.GREEN);

 37         style.knobBefore = skin.newDrawable("white", Color.GREEN);

 38         style.knobAfter = skin.newDrawable("white",Color.GRAY);

 39         style.background = skin.newDrawable("white",Color.RED);

 40 

 41         style.knob.setMinHeight(10);

 42         style.knobBefore.setMinHeight(10);

 43         style.knobAfter.setMinHeight(10);

 44 

 45         bar = new ProgressBar(0,100,1,false,style);

 46         bar.setWidth(logo.getWidth());

 47         bar.setCenterPosition(Gdx.graphics.getWidth()/2,(Gdx.graphics.getHeight()-logo.getHeight())/2-5);

 48         stage.addActor(bar);

 49 

 50         timer = new GameTimer(DURATION);

 51     }

 52 

 53     @Override

 54     public void render(float delta) {

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

 56         Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

 57 

 58         float d = CommonUtils.getDelta(delta);

 59         timer.update(d);

 60         if(timer.isFinished()){

 61             this.trans();

 62         }

 63         bar.setValue(timer.getLiveTime()*100/DURATION);

 64         stage.act(delta);

 65         stage.draw();

 66     }

 67 

 68     private void trans(){

 69         Screen nextScreen = null;

 70         switch (next){

 71             case SCREEN_ONE:

 72                 nextScreen = new ScreenOne(this.game);

 73             break;

 74             case SCREEN_TWO:

 75                 nextScreen = new ScreenTwo(this.game);

 76                 break;

 77         }

 78         this.game.setScreen(nextScreen);

 79         this.dispose();

 80     }

 81 

 82     @Override

 83     public void resize(int width, int height) {

 84         stage.getViewport().update(width,height,true);

 85     }

 86 

 87     @Override

 88     public void show() {

 89         LOGGER.debug("show");

 90     }

 91 

 92     @Override

 93     public void hide() {

 94 

 95     }

 96 

 97     @Override

 98     public void pause() {

 99 

100     }

101 

102     @Override

103     public void resume() {

104 

105     }

106 

107     @Override

108     public void dispose() {

109         LOGGER.debug("dispose");

110         stage.dispose();

111         logoTexture.dispose();

112         skin.dispose();

113     }

114 }

以上代码中使用了枚举的场景类型用以区分下一步是哪个,当然也可以用int或者更高级一点用Class<? extends Screen>,然后用class.newInstance等。

GameTimer是个特别简单的计时器。

这个过渡屏我加入了一个假的加载进度条,当然是假的,这时候next的Screen还没实例化呢。其实是个计时条=。=

还有一个image。加入这些,我就是为了感受一下切换是否生硬。

以下是效果图:

libgdx Screen 切换

 

以下是调试信息:

com.tide.g2d.screeneffect.two.ScreenOne: init
com.tide.g2d.screeneffect.two.ScreenOne: show
com.tide.g2d.screeneffect.ScreenTrans: init
com.tide.g2d.screeneffect.ScreenTrans: show
com.tide.g2d.screeneffect.two.ScreenOne: dispose

-----这时正在展示过渡屏
com.tide.g2d.screeneffect.two.ScreenTwo: init
com.tide.g2d.screeneffect.two.ScreenTwo: show
com.tide.g2d.screeneffect.ScreenTrans: dispose
com.tide.g2d.screeneffect.ScreenTrans: init
com.tide.g2d.screeneffect.ScreenTrans: show
com.tide.g2d.screeneffect.two.ScreenTwo: dispose

-----这时正在展示过渡屏
com.tide.g2d.screeneffect.two.ScreenOne: init
com.tide.g2d.screeneffect.two.ScreenOne: show
com.tide.g2d.screeneffect.ScreenTrans: dispose
com.tide.g2d.screeneffect.ScreenTrans: init
com.tide.g2d.screeneffect.ScreenTrans: show
com.tide.g2d.screeneffect.two.ScreenOne: dispose

-----这时正在展示过渡屏
com.tide.g2d.screeneffect.two.ScreenTwo: init
com.tide.g2d.screeneffect.two.ScreenTwo: show
com.tide.g2d.screeneffect.ScreenTrans: dispose

 

你可能感兴趣的:(libgdx)