一步步实现j2me游戏引擎(二),游戏虚拟键值

    技术2022-05-19  26

    j2me的事件响应主要通过keyCode来操作,对于手机上的keyCode有如下2个问题:

     

    手机上的导航键,左右软件的keyCode在不同机器上不同,需要做移植。导航键的上下左右,中间件需要和数字键盘上对应,我们玩手机游戏的时候,这2个操作都行的。

    由于这2个问题,我们在判断上下左右以及确定功能的时候,会有移植机型和相同功能映射到不同键位的麻烦。这是蛋疼的问题,因为游戏中上下左右等等操作是非常繁多的。我们就会想,如果有一套虚拟的键值,没有这2个蛋疼的问题就好了。其实是有的,我们先看一下,Canvas系统类为我们定义的按键常量:

     

    public static final int UP = 1; public static final int DOWN = 6; public static final int LEFT = 2; public static final int RIGHT = 5; public static final int FIRE = 8; public static final int GAME_A = 9; public static final int GAME_B = 10; public static final int GAME_C = 11; public static final int GAME_D = 12; public static final int KEY_NUM0 = 48; public static final int KEY_NUM1 = 49; public static final int KEY_NUM2 = 50; public static final int KEY_NUM3 = 51; public static final int KEY_NUM4 = 52; public static final int KEY_NUM5 = 53; public static final int KEY_NUM6 = 54; public static final int KEY_NUM7 = 55; public static final int KEY_NUM8 = 56; public static final int KEY_NUM9 = 57; public static final int KEY_STAR = 42; public static final int KEY_POUND = 35; 

     

    我来解释一下,0-9就是Num0-Num9,上下左右导航键就是up,down,left,righ, 导航中间键就是fire,gameABCD对应gameAction的转化值(这个后面说),star是#,poun是*号。

     

    我们可以直接用Canvas的常量来匹配KeyCode,但是有2个问题, 1)没有左右软件, 2)NUM4和left都要执行左边的功能等等。

     

    所以,我们接下来看Canvas帮我们实现了一个getGameAction方法,方法是干什么用的呢? 其实就是消除如上2)的问题。

     

    protected void keyReleased(int keyCode) { keyCode = this.getGameAction(keyCode); } 

     

    这句话就是系统根据自己的情况,把keyCode映射一个相对的gameAction值。

    意义就是经过上面的调用产生如下效果:

     

    原有的keyCode为NUM4 或 导航left都会映射到 Canvas.left

    原有的keyCode为NUM6 或 导航lright都会映射到 Canvas.right

    NUM7,9,1,3映射到GameABCD

     

    这样一来经过,this.gameAction我们只要判断left,up,down,fire就可以判断导航键和数字键盘的2映射了。

     

     

     

    现在,还剩下一个问题,那就是左右软件的问题,Canvas没有为我们搞定这个事情,所以要自己来。我们要在Canvas的基础上封装一套虚拟的键位包括Canvas的键位和左右软件就行了。名字一般叫GameKey,简称GK.

     

    /* * 手机按键的物理值, 不同的机器不同的值, 需要做预编译移植 */ int REAL_SOFT_LEFT = -6; int REAL_SOFT_RIGHT = -7; /* * 游戏逻辑按键 */ int GK_NONE = 0; // 导航上键或NUM8 int GK_UP = 1; // 导航下键或NMU2 int GK_DOWN = 2; // 导航左键或NUM4 int GK_LEFT = 3; // 导航右键或NUM6 int GK_RIGHT = 4; int GK_STAR = 5; int GK_POUND = 6; int GK_SOFT_LEFT = 7; int GK_SOFT_RIGHT = 8; // 导航中键或NUM5 int GK_OK = 9; 

     

    左右软件根据手机的真实值做需处理,GK开头的是虚拟按键会被映射到Canvas下面的定义。

     

     

    /** * 将系统按键值转换为游戏虚拟键值 * * @param keyCode 系统按键值 * @param gameAction 系统游戏按键值 * @return 游戏虚拟按键值 */ public static int getGKCode(int keyCode, int gameAction) { switch(keyCode) { // 左软件 case REAL_SOFT_LEFT: return GK_SOFT_LEFT; // 右软件 case REAL_SOFT_RIGHT: return GK_SOFT_RIGHT; } switch(gameAction) { case Canvas.DOWN: return GK_DOWN; case Canvas.UP: return GK_UP; case Canvas.LEFT: return GK_LEFT; case Canvas.RIGHT: return GK_RIGHT; case Canvas.FIRE: return GK_OK; // 按键"*" case Canvas.KEY_STAR: return GK_STAR; // 按键"#" case Canvas.KEY_POUND: return GK_POUND; } return 0; } 

     

    这个方法,只要传入事件触发中的keyCode,和系统调用getGameAction(keyCode)的gameAction值,就可以得到我们自己定义的虚拟键值了。

     

     

    核心思想是,我们定义了自己的一套GK值无所谓不重复就可以,因为我们要唯一性判定。接下来,我们利用上述方法在事件发生时候,把各种键位值映射到GK上的值。这样一来,我们仅仅在代码判断中GK的键位就确定系统按了什么键位了。至此文中开始的2个问题都解决了。

     

     

    补充:

     

    有些系统包括我公司的系统是这么定义GK的:

     

    //基本键 public static final int GK_UP = 1 << 0; 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; public static final int GK_POUND = 1 << 15; public static final int GK_SOFT_LEFT = 1 << 16; public static final int GK_SOFT_RIGHT = 1 << 17; public static final int GK_MIDDLE = 1 << 18; public static final int GK_RETURN = 1 << 19; //组合键 public static final int GK_OK = GK_MIDDLE | GK_SOFT_LEFT; public static final int GK_CANCEL = GK_SOFT_RIGHT; public static final int KEY_LEFT = Key.GK_LEFT | Key.GK_NUM4; public static final int KEY_RIGHT = Key.GK_RIGHT | Key.GK_NUM6; public static final int KEY_UP = Key.GK_UP | Key.GK_NUM2; public static final int KEY_DOWN = Key.GK_DOWN | Key.GK_NUM8; public static final int KEY_FRIE = Key.GK_MIDDLE | Key.GK_NUM5; 

     

    这里贴了一部分,不方面都贴出来。我解释一下,这样GK的代表的每一个键值,都是被位移到int类型32个bit位上了。

    int在java中4个字节,一共32位。

     

    GK_UP = 1 << 0; 就表示32位中第一位是1,其它都是0,

    GK_DOWN = 1 << 1; 就表示32位中的第二位是1,其它都是0。

     

    这么做是为了判断按键下按的,用了一个循环队列机制,我不是这么做的,所以我也没这个设置。

     

    大概的意思是:

     

    GK_UP 存储形式        0000 0000 0000 0000 0000 0000 0000 0001

     

    GK_DOWN 存储形式  0000 0000 0000 0000 0000 0000 0000 0010

     

    这个2个键位进行&, |等等位运算就可知道相应的键值了。

     

     


    最新回复(0)