libgdx游戏引擎教程外篇(三) 优美的自定义对话框(附源码)

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

 

本讲源代码下载(我第一次居然忘了传,囧)

edu.nju.wsj.libgdx.rar(3.78 MB, 下载次数: 358)

2012-7-17 18:57 上传
点击文件名下载附件
下载积分: 下载豆 -2



 

本讲是Libgdx游戏教程的第十八篇,我将其作为外篇三来讲。大家都知道,被我作为外篇的某一讲,一定是一个新的部分的引子。今天我们来讲一讲libgdx中的另一个控件:Window类,随后我们在实战篇中将用到这个控件。


我们先来看看官方文档中对Window是如何解释的:

java.lang.Object
|com.badlogic.gdx.scenes.scene2d.Actor
|com.badlogic.gdx.scenes.scene2d.Group
|com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup
|com.badlogic.gdx.scenes.scene2d.ui.tablelayout.Table
|com.badlogic.gdx.scenes.scene2d.ui.Window




 

我们可以看到,其实Window就是一个Actor,也就是我们非常熟悉的演员类,但是这个演员类似乎又和一般的Actor不太一样,我们来看看Window这个类的不同之处(注意,这里的Window乃是com.badlogic.gdx.scenes.scene2d.ui.Window,而不是SDK中的Window类,请大家注意一下



 

我们从以上的继承树从上往下看,最初的继承是从Actor继承而来的Group,其实Group很好理解,就是一个Actor的集合,那为什么有了Actor类又要写一个Group类呢?其实很简单,在演员类Actor实例很多的情况下我们可以通过一个Group统一管理这个Group里所有Actor的行为,其实就是把整个Group看作一个Actor,集合里的所有Actor的某一行为都根据这个Group来统一制定


 

这里给大家科普一下,其实我们很早以前就接触了这个Group类,大家能猜到是在哪里吗?我们先来看看Group类的方法吧,当然,时刻牢记Group也是继承自Actor的,那么对于Group的一些行为和属性就很好理解了,我们下面来看它的比较特别的一些属性。



 

官方文档中Group的方法有一个我们很是熟悉:


1.jpg

2012-7-17 17:48 上传
下载附件(10.72 KB)




是不是明白了?我们在舞台类Stage中添加新的演员Actor用的也是addActor()方法。其实很简单,Stage中就封装了一个Group来统一管理加入该舞台中的众多Actor。其实不光是这里,我们从Actor类的成员变量中也可以看到Group的踪影:

2.PNG

2012-7-17 17:48 上传
下载附件(36.68 KB)




画出红线的部分,大家可以看到,我们对于某一个Actor取得其成员变量parent,就可以得到一个Group,其实就是代表这个Actor所在的Group



 

我们再从继承树的位置往下看,接下来是WidgetGroup,这个就不做过多解释了,其实也就是一个Group,一般用来装libgdx中的Widget小组件,当然这里的Widget也是继承自Actor,所以WigetGroup和Group也是一个意思,相信大家能够理解。


 

接下来的Table和Window也是一样的。对于Table,我们可以用SDK中的概念来理解,大家都知道Android SDK中有布局Layout的概念,大家对比一下TableLayout的概念就可以知道这里的Table大概的作用了,当然和TableLayout还是有本质的区别的,但是相同的就是libgdx中的Table和SDK 中的TableLayout都是用来装控件的


 


至于Window和Table的区别也不大,只是做了一些更具体的封装,更适合某些场合的使用。



 

现在我们做一个总结,Window继承自Group,也就是说它既可以单独作为一个控件显示在stage中,也可以在其中添加别的Actor然后一起显示出来,Window可以对它们做统一的管理



 

我们接下来就在第九讲的基础上继续修改源代码,并且用我们刚才说到的Window类写一个类似于SDK中的Dialog的对话框。



 

这里插一句话,事实上在Libgdx写的游戏中也是可以使用SDK中的AlertDialog,我这里就不在给出代码演示了,和我们用SDK编写程序时的使用方法是一样的,都在在需要弹出对话框的地方新建一个AlertDialog并弹出即可,下面我给大家看看我在我新写的一个游戏中就使用了AlertDialog作为弹出的对话框:


1.png

2012-7-17 17:48 上传
下载附件(239.68 KB)




我解释一下,被对话框遮住的部分是一个Screen,我们在这个Screen实现了InputProcessor,也就是我们在第八和第九讲中提到了的输入监听。然后我们按下Back键,就弹出一个对话框提示用户是否退出。这是一个SDK和libgdx混用的典型例子,我们在前面还提到过一个SDK和libgdx的混用的例子,就是Activity和AndroidApplication的混用。我们从这里可以看到,SDK和libgdx的混用并不是不可以的,而且有些地方会产生很不错的效果。



 

接下来我们尝试用libgdx中的Window类来实现相同的效果代码在第九讲的基础上进行修改,目的是用Window实现一个对话框并且实现退出提示的功能。



 

我们在Game.java类里新建一个Window对象:
  1. Window dialog;
复制代码
我们把需要的素材放到assets文件夹下,dialog.png,ok.png.cancle.png:


dialog.png

2012-7-17 17:48 上传
下载附件(60.13 KB)

ok.png

2012-7-17 17:48 上传
下载附件(15.73 KB)

cancel.png

2012-7-17 17:48 上传
下载附件(15.84 KB)


我们首先在show()函数中对dialog进行初始化:
  1. TextureRegion txr=new TextureRegion(new Texture(Gdx.files.internal("dialog.png")), 512, 256);
  2. dialog=new Window("dialog",new Window.WindowStyle(bf, new Color(), new NinePatch(txr)));
  3. //做一个简单的适配,乘以1.2是为了让图片显示出来的时候大一点
  4. dialog.width=512*1.2f*Gdx.graphics.getWidth()/800f;
  5. dialog.height=256*1.2f*Gdx.graphics.getWidth()/800f;
  6. //为了让图片保持居中
  7. dialog.x=(Gdx.graphics.getWidth()-dialog.width)/2;
  8. dialog.y=(Gdx.graphics.getHeight()-dialog.height)/2;
复制代码
其中的构造函数也很简单,大家可以参见官方文档。
我们再将这个dialog在按下BACK键的时候加入舞台,这样在render()函数中调用stage.draw()的时候才能将其一并绘制出来。
  1. @Override
  2. public boolean keyDown(int arg0) {
  3. // TODO Auto-generated method stub
  4. if(arg0==Input.Keys.BACK){
  5. if(!hasdialog){
  6. stage.addActor(dialog);
  7. hasdialog=true;
  8. }
  9. else{
  10. stage.removeActor(dialog);
  11. hasdialog=false;
  12. }

  13. }
  14. return false;
  15. }
复制代码



 

我们将这个功能添加在回调函数KeyDown中,这个函数是我们通过继承InputProcessor得来的。


 

这里我们用了一个boolean变量hasdialog标记当前是否有对话框dialog显示出来,防止重复添加,并且在没有对话框显示的时候按下返回键Back时对话框弹出,再按下Back时对话框消失,代码也很简单,相信大家能看懂。


 

我们来看看效果:
进入程序界面:

3.png

2012-7-17 17:48 上传
下载附件(24.78 KB)




到达这个界面后,我们按下Back返回键



4.png

2012-7-17 17:48 上传
下载附件(69 KB)





这样对话框算是出来了,我们再按一下BACK键,对话框消失。那么我们初步的Window的实现是没有问题的了,我们进行下一步的操作,添加对应的按钮,并做出相应的操作,比如确定并退出程序或者取消继续游戏。
还记得我们在这一讲的开始特意介绍了Window是从Group继承下来的,因此我们可以直接在这个Window里面添加其他的Actor,这里我们直接在这个dialog中添加两个Button(我们可以从官方文档中看出Libgdx中的Button也是继承自Actor)



 

我们先在Game.java中添加两个按钮:
  1. //对话框上的两个按钮
  2. Button ok;
  3. Button cancle;
复制代码
我们在show()函数中对它们进行初始化,当然我们这里为了简单起见,先只初始化了一个确定按钮并将其加入dialog这个Window内。
  1. ok=new Button(new TextureRegion(new Texture(Gdx.files.internal("ok.png")), 160, 80));
  2. dialog.addActor(ok);
复制代码
然后我们运行一下,并让对话框弹出。



6.png

2012-7-17 17:48 上传
下载附件(75.6 KB)




我们看到按钮已经被加在了Dialog里,不过好像还有一个问题,位置不太对?
这里还有一个很有意思的事情,大家可以看一看。
左下角的按钮我们也是没有设置过位置直接添加进stage的。所以这个按钮的位置应该是(0,0),我们可以看到位置确实是在(0,0)



5.png

2012-7-17 17:48 上传
下载附件(75.59 KB)




然后我们新建的一个Button ok,我们也没有指定它的位置,也就是说它的位置也应该是(0,0),那么为什么不在屏幕的左下角呢?我们再看下面这张图:



7.png

2012-7-17 17:48 上传
下载附件(73.75 KB)





现在大家应该明白了,所谓的初始位置(0,0)应该是相对持有这个Actor的父控件而言的,刚才说到的那个Button它的父控件是整个stage,因此它是在父控件的(0,0)处,而上面那个蓝色的确定按钮,它的父控件是dialog这个Window的实例,所以它的(0,0)是相对于这个dialog而言的。



 

这些东西其实也不难理解。我们接下来就直接一些,直接把两个按钮都添加上去,并摆好位置(这里我偷了个懒,只对800*480的分辨率进行了适配,用的是绝对坐标,大家可以在不同的分辨率上做出不同的适配,让显示起来更好看一点),并且设置相应的监听函数,这样可以让程序做出相应的响应。


 

直接贴代码了:
  1. ok=new Button(new TextureRegion(new Texture(Gdx.files.internal("ok.png")), 160, 80));
  2. ok.x=160;
  3. ok.y=60;
  4. //给ok这个按钮添加监听器
  5. ok.setClickListener(new ClickListener() {

  6. @Override
  7. public void click(Actor arg0, float arg1, float arg2) {
  8. // TODO Auto-generated method stub
  9. //关闭程序
  10. activity.finish();
  11. android.os.Process.killProcess(android.os.Process.myPid());
  12. }
  13. });
  14. cancel=new Button(new TextureRegion(new Texture(Gdx.files.internal("cancel.png")), 160, 80));
  15. cancel.x=360;
  16. cancel.y=60;
  17. cancel.setClickListener(new ClickListener() {

  18. @Override
  19. public void click(Actor arg0, float arg1, float arg2) {
  20. // TODO Auto-generated method stub
  21. //移除对话框
  22. stage.removeActor(dialog);
  23. hasdialog=false;
  24. }
  25. });
  26. dialog.addActor(ok);
  27. dialog.addActor(cancel);
复制代码
来看看运行的结果(这次只对800*480分辨率做了一个适配,其他的机型可能显示不太正确)

8.png

2012-7-17 17:48 上传
下载附件(83.62 KB)





对话框显示后按下确定程序退出,按下取消对话框消失,一切正常,这个对话框就算完成了今后我们就可以直接用它在Libgdx游戏中使用了。

 

展开阅读全文

没有更多推荐了,返回首页