本文主要講述在MIDP1.0情況下處理開發過程遇到的連續按鍵事件,結合具體的實例給出一種實用的解決方案。
我們知道MIDP中的低級事件處理是通過keyPressed()、keyReleased()和keyRepeated()來處理的,分別在按鍵被按下、釋放和重復按鍵的時候被觸發。當方法被調用的時候,系統會把所按下鍵的鍵值傳遞給上述的三個方法,根據按鍵的鍵值我們可以進行相關的處理。在MIDP中定義了如下的按鍵值分別是:KEY_NUM0,KEY_NUM1,KEY_NUM2,KEY_NUM3,KEY_NUM4,KEY_NUM5,KEY_NUM6,KEY_NUM7,KEY_NUM8,KEY_NUM9,KEY_STAR 和 KEY_POUND。
在游戲開發中為了保證程序的可移植性,通常我們都會把鍵值轉換為游戲動作,在MIDP中定義了如下的游戲動作:UP,DOWN,LEFT,RIGHT,FIRE,GAME_A,GAME_B,GAME_C,GAME_D。轉換非常簡單,可以通過Canvas提供的方法getGameAction()。
一般來說處理keyPressed()和keyReleased()都比較容易,但是處理按鍵一直被按下的情況稍微復雜一些。因為我們使用的設備並不一定支持連續按鍵的事件。你可以通過方法hasRepeatEvents()來檢測平台是否支持當按鍵持續按下的時候產生重復事件。如果支持那麼你可以在keyRepeated()的方法中處理相關邏輯,如果不支持那麼你必須采取其他的方法。
這裡筆者介紹一種通過設置標志位的方式來處理連續按鍵的方法。其實原理非常的簡單,我們通過設置標志位判斷按鍵是否被按下了,比如我們判斷LEFT是不是被按下了。當LEFT被按下的時候,我們把成員變量leftPressed設置為true,代碼如下:
public void keyPressed(int keyCode)
{
int action = getGameAction(keyCode);
switch (action)
{
case LEFT:
left();
leftPressed = true;
break;
case RIGHT:
right();
rightPressed = true;
break;
default:
break;
}
repaint();
}
當按鍵被釋放的時候,我們就把相關的標記位設置為false。
public void keyReleased(int keyCode)
{
int action = getGameAction(keyCode);
switch (action)
{
case LEFT:
leftPressed = false;
buttonPressed = "";
break;
case RIGHT:
rightPressed = false;
buttonPressed = "";
break;
default:
break;
}
repaint();
}
這樣我們在重新繪制屏幕的時候就可以根據標記位的狀態進行繪畫了:
if (leftPressed)
{
left();
}
if (rightPressed)
{
right();
}
筆者給出一個簡單的實例來進行論證,我們制作一個MIDlet,當用戶按下LEFT的時候,J2ME字符串向左側移動,當用戶按下RIGHT的時候,J2ME字符串向右側移動。簡單起見,我沒有處理DOWN和UP的情況。下面是應用程序截圖和源代碼。
package com.j2medev;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
public class KeyActionMIDlet extends MIDlet
{
private Display display;
private MainCanvas mainCanvas;
protected void startApp() throws MIDletStateChangeException
{
display = Display.getDisplay(this);
mainCanvas = new MainCanvas();
new Thread(mainCanvas).start();
display.setCurrent(mainCanvas);
}
protected void pauseApp()
{
}
protected void destroyApp(boolean arg0) throws MIDletStateChangeException
{
}
}
package com.j2medev;
import javax.microedition.lcdui.*;
public class MainCanvas extends Canvas implements Runnable
{
private String buttonPressed;
private boolean leftPressed;
private boolean rightPressed;
private int px = getWidth() / 2;
public final int py = getHeight() / 2;
public MainCanvas()
{
buttonPressed = " ";
}
private void left()
{
if (px >= 0)
{
px--;
}
buttonPressed = "LEFT";
repaint();
}
private void right()
{
if (px <= getWidth())
{
px++;
}
buttonPressed = "RIGHT";
repaint();
}
public void run()
{
while (true)
{
if (leftPressed)
{
left();
}
if (rightPressed)
{
right();
}
try
{
Thread.sleep(50);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
public void paint(Graphics g)
{
g.setColor(0xFFFFFF);
g.fillRect(0,0,getWidth(),getHeight());
g.setColor(0x000000);
g.drawString(buttonPressed,20,20,Graphics.LEFT | Graphics.TOP);
g.drawString("J2ME",px,py,Graphics.HCENTER | Graphics.TOP);
}
public void keyReleased(int keyCode)
{
int action = getGameAction(keyCode);
switch (action)
{
case LEFT:
leftPressed = false;
buttonPressed = "";
break;
case RIGHT:
rightPressed = false;
buttonPressed = "";
break;
default:
break;
}
repaint();
}
public void keyPressed(int keyCode)
{
int action = getGameAction(keyCode);
switch (action)
{
case LEFT:
left();
leftPressed = true;
break;
case RIGHT:
right();
rightPressed = true;
break;
default:
break;
}
repaint();
}
public void keyRepeated(int keyCode)
{
int action = getGameAction(keyCode);
switch (action)
{
case LEFT:
left();
break;
case RIGHT:
right();
break;
default:
break;
}
repaint();
}
}