简体   繁体   English

WPF'地图'控件; 使用画布显示大量位图图像

[英]WPF 'Map' control; using canvas to display lots of bitmap images

I'm parsing minecraft file data using Substrate. 我正在使用Substrate解析minecraft文件数据。 Minecraft is made up of 'chunks', which are made up of blocks. Minecraft由“块”组成,块由块组成。 So I've got a spritesheet with the different 16x16 tiles. 所以我有一个spritesheet与不同的16x16瓷砖。 I use a croppedbitmap in WPF to find the appropriate graphic tile to make up a section of the map. 我在WPF中使用croppedbitmap来查找合适的图形切片以构成地图的一部分。 Then I assign an Image() control in WPF the 'source', which is my croppedbitmap. 然后我在WPF中指定一个Image()控件'source',这是我的croppedbitmap。 Finally, I do myCanvas.Children.Add(myImage)... The problem is that after about 30 or so images in my canvas, the application slows to a crawl. 最后,我做了myCanvas.Children.Add(myImage)...问题是在我的画布中大约30个左右的图像后,应用程序变慢了爬行速度。 This is a problem because typical minecraft maps will have hundreds or thousands of images. 这是一个问题,因为典型的我的地图将有数百或数千个图像。 Is there a better way to draw a large amount of bitmap data? 有没有更好的方法来绘制大量的位图数据? I like having Image controls because then I can put tooltips on the map and make it interactive. 我喜欢使用Image控件,因为我可以将工具提示放在地图上并使其具有交互性。 But I accept that an Image control is probably way more expensive and having thousands of them may not work. 但我接受一个I​​mage控件可能更昂贵,并且有数千个可能无法工作。 Here's my code. 这是我的代码。 (this only parses tiles of a certain value, hence if id == 9) (这只解析某个值的tile,因此如果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();
                         }

Instead of using the heavier Image, you could use an ImageBrush: 您可以使用ImageBrush而不是使用较重的Image:

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

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

Later: 后来:

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();
}

If I leave out Freeze, I can't get a test app with a 100x100 tile world to display properly. 如果我遗漏了Freeze,我无法获得具有100x100平铺世界的测试应用程序以正确显示。 When I freeze each of the brushes, I can get the map to display seamlessly up to about 300x300. 当我冻结每个画笔时,我可以让地图无缝显示到大约300x300。 At 1000x1000 it almost does not load, but at this point you need to consider virtualizing the view as the UI won't handle that many UIElement's gracefully. 在1000x1000它几乎不加载,但此时你需要考虑虚拟化视图,因为UI不会优雅地处理那么多UIElement。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM