绘制tileset图形到油漆事件运行缓慢的屏幕上

时间:2013-02-23 12:37:06

标签: c# performance graphics onpaint

你可以从下面的代码中看出我对C#很新。对于我的第一个项目(作为一种测试),我制作了一个2D级别的编辑器,它有5层。在下面的代码中,我通过一个短名单字典,每次更改地图时生成,只包含填充的图块,而不是使用for(x for(y表示z(绘制图形)))必须检查网格的每个部分是否有任何东西。

它运行良好,直到我在屏幕上有大约30个瓷砖,然后它开始运行非常慢,就像真的生涩。此paint事件仅在需要时调用,它不在计时器上运行,它在布置新图块时纯粹运行,或者鼠标光标悬停在新块上。所以我猜测问题出在图像实际绘制到屏幕的部分,就像有些东西在构建的那样。

DrawImage()函数下面注释的行是测试是否只绘制矩形而不是tileset的一部分更快。它是!!我为自己听起来多么吵闹道歉,但请记住,这是我的第一个项目,并不确定在哪个地方寻找这个特定主题的答案。

谢谢!,下面是我的绘画代码

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

1 个答案:

答案 0 :(得分:0)

万一有人遇到类似的表现问题,我会在回合中回答这个问题,感谢评论中的下面的人给我指出一些事情。

导致问题的一条线很可能非常明显:

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

当遇到一个图块并从原始图块集位图中选择一个正方形时,必须在每个foreach上创建一个新的位图。这样做30到40次是相当费力的。

所以我只是在第一次加载tileset时将所有tile缓存到一个数组中,如下所示:

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

BUT!阅读下面的评论后,我意识到winforms是较老的技术.Winforms并不是过时的,但WPF是更新的技术,可以在压力下表现更好,加上硬件加速。

我已经开始在WPF中重建项目,并且绘画不是问题。而不是说:这里是我的数据,现在每次屏幕绘制我想在这里和这里绘制这个对象,在WPF你只是说,我想在这里,这里和这里我的对象。其余的由WPF本身完成。