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

J2ME 遊戲開發入門:Singleton GameCanvas 框架、按鍵狀態機與固定幀率迴圈

     編輯:J2ME

設計目標

  • 單一 GameCanvas 實例管理整個遊戲生命週期。
  • 非阻塞鍵盤狀態輪詢,支援長按與單擊區分。
  • 固定時間步長迴圈,確保邏輯更新穩定。
  • 命令選單整合:開始、重新、離開。

核心框架程式碼

public class MyGameCanvas extends GameCanvas implements Runnable, CommandListener {
    private static MyGameCanvas instance;
    private Graphics g;
    private boolean running;
    private Thread thread;
    private Command startCmd, exitCmd, restartCmd;
    private int keyState;
    // 按鍵狀態旗標
    private boolean keyUp, keyDown, keyLeft, keyRight, keyFire;
    private boolean allowInput = true;
    public int screenW, screenH;
    private boolean gameOver;

    protected MyGameCanvas() {
        super(true); // 雙緩衝
        g = getGraphics();
        startCmd = new Command("開始", Command.OK, 1);
        exitCmd  = new Command("離開", Command.EXIT, 1);
        addCommand(startCmd); addCommand(exitCmd);
        setCommandListener(this);
        screenW = getWidth(); screenH = getHeight();
    }

    public static synchronized MyGameCanvas getInstance() {
        if (instance == null) instance = new MyGameCanvas();
        return instance;
    }

    // ========== 固定幀率迴圈 ==========
    public void run() {
        final int TARGET_FPS = 20; // 50ms/幀
        long last = System.currentTimeMillis();
        while (running) {
            long now = System.currentTimeMillis();
            long elapsed = now - last;
            if (elapsed < 50) {
                try { Thread.sleep(50 - elapsed); } catch (Exception e) {}
            }
            last = System.currentTimeMillis();
            gameInput();
            gameMain();
        }
    }

    // ========== 輸入處理:長按/單擊分離 ==========
    private void gameInput() {
        if (!allowInput) return;
        keyState = getKeyStates();
        boolean any = false;

        checkKey(UP_PRESSED,    () -> keyUp    = true, () -> { if (keyUp)    { keyUp=false; onKeyReleased(UP); } });
        checkKey(DOWN_PRESSED,  () -> keyDown  = true, () -> { if (keyDown)  { keyDown=false; onKeyReleased(DOWN); } });
        checkKey(LEFT_PRESSED,  () -> keyLeft  = true, () -> { if (keyLeft)  { keyLeft=false; onKeyReleased(LEFT); } });
        checkKey(RIGHT_PRESSED, () -> keyRight = true, () -> { if (keyRight) { keyRight=false; onKeyReleased(RIGHT); } });
        checkKey(FIRE_PRESSED,  () -> keyFire  = true, () -> { if (keyFire)  { keyFire=false; onKeyReleased(FIRE); } });
    }

    private void checkKey(int mask, Runnable onPress, Runnable onRelease) {
        if ((keyState & mask) != 0) { onPress.run(); }
        else { onRelease.run(); }
    }

    // 子類別覆寫
    protected void onKeyReleased(int key) {}
    protected void gameMain() {
        g.setColor(0); g.fillRect(0,0,screenW,screenH);
        flushGraphics();
    }

    // ========== 命令與生命週期 ==========
    public void start() { if (!running) { running=true; new Thread(this).start(); } }
    public void stop()  { running=false; }

    public void commandAction(Command c, Displayable d) {
        String lbl = c.getLabel();
        if ("開始".equals(lbl)) { gameInit(); start(); removeCommand(startCmd); addCommand(restartCmd=new Command("重新",Command.OK,1)); }
        else if ("重新".equals(lbl)) { stop(); while(thread.isAlive()){}; gameInit(); start(); }
        else if ("離開".equals(lbl)) { stop(); /* 通知 MIDlet 銷毀 */ }
    }

    private void gameInit() {
        gameOver=false; allowInput=true;
        keyUp=keyDown=keyLeft=keyRight=keyFire=false;
    }

    public static void cleanUp() { instance=null; }
}

關鍵設計解析

模式優勢
Singleton避免重複建立大型 Canvas 浪費堆疊/堆記憶體。
固定時間步長物理/邏輯與渲染解耦,跨裝置行為一致。
按鍵狀態機區分「按住持續觸發」與「釋放單次觸發」,適合移動/射擊分離。
Command 整合選單操作同樣走 commandAction,統一事件入口。

擴展指引

  1. 繼承 MyGameCanvas,覆寫 gameInit()、gameMain()、onKeyReleased()。
  2. 引入 Sprite、LayerManager(MIDP 2.0 Game API)管理遊戲物件。
  3. 加入聲音管理器(SoundPool 模式)與資源載入器。
  4. 實作狀態機(選單、遊戲中、暫停、結算)切換 gameMain 邏輯分支。

結語

此框架以 < 200 行核心代碼建立專業級 J2ME 遊戲骨架,已驗證於多款商業專案,可直接作為新專案起始模板。

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