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

J2ME 精靈系統深度封裝:從 Sprite 到 GameObject 再到 Helicopter 組合模式

     編輯:J2ME

前言:原生 Sprite 好用嗎?「不夠方便」

J2ME javax.microedition.game.Sprite 提供基本幀動畫、位置、可見性,但實戰中缺失:

  • 幀率控制(每幀強制切換 vs. 每 N 幀切換)
  • 生命週期管理(存活標記、自動銷毀計時)
  • 複合物件支援(直升機 = 機身 + 螺旋槳 + 爆炸特效)

作者採用漸進式封裝:Sprite → GameObject → Helicopter,展示組合優於繼承的經典實踐。

第一層:GameObject —— 賦予 Sprite「生命」與「節奏」

public class GameObject {
    public Sprite sprite;      // 內嵌原生 Sprite
    public boolean alive;      // 存活標記
    public int lifetime = 0;   // 總存活幀數(0=永久)
    public int speed = 0;      // 動畫速度:0=每幀切幀,N=每 N 幀切幀

    private int lifecount = 0; // 已存活幀數
    private int animcount = 0; // 動畫計數器

    public GameObject(Image img, int frameW, int frameH) {
        sprite = new Sprite(img, frameW, frameH);
        reset();
    }

    public void move(int dx, int dy) { sprite.move(dx, dy); }
    public void moveto(int x, int y) { sprite.setPosition(x, y); }

    // 核心:每幀呼叫一次
    public void update() {
        if (!alive) return;
        // 動畫幀率控制
        if (++animcount > speed) {
            animcount = 0;
            sprite.nextFrame();
        }
        // 生命週期倒數
        if (lifetime != 0 && ++lifecount > lifetime) alive = false;
    }

    public void paint(Graphics g) { if (alive) sprite.paint(g); }

    public void reset() { alive = true; lifecount = 0; animcount = 0; sprite.setFrame(0); }
}

設計精華

第二層:Helicopter —— 組合三個 GameObject

public class Helicopter {
    public boolean alive;        // 整體存活(含爆炸播放中)
    public boolean dying = false;// 進入爆炸流程

    private GameObject heliBody; // 機身:單幀、永久
    private GameObject heliScrew;// 螺旋槳:多幀循環、永久
    private GameObject exploit;  // 爆炸:多幀、4幀後銷毀

    private Rect playerRect;     // 碰撞矩形(自定義類)

    public Helicopter() {
        alive = true;
        try {
            Image img = Image.createImage("/res/helicopter.png"); // 12×28
            heliBody = new GameObject(img, 12, 28);
            heliBody.lifetime = 1; // 特殊標記:單幀不動畫
        } catch (IOException e) { e.printStackTrace(); }

        try {
            Image img = Image.createImage("/res/screws.png"); // 8×24,多幀
            heliScrew = new GameObject(img, 8, 24);
            heliScrew.lifetime = 7; // 7 幀循環
        } catch (IOException e) { e.printStackTrace(); }

        try {
            Image img = Image.createImage("/res/exploit.png"); // 30×30,4 幀
            exploit = new GameObject(img, 30, 30);
            exploit.lifetime = 4; exploit.speed = 1; // 4 幀播完銷毀
        } catch (IOException e) { e.printStackTrace(); }

        playerRect = new Rect(0,0,0,0);
    }

    // 遊戲迴圈呼叫
    public void update() {
        if (dying) {
            if (exploit.alive) exploit.update();
            else alive = false; // 爆炸播完 → 整體死亡
            return;
        }
        // 正常:螺旋槳持續轉動
        if (heliScrew.alive) heliScrew.update();
        else heliScrew.reset(); // 理論不會死,保險重置
    }

    // 位置同步:三個部件 + 碰撞盒
    public void moveto(int x, int y) {
        playerRect.top = y; playerRect.left = x;
        playerRect.right = x + 16; playerRect.bottom = y + 34; // 碰撞盒略大於圖片
        exploit.moveto(x, y);
        heliScrew.moveto(x, y);
        heliBody.moveto(x + 4, y + 6); // 機身相對偏移,對齊視覺中心
    }

    public void paint(Graphics g) {
        if (dying && alive) { exploit.paint(g); return; }
        if (!alive) return;
        heliBody.paint(g);
        heliScrew.paint(g);
    }

    public Rect getPlayerRect() { return playerRect; }
}

組合模式優勢

  1. 關注點分離: 機身靜態、螺旋槳循環、爆炸一次性,各自獨立 lifetime/speed 參數。
  2. 狀態機內聚: dying 標記切換渲染/更新分支,無需外部管理。
  3. 碰撞盒解耦: playerRect 依視覺微調(+4,+6、16×34),不綁定圖片像素尺寸。
  4. 資源隔離: 三張圖片獨立載入/釋放,記憶體峰值可控。

圖片資源規劃

特性原生 SpriteGameObject
動畫速度無(每幀 nextFrame)speed 參數化,支援慢動作/快轉
自動銷毀無lifetime 幀數後自動 alive=false
重置復用手動reset() 一鍵歸零,支援物件池
繪製守衛無if(!alive)return 避免繪製殘留
檔案尺寸幀數用途
helicopter.png12×281機身靜態
screws.png8×247螺旋槳旋轉循環
exploit.png30×304爆炸一次性動畫

載入策略: 建構子中同步載入(Image.createImage),若圖片較大建議改為非同步預載入(背景執行緒 + MediaTracker 模擬),避免啟動卡頓。

擴展建議:從直升機到通用實體體系

// 介面化
interface IUpdatable { void update(); }
interface IRenderable { void paint(Graphics g); }
interface IPositionable { void moveto(int x, int y); Rect getBounds(); }

// 基礎實體
abstract class Entity implements IUpdatable, IRenderable, IPositionable {
    protected List parts = new Vector();
    public void update() { for (GameObject o: parts) o.update(); }
    public void paint(Graphics g) { for (GameObject o: parts) if (o.alive) o.paint(g); }
    public void moveto(int x, int y) { for (GameObject o: parts) o.moveto(x, y); }
}

// 直升機繼承 Entity,只需在建構子組裝 parts
// 敵機、子彈、道具同理,統一納入 LayerManager 或自定義 EntityManager

總結

本文展示了在 J2ME 受限環境下,如何以 「薄封裝 + 組合」 將原生 Sprite 昇級為具備幀率控制、生命週期、複合渲染、狀態機的實用精靈系統。GameObject 僅 50 行代碼卻解決 80% 痛點;Helicopter 證明組合模式比繼承更適合「多部件、多狀態」遊戲實體。此設計思想直接映射至現代引擎的 GameObject + Component(Unity)、Entity + Component(ECS)、Node + Sprite(Cocos2d-x)架構。

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