為何要將 272 張圖片合成為一張大圖?因為遊戲若有裝備、坐騎等系統,需即時合成圖片源;合成 2 張大圖效率遠高於合成 272 張小圖。本例主角由身體與武器兩部分組成,定義交錯陣列快取已合成的裝備角色圖:
public static BitmapSource[,][,] PartImage = new BitmapSource[10, 20][,];
PartImage[a,b][c,d]:a 衣服代號、b 武器代號、c 朝向代號、d 合成圖列號。本例 1-5 列待機、6-13 列跑動、14-20 列攻擊、21-26 列施法、27-34 列死亡。若有帽子、坐騎則擴展為 4 維陣列。雖可用 Hashtable/Dictionary,但交錯陣列更清晰、優雅且高效。
public static BitmapSource[,] EquipPart(int[] Equipment, int rowNum, int colNum,
int totalWidth, int totalHeight, int singleWidth, int singleHeight)
{
if (PartImage[Equipment[0], Equipment[1]] == null)
{
BitmapSource[,] bitmap = new BitmapSource[rowNum, colNum];
BitmapSource bitmapSource = new BitmapImage(new Uri(@"Images\Body" + Equipment[0] + ".gif", UriKind.Relative));
if (Equipment[1] != 0)
{
BitmapSource bitmapSource1 = new BitmapImage(new Uri(@"Images\Weapon" + Equipment[1] + ".gif", UriKind.Relative));
DrawingVisual drawingVisual = new DrawingVisual();
Rect rect = new Rect(0, 0, totalWidth, totalHeight);
DrawingContext drawingContext = drawingVisual.RenderOpen();
drawingContext.DrawImage(bitmapSource, rect);
drawingContext.DrawImage(bitmapSource1, rect);
drawingContext.Close();
RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(totalWidth, totalHeight, 0, 0, PixelFormats.Pbgra32);
renderTargetBitmap.Render(drawingVisual);
bitmapSource = renderTargetBitmap;
}
for (int i = 0; i < rowNum; i++)
for (int j = 0; j < colNum; j++)
bitmap[i, j] = new CroppedBitmap(bitmapSource, new Int32Rect(j * singleWidth, i * singleHeight, singleWidth, singleHeight));
PartImage[Equipment[0], Equipment[1]] = bitmap;
return bitmap;
}
else
{
return PartImage[Equipment[0], Equipment[1]];
}
}
若快取中無對應裝備組合,則載入身體大圖、武器大圖,透過 DrawingVisual 合成渲染至 RenderTargetBitmap,再按單幀尺寸切割存入快取;若已存在則直接回傳快取,極大提升效能。