在上次的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了。
只有以後動手做。如果碰到具體的不能滿足的需要,就再去研究。
就講這麼多。