本篇文章由PeterShen_Skysim所作,我转载到这里,如有疑问请点击原文和他交流~
刚尝试手势的时候我差点选择放弃,现在想想还是自己不好好看SDK,小心使得万年船啊。
五一不想断更的,实在是没办法,出去的急忘了带笔记本,只好断更。下午才回来,毕竟这种万年没休的也习惯这种生活方式了,反而出去溜达感到闲的蛋疼。
废话不多说,直接贴代码,这段代码实现的是在画圈停止后输出一个Gesture通知,代码很顺利,结果很粗糙。由于手部肌肉连带,食指动的时候必然中指也动,加上Leap“超凡的精确度”,导致动了右手食指,出来四胞胎结果——拇指,食指,中指,无名指。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
public override void OnFrame(Controller arg0) { Frame frame = arg0.Frame(); GestureList gestures = frame.Gestures(); for (int i = 0; i < gestures.Count; i++) { Gesture gesture = gestures[i]; switch (gesture.Type) { case Gesture.GestureType.TYPE_CIRCLE: CircleGesture circle = new CircleGesture(gesture); // Calculate clock direction using the angle between circle normal and pointable String clockwiseness; if (circle.Pointable.Direction.AngleTo(circle.Normal) <= Math.PI / 2) { //Clockwise if angle is less than 90 degrees clockwiseness = "clockwise"; } else { clockwiseness = "counterclockwise"; } float sweptAngle = 0; // Calculate angle swept since last frame if (circle.State != Gesture.GestureState.STATE_START) { CircleGesture previousUpdate = new CircleGesture(arg0.Frame(1).Gesture(circle.Id)); sweptAngle = (circle.Progress - previousUpdate.Progress) * 360; } if(circle.State==Gesture.GestureState.STATE_STOP) Console.WriteLine(" Circle id: " + circle.Id + ", " + circle.State + ", progress: " + circle.Progress + ", radius: " + circle.Radius + ", angle: " + sweptAngle + ", " + clockwiseness); break; } } } |
修改过一个小东西后,手势明显变得好用了,就是阈值。图上是检测Key_Tap时候的反馈数据,由于设定了min_distance,即最小移动检测阈值,反馈良好,基本不会出现误操作的问题。由此可见好好看SDK是多么重要啊!阈值参数表如下:
画圈手势
Gesture.Circle.MinRadius float5mm
Gesture.Circle.MinArc float1.5 * piradians
按键手势
Gesture.KeyTap.MinDownVelocity float50mm/s
Gesture.KeyTap.HistorySeconds float0.1s
Gesture.KeyTap.MinDistance float3mm
横扫手势
Gesture.Swipe.MinLength float150mm
Gesture.Swipe.MinVelocity float1000mm/s
触摸手势
Gesture.ScreenTap.MinForwardVelocity float50mm/s
Gesture.ScreenTap.HistorySeconds float0.1s
Gesture.ScreenTap.MinDistance float5mm
第一项为名称,第二项是数据类型(都是float),第三项是默认阈值大小,第四项是单位,csdn的表格有点不方便,然而对于一个写程序刚入门的,还去用dreamwaver编个表格粘到源码里,太麻烦,大家就这么一看,我就这么一画吧。修改阈值的方式也很简单:这里用Circle手势作为参考,修改了最小半径和最小角速度,然后记得保存。
1 2 3 |
controller.Config.SetFloat ("Gesture.Circle.MinRadius", 10.0f); controller.Config.SetFloat ("Gesture.Circle.MinArc", .5f); controller.Config.Save (); |
那么问题又来了,手势是对了,怎么知道是哪根指头操作的呢,不能玩第二根半价(权值选择不读)的游戏啊,肯定得想办法把所有指头都用上。想了两个办法,第一个操作一个Hand循环,采样手指名称,比如finger.type等于“TYPE_INDEX”是食指,是需要的的指头操作,测试发现问题了,因为是foreach fingers,所以只要手指头被检测到,就会被刷出来,第一种方案胎死腹中。第二个方案比较原始,即判断激发点和手指的位置是不是重合,但是由于Finger中并没有postion参数,只好想其他办法,不过下期一定贴代码!
另外,细心的朋友发现程序失焦后会不工作,这是Leap的一种保护机制,然而这种保护机制我给零分,明明应该是默认读取数据,我可以选择关闭,现在是默认关闭我可以选择打开,好吧,我服,其实就是加了一句话:
1 |
Controller.SetPolicy(Controller.PolicyFlag.POLICY_BACKGROUND_FRAMES); |
这样子程序就可以后台继续数据了,回来路上我还纳闷这个问题呢,心想不应该,实在不行创建个新进程单独走,然而SDK再一次告诉我想多了,好好看SDK,东西全在里面,写不出都是自己的问题。现在节奏快,巴不得什么东西都不学,一口吃成个大胖子,唉,急不得啊。
如果有朋友有finger和gesture匹配的解决方案,记得留言!