I’m parsing minecraft file data using Substrate. Minecraft is made up of ‘chunks’, which are made up of blocks. So I’ve got a spritesheet with the different 16×16 tiles. I use a croppedbitmap in WPF to find the appropriate graphic tile to make up a section of the map. Then I assign an Image() control in WPF the ‘source’, which is my 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. 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. But I accept that an Image control is probably way more expensive and having thousands of them may not work. Here’s my code.
(this only parses tiles of a certain value, hence if 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:
Later:
If I leave out Freeze, I can’t get a test app with a 100×100 tile world to display properly. When I freeze each of the brushes, I can get the map to display seamlessly up to about 300×300. At 1000×1000 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.