我的项目中的图形太慢了

时间:2011-09-07 12:28:21

标签: c# graphics gdi+

我正在开发动物园模拟器项目。它包含三种类型:地图,动物环境和动物本身。地图太大,无法放在屏幕上,玩家需要移动屏幕才能看到它的其他部分。我正在使用计时器绘制。在它的刻度上,它会为正在绘制的表单调用Invalidate()。在ZooForm_Paint方法中,我首先在mapBuffer位图上绘制地图中的所有内容。由于mapBuffer太大而无法放在屏幕上,因此我(在屏幕上)绘制了玩家所在的mapBuffer部分。

不幸的是,似乎在mapBuffer上绘制地图中的所有内容(尽管可能无法查看)会减慢游戏速度。我可以画出我的环境和动物而不需要先绘制整个地图吗? 怎么样?

我的代码:

public void DrawGame(Graphics g, ref Point locationOnMap)
{
this.drawBufferMap();
this.drawMapLocation(g, ref locationOnMap);
}


private void drawBufferMap()
{
    Bitmap buffer = new Bitmap(this.map.Size.Width, this.map.Size.Height);
    using (Graphics graphics = Graphics.FromImage(buffer))
    {
        graphics.DrawImageUnscaled(this.map.Picture, new Point()); // draw entire map

        foreach (var item in this.zoo.Environments) // draw all env.
        {
            graphics.DrawImageUnscaled(item.Picture, item.Bounds.Location);
        }
        foreach (var item in this.zoo.ILocatables) // draw all ILocatables
        {
            graphics.DrawImageUnscaled(item.Picture, item.Location);
        }
    }

    if (this.mapBuffer != null)
    {
        this.mapBuffer.Dispose();
    }
    this.mapBuffer = buffer;
}

private void drawMapLocation(Graphics g, ref Point location)
{
    g.DrawImage(this.mapBuffer, new Rectangle(0, 0, viewSize.Width, viewSize.Height),
        new Rectangle(location.X, location.Y, viewSize.Width, viewSize.Height), GraphicsUnit.Pixel);
}

2 个答案:

答案 0 :(得分:3)

我认为你不会得到任何简单的解决方案。我可以提供一些提示和意见:

  • 每次画画时,您似乎都在创建一个新的BitMap。这绝对不是一个好主意,因为大内存在内存方面绝对是巨大的。您可能想要做的是在游戏加载时创建一个,然后只需清除它并在每一帧重新绘制它。我认为这可能是你遇到的更大的性能问题之一。
  • 之后可以进行一些优化。例如。您正在“渲染”您最终将在用户界面线程上绘制到屏幕上的图像。如果渲染过程需要很长时间,这将是显而易见的。通常,此工作在后台线程上进行,然后UI线程只检查它是否可以使用新映像进行重绘。 (我在这里大大简化了事情)。
  • 对于图形密集型应用程序,WinForms不是一个特别好的环境,正如其他人所指出的那样。你根本不会得到任何硬件加速。迁移到XNA是一种选择,但如果您的应用程序在标准WinForms屏幕和控件方面也非常丰富,这可能不是一个简单的选择。另一个建议的替代方案可能是WPF,您可以使用转换来移动, 硬件加速,并且与WinForms应用程序没有太大不同(好吧,你不要)需要实现自己的按钮等)。

希望这有点帮助。

答案 1 :(得分:1)

Daniel指出:每次需要绘制地图时创建一个新的位图会降低性能。反而重复使用相同的位图。

创建一个你需要的位图也是非常糟糕的性能。如果你需要它滚动,那就没关系。但是如果你每次都画一幅新图像,那么你应该创建它所需的完全相同的尺寸。然后你可以调用 Graphics.TranslateTransform 来补偿新的坐标,这样就可以保持你的existion代码不变。

这将使GDI +可以剪辑你的图形,只是不要在地图位图之外绘制东西 - 这会加快速度。