第十五讲 :libgdx游戏引擎教程(十五)在Libgdx中仿微信帮助滑动效果(附源码)

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

 

 

下面提到的可视化版的libgdx图片打包工具:TexturePacker:

TexturePacker.rar(5.71 MB, 下载次数: 163)

2012-7-26 16:52 上传
点击文件名下载附件
下载积分: 下载豆 -2


本讲源代码下载:


edu.nju.wsj.libgdx.rar(4.41 MB, 下载次数: 285)

2012-7-26 16:52 上传
点击文件名下载附件
下载积分: 下载豆 -2




这一讲我们来尝试用Libgdx来实现 实现高仿launcher拖动效果。我们在第一次打开一个程序的时候总是会出现像这样的类似帮助的界面:
1.png
2012-7-26 16:39 上传
下载附件(97.21 KB)


2.png

2012-7-26 16:39 上传
下载附件(82.51 KB)


这样的界面可以用来提供用户操作帮助或者介绍软件新版本特性,现在越来越多的软件都加入了这样的界面。对于我们写游戏用的libgdx,当然我们可以用SDK中的ViewPager并置于一个Activity来实现这一功能(相当于前面我介绍过的AndroidApplication和Activity的混用),但是我在DDMS的内存监控中发现这种方法占用的内存比较多,对于我们游戏这种需要有严格内存管理的程序而言显然是不合算的,而且我前面也和大家提到过,在Libgdx中使用AndroidApplication和Activity混用的切换不是非常流畅,所以我们需要用Screen来实现同样的功能
本讲的代码在十四讲的基础上进行修改,首先我们需要再添加一个按钮,用于进入我们将要编写的一个仿Launcher的Screen里面。另外我们将这个AndroidApplication在Manifest中从强制横屏改为强制竖屏,方便显示,不过这样的话我们曾经加入的Dialog显示就不太正确了,大家可以自行修改。



 

3.png
2012-7-26 16:39 上传
下载附件(36.67 KB)
画红圈的就是我们新加入的按钮。然后我们新建一个Screen,用来仿launcher滑动的效果,初步工作我就在下面直接贴出来,后面复杂的工作我们再一步步来,重要的地方我都在里面做好了注释。这里使用了TexturePacker工具将几张图片打包然后一次性载入,具体如何使用大家可以查看官方文档或者查看巴士内一篇帖子:


 


我用这个可视化工具打包这次我们要用的图片:

未命名.jpg

2012-7-26 16:51 上传
下载附件(313.65 KB)





这里建议大家用可视化版本的,极其方便,我会在附件中上传。
  1. public class PagerScreen implements GestureListener, Screen,InputProcessor{
  2. TextureAtlas pager;
  3. SpriteBatch batch;
  4. //只有在第一次启动的时候需要将资源初始化
  5. boolean hasini;
  6. TextureRegion[] pages;
  7. LibgdxActivity activity;
  8. //用来存储长和宽的值
  9. int min;
  10. int max;
  11. //用来标记第一张图片的位置,可以为负,无法显示的部分就不会被画出
  12. int position;
  13. //循环遍历用
  14. int i;

  15. @Override
  16. public void dispose() {
  17. // TODO Auto-generated method stub

  18. }

  19. @Override
  20. public void hide() {
  21. // TODO Auto-generated method stub

  22. }

  23. @Override
  24. public void pause() {
  25. // TODO Auto-generated method stub

  26. }

  27. @Override
  28. public void render(float arg0) {
  29. // TODO Auto-generated method stub
  30. Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
  31. Gdx.gl.glClearColor(0f,0f,0f,0f);
  32. batch.begin();
  33. for(i=0;i<pages.length;i++)
  34. batch.draw(pages[i],position+i*min, 0,min,max);
  35. batch.end();
  36. }

  37. @Override
  38. public void resize(int arg0, int arg1) {
  39. // TODO Auto-generated method stub

  40. }

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

  44. }

  45. public PagerScreen(LibgdxActivity activity) {
  46. super();
  47. this.activity=activity;
  48. // TODO Auto-generated constructor stub
  49. }

  50. @Override
  51. public void show() {
  52. // TODO Auto-generated method stub
  53. max=Gdx.graphics.getHeight()>Gdx.graphics.getWidth()?Gdx.graphics.getHeight():Gdx.graphics.getWidth();
  54. min=Gdx.graphics.getHeight()<Gdx.graphics.getWidth()?Gdx.graphics.getHeight():Gdx.graphics.getWidth();
  55. if(!hasini){
  56. batch=new SpriteBatch();
  57. //这里使用了TexturePacker工具将几张图片打包然后一次性载入,具体如何使用大家可以查看官方文档。
  58. pages=new TextureRegion[5];
  59. pager=new TextureAtlas(Gdx.files.internal("pack"));
  60. pages[0]=pager.findRegion("1");
  61. pages[1]=pager.findRegion("2");
  62. pages[2]=pager.findRegion("3");
  63. pages[3]=pager.findRegion("4");
  64. pages[4]=pager.findRegion("5");
  65. hasini=true;
  66. }
  67. //将当前Screen加入按键和手势监听队列
  68. InputMultiplexer multiplexer = new InputMultiplexer();
  69. multiplexer.addProcessor(this);
  70. multiplexer.addProcessor(new GestureDetector(this));
  71. Gdx.input.setInputProcessor(multiplexer); }

  72. @Override
  73. public boolean fling(float arg0, float arg1) {
  74. // TODO Auto-generated method stub
  75. return false;
  76. }

  77. @Override
  78. public boolean longPress(int arg0, int arg1) {
  79. // TODO Auto-generated method stub
  80. return false;
  81. }

  82. @Override
  83. public boolean pan(int arg0, int arg1, int arg2, int arg3) {
  84. // TODO Auto-generated method stub
  85. return false;
  86. }

  87. @Override
  88. public boolean pinch(Vector2 arg0, Vector2 arg1, Vector2 arg2, Vector2 arg3) {
  89. // TODO Auto-generated method stub
  90. return false;
  91. }

  92. @Override
  93. public boolean tap(int arg0, int arg1, int arg2) {
  94. // TODO Auto-generated method stub
  95. return false;
  96. }

  97. @Override
  98. public boolean touchDown(int arg0, int arg1, int arg2) {
  99. // TODO Auto-generated method stub
  100. return false;
  101. }

  102. @Override
  103. public boolean zoom(float arg0, float arg1) {
  104. // TODO Auto-generated method stub
  105. return false;
  106. }

  107. @Override
  108. public boolean keyDown(int arg0) {
  109. // TODO Auto-generated method stub
  110. //返回键按下的时候返回上一界面
  111. if(arg0==Input.Keys.BACK)
  112. activity.ag.setScreen(activity.mg);
  113. return false;
  114. }

  115. @Override
  116. public boolean keyTyped(char arg0) {
  117. // TODO Auto-generated method stub
  118. return false;
  119. }

  120. @Override
  121. public boolean keyUp(int arg0) {
  122. // TODO Auto-generated method stub
  123. return false;
  124. }

  125. @Override
  126. public boolean scrolled(int arg0) {
  127. // TODO Auto-generated method stub
  128. return false;
  129. }

  130. @Override
  131. public boolean touchDown(int arg0, int arg1, int arg2, int arg3) {
  132. // TODO Auto-generated method stub
  133. return false;
  134. }

  135. @Override
  136. public boolean touchDragged(int arg0, int arg1, int arg2) {
  137. // TODO Auto-generated method stub
  138. return false;
  139. }

  140. @Override
  141. public boolean touchMoved(int arg0, int arg1) {
  142. // TODO Auto-generated method stub
  143. return false;
  144. }

  145. @Override
  146. public boolean touchUp(int arg0, int arg1, int arg2, int arg3) {
  147. // TODO Auto-generated method stub
  148. return false;
  149. }

  150. }
复制代码
设置MyGame.java中新加入的按钮被按下时启动这个 Screen,具体代码稍作修改大家可以看源码:
  1. toPager = new Button( new ButtonStyle(n1, n2, n3, 0f, 0f, 0f, 0f), "Start");
  2. toPager.setClickListener(new ClickListener() {

  3. @Override
  4. public void click(Actor arg0, float arg1, float arg2) {
  5. // TODO Auto-generated method stub
  6. activity.ag.setScreen(activity.ps);
  7. }
  8. });
  9. toPager.x=Gdx.graphics.getWidth()/3;
  10. toPager.y=Gdx.graphics.getWidth()/3;
  11. stage.addActor(toPager);
复制代码
运行一下,并按下刚才我们加入的那个按钮,看看效果:


4.png

2012-7-26 16:39 上传
下载附件(155.93 KB)




这时候我们还是不能翻动。我们这个Screen还实现了GestureListener这个接口,我们在pan()函数中监听手势翻动作用,并且做出相应的处理.我们考虑一下极端情况,用于标记第一张图片位置的变量position最大值无非就是0,显示后面的图片的时候,这张图片的位置左移,其值一定小于0,但是又不能小于一定值,position的最小值对应于最后一张图片在最右侧并且无法继续右移。下面要用到这个范围,不然会出很严重的问题。



 

再介绍一下pan()这个回调函数中的四个参数:
  1. public boolean pan(int arg0, int arg1, int arg2, int arg3);
复制代码
前两个参数指的是当前触摸点的x,y值,后两个标记当前用户手指的分别在x,y方向的移动速度。这里我们只用第一个参数x。简单的原理如下:用户的每次手势都会触发touchDown()方法,我们在touchDown()中存储当前按下的位置的x值,然后滑动手势开始后我们不停更新前一个位置,并且将position的大小做出相应的改变,改变量为当前位置的x值减去前一个位置的x值。我们先在PageScreen.java中添加相应的标记当前触摸点和上一个触摸点的x值的变量。
  1. float prex;
  2. float currentx;
复制代码
在touchDown()函数中标记currentx:
  1. currentx=arg0;
复制代码
在pan()函数中做出相应的处理,当然首先应该满足我们上面提到过的,postion有最大值和最小值,不可能超过这个范围,这一点非常重要。
  1. @Override
  2. public boolean pan(int arg0, int arg1, int arg2, int arg3) {
  3. // TODO Auto-generated method stub
  4. //position应该有一定的范围
  5. System.out.println(position);
  6. if(position<=0&&position>=-(pages.length-1)*min){
  7. prex=currentx;
  8. currentx=arg0;
  9. if(position+currentx-prex<=0&&position+currentx-prex>=-(pages.length-1)*min)
  10. position+=currentx-prex;
  11. else{
  12. if(position+currentx-prex>0)
  13. position=0;
  14. if(position+currentx-prex<-(pages.length-1)*min)
  15. position=-(pages.length-1)*min;

  16. }
  17. }
  18. return false;
  19. }

复制代码
运行一下,看看效果 :


5.png

2012-7-26 16:39 上传
下载附件(144.18 KB)



我们发现,完全可以正常滑动了,不过还有一个小问题,整个页面的显示完全依赖我们的滑动,而不是像我们需要仿的Launcher滑动有个自动吸附的功能,也就是当滑动到一定程度的时候会自动跳转到下一个页面。因此我们还需要做进一步的处理 这里我们认为一张图片翻过一半的时候就应该跳转到下一张图片。我们在render()函数中实现这个效果,在手指按下的时候不回弹,手指松开后进行回弹的动作。我们需要在PageScreen.java中添加一个变量,用于回弹的标记:
  1. float targetposition;
复制代码
修改后的render()函数如下,复杂的地方下面都做了注释:
  1. @Override
  2. public void render(float arg0) {
  3. // TODO Auto-generated method stub
  4. Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
  5. Gdx.gl.glClearColor(0f,0f,0f,0f);
  6. batch.begin();
  7. for(i=0;i<pages.length;i++)
  8. batch.draw(pages[i],position+i*min, 0,min,max);
  9. batch.end();
  10. //用户放手时才进行回弹
  11. if(!Gdx.input.isTouched()){
  12. //巧妙的用一个取整数的函数来表示一张图片翻过一半的时候就应该跳转到下一张图片的效果
  13. targetposition=(int)((position-0.5f*min)/min)*min;
  14. if(targetposition<position){
  15. //注意不能越界,min/480f是一个因子,用于分辨率适配,让回弹速度和分辨率搭配得协调一些
  16. if(position-20*min/480f<targetposition)
  17. position=targetposition;
  18. else
  19. position-=20*min/480f;
  20. }
  21. if(targetposition>position)
  22. //注意不能越界
  23. if(position+20*min/480f>targetposition)
  24. position=targetposition;
  25. else
  26. position+=20*min/480f;
  27. }
  28. }
复制代码
运行一下:


6.png

2012-7-26 16:39 上传
下载附件(143.67 KB)




功能完全正常效果也不错,而且由于使用了Screen实现,在切换界面的时候非常流畅,我们可以用它来实现libgdx游戏中的帮助效果。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值