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

来源:互联网 发布:淘宝秒杀图片大全 编辑:程序博客网 时间:2024/04/29 06:31

转自:http://www.apkbus.com/android-57936-1-1.html

 

今天是#Testin杯#Mkey libgdx教程的第五讲,在第二讲我就曾经对大家承诺过写一个关于Libgdx内多屏幕显示的内容,可是我脑子一时糊涂竟然忘了这事,这里向大家道歉,今天这一讲我们就来八一八libgdx中的多游戏容器的实现。我在我的Libgdx教程中尽量给大家介绍一些实用的功能,至于那些libgdx API基本的使用方法则不过多侧重,想来大家通过查询API文档也能掌握。这里再提醒一下大家,API文档可以在官网上看到,也可以在下载下来的libgdx包中的docs下的index.html中查看。


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



 

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




 

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


 

http://www.apkbus.com/android-57355-1-1.html




 

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

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



 

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




 

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




 

这里有一点要注意,这里的Button是SDK API中的Button即android.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. public void onClick(View v) {
  11. // TODO Auto-generated method stub
  12. Intent intent=new Intent();
  13. intent.setClass(ActivityForSwitch.this,LibgdxActivity.class);
  14. ActivityForSwitch.this.startActivity(intent);
  15. }
  16. });

  17. }

  18. }
复制代码
顺带贴一下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),Button的Id设置为button1,然后设置一个监听器,在点击的时候由一个Intent跳转到LibgdxActivity,到底能不能成功启动呢?点击button,诶,成功跳转了哦。(这部分的代码将和后面的修改过的代码分成两个项目上传,便于大家对比效果)



 

Screenshot_2012-07-07-09-45-08.png
2012-7-7 11:28 上传
下载附件(50.09 KB)
Screenshot_2012-07-07-11-20-23.png
2012-7-7 11:28 上传
下载附件(25.55 KB)


Screenshot_2012-07-07-11-20-40.png

2012-7-7 11:28 上传
下载附件(35.88 KB)




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




 

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



 

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


 

第二讲:libgdx游戏引擎教程() ApplicationListener,着手第一个程序
http://www.apkbus.com/android-57372-1-2.html
未命名2.jpg
2012-7-7 11:32 上传
下载附件(61.73 KB)



 

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




 

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


public abstract classGameextends java.lang.ObjectimplementsApplicationListener

看看它的方法:


 

Game.jpg
2012-7-7 11:33 上传
下载附件(125.26 KB)



 

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


 

我们再看看Screen类。


public interfaceScreen

同样看看它的方法

methos.jpg
2012-7-7 11:33 上传
下载附件(106.24 KB)




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


Screen.jpg

2012-7-7 11:34 上传
下载附件(64.8 KB)




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




 

我们先要自定义一个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. }
复制代码
我们在构造函数中传入了一个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. @Override
  12. public void render(float arg0) {
  13. // TODO Auto-generated method stub
  14. Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
  15. Gdx.gl.glClearColor(1f,1f,1f,0f);
  16. stage.act(Gdx.graphics.getDeltaTime());
  17. stage.draw();
  18. if(!manager.update()){
  19. bar.setProgress(manager.getProgress()*100);
  20. }
  21. //加载完成且之前没有初始化过AnimalActor,且在手触摸屏幕时初始化AnimalActor,并将进度条从舞台中移除,并加入AnimalActor对象
  22. if(!hasini&&manager.update()){
  23. bar.setProgress(100);
  24. if(Gdx.input.isTouched()){
  25. stage.removeActor(bar);
  26. animal.iniResource();
  27. stage.addActor(animal);
  28. hasini=true;
  29. }
  30. }
  31. //我们做一个标记,看看未加载(Queued)完成的资源和已加载完成的资源的数量(Loaded)
  32. if(!manager.update()){
  33. System.out.println("QueuedAssets:"+manager.getQueuedAssets());
  34. System.out.println("LoadedAssets:"+manager.getLoadedAssets());
  35. System.out.println("Progress:"+manager.getProgress());
  36. }
  37. }
  38. @Override
  39. public void resize(int arg0, int arg1) {
  40. // TODO Auto-generated method stub

  41. }
  42. @Override
  43. public void resume() {
  44. // TODO Auto-generated method stub

  45. }
  46. @Override
  47. public void show() {
  48. // TODO Auto-generated method stub
  49. bar=new ProgressBar(0,0);
  50. //新建一个舞台
  51. stage=new Stage(Gdx.graphics.getWidth(),Gdx.graphics.getHeight(), true);
  52. stage.addActor(bar);
  53. //记得初始化一下AssetManager实例
  54. manager=new AssetManager();
  55. //传入AssetManger的引用,便于animal的资源初始化,但是注意了,只有在调用iniResourse()后资源才被初始化
  56. animal=new AnimalActor(manager);
  57. //把资源加入加载列表,这里我放了一个29帧的动画,在asset文件夹下animal下有29张图片
  58. for(int i=1;i<30;i++){
  59. manager.load("animal/"+i+".png", Texture.class);
  60. }
  61. }



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

  71. @Override
  72. public void pause() {
  73. // TODO Auto-generated method stub

  74. }


  75. }

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

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



 

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






 

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


API和libgdx混用的源码
edu.nju.wsj.libgdx(libgdx和SDK混用的demo).rar(3.52 MB, 下载次数: 177)

2012-7-7 11:45 上传
点击文件名下载附件
下载积分: 下载豆 -2


修改构架准备实现多界面的源码
edu.nju.wsj.libgd(多界面第一步)x.rar(3.52 MB, 下载次数: 287)

2012-7-7 11:45 上传
点击文件名下载附件
下载积分: 下载豆 -2




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

原创粉丝点击