#Testin杯#Mkey libgdx游戏引擎教程(五)多游戏界面的实现(一)附源码

219
回复
1614183
查看
  [复制链接]

30

主题

350

帖子

1089

安币

Android大神

Rank: 6Rank: 6

QQ达人

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




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

第一讲: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中的多游戏容器的实现。我在我的Libgdx教程中尽量给大家介绍一些实用的功能,至于那些libgdx API基本的使用方法则不过多侧重,想来大家通过查询API文档也能掌握。这里再提醒一下大家,API文档可以在官网上看到,也可以在下载下来的libgdx包中的docs下的index.html中查看。



       至于多容器,简单的理解就是多个游戏界面,那么大家一定联想到SDK 中的多界面是用Activity实现的,通过Intent跳转来实现多界面之间的切换。


     那么libgdx中又如何实现多界面的切换呢?可不可以用Activity实现呢?我曾经在第一讲中提到过这个问题,大家可以先参看一下第一讲的内容:



libgdx游戏引擎教程() 性能优良的游戏引擎—libgdx




在这一讲的最后我们提到了通过查询libgdx的官方API我们可以看到:

java.lang.Object
| Activity
|com.badlogic.gdx.backends.android.AndroidApplication


       也就是说,AndroidApplication继承自API中的Activity因此我们使用它也需要在Manifest中注册,这里就不再具体说明如何注册了,大家应该都是知道的吧!另外,这里也提供了一个更好的问题供大家思考,既然AndroidApplication继承自Activity,那么是不是可以像其他Activity一样使用Intent进行跳转呢?答案是肯定的。下面我们来试一试,代码还是老规矩,在第四讲的基础上做修改。



     我们新建一个类,名为ActivityForSwitch,意思就是用来跳转的类, 这是一个直接继承自SDKActivity的类,大家注意区分。在这个类的加入后,我们的程序就将变成libgdxSDK API混用的一个程序。想来这些都简单的不能再简单,因此我就直接贴出代码了:



     这里有一点要注意,这里的ButtonSDK API中的Buttonandroid.widget.Button,要注意和我们后面在libgdx中使用的Button要区分开,后者是com.badlogic.gdx.scenes.scene2d.ui.Button

  1. public class ActivityForSwitch extends Activity {
  2.     Button switchbutton;
  3.     @Override
  4.     protected void onCreate(Bundle savedInstanceState) {
  5.        // TODO Auto-generated method stub
  6.        super.onCreate(savedInstanceState);
  7.        setContentView(R.layout.main);
  8.        switchbutton=(Button)findViewById(R.id.button1);
  9.        switchbutton.setOnClickListener(new OnClickListener() {
  10.          
  11.            public void onClick(View v) {
  12.               // TODO Auto-generated method stub
  13.               Intent intent=new Intent();
  14.               intent.setClass(ActivityForSwitch.this,LibgdxActivity.class);
  15.               ActivityForSwitch.this.startActivity(intent);
  16.            }
  17.        });

  18.     }
  19.    
  20. }
复制代码
顺带贴一下Manifest.xml的代码。供大家参考一下。
  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2.     package="edu.nju.wsj.libgdx"
  3.     android:versionCode="1"
  4.     android:versionName="1.0" >

  5.     <uses-sdk
  6.         android:minSdkVersion="7"
  7.         android:targetSdkVersion="15" />

  8.     <application
  9.         android:icon="@drawable/ic_launcher"
  10.         android:label="@string/app_name"
  11.         android:theme="@style/AppTheme" >
  12.         <activity
  13.             android:name="edu.nju.wsj.libgdx.ActivityForSwitch"
  14.             android:screenOrientation="landscape"
  15.             android:configChanges="keyboardHidden|orientation"
  16.             android:label="@string/title_activity_main" >
  17.             <intent-filter>
  18.                 <action android:name="android.intent.action.MAIN" />

  19.                 <category android:name="android.intent.category.LAUNCHER" />
  20.             </intent-filter>
  21.         </activity>
  22.          <activity
  23.             android:screenOrientation="landscape"
  24.             android:configChanges="keyboardHidden|orientation"
  25.             android:name=".LibgdxActivity" >
  26.         </activity>
  27.     </application>

  28. </manifest>
复制代码
     至于main.xml的代码就不贴出来了,非常简单,一个最基本的layout上放了一个Button(android.widget.Button)ButtonId设置为button1然后设置一个监听器,在点击的时候由一个Intent跳转到LibgdxActivity,到底能不能成功启动呢?点击button,诶,成功跳转了哦。(这部分的代码将和后面的修改过的代码分成两个项目上传,便于大家对比效果)






      不过有一点大家却可以感觉到,就是在程序跳转的过程中有一个比较明显的切换的过程,虽然说并算不上是卡顿,但却不是很流畅,原因在于SDK API中的Activitylibgdx中的AndroidApplication的初始化机制不完全一样,比如AndroidApplication OnCreate()方法中就要调用initialize()方法加载Gdx,而只有在加载了Gdx后ApplicationListener才能正常工作,因此libgdx需要做额外的工作,这样一来,切换就出现了不流畅的情况,游戏讲究的就是用户的体验,显然对于现在苛刻的用户来说这是不能接受的。



       下面就是这第五讲的重点内容,讲述如何使用libgdx中的多游戏容器机制来在同一个AndroidApplication下进行多界面的切换,首先先给大家吃一个定心丸,用Libgdx的多界面机制切换的速度很流畅,对比之下比将SDK和libgdx混用(就像上面那样)要快得多,自然的多。


      要使用libgdx中的多游戏界面,我们不得不先回顾一下libgdx中的游戏框架,还记得我在第二讲中画过的一个图吗?

第二讲:libgdx游戏引擎教程() ApplicationListener,着手第一个程序


       也就是说,我们一开始都是新建一个AndriodApplication然后调用initialize()方法启动一个实现了ApplicationListener的实例即进入了libgdx的周期。因此一个ApplicationListener就好像是一个游戏容器,一个容器就是一个游戏界面,我们在这个游戏界面中进行着各种操作,可是当我们必须要切换界面的时候怎么办呢?毕竟所有的绘制和逻辑工作都放在一个界面里未免太麻烦了。既然一个ApplicationListener就是一个游戏容器,那么我们能不能让一个AndroidApplication管理多个ApplicationListener呢?事实证明这个思路是完全正确的。



       Libgdx正是用这个方法实现多界面切换的。首先我们需要看看libgdx中的API中给我们提供的两个类,GameScreen
首先看一看Game这个类。官方文档中的解释如下:

public abstract class Gameextends java.lang.Objectimplements ApplicationListener
看看它的方法:



        我们看到其实一个Game就是一个实现了ApplicationListener接口的虚类,它有所有ApplicationListener的方法,也就是说,它也可以用AndroidApplication的initialize()方法启动,那又怎么做到多界面的切换呢?我们可以看到其中有一个setScreen()方法,没错,我们就是用这个setScreen()方法进行切换。具体切换会在第六讲中演示。

我们再看看Screen类。

  public interface Screen

同样看看它的方法  




       我们发现,Screen是一个接口,就像我们直接实现ApplicationListener一样,它也有dispose(),pause()render()方法,但是它还多了hide()show()等方法(顾名思义,就是在显示和隐藏时分别调用)。现在大家应该已经明白一些了,那么我们再用一张图来表示,相信大家就更明白了:





      倚天一出,谁与争锋啊。此图一出,一切都明白了。解决方案就是在AndroidApplication中持有一个GameGame中持有一个或者多个Screen,然后initialize方法中的第一个参数传入这个Game,在需要切换屏幕的时候调用GamesetScreen()方法就可以了。



我们先要自定义一个Game,因为Game是虚类必须继承后才能使用。
  1. public class ApplicationGame extends Game {
  2.     private Screen sc;
  3.     public void create() {
  4.        // TODO Auto-generated method stub
  5.        setScreen(sc);
  6.     }

  7.     public ApplicationGame(Screen sc) {
  8.        super();
  9.        this.sc=sc;
  10.        // TODO Auto-generated constructor stub
  11.     }

  12.     @Override
  13.     public void resume() {
  14.        // TODO Auto-generated method stub
  15.        super.resume();
  16.     }
  17.    
  18. }
复制代码
       我们在构造函数中传入了一个Screen,并在Game初始化的时候将这个Screen用setScreen置为当前屏幕,这一步必不可少哦。

       我们重新把Manifest.xml文件修改一下,把启动Activity从ActivityForSwitch(SDK中的API)重新换成Libgdx,至于这个ActivityForSwitch的类我们依然让它保留,并在Manifest中保留注册。
和上面那个相比改动很小,就是更改了启动Activity
  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2.     package="edu.nju.wsj.libgdx"
  3.     android:versionCode="1"
  4.     android:versionName="1.0" >

  5.     <uses-sdk
  6.         android:minSdkVersion="7"
  7.         android:targetSdkVersion="15" />

  8.     <application
  9.         android:icon="@drawable/ic_launcher"
  10.         android:label="@string/app_name"
  11.         android:theme="@style/AppTheme" >
  12.         <activity
  13.             android:name="edu.nju.wsj.libgdx.LibgdxActivity"
  14.             android:screenOrientation="landscape"
  15.             android:configChanges="keyboardHidden|orientation"
  16.             android:label="@string/title_activity_main" >
  17.             <intent-filter>
  18.                 <action android:name="android.intent.action.MAIN" />

  19.                 <category android:name="android.intent.category.LAUNCHER" />
  20.             </intent-filter>
  21.         </activity>
  22.          <activity
  23.             android:screenOrientation="landscape"
  24.             android:configChanges="keyboardHidden|orientation"
  25.             android:name=".ActivityForSwitch" >
  26.         </activity>
  27.     </application>

  28. </manifest>
复制代码

       然后我们需要修改Progress.java,让其不再直接继承ApplicationListener,转而实现Screen接口,并根据Screen中的方法对初始化代码做出相应的调整。其中最主要的调整在于,原来的Progress继承自ApplicationListener,它有create()方法,而修改后的Progress没有create()方法,只有show()方法,其实意思是比较相近的,所以我们把原来的create()方法中的代码直接复制到show()方法中就可以了。其它的方法基本都不用做修改。
  1. public class Progress implements Screen{
  2.     ProgressBar bar;
  3.     AnimalActor animal;
  4.     Stage stage;
  5.     AssetManager manager;
  6.     boolean hasini;
  7.     @Override
  8.     public void hide() {
  9.        // TODO Auto-generated method stub
  10.       
  11.     }

  12.     @Override
  13.     public void render(float arg0) {
  14.        // TODO Auto-generated method stub
  15.        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
  16.        Gdx.gl.glClearColor(1f,1f,1f,0f);
  17.        stage.act(Gdx.graphics.getDeltaTime());
  18.        stage.draw();
  19.        if(!manager.update()){
  20.            bar.setProgress(manager.getProgress()*100);
  21.        }
  22.        //加载完成且之前没有初始化过AnimalActor,且在手触摸屏幕时初始化AnimalActor,并将进度条从舞台中移除,并加入AnimalActor对象
  23.        if(!hasini&&manager.update()){
  24.            bar.setProgress(100);
  25.            if(Gdx.input.isTouched()){
  26.            stage.removeActor(bar);
  27.            animal.iniResource();
  28.            stage.addActor(animal);
  29.            hasini=true;
  30.            }
  31.        }
  32.        //我们做一个标记,看看未加载(Queued)完成的资源和已加载完成的资源的数量(Loaded)
  33.        if(!manager.update()){
  34.        System.out.println("QueuedAssets:"+manager.getQueuedAssets());
  35.        System.out.println("LoadedAssets:"+manager.getLoadedAssets());
  36.        System.out.println("Progress:"+manager.getProgress());
  37.        }
  38.     }
  39.     @Override
  40.     public void resize(int arg0, int arg1) {
  41.        // TODO Auto-generated method stub
  42.       
  43.     }
  44.     @Override
  45.     public void resume() {
  46.        // TODO Auto-generated method stub
  47.       
  48.     }
  49.     @Override
  50.     public void show() {
  51.        // TODO Auto-generated method stub
  52.        bar=new ProgressBar(0,0);
  53.        //新建一个舞台
  54.        stage=new Stage(Gdx.graphics.getWidth(),Gdx.graphics.getHeight(), true);
  55.        stage.addActor(bar);
  56.        //记得初始化一下AssetManager实例
  57.        manager=new AssetManager();
  58.        //传入AssetManger的引用,便于animal的资源初始化,但是注意了,只有在调用iniResourse()后资源才被初始化
  59.        animal=new AnimalActor(manager);
  60.        //把资源加入加载列表,这里我放了一个29帧的动画,在asset文件夹下animal下有29张图片
  61.        for(int i=1;i<30;i++){
  62.            manager.load("animal/"+i+".png", Texture.class);
  63.        }
  64.     }



  65.     @Override
  66.     public void dispose() {
  67.        // TODO Auto-generated method stub
  68.        //同样的,在结束时释放资源
  69.        bar.dispose();
  70.        animal.dispose();
  71.        manager.clear();
  72.        manager.dispose();
  73.     }

  74.     @Override
  75.     public void pause() {
  76.        // TODO Auto-generated method stub

  77.     }


  78. }

  79. 我们最后需要修改LibgdxActivity(AndriodApplication)中的代码,从直接initialize()一个Progress改为initialize()一个Game,这个Game持有一个Screen,即修改过后的Progress类。

  80. public class LibgdxActivity extends  AndroidApplication {
  81.     Progress progress;
  82.     ApplicationGame ag;
  83.     @Override
  84.     public void onCreate(Bundle savedInstanceState) {
  85.         super.onCreate(savedInstanceState);
  86.         progress=new Progress();
  87.         ag=new ApplicationGame(progress);
  88.         initialize(ag, false);
  89.     }
  90. }
复制代码


然后我们运行程序,效果和第四讲的效果是完全一样的,但是内部的结构被我们完全修改过了。这里我为了方便,把所有的Activity包括libgdx中的AndroidApplication都在Manifest.xml中都强制设置成了横屏,大家注意一下就好。





       现在我们已经做好了准备进行多界面切换了,虽然现在还是单界面,只有Progress这一个Screen,但是我们距离多界面只有一步之遥了。欢迎大家继续支持!

API和libgdx混用的源码

修改构架准备实现多界面的源码



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

本帖子中包含更多资源

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

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

80

主题

495

帖子

6925

安币

码皇(巴士元老)

Rank: 8Rank: 8

发表于 2012-7-7 14:10:23 | 显示全部楼层
{:Music:}学习啦!

8

主题

111

帖子

726

安币

攻城狮

apkbus最高头衔

Rank: 3Rank: 3

QQ
发表于 2012-7-7 14:42:18 | 显示全部楼层
感谢楼主分享,
[img]http://e.hiphotos.bdimg.com/album/s%3D550%3Bq%3D90%3Bc%3Dxiangce%2C100%2C100/sign=aa7f9376d2160924d825a21ee43c44c7/5366d0160924ab188ba9151737fae6cd7b890b56.jpg?referer=a5838b80f403738d875d3912754

0

主题

6

帖子

9

安币

初级码农

Rank: 1

发表于 2012-7-7 18:14:52 | 显示全部楼层
顶一个~

0

主题

18

帖子

19

安币

初级码农

Rank: 1

发表于 2012-7-8 15:45:08 | 显示全部楼层
又更新了,顶楼主

0

主题

7

帖子

2

安币

初级码农

Rank: 1

发表于 2012-7-9 11:52:46 | 显示全部楼层
{:Skateboard:}

0

主题

12

帖子

21

安币

初级码农

Rank: 1

发表于 2012-7-9 17:46:56 | 显示全部楼层
讨厌逼我回复。。。{:Cupcake:}

30

主题

350

帖子

1089

安币

Android大神

Rank: 6Rank: 6

QQ达人

 楼主| 发表于 2012-7-9 17:49:22 | 显示全部楼层
live17909 发表于 2012-7-9 17:46
讨厌逼我回复。。。

实在抱歉啦,不然帖子会沉掉...如果你要源码可以直接找我要的,就不用回复啦
君见一叶舟,出没风波里
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

扫一扫关注我们

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