#Testin杯#Mkey libgdx游戏引擎教程(九)libgdx中的用户手势识别(二)附源码

76
回复
637786
查看
  [复制链接]

30

主题

350

帖子

1089

安币

Android大神

Rank: 6Rank: 6

QQ达人

发表于 2012-7-15 11:53:49 | 显示全部楼层 |阅读模式
本帖最后由 耒佲請ぁ留埗 于 2012-8-3 11:34 编辑


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

第一讲: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中提供了一个手势检测的类:GestureDetector
ClassGestureDetector

java.lang.Object
  |com.badlogic.gdx.InputAdapter
      |com.badlogic.gdx.input.GestureDetector  


All ImplementedInterfaces:
InputProcessor
   可以看出GestureDetector实现了InputProcessor接口,我们在上一讲中已经给大家全面介绍了InputProcessor这个接口的原理和使用方法,并实际操作了一下,将我们曾经使用的按键捕捉方法(在一个Screenrender()方法内不停调用Gdx.input.isKeyPressed() )替换成了一个回调函数:
  1. @Override
  2.         public boolean keyDown(int arg0) {
  3.                 // TODO Auto-generated method stub
  4.                 //这里还要检测一下按键的类型
  5.                 if(arg0==Input.Keys.BACK){
  6.                         System.out.println("Back Pressed");
  7.                         activity.ag.setScreen(activity.mg);
  8.                         stage.removeActor(animal);
  9.                 }
  10.                 return false;
  11.         }
复制代码
    只要实现了InputProcessor接口,那么在系统接收到用户按键相应的时候系统就会自动调用这个函数,我们只要在这个函数中添加对应的处理代码就可以了,相比我们在render()函数中用代码去主动接收简单得多。


    现在终于要进入正题了,我们尝试使用GestureDetector来对用户的手势做出相应的响应。除却自定义的手势,常见的手势有哪些呢?

          我们来看看0.9.4API里面对 GestureDetector.GestureListener的介绍:



其中介绍了六个动作:
1.fliping 中文的理解和划页很类似,API中告诉我们,这个函数当用户用手在屏幕上拖拽并且做出翻页动作时触发。



2.longPressed 这个很好理解,就是手指的长按动作,用户做出长按动作的时候触发。



3.pinch 直接翻译过来的意思是收缩,其实就是一个多点触摸的手势,并且两个手指做出收缩的动作,为了解释方便,我画了一张图:




4.tap 就是轻击了,和触摸有点类似,不过速度应该比触摸快一些


5.TouchDown 也非常好理解,手指按下的一瞬间就触发,不管其后是什么其他的动作都会触发touchDown()方法,如果时间较短,在touchDown()后会触发tap()


6.zoom pinch对应,也是是一个多点触摸的手势,并且两个手指做出放大的动作


7.pan 和fliping比较类似,但是没有最后翻页的动作:



有了之前的介绍,相信大家已经大概明白了。我们实际尝试一下,代码在第八讲的基础上修改,让Progress.java实现 GestureDetector.GestureListener:

  1. public class Progress implements Screen,InputProcessor,GestureListener
复制代码
并添加相应的方法,GestureDetector.GestureListener需要实现的方法有以下几个(我们这里在每一段里面添加一个Log,便于我们查看系统相应的过程)。
  1. @Override
  2.         public boolean fling(float arg0, float arg1) {
  3.                 // TODO Auto-generated method stub
  4.                 Log.i("Testin-apkbus", "fling");
  5.                 return false;
  6.         }

  7.         @Override
  8.         public boolean longPress(int arg0, int arg1) {
  9.                 // TODO Auto-generated method stub
  10.                 Log.i("Testin-apkbus", "longPress");
  11.                 return false;
  12.         }

  13.         @Override
  14.         public boolean pan(int arg0, int arg1, int arg2, int arg3) {
  15.                 // TODO Auto-generated method stub
  16.                 Log.i("Testin-apkbus", "pan");
  17.                 return false;
  18.         }

  19.         @Override
  20.         public boolean pinch(Vector2 arg0, Vector2 arg1, Vector2 arg2, Vector2 arg3) {
  21.                 // TODO Auto-generated method stub
  22.                 Log.i("Testin-apkbus", "pinch");
  23.                 return false;
  24.         }

  25.         @Override
  26.         public boolean tap(int arg0, int arg1, int arg2) {
  27.                 // TODO Auto-generated method stub
  28.                 Log.i("Testin-apkbus", "tap");
  29.                 return false;
  30.         }

  31.         @Override
  32.         public boolean touchDown(int arg0, int arg1, int arg2) {
  33.                 // TODO Auto-generated method stub
  34.                 Log.i("Testin-apkbus", "touchDown");
  35.                 return false;
  36.         }

  37.         @Override
  38.         public boolean zoom(float arg0, float arg1) {
  39.                 // TODO Auto-generated method stub
  40.                 Log.i("Testin-apkbus", "zoom");
  41.                 return false;
  42.         }
复制代码
     最后还有一个工作一定不要忘了,我们要让系统能够监听手势动作,我们需要调用
  1. Gdx.input.setInputProcessor();
复制代码

     这里还有一个问题,GestureDetector.GestureListener并不是一个InputProcessor,我们需要封装一个GestureDetector(它是一个InputProcessor)并加入系统监听列表
  1. Gdx.input.setInputProcessor(new GestureDetector(this));
复制代码
     同样的,对于这里有多个对象需要捕捉用户触摸事件的情况(如Progress既实现了InputProcessor接口也实现了GestureDetecotor.Listener),我们实际中的语句如下:
  1. multiplexer.addProcessor(this);
  2.                 multiplexer.addProcessor(stage);
  3.                 multiplexer.addProcessor(new GestureDetector(this));
  4.                 Gdx.input.setInputProcessor(multiplexer);
复制代码
这就算是加入了手势捕捉的代码,具体的手势识别是由系统来识别的,我们只需要在识别后做处理就可以,是不是很方便?

    编译一下,运行,进入游戏界面(在代码层次是Progress.java),我们用手来做出各种手势,观察输出。




进入该界面后,用手做出各种手势。


我们一个个来,先做轻击Tap的动作,即速度较快的敲击一下,输出:


我轻击的速度比较快,因此我们可以看到两条输出,一条是标记触摸下TouchDown事件,另一条就是我们的Tap事件了。


其次我们来看看fliping,即划动翻页的动作。




    我们可以看到,除了一定会有的TouchDown()动作,还有几个pan动作也被识别到了,这也是很好理解的,我们一个flip的动作时间比较长,除了动作的最后一瞬间手做出了一个翻页的动作以外,我们的手都是在屏幕上进行拖拽,也就是pan动作了,因此如果我们要识别翻页的动作,我们要人为做进一步的处理,才能去除一些干扰。

    剩下就是zoom和pinch这一对动作了,我们再来看看这两个动作时的输出,这一次的输出比较多,大家要注意看我下面的分析了



     首先是两个ToucDown的动作,因为我们用两个手指才能做出缩放的手势。那为什么会有那么多的输出呢?想一想也能明白,我们的缩放过程是一个持续的过程,时间比较长,而且我们需要实时捕捉两个手指的位置获取它们之间的距离才能在代码中绘图并做出缩放的效果,所以系统才会不停地触发这两个事件而不是像其他动作那样只触发少数的几次。

    其他的手势都很好处理,这里我们主要实践并演示一下缩放手势zoom和pinch的处理,这也是我们在游戏中经常用到的一个手势。

我们来看看这两个回调函数:
  1. boolean pinch(Vector2 initialFirstPointer, Vector2 initialSecondPointer, Vector2 firstPointer, Vector2 secondPointer)

  2. boolean zoom(float originalDistance, float currentDistance)
复制代码
    其中pinch()方法中用到了一个类,Vector2,我们从名字就可以看出来,这个类代表了一个二维矢量,不过我们可以更简单的理解为Vector2就是一个点,里面有x,y两个坐标。回调函数pinch()里有四个Vector2对象,分别代表动作开始时的两个手指的位置和当前两个手指的位置      

    同理对于zoom()方法也是一样,回调函数里面传入了两个参数,一个是动作开始时两个手指的距离,第二个参数就是当前两个手指之间的距离。    
  
     其实我们可以看出,pinch()方法比zoom()方法更全面,因为我们在pinch()方法中得到的是点的坐标,也可以转化成zoom()中的距离。    

   既然pinch()zoom()成对出现,那么我们在两个函数中任意一个做处理都是可以的。接下来我们做一个简单的功能,用手指实现舞台stage上的Animal的大小的缩放。     我们在AnimalActor.java中添加一个float变量power,标记缩放的倍数,初始值为1.0
  1. //标记AnimalActor的缩放倍数
  2.         float power=1;
复制代码
   
然后我们将AnimalActordraw()函数中绘图部分的参数乘以power:
  1. public void draw(SpriteBatch arg0, float arg1) {
  2.                 // TODO Auto-generated method stub
  3.                 stateTime += Gdx.graphics.getDeltaTime();
  4.                 //得到下一帧
  5.                 currentFrame = animation.getKeyFrame(stateTime, true);
  6.                 //以(0,0)绘制为起点(左下角为0,0)画出动画,大小128*128
  7.                 arg0.draw(currentFrame,0, 0,128*power,128*power);
  8.         }
复制代码
   
然后我们在Progress.javazoom()函数中实时修改AnimalActor的power值
  1. @Override
  2.         public boolean zoom(float arg0, float arg1) {
  3.                 // TODO Auto-generated method stub
  4.                 Log.i("Testin-apkbus", "zoom");
  5.                 animal.power=arg1/arg0;
  6.                 return false;
  7.         }
复制代码
运行看一下效果,我们用两个手指做一个放大的动作,看看效果吧:


放大的效果




我们再将它缩小



      我们借助GestureDector还可以做出更复杂的手势识别,这里只是简单地演示一下,还要大家在平时的使用中多多尝试,就能开发出优秀的手势识别的游戏,提高游戏与用户之间的交互能力。


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

本帖子中包含更多资源

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

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

2826

主题

7684

帖子

9586

安币

管理员

Rank: 9Rank: 9Rank: 9

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

QQ
发表于 2012-7-15 22:13:14 | 显示全部楼层
居然没人沙发!!!!!

30

主题

350

帖子

1089

安币

Android大神

Rank: 6Rank: 6

QQ达人

 楼主| 发表于 2012-7-15 22:16:32 | 显示全部楼层
chino 发表于 2012-7-15 22:13
居然没人沙发!!!!!

今天有个人和我说...说我写教程就和讲评书一样...一到精彩的地方就要等到下一讲...让我羞愧难当啊{:4_137:}
君见一叶舟,出没风波里

0

主题

46

帖子

171

安币

程序猿

Rank: 2

发表于 2012-7-16 08:18:52 | 显示全部楼层
哦,是我说的,呵呵

0

主题

59

帖子

120

安币

程序猿

Rank: 2

发表于 2012-7-16 10:29:19 | 显示全部楼层
手势讲的灰常好,受教了。。。。。

0

主题

59

帖子

120

安币

程序猿

Rank: 2

发表于 2012-7-16 15:11:58 | 显示全部楼层
楼主讲的很好,我一直在等你的更新哦!。。。。不会断更了吧

30

主题

350

帖子

1089

安币

Android大神

Rank: 6Rank: 6

QQ达人

 楼主| 发表于 2012-7-16 15:14:46 | 显示全部楼层
xlwar 发表于 2012-7-16 15:11
楼主讲的很好,我一直在等你的更新哦!。。。。不会断更了吧

{:Nose:}我错了...今天的还没开始写....不过应该要有一讲....对接下来讲哪方面的内容有没有什么建议?
君见一叶舟,出没风波里

0

主题

9

帖子

20

安币

初级码农

Rank: 1

发表于 2012-7-16 16:03:44 | 显示全部楼层
感谢分享
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

扫一扫关注我们

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