Programming Technology

实现J2ME游戏的按键(键盘)缓冲

1. 什么是键盘缓冲?

J2ME当中键盘响应是用Canvas下的keyPressed()和keyReleased()方法实现的,所以就有可能出现这种情况: 把所有的键盘响应放在keyPressed()中实现

这样出现三种问题:

  1. 首先就是无法响应持续按键信息,如RPG游戏有的时候需要选择数量,让玩家选择99,莫非让玩家点99次键盘吗?如果使用MIDP2.0,可以使用getKeyStates()函数,但是又出问题了,在选择菜单的时候,菜单会来回蹦,造成选不中所要选择的菜单,必然还要使用keyPressed()方法,况且2.0也有其他的种种问题....
  2. 所有键盘响应放在keyPressed()中,当逻辑逐渐变大时,函数执行时间必然会变大,当又有一个keyPressed()事件发生时,后果无法预料....(因为模拟器,真机,响应方式都不相同,还存在支持不支持多按键操作的问题,所以我也没测...)
  3. 这样,必然会造成相关的逻辑分离,从代码的美观和整体的逻辑上都大打折扣,阅读代码必然会造成困难

有这么多问题,当然就要解决,解决办法就是缓冲,就是找个地方把它存起来,用的时候再取

2. 什么时候发生键盘响应?

我认为,理论上说是即时响应的,在我测试看来,不存在 Thread.sleep(100) 后系统才调用的事情,所以只要有时间片,虚拟机就会自动调用keyPressed方法

所驳文章地址: http://www.j2megame.cn/bbs/viewthread.php?tid=4246&page=1

相关我的回复: http://www.j2megame.cn/bbs/viewthread.php?tid=4246&page=1#pid37075
见最下方

3. 实现方法

今天用了一天的时间研究了键盘缓冲,看起来就区区几行代码,这一天下来,可是收获不少

下面先来看实现,现在发现两种比较好的实现

a实现

  1. public void keyPressed(int keyCode){            
  2.         int value = getKeyValue(keyCode) ; //自己定义的转换键值函数
  3.         keyPressedBuffer |= value ;
  4. }
  5. public void keyReleased(int keyCode){            
  6.         int value = getKeyValue(keyCode) ;
  7.         keyReleasedBuffer |= value ;
  8. }
  9. private static void acquireKey(){ //主循环中调用
  10.         keyPressed = keyPressedBuffer;
  11.         keyReleased = keyReleasedBuffer;
  12.  
  13.         keyCurrent |= keyPressed;
  14.         keyCurrent &= ~keyReleased;
  15.  
  16.         keyPressedBuffer = 0;
  17.         keyReleasedBuffer = 0;
  18. }
  19. public static boolean keyHold(int gameKey){ //按住
  20.         return ((keyCurrent & gameKey)!=0) ;
  21. }
  22. public static boolean keyDown(int gameKey){ //按下
  23.         return ((keyPressed & gameKey)!=0) ;
  24. }
  25. public static boolean keyUp(int gameKey){ //抬起
  26.         return ((keyReleased & gameKey)!=0) ;
  27. }


b实现

  1. public void keyPressed(int keyCode){            
  2.         int value = getKeyValue(keyCode) ; //自己定义的转换键值函数
  3.         key |= value ;
  4.         pressedKey |= value ;
  5. }
  6. public void keyReleased(int keyCode){            
  7.         int value = getKeyValue(keyCode) ;
  8.         key ^= value ;
  9.         releasedKey |= value ;
  10. }
  11. private static void acquireKey(){ //主循环中调用
  12.         frameKey = key ;
  13.         framePressedKey = pressedKey ;
  14.         frameReleasedKey = releasedKey ;
  15.         pressedKey = 0 ;
  16.         releasedKey = 0 ;
  17. }
  18. public static boolean keyHold(int gameKey){ //按住
  19.         return ((frameKey & gameKey)!=0) ;
  20. }
  21. public static boolean keyDown(int gameKey){ //按下
  22.         return ((framePressedKey & gameKey)!=0) ;
  23. }
  24. public static boolean keyUp(int gameKey){ //抬起
  25.         return ((frameReleasedKey & gameKey)!=0) ;
  26. }


使用的时候直接调用keyHold(),keyDown(),keyUp()就可以了

两种实现都不错,但是我更倾向于第一种,从代码清晰度和健壮程度来说,都很好

比如有的手机键盘不支持多键输入,当按下两个键以后,只会响应一个keyPressed(),但传说有的手机会响应两个keyReleased().......也就是没有按下,直接弹起按键了......这样第二种方法就会出现问题了,就是因为第二种方法使用的时异或操作符

测试:
1000 & ~1000 = 0000     1000 ^ 1000 = 0000 //按下1000,弹起1000
1000 & ~1001 = 0000     1000 ^ 1001 = 0001  出问题...
同时弹起两个按键?..... 呵呵..不管怎么样,可能会出问题

关于getKeyValue(keyCode)说明:
就是一个自己的键值转换的函数,比如定义  YOUR_LEFT = 1;   如果keyCode是左方向键返回   YOUR_LEFT就可以了,也是各种品牌手机真实键值不同惹得祸...

今天研究一天的成果,如果叙述有误,请提出,共同探讨

虽然这个是对J2ME键盘缓冲的研究,但是我感觉在其他平台上的游戏同样存在着类似的问题,思路是一样的





-----------------------
关于《sleep后响应keyPressed()》我的回复
http://www.j2megame.cn/bbs/viewthread.php?tid=4246&page=1#pid37075

在做项目的时候发现,我从来没有sleep过,但是仍然响应keyPressed()的
使用的是nokia的S60模拟器,使用手机顽童模拟器照样响应,使用fullcanvas

作者也说了是使用nokia的~什么问题...?

莫非WTK是这样的吗?

而且如果有sleep的话,也不是在sleep的时候触发的,看代码

  1. while(true){
  2.     System.out.println("\nBegin");
  3.  
  4.     updateGame();
  5.  
  6.     repaint(0, 0, 172, 208);
  7.  
  8.     serviceRepaints(); //调用System.out.println("paint");
  9.  
  10.     System.out.println("End\n");
  11.  
  12.     Thread.sleep(80);
  13. }


Begin 和 End 之间也是可以响应的

我的输出 aaa************    为  keyPressed()  输出

1. 正常按键

Begin
paint
End

aaa*****************

Begin
paint
End


Begin
paint
End

aaa*****************

Begin
paint
End

2. 快速按键

aaa*****************

Begin
aaa*****************
paint
aaa*****************
End


Begin
aaa*****************
paint
End

aaa*****************

发表评论 ( 如果您刚刚提交过评论,但是还没有被显示出来,请点击这里刷新一下: 刷新评论 )

标题

内容*

昵称*

电子邮件

个人网页


 authimage