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

MIDP 1.0 鍵盤輸入處理完全指南

     編輯:J2ME

前言

互動遊戲核心在於輸入響應。MIDP 1.0 提供三層鍵盤抽象:**原始鍵碼 → 遊戲動作 → 高級事件**。理解三者關係與差異,是跨機型輸入處理的基石。

三層抽象模型

層級API特點適用場景
原始鍵碼keyPressed(int keyCode)
getKeyName(keyCode)
設備特定、數值固定 (0=48, 9=57, * =42, # =35)
方向鍵常為負值 (-1~-7)
文字輸入、特定功能鍵、除錯
遊戲動作getGameAction(keyCode)
返回:
UP/DOWN/LEFT/RIGHT/FIRE/
GAME_A~D
**跨平台標準化**,將物理鍵映射為邏輯動作
僅覆蓋 8~12 個常用動作
**遊戲移動/確認/取消/選單** 核心邏輯
高級事件CommandListener
Command + 軟鍵
UI 導向、系統分發、支援長按選單選單、對話框、表單操作

三種按鍵事件回呼

protected void keyPressed(int keyCode)   { /* 按下瞬間 */ }
protected void keyRepeated(int keyCode)  { /* 長按重複 (設備依賴) */ }
protected void keyReleased(int keyCode)  { /* 鬆開瞬間 */ }

注意:keyRepeated 並非所有設備支援,遊戲長按邏輯建議自行在主迴路用狀態機實現。

方案一:直接在 keyPressed 用 switch (keyCode) — 僅限測試/單機型

public void keyPressed(int keyCode) {
    switch (keyCode) {
        case 48: case 49: case 50: /* 數字鍵 */ break;
        case -1: /* UP */ break; // 某設備方向鍵
        default: break;
    }
}

缺點:硬編碼鍵碼,移植必改代碼,邏輯與輸入耦合。

方案二:標準遊戲動作 — 推薦基礎跨平台做法

public void keyPressed(int keyCode) {
    int action = getGameAction(keyCode);
    switch (action) {
        case Canvas.UP:    y = Math.max(0, y - 2); break;
        case Canvas.DOWN:  y = Math.min(getHeight(), y + 2); break;
        case Canvas.LEFT:  x = Math.max(0, x - 2); break;
        case Canvas.RIGHT: x = Math.min(getWidth(), x + 2); break;
        case Canvas.FIRE:  shoot(); break;
    }
}

優點:零配置適配大多數手機方向鍵/確認鍵。缺點:無法覆蓋數字鍵、*、#、軟鍵等擴充功能。

方案三:虛擬鍵位狀態機 — 專業遊戲標準架構

核心設計

  1. 32-bit 狀態整數 keyState,每 bit 對應一虛擬鍵 (Bit 0=UP, 1=DOWN, 2=LEFT, 3=RIGHT, 4=FIRE, 5=数字0...)
  2. keyPressed/Released 只負責 **映射物理鍵碼 → 設定/清除對應 bit**
  3. 遊戲邏輯 (主迴路/更新函數) **唯讀檢查** (keyState & MASK) != 0
  4. 映射函數 mapKeyCode(int keyCode) -> int virtualBit **每機型一份實現**

代碼骨架

public class InputManager {
    // 虛擬鍵位掩碼
    public static final int VK_UP        = 1 << 0;
    public static final int VK_DOWN      = 1 << 1;
    public static final int VK_LEFT      = 1 << 2;
    public static final int VK_RIGHT     = 1 << 3;
    public static final int VK_FIRE      = 1 << 4;
    public static final int VK_NUM0      = 1 << 5;
    // ... 至 VK_NUM9, VK_STAR, VK_POUND, VK_SOFT1, VK_SOFT2

    private int keyState = 0;

    // Canvas 回呼委託
    public void onKeyPressed(int keyCode) {
        int vk = mapKeyCode(keyCode);
        if (vk != 0) keyState |= vk;
    }
    public void onKeyReleased(int keyCode) {
        int vk = mapKeyCode(keyCode);
        if (vk != 0) keyState &= ~vk;
    }

    // 邏輯層查詢
    public boolean isPressed(int vk) { return (keyState & vk) != 0; }
    public boolean isJustPressed(int vk) { /* 需額外記錄前幀狀態 */ return false; }

    // --- 每機型專屬實現 ---
    protected int mapKeyCode(int keyCode) {
        // 預設:標準遊戲動作映射
        int action = Canvas.getGameAction(keyCode); // 需實例或靜態輔助
        switch (action) {
            case Canvas.UP: return VK_UP;
            case Canvas.DOWN: return VK_DOWN;
            case Canvas.LEFT: return VK_LEFT;
            case Canvas.RIGHT: return VK_RIGHT;
            case Canvas.FIRE: return VK_FIRE;
        }
        // 數字鍵通用映射 (ASCII 碼)
        if (keyCode >= '0' && keyCode <= '9') return VK_NUM0 << (keyCode - '0');
        if (keyCode == '*') return VK_STAR;
        if (keyCode == '#') return VK_POUND;
        // 方向鍵負值常見映射 (Nokia/SonyEricsson)
        switch (keyCode) {
            case -1: return VK_UP;
            case -2: return VK_DOWN;
            case -3: return VK_LEFT;
            case -4: return VK_RIGHT;
            case -5: return VK_FIRE;
            case -6: return VK_SOFT1;
            case -7: return VK_SOFT2;
        }
        return 0; // 未識別
    }
}

Motorola 等特殊機型映射表

// Motorola V600 等
case 1: return VK_UP;      // 實際測試獲取
case 6: return VK_DOWN;
case 2: return VK_LEFT;
case 5: return VK_RIGHT;
case 20: return VK_FIRE;
case 22: return VK_SOFT1;
case 21: return VK_SOFT2;
case 10: return VK_NUM0; // 視具體定義

進階:長按/連擊/組合鍵檢測

  • 長按:主迴路記錄 pressStartTime[vk],超過閾值觸發加速/連發
  • 連擊:記錄 lastReleaseTime[vk],兩次間隔 < 300ms 判定雙擊
  • 組合鍵:(keyState & (VK_LEFT | VK_FIRE)) == (VK_LEFT | VK_FIRE) 同時按下

完整範例:方塊移動 Demo

public class InputDemo extends Canvas implements Runnable {
    private int x, y, speed = 3;
    private InputManager input = new InputManager();

    public InputDemo() {
        x = getWidth()/2; y = getHeight()/2;
        new Thread(this).start();
    }
    protected void keyPressed(int k) { input.onKeyPressed(k); }
    protected void keyReleased(int k) { input.onKeyReleased(k); }
    public void run() {
        while (true) {
            if (input.isPressed(InputManager.VK_UP))    y = Math.max(0, y - speed);
            if (input.isPressed(InputManager.VK_DOWN))  y = Math.min(getHeight(), y + speed);
            if (input.isPressed(InputManager.VK_LEFT))  x = Math.max(0, x - speed);
            if (input.isPressed(InputManager.VK_RIGHT)) x = Math.min(getWidth(), x + speed);
            repaint(); serviceRepaints();
            try { Thread.sleep(33); } catch (Exception e) {}
        }
    }
    protected void paint(Graphics g) {
        g.setColor(0xFFFFFF); g.fillRect(0,0,getWidth(),getHeight());
        g.setColor(0); g.fillRect(x, y, 20, 20);
    }
}

總結

MIDP 1.0 鍵盤處理**進化路徑**:硬編碼 keyCode → getGameAction() 標準動作 → 虛擬鍵位狀態機 + 映射表。專業遊戲**必須採用方案三**,將平台差異封裝在 mapKeyCode() 單一函數,上層邏輯純粹查詢位掩碼,實現真正的「一碼多機」與複雜輸入組合支援。

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