我正在寻找一种方法来改善我正在做的一些绘图的性能。目前,我正在绘制一个32x32的瓷砖网格。使用以下代码绘制到绘图上下文
for (int x = startX; x < endX; x++)
{
for (int y = startY; y < endY; y++)
{
dg.Children.Add(
new ImageDrawing(_mapTiles[GameWorldObject.GameMap[x, y].GraphicsTile.TileStartPoint],
new Rect(CountX * 8, CountY * 8, 8, 8)
));
dg.Children.Add(
new GeometryDrawing(
null,
new Pen(
new SolidColorBrush(
Color.FromRgb(255, 0, 20)), .3),
new RectangleGeometry(
new Rect(CountX * 8, CountY * 8, 8, 8)
)
)
);
CountY++;
}
CountY = 0;
CountX++;
}
dc.DrawDrawing(dg);
我正在绘制的图像是CachedBitmap。即使使用CachedBitmap,每次我需要重绘Canvas时仍然会有大约半秒的延迟。
不确定是否有更高效的方法来处理此网格的绘图。最终我想扩展控制以充当迷你地图,所以我需要牢记这一点。
另外,我之前尝试过将每个位图直接绘制到绘图上下文,但这似乎有点慢。
答案 0 :(得分:1)
我在绘图之前添加了DrawingGroup.Freeze(),它似乎有助于提高性能。
答案 1 :(得分:0)
如果它主要是静态迷你地图将其绘制成图像,并绘制该图像。或者你可以做一个大图像,将整个地图绘制到其中,然后绘制当前可见的部分。
修改:也许this blog post值得检查一下,无论您是使用软件还是硬件加速来绘制它。
答案 2 :(得分:0)
这是使用WriteableBitmap的示例,其性能主要与整个地图的大小有关,而原始方法更多地取决于切片的数量。您可以将其更改为在瓷砖之间具有alpha混合边框,但在它们之间留下间隙会更容易且性能更高。你不需要随机化瓷砖的代码,但你应该有一些脏标志,所以你只需要重新绘制位图。
您可能还想查看我的答案以及其他人question。那说你没有那么多项目,使用你的方法32x32对我来说并不慢。
<local:Map x:Name="map" />
<RepeatButton Click="Button_Click" Content="Change" />
private void Button_Click(object sender, RoutedEventArgs e)
{
map.seed++;
map.InvalidateVisual();
}
public class Map : FrameworkElement
{
private int[][] _mapTiles;
public Map()
{
_mapTiles = Directory.GetFiles(@"C:\Users\Public\Pictures\Sample Pictures", "*.jpg").Select(x =>
{
var b = new BitmapImage(new Uri(x));
var transform = new TransformedBitmap(b, new ScaleTransform((1.0 / b.PixelWidth)*tileSize,(1.0 / b.PixelHeight)*tileSize));
var conv = new FormatConvertedBitmap(transform, PixelFormats.Pbgra32, null, 0);
int[] data = new int[tileSize * tileSize];
conv.CopyPixels(data, tileSize * 4, 0);
return data;
}).ToArray();
bmp = new WriteableBitmap(w * tileSize, h * tileSize, 96, 96, PixelFormats.Pbgra32, null);
destData = new int[bmp.PixelWidth * bmp.PixelHeight];
}
const int w = 64, h = 64, tileSize = 8;
public int seed = 72141;
private int oldSeed = -1;
private WriteableBitmap bmp;
int[] destData;
protected override void OnRender(DrawingContext dc)
{
if(seed != oldSeed)
{
oldSeed = seed;
int startX = 0, endX = w;
int startY = 0, endY = h;
Random rnd = new Random(seed);
for(int x = startX; x < endX; x++)
{
for(int y = startY; y < endY; y++)
{
var tile = _mapTiles[rnd.Next(_mapTiles.Length)];
var rect = new Int32Rect(x * tileSize, y * tileSize, tileSize, tileSize);
for(int sourceY = 0; sourceY < tileSize; sourceY++)
{
int destY = ((rect.Y + sourceY) * (w * tileSize)) + rect.X;
Array.Copy(tile, sourceY * tileSize, destData, destY, tileSize);
}
}
}
bmp.WritePixels(new Int32Rect(0, 0, w * tileSize, h * tileSize), destData, w * tileSize * 4, 0);
}
dc.DrawImage(bmp,new Rect(0,0,w*tileSize,h*tileSize));
}
}