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

143
回复
685438
查看
  [复制链接]

30

主题

350

帖子

1089

安币

Android大神

Rank: 6Rank: 6

QQ达人

发表于 2012-7-17 18:06:54 | 显示全部楼层 |阅读模式
本帖最后由 耒佲請ぁ留埗 于 2012-8-3 11:37 编辑


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

第一讲: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




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



     本讲是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的方法有一个我们很是熟悉:




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




画出红线的部分,大家可以看到,我们对于某一个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作为弹出的对话框:




我解释一下,被对话框遮住的部分是一个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:


我们首先在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.                         }
  15.                         return false;
  16.                 }
复制代码


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

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

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



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






这样对话框算是出来了,我们再按一下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);
复制代码
然后我们运行一下,并让对话框弹出。





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





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






现在大家应该明白了,所谓的初始位置(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.                                 
  7.                                 @Override
  8.                                 public void click(Actor arg0, float arg1, float arg2) {
  9.                                         // TODO Auto-generated method stub
  10.                                         //关闭程序
  11.                                          activity.finish();
  12.                                          android.os.Process.killProcess(android.os.Process.myPid());
  13.                                 }
  14.                         });
  15.                         cancel=new Button(new TextureRegion(new Texture(Gdx.files.internal("cancel.png")), 160, 80));
  16.                         cancel.x=360;
  17.                         cancel.y=60;
  18.                         cancel.setClickListener(new ClickListener() {
  19.                                 
  20.                                 @Override
  21.                                 public void click(Actor arg0, float arg1, float arg2) {
  22.                                         // TODO Auto-generated method stub
  23.                                         //移除对话框
  24.                                         stage.removeActor(dialog);
  25.                                         hasdialog=false;
  26.                                 }
  27.                         });
  28.                         dialog.addActor(ok);
  29.                         dialog.addActor(cancel);
复制代码
来看看运行的结果(这次只对800*480分辨率做了一个适配,其他的机型可能显示不太正确)




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


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

本帖子中包含更多资源

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

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

2826

主题

7684

帖子

9561

安币

管理员

Rank: 9Rank: 9Rank: 9

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

QQ
发表于 2012-7-18 11:59:33 | 显示全部楼层
沙发居然没人要,今天仔细看了帖子,,不错哈!!

30

主题

350

帖子

1089

安币

Android大神

Rank: 6Rank: 6

QQ达人

 楼主| 发表于 2012-7-18 12:01:58 | 显示全部楼层
chino 发表于 2012-7-18 11:59
沙发居然没人要,今天仔细看了帖子,,不错哈!!

写的太多都招人烦了{:Cry:}
君见一叶舟,出没风波里

2826

主题

7684

帖子

9561

安币

管理员

Rank: 9Rank: 9Rank: 9

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

QQ
发表于 2012-7-18 12:04:34 | 显示全部楼层
耒佲請ぁ留埗 发表于 2012-7-18 12:01
写的太多都招人烦了

其实没有哈,你写的这一系列非常不错哈!!!加油哦!!我还准备 到时候跟另外一个哥们写的一系列做个 游戏开发专题的呢!!!

30

主题

350

帖子

1089

安币

Android大神

Rank: 6Rank: 6

QQ达人

 楼主| 发表于 2012-7-18 12:10:22 | 显示全部楼层
chino 发表于 2012-7-18 12:04
其实没有哈,你写的这一系列非常不错哈!!!加油哦!!我还准备 到时候跟另外一个哥们写的一系列做个 游 ...

哈哈~听了这句话好开心!当初就打算这个教程会一直写下去....说不定要个五六十篇呢...{:Jump:}
君见一叶舟,出没风波里

2826

主题

7684

帖子

9561

安币

管理员

Rank: 9Rank: 9Rank: 9

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

QQ
发表于 2012-7-18 13:22:30 | 显示全部楼层
耒佲請ぁ留埗 发表于 2012-7-18 12:10
哈哈~听了这句话好开心!当初就打算这个教程会一直写下去....说不定要个五六十篇呢... ...

现在会搞开发,还会写东西的人太少了!!!加油哦!!!巴士准备出书的呢,记下你了!!!

0

主题

46

帖子

171

安币

程序猿

Rank: 2

发表于 2012-7-18 18:26:52 | 显示全部楼层
一直在等新文章呢

0

主题

21

帖子

47

安币

初级码农

Rank: 1

发表于 2012-7-18 21:22:09 | 显示全部楼层
写的确实不错,反正每一节都有新东西
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

联系我们
关闭
合作电话:
15618560077
Email:
805941275@qq.com
商务市场合作/投稿
问题反馈及帮助
联系我们
领先的中文移动开发者社区
18620764416
7*24全天服务
意见反馈:1294855032@qq.com

扫一扫关注我们

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