zoukankan      html  css  js  c++  java
  • 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。加入这些,我就是为了感受一下切换是否生硬。

    以下是效果图:

    以下是调试信息:

    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

  • 相关阅读:
    SQL80001: Incorrect syntax near ':'
    Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
    log4net 日志配置及使用
    在C#中将String转换成Enum:
    未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序解决办法
    五大编程算法
    CodeSmith 使用说明
    PowerDesigner使用教程
    一个七年程序员的经验
    未能正确加载包“Microsoft.Data.Entity.Design.Package.MicrosoftDataEntityDesignPackage
  • 原文地址:https://www.cnblogs.com/hanhongmin/p/3968594.html
Copyright © 2011-2022 走看看