暴风魔镜安卓手柄输入检测接口

  更新说明下:今天我发现本文中设计的代码有些bug,关于按下和抬起状态的检测只能监听一次,关于解决方案,我会尽快补上,谢谢。

  使用暴风魔镜做安卓VR开发,自己尝试弄了一天,发现效果太差,主要是手柄输入函数检测不到,或者检测的不灵敏。第二天才想起来百度,然后才发现暴风魔镜官方已经提供了手柄SDK。链接地址http://bbs.open.mojing.cn/forum.php?mod=viewthread&tid=48&extra=page%3D1。

  好,以上就是原生的SDK,关于相机我就不说了,最要紧是把手柄函数给找到。开发文档大概介绍了一下,在BaoFengZeemoteManager.cs中提供了按键的获取事件,能够获取到键按下和按键抬起的事件。

  经过测试,阿亮发现了以下缺点:

  1,提供的方法不好用,或者说根本没有像Input输入检测那样的函数:没有实际意义的按下,一直按,抬起的直接获取函数

  2,不能同时多个按键的检测(例如只能单方向行走,走的时候不能开火等)

  3,抬起键的检测不好,例如同时按下了多个键,只能检测其中一个是否抬起

 

  其他的不说,基本的按键事件不能正常使用,这个函数无异于鸡肋。OK,既然原开发者不走心,那咱就走点心吧。

  首先,要明确需求,就是为了解决上面提到的三个问题。

  在解决这个问题之前,先来看看BaoFengZeemoteManager.cs是怎么跑起来的,ZeemoteManager.cs是获取事件的,然后把事件处理的结果传递个BaoFengZeemoteManager.cs,它主要有两个函数,一个是获取按下事件,另一个是抬起事件。

  

public void ZeemoteUpBtn(string currentButton)//抬起的按键名称
    {
        state = "Button up: " + currentButton;
        //Message = currentButton;


        switch (currentButton)
        {

            case "OK":

                break;
            case "BACK":
                break;
            case "MENU":
                break;
            case "LEFT_BUTTON":
                break;
            case "RIGHT_BUTTON":
                break;
            case "UP_BUTTON":
                break;
            case "DOWN_BUTTON":
                break;
            case "CENTER_POSITION":
                break;


            case "A":
                break;
            case "B":
                break;
            case "C":
                break;
            case "D":
                break;
        }
}
public void ZeemoteDownBtn(string currentBtn)//按下的按键名称
    {
        state = "Button down: " + currentBtn;
        switch (currentBtn)
        {
            case "OK":
                break;
            case "BACK":
 
                break;
            case "MENU":
                break;
            case "LEFT_BUTTON":
 
                break;
            case "RIGHT_BUTTON":
 
                break;
            case "UP_BUTTON":
 
                break;
            case "DOWN_BUTTON":
 
                break;
            case "CENTER_POSITION":
 
                break;
            //以下为老遥控器(一代遥控器)特有按键;
            case "A":
 
                break;
            case "B":
 
                break;
            case "C":
 
                break;
            case "D":
 
                break;
        }
}
 

  OK,拿到这两个函数怎么用呢,直接用很难用,你总不能把输入逻辑的处理放到这里面来吧?还有,像Input.GetButton(name),Input.GetButtonDown(name),Input.GetButtonUp(name)的检测输入性函数也是没有的,如何丰富这个鸡肋呢?

  算法这东西需要你分析逻辑关系的,我们来看看如何处理这个逻辑:他们每次接收一个参数数值,同时更新掉上一个。针对同一个按键,这两个函数是互斥的。

  根据这个条件,以及我们的需求,然后我想到了这个方案:一个按键有三个状态:按下,一直按,抬起。用一个hashtable将按键和状态存起来,执行ZeemoteDownBtn(string currentBtn)和ZeemoteUpBtn(string currentButton)时去调整状态。其他类调用检测输入时,去哈希表中去查它对应的状态就行了。

  更改以上的两个函数如下:

  

public void ZeemoteUpBtn(string currentButton)
    {
        state = "Button up: " + currentButton;
        //Message = currentButton;


        switch (currentButton)
        {

            case "OK":

                break;
            case "BACK":
                break;
            case "MENU":
                break;
            case "LEFT_BUTTON":
                break;
            case "RIGHT_BUTTON":
                break;
            case "UP_BUTTON":
                break;
            case "DOWN_BUTTON":
                break;
            case "CENTER_POSITION":
                break;


            case "A":
                break;
            case "B":
                break;
            case "C":
                break;
            case "D":
                break;
        }
        
        SetAxis(currentButton,false);//调整按键的状态
        
        
    }
    private void SetAxis(string buttonName,bool isPress) {//抬起键和按下,一直按的事件是互斥的
        ((Hashtable)table[buttonName])["up"] = !isPress;
        ((Hashtable)table[buttonName])["down"] = isPress;
        ((Hashtable)table[buttonName])["press"] = isPress;
    }
    private Hashtable table = new Hashtable();
    public void ZeemoteDownBtn(string currentBtn)
    {
        state = "Button down: " + currentBtn;
        switch (currentBtn)
        {
            case "OK":
                break;
            case "BACK":

                break;
            case "MENU":
                break;
            case "LEFT_BUTTON":

                break;
            case "RIGHT_BUTTON":

                break;
            case "UP_BUTTON":

                break;
            case "DOWN_BUTTON":

                break;
            case "CENTER_POSITION":

                break;
            //以下为老遥控器(一代遥控器)特有按键;
            case "A":

                break;
            case "B":

                break;
            case "C":

                break;
            case "D":

                break;
        }

        if ((bool)((Hashtable)table[currentBtn])["down"]==false) {//按下事件是一次性的,所以只有当down为false时再更新
            SetAxis(currentBtn, true);
        }
        if (currentBtn == AndroidInput.CENTER_POSITION.ToString())//这个是轴归零时函数
        {
            SetAxis(AndroidInput.LEFT_BUTTON.ToString(), false);
            SetAxis(AndroidInput.RIGHT_BUTTON.ToString(), false);
            SetAxis(AndroidInput.UP_BUTTON.ToString(), false);
            SetAxis(AndroidInput.DOWN_BUTTON.ToString(), false);
        }
    }

好,函数改好了,看看怎么用:

 public bool GetButton(string button) {//一直按状态
        return (bool)(((Hashtable)table[button])["down"]);
    }
    public bool GetButtonDown(string button)//按下的检测
    {
        bool isPress = (bool)(((Hashtable)table[button])["press"]);
        if (isPress && (bool)(((Hashtable)table[button])["down"]))
        {
            ((Hashtable)table[button])["press"] = false;//检测过按下事件后,将其状态清零
            return true;
        }
        return false;
    }
    public bool GetButtonUp(string button)//检测抬起按键事件
    {
        bool isUp = (bool)(((Hashtable)table[button])["up"]);
        if (isUp) {
            
            ((Hashtable)table[button])["up"] = false;//检测过后清零
            return true;
        }
        return false;
    }

  修改完毕,手柄能用了!

 

  例如,按下MENU键,直接调用:

BaoFengZeemoteManager.Instance.GetButtonDown(AndroidInput.MENU.ToString());
一直按:
BaoFengZeemoteManager.Instance.GetButton(AndroidInput.MENU.ToString());

 抬起:

 

BaoFengZeemoteManager.Instance.GetButtonUp(AndroidInput.MENU.ToString())

 

  结尾来谈一下第一人称控制器,不要说这个多简单,unity自带什么的,我知道,可是那是基于PC端有鼠标键盘的情况,怎样用手柄控制呢?

  我为什么提出这个问题--相机。在PC端,用鼠标移动控制相机还有角色旋转,这是最简单不过了,可是,暴风魔镜的相机旋转是陀螺仪控制的,角色怎么跟着旋转呢?因为第一人称的MouseLook是通过计算鼠标的XY偏移量来确定角色的方位的,如果方位不正确,那么角色的移动就不会以相机的正前方为方向移动了。

  我开始用相机的角度,来调整角色的旋转角度,但是问题又来了:相机是基于角色的,旋转角色,相机又跟着转,好吧,具体的问题,大家可以试试。

  我解决了?那是当然。来看看图吧。

最后是一个演示demo的apk,有暴风魔镜的小伙伴们可以试试,Menu键切换武器。OK键发射。链接: http://pan.baidu.com/s/1hqhFKCO 密码: mf7q

 原文链接http://www.cnblogs.com/jqg-aliang/p/4615029.html   转载请申明出处,谢谢!

游戏已更新:链接:http://pan.baidu.com/s/1dD8Q8RB 密码:adwf,欢迎测试!

posted @ 2015-07-02 02:29  决晴谷  阅读(2368)  评论(0编辑  收藏  举报