首页 > 代码库 > libgdx Screen 切换
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 @Override103 public void resume() {104 105 }106 107 @Override108 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。加入这些,我就是为了感受一下切换是否生硬。
以下是效果图:
以下是调试信息:
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 Screen 切换