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

J2ME 俄羅斯方塊遊戲完整實現 (一):架構設計、界面渲染、輸入處理、主循環

     編輯:Java 相關知識

項目架構概覽

經典三層 J2ME 遊戲架構:

  • TerrisMIDlet:應用入口,啟動顯示
  • GameCanvas:繼承 Canvas 實現 Runnable,負責渲染管線、輸入事件、遊戲主循環
  • GameEngine:純邏輯類,封裝方塊數據、地圖狀態、運動算法、分數計算,無 UI 依賴

測試環境:WTK 2.5.1 運行通過。

核心類實現

1. TerrisMIDlet - 極簡入口


public class TerrisMIDlet extends MIDlet {
    public TerrisMIDlet() {
        Display.getDisplay(this).setCurrent(new GameCanvas());
    }
    protected void destroyApp(boolean unconditional) {}
    protected void pauseApp() {}
    protected void startApp() {}
}

2. GameCanvas - 遊戲主視圖與循環


public class GameCanvas extends Canvas implements Runnable {
    private GameEngine engine = new GameEngine();
    private int width, height;
    private boolean gameOver = false;
    private boolean isPaused = false;
    private final String pauseStr = "暫停", continueStr = "繼續";
    
    public GameCanvas() {
        setFullScreenMode(true);           // 全屏模式
        width = getWidth(); height = getHeight();
        new Thread(this).start();          // 啟動遊戲循環線程
    }
    
    // 渲染管線
    protected void paint(Graphics g) {
        clearScreen(g);                    // 1. 清屏
        paintBoard(g);                     // 2. 邊框
        engine.paintMap(g);                // 3. 地圖已固化方塊
        engine.paintBrick(g);              // 4. 當前下落方塊
        engine.paintNextBrick(g);          // 5. 下一個方塊預覽
        engine.paintLevelAndScore(g);      // 6. 分數/等級
        
        if (gameOver) 
            g.drawString("Game Over", 30, 85, Graphics.TOP | Graphics.LEFT);
        
        // 暫停/繼續提示 (右下角)
        g.drawString(isPaused ? pauseStr : continueStr, 
                     width, height, Graphics.RIGHT | Graphics.BOTTOM);
    }
    
    // 輸入處理
    public void keyPressed(int keyCode) {
        if (keyCode == -7) {               // 右軟鍵:暫停/繼續切換
            isPaused = !isPaused; return;
        }
        if (isPaused) return;              // 暫停狀態忽略遊戲按鍵
        
        int action = getGameAction(keyCode); // 映射為標準遊戲鍵
        switch (action) {
            case UP:    case FIRE: engine.changeShape(); break; // 旋轉
            case LEFT:  engine.moveToLeft();  break;
            case RIGHT: engine.moveToRight(); break;
            case DOWN:  engine.highSpeed();   break; // 加速下落
        }
        repaint();
    }
    
    public void keyReleased(int keyCode) {
        int action = getGameAction(keyCode);
        if (action == DOWN) engine.normalSpeed(); // 釋放下鍵恢復正常速度
    }
    
    // 輔助繪製
    private void paintBoard(Graphics g) {
        g.drawRect(0, 0, 
            engine.MAXCOL * engine.CELLWIDTH, 
            engine.MAXROW * engine.CELLWIDTH);
    }
    
    private void clearScreen(Graphics g) {
        g.setColor(0xffffff); g.fillRect(0, 0, width, height);
        g.setColor(0);
    }
    
    // 遊戲主循環
    public void run() {
        try {
            while (true) {
                Thread.sleep(engine.speed / engine.times); // 速度/加速因子
                
                if (!isPaused) {
                    engine.brickDown();                 // 邏輯更新
                    if (engine.isGameOver()) {          // 結束判定
                        gameOver = true;
                        repaint();
                        break;                          // 退出循環
                    }
                }
                repaint();                              // 幀渲染
            }
        } catch (Exception e) { e.printStackTrace(); }
    }
}

3. GameEngine - 遊戲數據與邏輯核心 (上)


public class GameEngine {
    // 7種方塊 × 旋轉態數 × 4×4 矩陣 (0=空, 1=實心)
    // I, J, L, O, S, T, Z 型完整定義
    int[][][][] brick = { /* 見源碼完整數據 */ };
    
    // 遊戲區域常量
    final int MAXROW = 19;      // 行數
    final int MAXCOL = 10;      // 列數
    public static final int CELLWIDTH = 10; // 像素大小
    
    // 地圖狀態
    int[][] map = new int[MAXROW][MAXCOL];
    
    // 遊戲狀態變量
    int nextBrickType = 0;      // 下一個方塊類型
    int brickType, index;       // 當前方塊類型、旋轉態
    int cRow, cCol;             // 當前方塊左上角在地圖中的位置
    int speed = 500;            // 基礎下落間隔 (ms)
    int times = 1;              // 加速倍數
    int level = 0;              // 關卡
    int score = 0;              // 分數 (每行10分)
    Random r = new Random();
    
    public GameEngine() { gernerateBrick(); }
    
    // 單格繪製 (3層漸變效果)
    private void paintCell(Graphics g, int x, int y) {
        g.setColor(0);                           // 黑色邊框
        g.drawRect(x, y, CELLWIDTH, CELLWIDTH);
        g.setColor(0xffffff);                    // 白色內框
        g.fillRect(x+1, y+1, CELLWIDTH-2, CELLWIDTH-2);
        g.setColor(0);                           // 黑色核心
        g.fillRect(x+2, y+2, CELLWIDTH-4, CELLWIDTH-4);
    }
    
    // 地圖渲染
    public void paintMap(Graphics g) {
        for (int row = 0; row < MAXROW; row++)
            for (int col = 0; col < MAXCOL; col++)
                if (map[row][col] == 1)
                    paintCell(g, col * CELLWIDTH, row * CELLWIDTH);
    }
    // ... 其餘邏輯方法見下篇
}

關鍵設計要點

層面設計決策優勢
分層MIDlet/Canvas/Engine 三層分離邏輯可單測、UI 可替換、符合 MVC
主循環獨立線程 + Thread.sleep 固定幀率簡單可靠、J2ME 標準模式
渲染管線清屏→邊框→地圖→當前方塊→預覽→UI 疊加層次分明、繪製順序正確
輸入映射getGameAction() 標準化鍵盤跨設備兼容 (鍵盤/觸屏/手柄)
暫停機制右軟鍵切換 isPaused,邏輯/渲染雙重守護即時響應、無幀丟失
加速下落按下/釋放下鍵切換 times 倍率手感自然、實現簡單
方塊數據4維數組 [type][rotation][row][col]查詢 O(1)、內存緊湊、易擴展新方塊
單格繪製三層矩形漸變 (邊框/高光/核心)偽 3D 效果、視覺層次豐富

方塊數據結構說明

brick[7][max_rotations][4][4] 完整定義了 7 種標準方塊 (I/J/L/O/S/T/Z) 的所有旋轉態:

  • I 型:2 種態 (橫/豎)
  • O 型:1 種態 (正方形)
  • 其餘:4 種態 (0°/90°/180°/270°)

總計 19 個旋轉態,每態 4×4 矩陣,1 表示實心格子。這種預計算查表法避免了運行時旋轉變換運算,極大降低 CPU 佔用,適合 J2ME 受限環境。

運行流程時序


MIDlet.startApp()
  → new GameCanvas()
      → setFullScreenMode()
      → new Thread(run).start()
          → loop:
              sleep(speed/times)
              if !paused:
                  engine.brickDown()      // 邏輯幀
                  if engine.isGameOver(): break
              repaint()                   // 渲染幀
                  → paint()
                      → clearScreen()
                      → paintBoard()
                      → engine.paintMap()
                      → engine.paintBrick()
                      → engine.paintNextBrick()
                      → engine.paintLevelAndScore()
                      → draw GameOver/Pause overlay

總結

這個實現展示了 J2ME 遊戲開發的標準最佳實踐:

  1. 架構清晰:三層分離,職責單一
  2. 渲染高效:定點繪製、預計算方塊數據、最小化繪製調用
  3. 輸入健壯:標準鍵映射、暫停/加速狀態機完善
  4. 邏輯完整:核心規則 (移動/旋轉/消行/結束) 全覆蓋
  5. 代碼可維護:常量集中、方法單一職責、註釋清晰

下篇將深度解析 GameEngine 中的運動算法、碰撞檢測、消行邏輯及遊戲結束判定。

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