Есть ли способ ускорить рендеринг множества движущихся объектов на холсте (C # w / WPF) - PullRequest
4 голосов
/ 16 апреля 2011

Я делаю игру с частицами (пока что только с водой), и метод Draw () внутри элемента довольно медленный, с несколькими, идущими одновременно. Я предполагаю, что это потому, что он вычисляет так много раз в секунду, но я все еще весьма недоволен этим, учитывая, что это просто базовые 2D фигуры. Как я могу сделать это более эффективным?

Вот мой код:

(цикл) (выполняется каждые 50 миллисекунд) (Обратите внимание, я просто включил формы для таймера, я использую WPF.)

    void TimeKeeper_Tick(object sender, EventArgs e)
    {
        foreach (Element ele in Elements)
        {
            ele.Draw();
        }
    }

И метод рисования. Pos - это Vector2 (класс, который я сделал, чтобы сэкономить время):

    public void Draw()
    {
        Pos.Add(3, 10);

        if (Pos.Y > (int)canvas.ActualHeight)
        {
            Pos.Set(Pos.X, (int)shape.RenderSize.Width);
        }

        if (Pos.X+shape.RenderSize.Width > (int)canvas.ActualWidth)
        {
            Pos.Set(0, Pos.Y+(int)shape.RenderSize.Height);
        }

        shape.SetValue(Canvas.LeftProperty, (double)Pos.X);
        shape.SetValue(Canvas.TopProperty, (double)Pos.Y);

        if (canvas.Children.IndexOf(shape) != null)
        {
            canvas.Children.Remove(shape);
        }

        canvas.Children.Add(shape);
    }

Ответы [ 3 ]

3 голосов
/ 16 апреля 2011

Переопределение Canvas.OnRender в потомке Canvas - ваш лучший выбор для множества движущихся фигур.

WPF оптимизирован для статических фигур.Если вы перемещаете все эти статические фигуры вокруг, вы проходите через все издержки этой оптимизации, не извлекая выгоды из нее (по мере движения фигур).

Код выглядит примерно так:

public delegate void RenderEventHandler(CanvasRender sender, DrawingContext dc);

public class CanvasRender : Canvas
{
    public event RenderEventHandler Render;

    public CanvasRender()
    {
    }

    protected override void OnRender(DrawingContext dc)
    {
        if (Render != null)
            Render(this, dc);
        base.OnRender(dc);
    }
}

Затем вы используете этот класс вместо Canvas и назначаете обработчик для события Render.В этом случае вы перерисовываете весь визуал, используя явные вызовы DrawingContext.

Может показаться, что вы делаете намного больше работы таким образом, но на самом деле это гораздо эффективнее, чем создавать все движущиеся объекты и затем перемещать их вокруг.Особенно, если эти объекты представляют собой линии, угол / длина которых изменяется со временем, поскольку WPF не может предварительно визуализировать их и предварительно визуализированную форму при перемещении.

1 голос
/ 16 апреля 2011

Если вы хотите, чтобы это было действительно быстро, вы должны использовать некоторые передовые методы. В частности, это так называемые процедурные анимации и анимации с использованием записываемых растровых изображений.

Вот отличное сообщение в блоге, описывающее эти методы (с примером эффекта частиц): http://blogs.claritycon.com/blog/2011/03/30/advanced-animation-animating-15000-visuals-in-silverlight-2/. Речь идет о Silverlight, но поскольку Silverlight является подмножеством WPF, методы такие же.

0 голосов
/ 16 апреля 2011

Многое зависит от того, что вы считаете «медленным»

Если вы перемещаете фигуры каждые 50 мс, вы должны перемещать их больше каждый интервал, чтобы заставить их двигаться быстрее.

Но добавление таймера, как вы сделали, не лучший способ создания анимации в WPF.

Есть несколько вариантов:

  1. задайте скорость для каждой фигуры (что-то вроде: 10 единиц в секунду), затем при каждом обновлении экрана перемещайте фигуры в соответствии с временем, прошедшим с момента последнего перемещения, и скоростью. Таким образом, вам также нужно следить за прошедшим временем.

  2. Создавайте раскадровки, у них есть свои таймеры (временные шкалы), поэтому все, что вам нужно сделать, это установить начальную и конечную позиции, указать продолжительность и, наконец, воспроизвести анимацию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...