3

我正在使用 Substrate 解析 minecraft 文件数据。Minecraft 由“块”组成,“块”由块组成。所以我有一个带有不同 16x16 瓷砖的精灵表。我在 WPF 中使用croppedbitmap 来查找合适的图形平铺以构成地图的一部分。然后我在 WPF 中为“源”分配一个 Image() 控件,这是我的裁剪位图。最后,我执行 myCanvas.Children.Add(myImage)... 问题是,在我的画布中有大约 30 个左右的图像后,应用程序变得缓慢。这是一个问题,因为典型的我的世界地图会有成百上千的图像。有没有更好的方法来绘制大量的位图数据?我喜欢拥有图像控件,因为这样我就可以在地图上放置工具提示并使其具有交互性。但我接受 Image 控件可能更昂贵,并且拥有数千个控件可能无法正常工作。这是我的代码。(这只解析特定值的图块,因此如果 id == 9)

     var mapTiles = (BitmapImage)FindResource("mapTiles");
         CroppedBitmap waterImage = new CroppedBitmap(mapTiles, new Int32Rect(352, 48, 16, 16));
         CroppedBitmap grassImage = new CroppedBitmap(mapTiles, new Int32Rect(0, 0, 16, 16));
         foreach (ChunkRef chunk in chunkManager)
         {
             countOfTiles++;

             for (int x = 0; x <= 15; x++)
             {
                 for (int z = 0; z <= 15; z++)
                 {
                     int height = chunk.Blocks.GetHeight(x, z);
                     //TODO: Normalize Chunk X, Z so 0,0 is the smallest chunk so everything is visible on the canvas.
                     if (height > 0 && chunk.X > 0 && chunk.Z > 0)
                     {
                         var block = chunk.Blocks.GetBlock(x, height - 1, z);

                         if (block.ID == 9)
                         {
                             //352, 48
                             Image image = new Image();
                             image.Source = waterImage;
                             worldMap.Children.Add(image);
                             Canvas.SetTop(image, (chunk.X + x) * 16);
                             Canvas.SetLeft(image, (chunk.Z + z) * 16);
                             image.ToolTip = countOfTiles.ToString();
                         }
4

1 回答 1

2

您可以使用 ImageBrush,而不是使用较重的 Image:

// use ImageBrush's instead
var waterImage = new ImageBrush(new CroppedBitmap(...));
var grassImage = new ImageBrush(new CroppedBitmap(...));

waterImage.Freeze();
grassImage.Freeze();

之后:

if (block.ID == 9)
{
    var water = new Rectangle
    {
        Width = 16,
        Height = 16,
        Fill = waterImage
    };
    worldMap.Children.Add(water);
    Canvas.SetTop(water, (chunk.X + x) * 16);
    Canvas.SetLeft(water, (chunk.Z + z) * 16);
    water.ToolTip = countOfTiles.ToString();
}

如果我忽略了 Freeze,我将无法让具有 100x100 磁贴世界的测试应用程序正确显示。当我冻结每个画笔时,我可以让地图无缝显示到大约 300x300。在 1000x1000 时它几乎不会加载,但此时您需要考虑虚拟化视图,因为 UI 无法优雅地处理那么多 UIElement。

于 2012-07-02T13:25:10.653 回答