雙緩衝是遊戲開發核心技術,解決畫面閃爍與撕裂。MIDP 1.0 缺乏 game 套件,許多開發者自行實作。本文提供一個完整、可直接繼承的 GameCanvas 基礎類,支援區域重繪與全螢幕模式切換。
將螢幕視為黑板:先在記憶體建立「虛擬黑板」(Image),完成所有繪圖操作後,再一次性 drawImage 到真實螢幕。這樣可大幅提升繪圖效能、消除閃爍。
package org.wuhua.game;
import javax.microedition.lcdui.*;
public abstract class GameCanvas extends Canvas {
/** 離屏緩衝圖片,所有繪圖操作針對此圖片進行 */
private Image bufferImage;
private int width, height;
private int clipX, clipY, clipWidth, clipHeight;
private boolean useClip;
protected GameCanvas() {
super();
width = getWidth();
height = getHeight();
bufferImage = Image.createImage(width, height);
}
/** 系統呼叫:將緩衝圖片繪製到螢幕 */
protected void paint(Graphics g) {
if (useClip) {
g.clipRect(clipX, clipY, clipWidth, clipHeight);
useClip = false;
}
g.drawImage(bufferImage, 0, 0, Graphics.TOP | Graphics.LEFT);
}
/** 區域重繪:僅更新指定矩形區域 */
public void flushGraphics(int x, int y, int width, int height) {
useClip = true;
clipX = x; clipY = y; clipWidth = width; clipHeight = height;
repaint();
serviceRepaints();
}
/** 全螢幕重繪 */
public void flushGraphics() {
repaint();
serviceRepaints();
}
/** 子類呼叫:取得緩衝圖片的 Graphics 進行繪圖 */
protected Graphics getGraphics() {
return bufferImage.getGraphics();
}
/** 處理 Nokia 全螢幕模式切換:重建緩衝圖片適應新尺寸 */
protected void sizeChanged(int w, int h) {
if (h > height) {
bufferImage = Image.createImage(w, h);
}
}
}
public class MyGameCanvas extends GameCanvas {
public MyGameCanvas() {
// 構造器中自動建立緩衝
}
protected void updateGameLogic() {
// 1. 取得繪圖上下文
Graphics g = getGraphics();
// 2. 清背景
g.setColor(0xFFFFFF);
g.fillRect(0, 0, getWidth(), getHeight());
// 3. 繪製遊戲元素(角色、背景、UI...)
drawGameElements(g);
// 4. 刷新到螢幕
flushGraphics(); // 或 flushGraphics(x, y, w, h) 區域更新
}
}
getGraphics() 繪圖,flushGraphics() 刷新,無需關心雙緩衝細節flushGraphics(x,y,w,h) 配合 clipRect,僅重繪變動區域,效能更優sizeChanged 自動重建緩衝適應尺寸變化MIDP 2.0 已提供 javax.microedition.lcdui.game.GameCanvas,功能更完整(內建鍵盤狀態查詢、強制刷新等)。若目標裝置支援 MIDP 2.0,建議直接使用官方實作;本類主要服務於 MIDP 1.0 環境或需自訂擴展的場景。
雙緩衝是流暢遊戲體驗的基石,掌握其原理與實作,是 J2ME 遊戲開發者的必修課。