程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2ME >> j2me游戲教程(四)——按鍵事件的處理

j2me游戲教程(四)——按鍵事件的處理

編輯:J2ME
接下來要說的是:
按鍵事件的處理。
所謂按鍵處理,就是在游戲中,玩家按了一個鍵。
你把它記錄下來,然後在程序中判斷,按了什麼鍵,要完成什麼相應的功能。
這個按鍵處理系統也是十分巧妙,實現的方式不一樣,照顧的方面也不一樣。
我現在只能說些簡單的例子。
一個簡單的鍵盤處理系統,可能會經過很長期的完善才能變得成熟。
因為這個東西實現起來很復雜。(對我來說^^)
在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了。
只有以後動手做。如果碰到具體的不能滿足的需要,就再去研究。
就講這麼多。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved