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

J2ME 行動裝置動畫實現全攻略 (MIDP 1.0/2.0)

     編輯:J2ME

前言

MIDP 1.0 無內建動畫 API (MIDP 2.0 引入 Game API/LayerManager),但自行實現幀動畫並不複雜。核心原理:固定時間間隔切換預載入的連續圖片幀,利用視覺暫留形成動態效果。本文詳細講解從素材準備、核心類設計、雙重緩衝繪製到完整 MIDlet 範例。

素材準備規範

  • 每幀等尺寸 PNG 圖片 (MIDP 唯一支援格式)
  • 幀數越多越流暢,但記憶體/包體積權衡 (典型 6~12 幀)
  • 命名規則:bird0.png ~ bird6.png 便於批次載入
  • 打包方式:置於 JAR 內 (推薦) 或 HTTP 下載

核心類:AnimatedImage

封裝幀陣列、當前幀索引、裁切列表 (模擬透明)、Canvas 回呼、TimerTask 整合。

public class AnimatedImage extends TimerTask {
    private Canvas canvas;
    private Image[] frames;
    private int[][] clipList; // 每幀裁切矩形陣列 [x,y,w,h...] 模擬透明
    private int current = 0;
    private int x, y, w, h;

    // 建構子多載:支援帶/不帶 Canvas、帶/不帶 clipList
    public AnimatedImage(Canvas canvas, Image[] frames, int[][] clipList) { ... }

    // 推進到下一幀,選擇性觸發重繪
    public void advance(boolean repaint) {
        if (++current >= frames.length) current = 0;
        if (repaint && canvas != null && canvas.isShown()) {
            canvas.repaint(x, y, w, h);
            canvas.serviceRepaints();
        }
    }

    // 繪製當前幀:無 clipList 直接 drawImage;有則多次 setClip+drawImage 合成透明效果
    public void draw(Graphics g) { ... }

    // TimerTask 執行入口
    public void run() { if (w>0 && h>0) advance(true); }

    // 位置控制
    public void move(int x, int y) { this.x = x; this.y = y; }
}

關鍵細節:ClipList 模擬透明

MIDP 1.0 不支援 Alpha 通道。將每幀不透明區域拆解為若干矩形 (clipList),繪製時逐一切換 Clip 區域繪製同一張圖,拼湊出非矩形輪廓。注意:過多 Clip 會降低效能,複雜形狀建議改用向量繪圖或 MIDP 2.0 透明 PNG。

雙重緩衝畫布:AnimatedCanvas

class AnimatedCanvas extends Canvas {
    private Vector animations = new Vector(); // AnimatedImage 集合
    private Image offscreen; // 離屏緩衝

    public void add(AnimatedImage ai) { animations.addElement(ai); }

    protected void paint(Graphics g) {
        Graphics target = g;
        if (offscreen != null) target = offscreen.getGraphics(); // 導向離屏

        target.setColor(0xFFFFFF);
        target.fillRect(0, 0, getWidth(), getHeight());

        for (int i = 0; i < animations.size(); i++) {
            ((AnimatedImage)animations.elementAt(i)).draw(target);
        }

        if (target != g) // 離屏模式:一次性貼回螢幕
            g.drawImage(offscreen, 0, 0, Graphics.LEFT | Graphics.TOP);
    }
}

離屏緩衝消除閃爍,批次繪製提升效能。

完整 MIDlet 範例:隨機飛鳥動畫

public class AnimationTest extends MIDlet implements CommandListener {
    private static final int BIRD_FRAMES = 7;
    private static final int NUM_BIRDS = 5;

    private Display display;
    private Timer timer = new Timer();
    private AnimatedImage[] birds;
    private Random random = new Random();
    private Command exitCmd = new Command("Exit", Command.EXIT, 1);

    protected void startApp() {
        if (display == null) {
            display = Display.getDisplay(this);
            initMIDlet();
        }
    }

    private void initMIDlet() {
        try {
            AnimatedCanvas canvas = new AnimatedCanvas(display);
            Image[] frames = loadFrames("/images/bird", BIRD_FRAMES); // 載入 7 幀

            int w = canvas.getWidth(), h = canvas.getHeight();
            birds = new AnimatedImage[NUM_BIRDS];
            for (int i = 0; i < NUM_BIRDS; i++) {
                birds[i] = new AnimatedImage(canvas, frames);
                birds[i].move(randomInt(w), randomInt(h));
                canvas.add(birds[i]);
                // 隨機啟動延遲 0~1000ms,幀率 250~650ms/幀
                timer.schedule(birds[i], randomInt(1000), randomInt(400) + 200);
            }
            canvas.addCommand(exitCmd);
            canvas.setCommandListener(this);
            display.setCurrent(canvas);
        } catch (IOException e) { exitMIDlet(); }
    }

    private Image[] loadFrames(String name, int count) throws IOException {
        Image[] imgs = new Image[count];
        for (int i = 0; i < count; i++)
            imgs[i] = Image.createImage(name + i + ".png");
        return imgs;
    }
    // commandAction, pauseApp, destroyApp, exitMIDlet, randomInt 略
}

進階優化建議

  • 幀率自適應:根據裝置效能動態調整 Timer 間隔
  • 記憶體池:共用相同動畫的幀陣列 (範例中 birds 共用 frames)
  • 暫停/恢復:pauseApp() 取消 Timer,startApp() 重建
  • MIDP 2.0 升級:改用 LayerManager + Sprite 獲得硬體加速與內建碰撞檢測

總結

J2ME 動畫核心三步:素材標準化 → AnimatedImage 封裝幀邏輯 → Canvas 雙重緩衝批次繪製。MIDP 1.0 下以 TimerTask 驅動幀推進,配合 ClipList 模擬透明,即可實現流暢動畫。掌握此模式,輕鬆構建遊戲角色、UI 特效、過場動畫等核心視覺元素。

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