今天在公司里吃完了中饭,下定决心一定要把这个问题给解决,下面是我的分析,可能不全面,如有疑问和个人见解和改进方案,欢迎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
哈哈,终于搞定,也就是说和实际的验证刚好吻合,后面的就不分析了,感兴趣的自己研究