首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2ME

MIDP 1.0 組合鍵實作:以執行緒模擬同時按鍵偵測

     編輯:J2ME

早期手機不支援 keyRepeated 重複按鍵事件,更無原生組合鍵偵測。本文展示如何以單一背景執行緒維護「目前被按下鍵碼集合」,實現組合鍵(同時按下多鍵)與長按重複功能。

核心設計

  • 資料結構:byte[] pressedKeys = new byte[2] 環狀緩衝區,儲存目前按下的鍵碼(最多 2 鍵,足應付手機操作)
  • 同步機制:所有存取 pressedKeys 的方法加 synchronized,確保執行緒安全
  • 事件流:
    1. keyPressed → startAction(keyCode) 寫入緩衝區
    2. keyReleased → stopAction(keyCode) 從緩衝區移除
    3. 背景執行緒 run() 持續輪詢緩衝區,對每個被按下的鍵觸發遊戲邏輯

完整實作

1. 按鍵事件管理類


import javax.microedition.lcdui.*;

public class KeyEventManager implements Runnable {
    private Canvas canvas;           // 回呼目標
    private byte[] pressedKeys = new byte[2];  // 環狀緩衝區
    private int writeIndex = 0;      // 寫入指標
    private boolean hasPressedKey = false;     // 快速檢查旗標

    public KeyEventManager(Canvas canvas) {
        this.canvas = canvas;
        new Thread(this).start();
    }

    // 鍵按下:寫入環狀緩衝區
    public synchronized void startAction(int keyCode) {
        pressedKeys[writeIndex] = (byte) keyCode;
        writeIndex = (writeIndex + 1) % pressedKeys.length;
        hasPressedKey = true;
    }

    // 鍵釋放:從緩衝區移除
    public synchronized void stopAction(int keyCode) {
        for (int i = 0; i < pressedKeys.length; i++) {
            if (pressedKeys[i] == keyCode) {
                pressedKeys[i] = 0;
                break;
            }
        }
        // 更新旗標
        hasPressedKey = false;
        for (byte k : pressedKeys) if (k != 0) { hasPressedKey = true; break; }
    }

    // 檢查是否有按鍵被按住
    public synchronized boolean hasPressedKeys() {
        return hasPressedKey;
    }

    // 取得目前按鍵快照(供執行緒讀取)
    public synchronized byte[] getPressedKeysSnapshot() {
        return pressedKeys.clone();
    }

    // 背景執行緒主迴路
    public void run() {
        while (true) {
            if (hasPressedKeys()) {
                byte[] keys = getPressedKeysSnapshot();
                for (byte keyCode : keys) {
                    if (keyCode != 0) {
                        handleGameAction(keyCode);
                    }
                }
                canvas.repaint();
            }
            try { Thread.sleep(10); } catch (InterruptedException e) {}
        }
    }

    // 實際遊戲邏輯處理
    private void handleGameAction(int keyCode) {
        int action = canvas.getGameAction(keyCode);
        // 假設 Canvas 有 x, y 座標屬性
        switch (action) {
            case Canvas.UP:    canvas.y--; break;
            case Canvas.DOWN:  canvas.y++; break;
            case Canvas.LEFT:  canvas.x--; break;
            case Canvas.RIGHT: canvas.x++; break;
            case Canvas.FIRE:  /* 射擊/確認 */ break;
        }
    }
}

2. Canvas 整合


public class GameCanvas extends Canvas {
    public int x = 50, y = 50;  // 角色座標
    private KeyEventManager keyManager;

    public GameCanvas() {
        keyManager = new KeyEventManager(this);
    }

    protected void keyPressed(int keyCode) {
        keyManager.startAction(keyCode);
    }

    protected void keyReleased(int keyCode) {
        keyManager.stopAction(keyCode);
    }

    protected void paint(Graphics g) {
        g.setColor(0xFFFFFF);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(0xFF0000);
        g.fillRect(x, y, 8, 8);  // 繪製角色方塊
    }
}

組合鍵應用範例


// 在 handleGameAction 中檢測組合鍵
private void handleGameAction(int keyCode) {
    byte[] keys = getPressedKeysSnapshot();
    boolean up = false, left = false, fire = false;
    for (byte k : keys) {
        int a = canvas.getGameAction(k);
        if (a == Canvas.UP) up = true;
        else if (a == Canvas.LEFT) left = true;
        else if (a == Canvas.FIRE) fire = true;
    }

    if (up && left) { /* 左上斜向移動 */ }
    if (fire && up) { /* 跳躍射擊 */ }
    // ... 其他組合
}

優缺點分析

優點缺點/限制
無需平台支援 keyRepeated手機鍵盤緊湊,三鍵以上極難操作
同時實現長按重複與組合鍵輪詢間隔 (sleep 10ms) 影響回應速度
邏輯集中於單一執行緒,易維護需妥善處理 synchronized 避免死鎖
跨裝置相容性極佳 (MIDP 1.0+)環狀緩衝區固定長度限制同時鍵數

改進建議

  1. 動態陣列:改用 Vector 儲存按鍵,支援任意數量同時鍵
  2. 事件驅動替代輪詢:若平台支援 keyRepeated,優先使用原生事件
  3. 按鍵去抖動:加入按下時間戳記,過濾極短抖動
  4. 優先級處理:組合鍵優先於單鍵,避免衝突

這個模式在 MIDP 1.0 時代被廣泛採用,雖然現代裝置多支援原生重複事件,但其組合鍵偵測邏輯在觸控不普及的鍵盤手機上仍具實用價值。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved