0

以下のコードからわかるように、私はC#を初めて使用します。私の最初のプロジェクト(一種のテストとして)では、2Dレベルエディターを作成しました。これには5つのレイヤーがあります。以下のコードでは、for(x for(y for z(draw graphics)))を使用するのではなく、マップが変更されるたびに生成され、塗りつぶされたタイルのみが含まれるショートリストディクショナリを使用しています。グリッドのすべての部分に何かがあるかどうかを確認する必要があります。

画面に約30個のタイルが表示されるまでは正常に実行され、その後、非常にぎくしゃくしたように、かなり遅く実行され始めます。このペイントイベントは、必要な場合にのみ呼び出され、タイマーでは実行されません。新しいタイルが配置されたとき、またはマウスカーソルが新しいブロックの上に置かれたときに純粋に実行されます。ですから、問題は、何かがたくさん蓄積されているように、画像が実際に画面に描画される部分にあると思います。

DrawImage()関数の下にコメントアウトされた行は、タイルセットの一部ではなく長方形を描画する方が高速かどうかをテストするためのものでした。そしてそうだった!!申し訳ありませんが、これは私の最初のプロジェクトであり、この特定の主題に関する答えをどこで探すべきかがよくわからないことを覚えておいてください。

ありがとう!、ここに私の絵のコードがあります

public void editor_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        string[] keys;
        string[] values;

        foreach(KeyValuePair<string, string> dict in map.shortlist){
            keys = dict.Key.Split('|');
            values = dict.Value.Split('|');
            int xpos = Convert.ToInt16(keys[0]);
            int ypos = Convert.ToInt16(keys[1]);
            int zpos = Convert.ToInt16(keys[2]);

            Tile tile = map.data[xpos, ypos, zpos];
            if (tile.type == "tile")
            {
                Bitmap img = tileset.bitmap.Clone(new Rectangle(tile.x * 16, tile.y * 16, 16, 16), tileset.bitmap.PixelFormat);
                g.DrawImage(img, new Point(xpos * 16, ypos * 16));                                       
                //g.DrawRectangle(Pens.Blue, new Rectangle(new Point(xpos * 16, ypos * 16), new Size(16,16)));                                       
            }
        }

        if (selector.MouseOver == true)
        {
            int tileSize = Preferences.blockSize;                
            Pen pen = new Pen(Color.Red, 1);                
            g.DrawRectangle(pen, new Rectangle(new Point((MouseX / tileSize) * tileSize, (MouseY / tileSize) * tileSize), new Size(tileSize, tileSize)));
        }
    }
4

1 に答える 1

0

誰かが同様のパフォーマンスの問題を抱えていた場合に備えて、私はこの質問にラウンドアバウトで答えます。コメントの中で私にいくつかのことを指摘してくれた人たちに感謝します。

問題を引き起こしている線は、おそらく非常に明白です。

Bitmap img = tileset.bitmap.Clone(new Rectangle(tile.x * 16, tile.y * 16, 16, 16), tileset.bitmap.PixelFormat);

タイルに出くわしたときにすべてのforeachに新しいビットマップを作成し、元のタイルセットビットマップから正方形を選択する必要があります。これを30〜40回行うと、かなり労働集約的です。

したがって、代わりに、タイルセットが最初にロードされたときに、次のようにすべてのタイルを配列にキャッシュしました。

    private void GenerateBitmapTiles() {
        Bitmap bitmap = new Bitmap(TilesetImageFile);

        bitmaps = new Bitmap[image.Width / 16, image.Height / 16];
        for (int x = 0; x < image.Width / 16; x++)
        {
            for (int y = 0; y < image.Height / 16; y++)
            {
                bitmaps[x, y] = bitmap.Clone(new Rectangle(x * 16, y * 16, 16, 16), bitmap.PixelFormat);
            }
        }

        bitmap.Dispose();
    }

次に、次のようにしてタイルを引き込むことができます。

g.DrawImage(bitmap[x, y], new Point(xpos * 16, ypos * 16));

しかし!以下のコメントを読んだ後、winformsは古いテクノロジであることに気付きました。Winformsは廃止されていませんが、WPFはより新しいテクノロジであり、ストレス下ではるかに優れたパフォーマンスを発揮し、ハードウェアが高速化されています。

私はWPFでプロジェクトを再構築し始めましたが、ペイントは問題ではありません。言うのではなく、ここに私のデータがあります。毎回、スクリーンペイントで、このオブジェクトをこことここに描画します。WPFでは、オブジェクトがここ、ここ、ここに必要です。残りはWPF自体によって行われます。

于 2013-02-27T10:05:48.707 に答える