3

Substrateを使用してMinecraftファイルデータを解析しています。Minecraftは、ブロックで構成された「チャンク」で構成されています。だから私はさまざまな16x16タイルのスプライトシートを持っています。WPFでcroppedbitmapを使用して、マップのセクションを構成する適切なグラフィックタイルを見つけます。次に、WPFでImage()コントロールに「ソース」を割り当てます。これは私のcroppedbitmapです。最後に、myCanvas.Children.Add(myImage)を実行します...問題は、キャンバスに約30枚の画像を配置した後、アプリケーションのクロールが遅くなることです。典型的なMinecraftマップには数百または数千の画像があるため、これは問題です。大量のビットマップデータを描画するためのより良い方法はありますか?マップにツールチップを配置してインタラクティブにすることができるので、画像コントロールがあるのが好きです。しかし、私は、画像コントロールはおそらくはるかに高価であり、何千もの画像コントロールを使用しても機能しない可能性があることを認めます。これが私のコードです。(これは特定の値のタイルのみを解析するため、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を使用できます。

// 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 に答える