Графика слишком медленная в моем проекте - PullRequest
0 голосов
/ 07 сентября 2011

Я занимаюсь разработкой проекта симулятора зоопарка.Он содержит три типа объектов: карту, среду обитания животных и самих животных.Карта слишком велика, чтобы уместиться на экране, игрок должен переместить экран, чтобы увидеть другие ее части.Я использую таймер для рисования.На своем галочке он вызывает Invalidate() для формы, на которой рисуется.В методе ZooForm_Paint я сначала рисую каждую вещь на карте в mapBuffer Bitmap.Поскольку 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 ]

3 голосов
/ 07 сентября 2011

Я не думаю, что вы получите легкие решения. Могу предложить несколько советов и мнений:

  • Кажется, вы создаете новый BitMap каждый раз, когда рисуете экран. Это определенно не очень хорошая идея, поскольку большие растровые изображения абсолютно огромны с точки зрения памяти. Что вы, вероятно, хотите сделать, это создать его, когда ваша игра загружается, а затем просто очистить его и перекрасить в каждом кадре. Я думаю, что это, вероятно, одна из самых больших проблем с производительностью, которые у вас есть.
  • Есть ряд оптимизаций, которые вы могли бы сделать потом. Например. Вы «рендеринг» изображения, которое вы в конечном итоге рисовать на экране в потоке пользовательского интерфейса. Если процесс рендеринга займет много времени, это будет заметно. Обычно эта работа выполняется в фоновом потоке, а затем поток пользовательского интерфейса просто проверяет, может ли он перерисовываться с использованием нового изображения. (Я сильно упрощаю вещи здесь).
  • Для приложений, интенсивно использующих графику, WinForms - не очень хорошая среда, как отмечали другие. Вы не получите никакого аппаратного ускорения вообще. Переход на XNA является одним из вариантов, но если ваше приложение также достаточно богато с точки зрения стандартных экранов и элементов управления WinForms, это, вероятно, не простой вариант. Другой предлагаемой альтернативой может быть WPF, где вы можете избежать использования преобразований для перемещения вещей, аппаратное ускорение которых * и не слишком отличается от приложения WinForms (ну, вы не необходимо реализовать собственные кнопки и т. д.).

Надеюсь, это немного поможет.

1 голос
/ 08 сентября 2011

Как отметил Дэниел: создание нового растрового изображения каждый раз, когда вам нужно рисовать карту, снижает производительность.Вместо этого используйте снова и снова одно и то же растровое изображение.

Создание нужного растрового изображения также очень плохо сказывается на производительности.Если вам это нужно, чтобы прокрутить, то все в порядке.Но если вы все равно каждый раз рисуете новое изображение, то вам просто нужно создать его точно такого же размера, как вам нужно.Затем вы можете вызвать Graphics.TranslateTransform , чтобы компенсировать новые координаты, чтобы вы могли оставить свой код existion без изменений.

Это позволит GDI + обрезать вашу графику и просто нерисовать вещи за пределами вашей карты - это ускорит процесс.

...