#Testin杯#Mkey libgdx游戏引擎教程(四) 游戏正式开始,资源异步加载(附源码)

300
回复
1480970
查看
  [复制链接]

30

主题

350

帖子

1089

安币

Android大神

Rank: 6Rank: 6

QQ达人

发表于 2012-7-5 14:25:21 | 显示全部楼层 |阅读模式
本帖最后由 耒佲請ぁ留埗 于 2012-8-3 11:22 编辑




以下系列教程按讲课顺序排列,也是推荐阅读的顺序

第一讲:libgdx游戏引擎教程(一)性能优良的游戏引擎—libgdx http://www.apkbus.com/android-57355-1-1.html

第二讲: libgdx游戏引擎教程(二) ApplicationListener,着手第一个程序http://www.apkbus.com/android-57372-1-1.html

第三讲:libgdx游戏引擎教程()libgdx粒子系统的使用 http://www.apkbus.com/android-57456-1-1.html

外篇一:libgdx游戏引擎教程外篇(一)优美的自定义进度条(附源码) http://www.apkbus.com/android-57523-1-1.html

第四讲:libgdx游戏引擎教程(四) 游戏正式开始,资源异步加载(附源码)http://www.apkbus.com/android-57716-1-1.html

第五讲 libgdx游戏引擎教程(五)多游戏界面的实现(一)附源码 http://www.apkbus.com/android-57936-1-1.html

第六讲 libgdx游戏引擎教程(六)多游戏界面的实现(二)附源码 http://www.apkbus.com/android-57991-1-1.html  

第七讲 libgdx游戏引擎教程(七) 在libgdx中拦截Android按键事件 http://www.apkbus.com/android-58030-1-1.html  

外篇二: libgdx游戏引擎教程外篇(二)libgdx移植俄罗斯方块(附源码) http://www.apkbus.com/android-58102-1-1.html   

实战一:libgdx游戏引擎教程实战篇(一)移植俄罗斯方块(附源码) http://www.apkbus.com/android-58404-1-1.html  

实战二:libgdx游戏引擎教程实战篇(二)移植俄罗斯方块(附源码) http://www.apkbus.com/android-58408-1-1.html  

实战三:libgdx游戏引擎教程实战篇(三)移植俄罗斯方块(附源码) http://www.apkbus.com/android-58414-1-1.html  

实战四:libgdx游戏引擎教程实战篇(四)移植俄罗斯方块(附源码) http://www.apkbus.com/android-58418-1-1.html  

实战五:libgdx游戏引擎教程实战篇(五)移植俄罗斯方块(附源码) http://www.apkbus.com/android-58419-1-1.html

实战六:libgdx游戏引擎教程实战篇(六)移植俄罗斯方块(附源码) http://www.apkbus.com/android-58760-1-1.html

第八讲 libgdx游戏引擎教程(八) libgdx中的用户手势识别(一)附源码 http://www.apkbus.com/android-58933-1-1.html

第九讲 libgdx游戏引擎教程(九) libgdx中的用户手势识别(二)附源码 http://www.apkbus.com/android-59152-1-1.html

外篇三: libgdx游戏引擎教程外篇(三) 优美的自定义对话框(附源码) http://www.apkbus.com/android-59654-1-1.html  

第十讲:  libgdx游戏引擎教程(十)演员类的复杂动画(一)(附源码) http://www.apkbus.com/android-59998-1-2.html

第十一讲:libgdx游戏引擎教程(十一)演员类的复杂动画(二)(附源码) http://www.apkbus.com/android-60053-1-1.html

第十二讲:libgdx游戏引擎教程(十二)演员类的复杂动画(三)(附源码) http://www.apkbus.com/android-60194-1-1.html   

第十三讲: libgdx游戏引擎教程(十三)演员类的用户交互功能详解(附源码)  http://www.apkbus.com/android-60457-1-1.html

第十四讲:libgdx游戏引擎教程(十四)libgdx中常用的控件(附源码) http://www.apkbus.com/android-60569-1-1.html

最新更新 第十五讲 :libgdx游戏引擎教程(十五)在Libgdx中仿微信帮助滑动效果(附源码) http://www.apkbus.com/android-60822-1-1.html



       今天是Testin Mkey libgdx游戏教程的第四讲。昨天我们在外篇(一)中用很短的时间自定义出了一个样子看起来还不算太糟的自定义进度条,但是这个进度条没有什么实际的意义,仅仅是能够自动的进行进度的变化。那么,今天我们就要利用这个进度条来做一些实际的工作了。如果大家还没有看昨天那篇

libgdx游戏教程外篇()优美的自定义进度条(附源码)

          建议大家还是先看一下,对我和大家一起完成的那个进度条的工作机制有一个很好的了解,今天这篇文章大家理解起来就很轻松了。

       请原谅我在考虑教程内容安排上的考虑而把资源载入放在前面先讲。个人窃以为没有资源载入的正确方法和习惯,在游戏的后期是非常麻烦的。作为一个非常棒的游戏开发引擎,Libgdx肯定是拿来做游戏的(哈哈,这好像是废话),而游戏就有一个最大的特点,就是图片资源和音频资源都非常地庞大,越是精美的游戏,越需要强大的图形渲染来支撑。

       那么,图片的加载就是一个很大的问题。我们不可能直接在UI线程中去加载,在我昨天给大家看的那个我现在正在编写的宠物对战游戏中,我用到了大量的图片来形成宠物的一帧帧的动作,因此加载问题就是一个不得不解决的问题。我曾经尝试过直接加载或者独立新开一个线程去加载图片资源文件,效果都很不理想。

       直接加载接口启动速度太慢,会有很长时间的黑屏,想来没有人愿意玩这样的游戏。自己独立开一个线程加载也存在很大的问题,由于Android和java复杂的相互制约的初始化机制和垃圾回收机制,资源很可能还没有加载完成就被使用,在Libgdx中的典型症状就是纹理花屏(因此大家若在自己学习的过程中遇见了花屏的症状,一定不要着急,这是资源没有完全加载或者资源被回收的情况,大家可以使用下面要具体分析的AssetManager或者在每次需要显示的时候都重新把资源加载一次,当然这需要资源不太大的情况下才比较合适)。资源自动回收这个问题就更为复杂,系统会在内存不够的时候回收一些资源,这是我们更难掌控的。

      好在强大的libgdx引擎是专门为游戏设计的引擎,它提供了一个非常有用的工具,即为AssetManager,简单的说就是一个资源异步加载和资源自动管理类,具体的介绍可以看巴士内的帖子:

android游戏开发框架libgdx的使用(二十)资源预加载与AssetManager的使用


          今天大家完全不需要把这个AssetManager完全搞懂,只要先大概知道怎么加载资源并且获得资源就可以了。一些复杂的参数一般也不常用。

          在加载前,AssetManager需要知道加载什么类型的资源,这个功能通过资源加载器实现。有两个变量,同步资源加载器SynchronourAssetLoader和异步资源加载器AsynchronousAssetLoader。前者加载任何资源都在渲染进程中,后者加载资源在另外一个线程中。比如说,一个Texture需要一个Pixmap,然后加载OpenGL依赖于渲染线程。


          这里我解释一下,所谓的AssetManager异步加载是指相对于我们开发者而言的异步,因为我们主要的显示操作是在UI线程上,因此AssetManager的加载是异步的。但为什么这里又有同步加载和异步加载之分呢?这里的同步和异步是相对渲染线程而言的,简单的理解就是相对系统专门用来调用render()函数的那个线程而言的。那么这样就很简单了,所谓异步加载就是另开一个线程而不在渲染线程里面,同步就是在render()线程里加载咯…而这两种加载方式相对UI线程都是异步的。


下面的资源类型可以由AssetManager直接创建。
·        Pixmaps 通过 PixmapLoader
·        Textures 通过 TextureLoader
·        BitmapFonts 通过BitmapFontLoader
·        TextureAtlases 通过TextureAtlasLoader
·        TiledAtlases 通过TiledAtlasLoader
·        TileMapRenderers 通过 TileMapRendererLoader
·        Music instances 通过 MusicLoader
·        Sound instances 通过 SoundLoader


加载某个资源很简单:
manager.load("data/testin.png", Texture.class);
manager.load("data/ testin.fnt", BitmapFont.class);

           目前为止,我们只是将资源放入加载队列,AssetManager还没有载入任何东西。我们必须不断调用AssetManager的update()才能将队列中的资源不断加载进来。


          什么地方能让我们不停调用update()方法呢?难道再新开一个线程?想来大家心中都已经有了答案。没错就是在Progress(还记得吗,这个继承自ApplicationListener)的render()函数中去不停调用update()就可以了,而且这是系统自动调用的,不用我们操心,很省心吧,哈哈。


         噢,对了,这里还有一个小问题要提醒一下大家,AssetManager在API里也有,大家写import的时候不要写错了。
  1. public Progress implements ApplicationListener {

  2.    public void render() {
  3.       if(manager.update()) {
  4.          // 完成加载,进行跳转
  5.       }

  6.    }
  7. }
复制代码
         为了画出动画,我们先新建一个类,AnimalActor ,这是一个Actor,也就是libgdx中最常说的演员了。这里建议大家养成良好的习惯,一般这种持有较多资源的类建议都继承Disposable接口,便于最后资源的释放和回收。


        至于其中用到的动画,由Texture和Animation配合,大家可以看一下官方的API,可以在下载好的libgdx文件夹下的docs/api/index里面查到。或者参加巴士内一文,其中也有Actor和Animation的使用

android游戏开发框架libgdx的使用(四)--舞台和演员

下面是AnimalActor的代码:

  1. public class AnimalActor extends Actor implements Disposable{
  2.     ArrayList<Texture> TexArray=new ArrayList<Texture>();
  3.     ArrayList<TextureRegion> TexReArray=new ArrayList<TextureRegion>();
  4.     Animation animation;

  5.     TextureRegion[] walksFrame;
  6.     float stateTime;
  7.     TextureRegion currentFrame;//当前帧
  8.     AssetManager manager;//保存Progress里面保存的manager实例
  9.     @Override
  10.     public void draw(SpriteBatch arg0, float arg1) {
  11.        // TODO Auto-generated method stub
  12.        stateTime += Gdx.graphics.getDeltaTime();
  13.        //得到下一帧
  14.        currentFrame = animation.getKeyFrame(stateTime, true);
  15.        //以(0,0)绘制为起点(左下角为0,0)画出动画,大小128*128
  16.        arg0.draw(currentFrame,0, 0,128,128);
  17.     }
  18.    
  19.    
  20.     public AnimalActor(AssetManager manager) {
  21.        super();
  22.        //关联Progress内的AssetManager
  23.        this.manager=manager;
  24.     }


  25.     @Override
  26.     public Actor hit(float x, float y) {
  27.        // TODO Auto-generated method stub
  28.             return this;
  29.     }

  30.     @Override
  31.     public boolean touchDown(float arg0, float arg1, int arg2) {
  32.        // TODO Auto-generated method stub
  33.        return false;
  34.     }

  35.     @Override
  36.     public void touchDragged(float arg0, float arg1, int arg2) {
  37.        // TODO Auto-generated method stub

  38.     }

  39.     @Override
  40.     public void touchUp(float arg0, float arg1, int arg2) {
  41.        // TODO Auto-generated method stub

  42.     }

  43.     //初始化方法,在Progress中的AssetManager初始化完成后通知AnimalActor初始化
  44.     public void iniResource(){
  45.        Texture tex;
  46.        int j;
  47.        for(int i=1;i<30;i++){
  48.            TexArray.add(manager.get("animal/"+i+".png", Texture.class));
  49.        }
  50.        // TODO Auto-generated constructor stub
  51.       
  52.        for(int i=0;i<TexArray.size();i++){
  53.               tex=TexArray.get(i);
  54.               TextureRegion temtex=new TextureRegion(tex);
  55.               TexReArray.add(temtex);
  56.        }
  57.       
  58.        j=TexReArray.size();
  59.        walksFrame=new TextureRegion[j];
  60.        for(int i=0;i<j;i++)
  61.        walksFrame[i]=TexReArray.get(i);
  62.       
  63.        //设置的是0.06s一帧
  64.        animation = new Animation(0.06f, walksFrame);
  65.       
  66.     }


  67.     @Override
  68.     public void dispose() {
  69.        // TODO Auto-generated method stub
  70.       
  71.        //释放AnimalActor中持有的资源
  72.        for(int i=0;i<TexArray.size();i++)
  73.            TexArray.get(i).dispose();
  74.     }
  75.     }
复制代码
其中大部分难点都在源码中做出了注释。
ProgressBar不需要做任何的修改,这就是封装的好处了。
当然Progress类需要做一些修改,比如用于加载的AssetManger,AnimalActor对象。
  1. public class Progress implements ApplicationListener {
  2.     ProgressBar bar;
  3.     AnimalActor animal;
  4.     Stage stage;
  5.     AssetManager manager;
  6.     boolean hasini;
  7.     @Override
  8.     public void create() {
  9.        // TODO Auto-generated method stub
  10.        bar=new ProgressBar(0,0);
  11.        //新建一个舞台
  12.        stage=new Stage(Gdx.graphics.getWidth(),Gdx.graphics.getHeight(), true);
  13.        stage.addActor(bar);
  14.        //记得初始化一下AssetManager实例
  15.        manager=new AssetManager();
  16.        //传入AssetManger的引用,便于animal的资源初始化,但是注意了,只有在调用iniResourse()后资源才被初始化
  17.        animal=new AnimalActor(manager);
  18.        //把资源加入载入列表,这里我放了一个29帧的动画,在asset文件夹下animal下有29张图片
  19.        for(int i=1;i<30;i++){
  20.            manager.load("animal/"+i+".png", Texture.class);
  21.        }
  22.     }

  23.     @Override
  24.     public void dispose() {
  25.        // TODO Auto-generated method stub
  26.        //同样的,在结束时释放资源
  27.        bar.dispose();
  28.        animal.dispose();
  29.        manager.clear();
  30.        manager.dispose();
  31.     }

  32.     @Override
  33.     public void pause() {
  34.        // TODO Auto-generated method stub

  35.     }

  36.     @Override
  37.     public void render() {
  38.        // TODO Auto-generated method stub
  39.        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
  40.        Gdx.gl.glClearColor(1f,1f,1f,0f);
  41.        stage.act(Gdx.graphics.getDeltaTime());
  42.        stage.draw();
  43.        if(!manager.update()){
  44.            bar.setProgress(manager.getProgress()*100);
  45.        }
  46.        //加载完成且之前没有初始化过AnimalActor,且在手触摸屏幕时初始化AnimalActor,并将进度条从舞台中移除,并加入AnimalActor对象
  47.        if(!hasini&&manager.update()&&Gdx.input.isTouched()){
  48.            stage.removeActor(bar);
  49.            animal.iniResource();
  50.            stage.addActor(animal);
  51.            hasini=true;
  52.        }
  53.        //我们做一个标记,看看未加载(Queued)完成的资源和已载入完成的资源的数量(Loaded)
  54.        if(!manager.update()){
  55.        System.out.println("QueuedAssets:"+manager.getQueuedAssets());
  56.        System.out.println("LoadedAssets:"+manager.getLoadedAssets());
  57.        System.out.println("Progress:"+manager.getProgress());
  58.        }
  59.     }

  60.     @Override
  61.     public void resize(int arg0, int arg1) {
  62.        // TODO Auto-generated method stub

  63.     }

  64.     @Override
  65.     public void resume() {
  66.        // TODO Auto-generated method stub

  67.     }

  68. }
复制代码
      按照老规矩,我会对其中的难点做出一些解释。manager.load()方法只是将资源放入加载列表,而真正的加载要不停地调用manager.update()才可以,且update()函数有一个返回值,载入完成返回true,未完成返回false.


     为了使大家更直观一些,我加了几条语句:
  1.    if(!manager.update()){
  2.        System.out.println("QueuedAssets:"+manager.getQueuedAssets());
  3.        System.out.println("LoadedAssets:"+manager.getLoadedAssets());
  4.        System.out.println("Progress:"+manager.getProgress());
  5.        }
复制代码
从名字我们就可以看出,manager.getQueuedAssets()是获得还在载入列表中也就是还没有完成载入的资源的个数,manager.getLoadedAssets()则是已经载入完成的资源的个数。我们可以在输出中看看未加载(Queued)完成的资源和已载入完成的资源的数量(Loaded)的个数的变化。

    dispose()方法中记得把animal和manager一并回收了。


老样子,启动Progress:

  1. public class LibgdxActivity extends  AndroidApplication {
  2.     Progress progress;
  3.     @Override
  4.     public void onCreate(Bundle savedInstanceState) {
  5.         super.onCreate(savedInstanceState);
  6.         progress=new Progress();
  7.         initialize(progress, false);
  8.     }
  9. }
复制代码
接下来我们来看看效果



加载完成了,记得要点一下屏幕才能继续哦~!咱们在代码中用一两句就实现了加载完成,触摸继续游戏的功能,是不是很简单呢?如果不记得了,回头看看上面的源码哈!


这货其实是动画=。=大家实际看看就知道了,很快有没有!Libgdx的效率!


看看输出吧




这就是第四讲,希望大家继续支持Testin杯——Mkey libgdx游戏引擎系列教程!

Testin ID:ilovemkey@gmail.com 总的而言这个平台真的非常好用!我正是用这个平台发现了现在写的这个应用的一些内存管理方面的问题。另外建议能够在测试报告中看到某一台机型在整个执行过程中的cpu和内存占用的变化情况,这样可以更快地锁定问题。感谢Itestin让测试变得轻松了太多太多!

这里是源代码哦!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
君见一叶舟,出没风波里

2826

主题

7684

帖子

9602

安币

管理员

Rank: 9Rank: 9Rank: 9

QQ达人最佳新人活跃会员热心会员推广达人灌水之王突出贡献

QQ
发表于 2012-7-5 14:26:24 | 显示全部楼层
{:soso_e113:}沙发再一次是我的。。。。楼主冲击小米的力度不小啊!!!!

1

主题

2

帖子

24

安币

初级码农

小宝

Rank: 1

QQ达人

QQ
发表于 2012-7-5 16:38:42 | 显示全部楼层
学习学习
蛋定

0

主题

41

帖子

166

安币

程序猿

Rank: 2

QQ达人

发表于 2012-7-5 18:10:27 | 显示全部楼层
学习了  

2

主题

29

帖子

34

安币

初级码农

Rank: 1

发表于 2012-7-5 21:08:53 | 显示全部楼层
谢谢Lz{:Music:}

0

主题

59

帖子

120

安币

程序猿

Rank: 2

发表于 2012-7-6 00:29:35 | 显示全部楼层
顶起楼主。。。。下次做个资源预加载!搞个进度条给用户。感觉不错!上个月接触的libgdx,自己开发了个小游戏, 感觉很多地方不满意。。下次的项目 改进改进

0

主题

46

帖子

171

安币

程序猿

Rank: 2

发表于 2012-7-6 10:36:16 | 显示全部楼层
教程写的真好,我要好好学习

0

主题

18

帖子

19

安币

初级码农

Rank: 1

发表于 2012-7-6 11:24:55 | 显示全部楼层
看看,好像不错{:Big Chin 2:}
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

领先的中文移动开发者社区
18620764416
7*24全天服务
意见反馈:1294855032@qq.com

扫一扫关注我们

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粤ICP备15117877号 )