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

J2ME 2D 遊戲開發入門(一):GameCanvas 單例框架與輸入系統

     編輯:Java 相關知識

構建 J2ME 遊戲的骨架:基於 GameCanvas 的單例框架、固定幀率主循環、鍵盤事件系統 (按下/釋放/長按區分)、命令菜單 (開始/重來/退出)。

核心類:MyGameCanvas

public class MyGameCanvas extends GameCanvas implements Runnable, CommandListener {
    // 單例
    private static MyGameCanvas instance;
    public static synchronized MyGameCanvas getInstance() {
        if (instance == null) instance = new MyGameCanvas();
        return instance;
    }
    public static void cleanJob() { instance = null; }

    // 狀態
    private Graphics g;
    private boolean running;
    private Thread thread;
    private int frameRate = 50; // ms, ~20 FPS

    // 輸入狀態
    private boolean allowInput;
    public boolean keyUp, keyDown, keyLeft, keyRight, keyFire;
    public boolean keyEvent; // 本幀是否有按鍵

    // 命令
    private Command startCmd, exitCmd, restartCmd;

    // 遊戲變量
    public int screenW, screenH;
    public boolean gameOver;
    // ... 自定義變量

    protected MyGameCanvas() {
        super(true); // 雙緩衝
        g = getGraphics();
        screenW = getWidth(); screenH = getHeight();

        // 命令菜單
        startCmd = new Command("Start", Command.OK, 1);
        exitCmd = new Command("Exit", Command.EXIT, 1);
        addCommand(startCmd); addCommand(exitCmd);
        setCommandListener(this);

        // 一次性初始化 (載入圖片、聲音等)
    }

    // 主循環
    public void run() {
        long start, end, diff;
        while (running) {
            start = System.currentTimeMillis();
            gameInput();   // 輸入
            gameMain();    // 邏輯+渲染
            end = System.currentTimeMillis();
            diff = end - start;
            if (diff < frameRate) {
                try { Thread.sleep(frameRate - diff); }
                catch (InterruptedException ignored) {}
            }
        }
    }

    // 輸入處理:區分按下/長按/釋放
    private void gameInput() {
        if (!allowInput) return;
        int ks = getKeyStates();
        keyEvent = false;

        checkKey(ks, UP_PRESSED,    () -> keyUp    = true, () -> keyUp    = false);
        checkKey(ks, DOWN_PRESSED,  () -> keyDown  = true, () -> keyDown  = false);
        checkKey(ks, LEFT_PRESSED,  () -> keyLeft  = true, () -> keyLeft  = false);
        checkKey(ks, RIGHT_PRESSED, () -> keyRight = true, () -> keyRight = false);
        checkKey(ks, FIRE_PRESSED,  () -> keyFire  = true, () -> keyFire  = false);

        // keyEvent = keyUp|keyDown|keyLeft|keyRight|keyFire (任意為 true)
    }

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

    // 邏輯+渲染入口 (子類/外部實現)
    private void gameMain() {
        g.setColor(0x000000);
        g.fillRect(0, 0, screenW, screenH); // 清屏
        // background.paint(g); plane.paint(g); ...
        flushGraphics(); // 雙緩衝翻轉
    }

    // 生命週期
    public void start() { if (!running) { running=true; thread=new Thread(this); thread.start(); } }
    public void stop() { running=false; }
    private void gameInit() { gameOver=false; /* 重置變量 */ }

    // 命令響應
    public void commandAction(Command c, Displayable d) {
        String cmd = c.getLabel();
        if ("Start".equals(cmd)) { gameInit(); start(); removeCommand(startCmd); addCommand(restartCmd=new Command("Restart",Command.OK,1)); }
        else if ("Restart".equals(cmd)) { stop(); while(thread.isAlive()); gameInit(); start(); }
        else if ("Exit".equals(cmd)) { stop(); /* 通知 MIDlet 銷毀 */ }
    }
}

關鍵設計決策

擴展點

  • gameInit():每局重置邏輯 (位置、分數、敵人生成)。
  • gameMain():核心邏輯渲染管線,後續接入背景、飛機、子彈、特效、UI。
  • allowInput:暫停/菜單時禁用遊戲輸入。

此框架簡潔穩健,支撐了整個系列教程的所有遊戲邏輯。下一篇構建工具類庫。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
決策理由
單例模式GameCanvas 佔用大量堆內存 (雙緩衝),全程僅需一個實例,避免重複創建 OOM
固定幀率 + 睡眠補齊確保邏輯確定性,節省電量,避免空跑佔用 CPU
輸入狀態機 (按下/釋放/長按)支援「按住移動」與「單擊觸發」不同語義,關鍵於動作遊戲手感
命令菜單驅動狀態流轉Start → Running → Restart/Exit,清晰管理遊戲生命週期
雙緩衝 flushGraphics()消除閃爍,MIDP 2.0 標準特性