按键事件的处理

来源:互联网 发布:我国外汇储备数据 编辑:程序博客网 时间:2024/04/27 16:41

接下来要说的是:

 

按键事件的处理。

 

所谓按键处理,就是在游戏中,玩家按了一个键。
你把它记录下来,然后在程序中判断,按了什么键,要完成什么相应的功能。

 

这个按键处理系统也是十分巧妙,实现的方式不一样,照顾的方面也不一样。
我现在只能说些简单的例子。
一个简单的键盘处理系统,可能会经过很长期的完善才能变得成熟。
因为这个东西实现起来很复杂。(对我来说^^)

 

在game.java中添加如下代码:

 

    public void keypressed(int keycode) {
        //
系统事件,当键盘被按下,系统会调用这个方法,并把你按得键值keycode传进来。
        // 注意,这个 keycode键值不是数值,就是说你按
number
1,不一定是1。在手机上,每个键都有一个独特的keycode,这和生产厂商有关。
        //
不同的手机,keycode可能不相同。模拟器的keycode和真实手机的也可能不相同.
:)
    }

 

    public void keyreleased(int keycode) {
        //
同上,当一个键被松开,系统会调用这个方法。
    }

 

    public void keyrepeated(int keycode) {
       //
同上,当一个键被持续按着,系统会调用这个方法。
       //
大多数手机不支持这个方法,反而支持keypressed方法。
       //
就是说,如果你一直按着某个键,keypressed方法会被持续调用,而不是这个方法。
    }

 

所以我们就只看
    public void keypressed(int keycode) {
    }

 

    public void keyreleased(int keycode) {
    }
这两个方法就够了。一个好的设计完全可以用这两个方法满足所有需要。

 

在上次的game.java中,第二个状态是这样:
            case 2:
                ourgraphics.setcolor(0);
                ourgraphics.fillrect(0, 0, 128, 128);
                ourgraphics.setcolor(0xffffff);
                ourgraphics.drawstring("fuck man! it's new game!", 128

 

 

 

>> 1, 128 >> 1, graphics.top | graphics.hcenter);

 

                                                                // 我们在这里添上键盘处理事件:
                                                                /**
                                                                if (keyvalue == num6) {
                                                                  gamestate = 3; // 如果按了6键,就跑到状态3里面.
                                                                }
                                                                */

 

                break;

 

然后我们再添一个状态3,
            case 3:
                ourgraphics.setcolor(0);
                ourgraphics.fillrect(0, 0, 128, 128);
                ourgraphics.setcolor(0xffffff);
                ourgraphics.drawstring("haha, dao 3 le!", 128 >> 1, 128

 

>> 1, graphics.top | graphics.hcenter);

 

                                                                // 我们在这里添上键盘处理事件:
                                                                /**
                                                                if (keyvalue == num4) {
                                                                  gamestate = 2; // 如果按了4键,又跑回状态2里面.
                                                                }
                                                                */
                break;

 

上面的代码先就那样把注释加着, /** */

 

定义一个变量,
  int keyvalue;
  //然后在这里面
  public void keypressed(int keycode) {
      //加上一句:
      system.out.println("the keycode of the key you pressed is " +
keycode);

 

//这样你每按一个键,控制台就会把这个键对应的键值打印出来.

 

//把这个键值赋给这个变量,作为以后判断按键事件的依据。
      keyvalue = keycode;
         }

 

现在可以试试这个程序,按一下4,或6,看看他们的键值是多少,然后定义以下两个变量:
    final static int num4 = 52; //在这里写按4时得到的键值
    final static int num6 = 54; //在这里写按6时得到的键值

 

// final 就意味不可改变。static final就是一个常量。

 

一般来说,这些键值都事先定义好。手机不同,只需要改变这些常量的值就可以了。

 

现在可以把case 2 和 case 3的注释去掉。运行程序:
这样 在到达状态2以后,按6键,游戏就会跑到状态3。
然后再按4,就会返回到状态2。

 

为了避免keyvalue这个值一直保存,在
case 2的里面加上:
                                                                /**
                                                                if (keyvalue == num6) {
                                                                  gamestate = 3; // 如果按了6键,就跑到状态3里面.

 

                                                                  keyvalue = -1; //
随便搞个负数给它,免得这个值在其它状态还可能起作用.意思就是判断完了就不要了.
                                                                }
                                                                */

 

一个简单的键盘处理的例子就完成了。:)

 

但是这个键盘处理的方法非常不完善。
case 2运行的时候,如果很快的按6再按4,
这时keyvalue变成num4,然后在 case
2的判断中,就判断不到你按过6。

 

看来现在的问题就是用一个keyvalue变量存储按过的键,只能存储一个。

 

有个办法:
假设 keyvalue 用2进制表示,他就有很多位可以利用。
int keyvalue = 0; // 0000 00000 0000.....
假设第四位表示按键4,第六位表示按键6......依此类推。
那么如果按了 num6, 就把
keyvalue的第6位表示成1,表示按下。
那么如果按了 num4, 就把
keyvalue的第4位表示成1,表示按下。
只要存储的位置不同,那么一个整数就可以同时存储多个按键的状态了。

 

现在定义两个变量,表示某个键在这个整形中的位置:
static final int game_num4 = 1 << 4; // 意思是二进制的10000,
把1向右移4位。
static final int game_num6 = 1 << 6; // 意思是二进制的1000000,
把1向右移6位。

 

修改 这个函数。
public void keypressed(int keycode) {
  switch (keycode) {
    case num4:
        keyvalue |= game_num4;  // 如果二进制keyvalue的值是 0,
那么|(或)了之后,keyvalue = 10000.
                                // 如果 keyvalue = 0010
0000,那么|(或)了之后,keyvalue = 0011
0000.就是右数第5位改变了,其他位不变。
        break;
    case num6:
        keyvalue |= game_num6;
        break;
    // case
....完整的游戏代码里,后面还有很多case,要把所有手机上的按键都给写全了。java的整型是32位的。应该能存32个键。足够了。
  }

 

 

 

}

 

存储按键值得方法变了,判断的方法也要变。
修改case 2中的
                                                                if (keyvalue == num6) {
                                                                  gamestate = 3;
                                                                  keyvalue = -1;
                                                                }
变成

 

                if ((keyvalue & game_num6) != 0 ) { //
如果按了6键那一位是1,就表示6被按下了。
                                                    // 0 & 1 = 0, 1 & 1
= 1
                                                    //
那么keyvalue的每一位和game_num6的每一位 &
                                                    // 1111 1010
keyvalue (随便写的值)
                                                    // 0100 0000
game_num6
                                                    //
这样看来那么keyvalue &
game_num6的值就决定在第7位。其他位&的结果肯定是0。
                                                    //
如果keyvalue的第7位是1,就意味着keyvalue & game_num6 != 0.
                                                                  gamestate = 3;

 

                                                                  keyvalue &= ~game_num6; //
使用完之后,把这一个按键位清空,其他位保留。
                                                                                          // ~符号的意思是取反.
game_num6 的二进制是 0100 0000, 取反之后等于1011 1111
                                                                                          // 再跟keyvalue
&,就相当于其他为保持不变,第7位变成0了。
                }

 

可以试试看了,现在的话,很快的按6再按4,6仍然是起作用的。
一般在
keyreleased方法中,也要把释放的键位给清空,也用上面的方法。

 

恩,我举的例子似乎不是很好。没能表现key系统的处理。

 

按键可能随时发生,所以keyvalue的值可能会随时改变。这样的话,直接用keyvalue来进行判断就非常不稳定了。
现在的解决办法是:
使用keyvalue来记录按键的状态。
按下-->打开相应的位, 释放-->清空相应的位

 

然后再搞一个变量专门进行判断。
假设这个变量是framekey.
在每一桢开始时,framekey = keyvalue.
那么对这一桢来说,framekey是不变的!不管你怎么按键,变得都是keyvalue.
在这一桢里,我们始终用framekey来进行按键的判断。因此,按键的状态变得稳定了。
然后在下一桢,又把变过的keyvalue赋给framekey,再使用framekey进行判断。

 

呵呵。这样的判断也可能漏掉某些按键。
其实我很长时间都没有去认真研究代码,去理解代码了。
成天忙于改bug,对游戏开发本身的知识简直蜕变为0了。

原创粉丝点击