2018/09/11
距离上一篇博客已经过去快两个月了,目前我的游戏已经基本上是算粗糙地开发完了,过了ican的校赛,正在准备市赛。
现在我接着上一篇继续往下写~
手势识别
如果按照上一篇的步骤安装好leap motion,就能够实现在空白的游戏场景中看到一双手,并且自己的手动起来,屏幕中的手也能一起动。那接下来最重要的就是进行手势识别。
leapmotion最厉害的地方在于手上的每一个关节,每一个骨头它都有很细致的关联,能够很轻易的获取角度,以及手掌的位置。这样在理论上就能够实现很多手势的识别(为什么说是理论上呢?后面会谈到嘎嘎)。那么像我这样的小白怎么可能会知道写呢?当然是thanks to the Internet~下面是完整的代码
using UnityEngine;
using Leap;
using Leap.Unity;
public class food_select : MonoBehaviour
{
public static bool Gesture_left = false;
public static bool Gesture_right = false;
public static bool Gesture_up = false;
public static bool Gesture_down = false;
public static bool Gesture_zoom = false;
public static float movePOs = 0.0f;
private LeapProvider mProvider;
private Frame mFrame;
private Hand mHand;
private Vector leftPosition;
private Vector rightPosition;
public static float zoom = 1.0f;
[Tooltip("Velocity (m/s) of Palm ")]
public float smallestVelocity = 1.45f;//手掌移动的最小速度
public float moveSpeed = 1f;
[Tooltip("Velocity (m/s) of Single Direction ")]
[Range(0, 1)]
public float deltaVelocity = 1.0f;//单方向上手掌移动的速度
// Use this for initialization
//控制物体后退
//public float w=0;
//Vector3 box_position;
public GameObject Obj;
void Start()
{
mProvider = FindObjectOfType<LeapProvider>() as LeapProvider;
// box_position = GetComponent<Transform>().position;
}
// Update is called once per frame
void Update()
{
mFrame = mProvider.CurrentFrame;//获取当前帧
//获得手的个数
// print("box1的位置" + box_position);
//print ("hand num are " + mFrame.Hands.Count);
if (mFrame.Hands.Count > 0)
{
if (mFrame.Hands.Count == 2)
zoom = CalcuateDistance(mFrame);
if (mFrame.Hands.Count == 1)
{
LRUDGestures(mFrame, ref movePOs);
}
}
}
float CalcuateDistance(Frame mFrame)
{
Gesture_zoom = true;
Gesture_left = false;
Gesture_right = false;
float distance = 0f;
//print ("Two hands");
foreach (var itemHands in mFrame.Hands)
{
if (itemHands.IsLeft)
{
leftPosition = itemHands.PalmPosition;
//print ("leftPosition" + leftPosition);
}
if (itemHands.IsRight)
{
rightPosition = itemHands.PalmPosition;
//print ("rightPosition" + rightPosition);
}
}
if (leftPosition != Vector.Zero && rightPosition != Vector.Zero)
{
Vector3 leftPos = new Vector3(leftPosition.x, leftPosition.y, leftPosition.z);
Vector3 rightPos = new Vector3(rightPosition.x, rightPosition.y, rightPosition.z);
distance = 10 * Vector3.Distance(leftPos, rightPos);
print("distance" + distance);
}
if (distance != 0)
return distance;
else
return distance = 1;
}
/*void OnCollisionEnter(Collision collision)
{if(ra.collider.tag=="Hand")
print ("手发生碰撞");
}*/
void LRUDGestures(Frame mFrame, ref float movePOs)
{
Gesture_zoom = false;
foreach (var item in mFrame.Hands)
{
int numFinger = item.Fingers.Count;
//print ("item is " + numFinger);
//print("hand are " + isOpenFullHand (item));
// print ("isOpenFullHands is " + isOpenFullHands(item));
if (item.GrabStrength == 1)
{
//print ("num is 0, gestures is woquan");
}
else if (item.GrabStrength == 0)
{
//print ("num is 5, open your hand");
//print("PalmVelocity" + item.PalmVelocity);
//print("PalmPosition" + item.PalmPosition);
movePOs = item.PalmPosition.x;
if (isStone(item))
{
Gesture_left = false;
Gesture_right = false;
print("握拳");
print("选中");
toBlue();
}
if (isGrabHand(item))
{
Gesture_left = false;
Gesture_right = false;
}
}
}
}
private bool isStone(Hand hand)
{
bool w = false;
w = hand.PalmPosition.x < -0.09f && hand.PalmPosition.x > -0.18f;
//print ("hand.GrabAngle" + hand.GrabAngle);
return hand.GrabAngle > 2.0f&&w;
}
//是否抓取
public bool isGrabHand(Hand hand)
{
return hand.GrabStrength > 0.8f; //抓取力
}
//hand move four direction
public bool isMoveRight(Hand hand)
{
return hand.PalmVelocity.x > deltaVelocity && !isStationary(hand);
}
// 手划向右边
public bool isMoveLeft(Hand hand)
{
//print (hand.PalmVelocity.x );
return hand.PalmVelocity.x < -deltaVelocity && !isStationary(hand);
}
//手向上
public bool isMoveUp(Hand hand)
{//print ("hand.PalmVelocity.y" + hand.PalmVelocity.y);
return hand.PalmVelocity.y > deltaVelocity && !isStationary(hand);
}
//手向下
public bool isMoveDown(Hand hand)
{
return hand.PalmVelocity.y < -deltaVelocity && !isStationary(hand);
}
//手向前
public bool isMoveForward(Hand hand)
{
print(hand.PalmPosition);
return hand.PalmVelocity.z > deltaVelocity && !isStationary(hand);
}
//手向后
public bool isMoveBack(Hand hand)
{
return hand.PalmVelocity.z < -deltaVelocity && !isStationary(hand);
}
//固定不动的
public bool isStationary(Hand hand)
{
return hand.PalmVelocity.Magnitude < smallestVelocity; //Vector3.Magnitude返回向量的长度
}
//手掌全展开~
protected bool isOpenFullHand(Hand hand)
{
//Debug.Log (hand.GrabStrength + " " + hand.PalmVelocity + " " + hand.PalmVelocity.Magnitude);
return hand.GrabStrength == 0;
}
/*
//拍手
public bool isClap(Hand hand)
{
return leftPosition.x == rightPosition.x;
}
*/
public void toBlue()//变蓝色
{
Obj.GetComponent<Renderer>().material.color = Color.blue;
}
}
建一个脚本,把这些复制进去,加到摄像机上,在有手势识别的地方加上一个print,这样运行之后,观察控制台的输出,就知道手势到底有没有被识别到啦~~注意三个using,别搞错咯。
游戏设计
手势识别做好之后,其实大家都站在了同一个起点,怎么把游戏设计做好才是取胜之道。在这一趟开发过程中,据我所知用leapmotion做游戏开发是比较冷门的,除非有很好的idea~
单独把这一部分拿出来讲是想给读者们提一个醒。在我开始做游戏设计时,看了太多的leapmotion的介绍文档和视频,脑袋里面有超级多的想法,设计方案更是写的出神入化,但是越往后面做,方案又一再调整。所以提醒读者,设计的动作不要太复杂,不要太轻易地相信那些介绍的视频,那些很多是为了宣传的,只有自己用过才会知道。