MIDP 2.0 無內建任意角度旋轉 API,僅 Sprite 支援 90° 倍數。本文從 2D 旋轉數學推導、掃描線填充算法、CLDC 1.0 定點數移植 (MathFP)、預計算三角函數表、Sprite 整合、預置圖片/TinyLine 2D 替代方案,給出完整工程級解決方案。
點 P(x,y) 繞 Q(x0,y0) 順時針旋轉 θ:
x' = x0 + (x-x0)cosθ - (y-y0)sinθ
y' = y0 + (y-y0)cosθ + (x-x0)sinθ
設備座標系:原點左上,Y 向下,θ 視為順時針角度,公式不變。
getRGB() 像素陣列 srcMap[w*h]。dr = max(dist(Q, 四頂點)),新圖尺寸 wh2 = 2*dr+1。destMap[wh2*wh2],初始化透明 (0x00000000)。(i,j),計算目標座標 (destX, destY),寫入 destMap。dd[0]=cx-dr, dd[1]=cy-dr,繪製時補償。
public Image rotate(Image src, int cx, int cy, double theta, int[] dd) {
if (Math.abs(theta % 360) < 0.1) return src;
int w = src.getWidth(), h = src.getHeight();
int[] srcMap = new int[w*h];
src.getRGB(srcMap, 0, w, 0, 0, w, h);
int dx = Math.max(cx, w-cx), dy = Math.max(cy, h-cy);
int dr = (int)Math.sqrt(dx*dx + dy*dy);
int wh2 = 2*dr + 1;
int[] destMap = new int[wh2*wh2];
double rad = theta * Math.PI / 180;
double cos = Math.cos(rad), sin = Math.sin(rad);
for (int i=0; i> 24) != 0) { // 非透明
int destX = (int)(dr + (i-cx)*cos - (j-cy)*sin);
int destY = (int)(dr + (j-cy)*cos + (i-cx)*sin);
destMap[destY*wh2 + destX] = rgb;
}
}
}
dd[0] = cx - dr; dd[1] = cy - dr;
return Image.createRGBImage(destMap, wh2, wh2, true);
}
前向映射導致多源像素映射同一目標、或目標空洞。對策:
引入 MathFP (Onne Hommes) 庫,int 模擬定點數:
int xFP = MathFP.toFP("0.10");
int yFP = MathFP.toFP("0.2");
int zFP = MathFP.mul(xFP, yFP);
System.out.println(MathFP.toString(zFP)); // 0.02
三角函數預計算表 (0-359°):
static int[] cosFP = new int[360], sinFP = new int[360];
for (int i=0; i<360; i++) {
int radFP = MathFP.div(MathFP.mul(MathFP.toFP(i), MathFP.PI), MathFP.toFP(180));
cosFP[i] = MathFP.cos(radFP);
sinFP[i] = MathFP.sin(radFP);
}
// 使用時:cosFP[theta], sinFP[theta]
精度優化:僅存 0-90°,利用對稱性推導;或存 sin*4096 整數,運算後右移 12 位。
getFrame() 截取單幀 Image。Image 替換該幀或動態繪製。pixelLevel=true,因旋轉後邊界框變大。應用例:「淘金者」鉤子 0-60° 連續旋轉(圖 5)。
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| 實時算法旋轉 | 任意角度、動態、無額外存儲 | CPU 重、失真處理麻煩、大圖記憶體峰值高 | 連續旋轉動畫(指針、鉤子、轉盤) |
| 預置圖片 (含 Sprite 90° 變換) | 零運行時運算、品質可控、Sprite 90° 免費 | 角度多時存儲大、美術成本高 | 固定角度集(坦克 12 方向、角色 8 方向) |
| TinyLine 2D (純 Java, <35KB) | 支援向量/光柵旋轉、CLDC 1.0、API 豐富 | 第三方依賴、學習成本 | 需複雜 2D 圖形渲染、不想造輪子 |
getRGB/createRGBImage) 與 Alpha 通道支援。DirectUtils)。無銀彈,視專案選型:連續旋轉用實時算法+超採樣;固定角度用預置圖+Sprite 90° 優化;複雜 2D 場景引入 TinyLine。掌握數學本質與平台限制,才能在資源受限設備上做出流暢旋轉效果。