是否有任何方法可以更快地在画布上渲染大量移动对象(c# w/ WPF)

本文关键字:移动 对象 WPF 方法 任何 是否 | 更新日期: 2023-09-27 17:50:17

我正在制作一个粒子游戏(到目前为止,只使用水),并且元素中的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);
    }

是否有任何方法可以更快地在画布上渲染大量移动对象(c# w/ WPF)

在Canvas后代中重写Canvas.OnRender是您对许多移动形状的最佳选择。

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无法在移动时预渲染它们和预渲染的形状。

如果你想让它非常快,你必须使用一些高级的技术。特别是这些所谓的过程动画和使用可写位图的动画。

这里有一篇很好的博客文章描述了这些技术(有一个粒子效果的例子):http://blogs.claritycon.com/blog/2011/03/30/advanced-animation-animating-15000-visuals-in-silverlight-2/。它是关于Silverlight的,但是因为Silverlight是WPF的一个子集,所以技术是相同的。

这在很大程度上取决于你如何看待"慢"

如果你每隔50毫秒移动一个形状,你就必须每隔一段时间移动它们更多,以使它们移动得更快。

但是像你那样添加计时器并不是在WPF中创建动画的最佳方式。

有两个选项:

  1. 为每个形状指定一个速度(例如:每秒10个单位),然后随着屏幕的每次更新,根据距离上次移动的时间和速度移动形状。因此,您还需要跟踪经过的时间。

  2. 创建故事板,它们有自己的计时器(时间线),所以你所要做的就是设置开始和结束的位置,并指定持续时间,最后播放动画