GameLoft按键处理的解答

 今天在公司里吃完了中饭,下定决心一定要把这个问题给解决,下面是我的分析,可能不全面,如有疑问和个人见解和改进方案,欢迎QQ:523851253

 

 

首先是Const类,
这里我们一直都把问题给局限死了,他是怎么可能做的到的呢?怎么可能判断出里面的每一位呢,0和1是随便乱摆放,其

实不然,仔细观察下,发现

    public static final int GK_UP = 1;
    public static final int GK_DOWN = 1 << 1;
    public static final int GK_LEFT = 1 << 2;
    public static final int GK_RIGHT = 1 << 3;
    public static final int GK_NUM0 = 1 << 4;
    public static final int GK_NUM1 = 1 << 5;
    public static final int GK_NUM2 = 1 << 6;
    public static final int GK_NUM3 = 1 << 7;
    public static final int GK_NUM4 = 1 << 8;
    public static final int GK_NUM5 = 1 << 9;
    public static final int GK_NUM6 = 1 << 10;
    public static final int GK_NUM7 = 1 << 11;
    public static final int GK_NUM8 = 1 << 12;
    public static final int GK_NUM9 = 1 << 13;
    public static final int GK_STAR = 1 << 14;

发现出什么规律没有啊?

首先都是1<<N,而且都是按递增的格式进行排布的

我仔细查看了下,发现这样设计是很有规律的,

直接说吧,意思就是

从上到下,左移N位代表所产生的数的暗含意思就是这个数的第N位是1,从0开始哦,
而且N<=32,因为int类型由4个字节组成,一个字节代表的是8位的二进制,4*8最大为32位,超过了我也不知道,可以试

一下,现在问题已经理清了很多了吧

 

首先要弄明白的是JAVA中的运算符代表的意思是什么?

JAVA中的运算符主要有4种:&(位与) |(位或) ^(异或)  ~(按位取反)

因为首先用到了位或,那么先从位或解决起:

运算规则:参与运算的数字,低位对齐,高位不足的补零,对应的二进制位有一个为1则为1,否则为0,

适用场合:

将数字钟的某一位或者某些位修改成一,因为1和任何位位或都是1

private int  s_keyA ;
private int  s_fastCurrentKey ;

      protected void keyPressed(int keyCode)
       {
  
  s_keyA = getKey(keyCode);
                s_fastCurrentKey |= s_keyA;
       }

那么这两句话的意思现在可以理解了吧!

s_keyA = getKey(keyCode);
//将系统按键值转换为我们自己定义的值
//如果这样理解就太肤浅了,正确的理解是我们按了某一个按键后,程序就会返回一个指定位为1的数字,其余位为0,这

是基础,很重要!切记!

s_fastCurrentKey |= s_keyA ;

首先s_fastCurrentKey的所有位都等于0,而s_keyA中只有一位等于0,两者或后,结果等价于 s_fastCurrentKey =

s_keyA ;只不过上面的方法比数学运算式快很多

也许你会有疑问,那么如果下次进来的时候岂不s_fastCurrentKey不等于0了

那么就看下keyReleased(int keyCode)方法了

    protected void keyReleased(int keyCode)
    {

     s_keyB = getKey(keyCode);
            s_fastCurrentKey &= ~s_keyB;
    }

异或就不用说了,操作对象是一个数字,将该数字的所有位取反

~s_keyB也就是将所有的位取反,也就是只有一个是0了
s_fastCurrent经过keyPreesd方法后,变成了只有一位为1了,而与的特效就是

一个为0得出的结果就是0,

综合来说就是
s_fastCurrent中只有一位为1,其余位数都为0,~s_keyB只有一位为0,其余位都为1,基本可以直接的说这句话等效于

s_fastCurrent = 0;疑问:那么如果两个一相碰了呢?那么s_faseCurrent就不等于0了,非常好,注意观察的人都知道,

其实s_fastCurrent其实和s_keyB是相等的,原因自己留给大家自己去想了,我就不多说了,这样毫无疑问s_fastCurrent

已经归0了

protected void keyRepeated(int keyCode)
    {
        s_fastCurrentKey |= getKey(keyCode);
    }

这句话到现在为止,已经不难解决了,意思就是如果一直按了某个键的话,s_rentKey就等于getKey(keyCode)

 

通过这些步骤后,思路应该有点清晰了

那么接下来有个疑问我也不是很清楚

如果经过了updataKey()和不经过updataKey()方法,对程序会造成什么样的影响

现在进入运用阶段了,核心中的核心,前面所写的一切都是为了使用方便,使用不方便,那就没有必要了

不过这个问题似乎设计到按键调用的机制,不过我看了程序也猜到是哪一种情况了

因为运用主要是靠s_pressKey来控制的,而对s_pressKey进行的赋值是在updataKey()方法里面

下面来看下updataKey()

 private static void updateKey()
    {
        s_pressedKey = ~s_currentKey & s_fastCurrentKey | (s_keyA & s_keyB);
        s_currentKey = s_fastCurrentKey;
        s_keyA = s_keyB = 0;
        keyTick++;
        if (s_pressedKey != 0)
        {
            if ( (s_lastPressed != 0) && (keyTick < Const.DBL_PRESS_INTERVAL) &&
                 (s_lastPressed == s_pressedKey))
            {
                    s_lastPressed = 0;
            }
            else
            {
                    keyTick = 0;
                    s_lastPressed = s_pressedKey;
            }
        }
    }

天杀的,我猜就知道写这段程序的程序员很邋遢,括号总要加两个吧和

不过还好,它们优先级别是相同的,
一段段理解就好了,
不知道我的理解有没有错误

首先s_keyA & s_keyB
只有当s_keyB抬起的时候,s_keyA才会和s_keyB相等,如果持续按了某个键的话,那么

s_keyA & s_keyB等于0,抬起的时候等于s_keyA 等于s_keyB 抬起的时候s_fastCurrentKey已经等于0了
,但是奇怪的是
这两种情形经过
s_pressedKey = ~s_currentKey & s_fastCurrentKey | (s_keyA & s_keyB);

持续按键的时候

s_pressedKey = ~s_currentKey & s_fastCurrentKey | 0 ;

抬起的时候
s_pressedKey = ~s_currentKey & 0| s_keyA ;

程序中还有一段代码s_currentKey = s_fastCurrentKey;

也就是说s_currentKey 记录了上一次s_fastCurrentKey的值,而上一次跟本次,

如果是一直按着的s_currentKey=s_fasetCurrentKey
如果是抬起后再按着的 s_currentKey = 0 ;

回归到上面
s_pressedKey = ~s_currentKey & s_fastCurrentKey | (s_keyA & s_keyB);

如果玩家是一直按着某个键的话

首先判断s_currentKey,
如果上一次按键也是按着的
s_pressdKey = ~s_keyA & s_keyA |(s_keyA & 0);
简化后就是
对一个数取反后然后在跟这个数与,有意思,研究下
举个例子:

1101 = 13  取反~13 = 0010 
13 & ~13 
  1101
& 0010
  0000
0|0等于0

也就是说如果持续按着某个键的话,那么s_pressKey = 0 ;

通过研究实际的程序我发现,只有当突然按了某个键的时候,s_preeKey才会变化

如果上一次按键不是按着的
也就是突然按了某个键的时候

这个时候要明白的是
s_currentKey = 0 ;
但是s_fastCurrentKey等于s_keyA ,s_keyA等于s_keyB

也就是说

s_pressedKey = 0 & s_keyA | (s_keyA & s_keyA)
             = 0 | s_keyA
             = s_keyA

哈哈,终于搞定,也就是说和实际的验证刚好吻合,后面的就不分析了,感兴趣的自己研究