c# - 有什么方法可以更快地在 Canvas 上渲染大量移动对象(C# w/WPF)

标签 c# wpf performance rendering

我正在制作一个粒子游戏(到目前为止,只有水),并且元素内的 Draw() 方法非常慢,同时有几个。我认为这是因为它每秒计算太多,但考虑到它们只是基本的 2D 形状,我仍然对此很不满意。如何提高效率?

这是我的代码:

(循环)(每 50 毫秒运行一次)(注意,我只是包含了计时器的表单,我使用的是 WPF。)

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

和绘制方法。 Pos 是一个“Vector2”(我为了节省时间而制作的类(class)):

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

最佳答案

覆盖 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 无法预渲染它们以及移动时预渲染的形状。

关于c# - 有什么方法可以更快地在 Canvas 上渲染大量移动对象(C# w/WPF),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5688627/

相关文章:

wpf - 如何通过带有文本框的 ListView 作为 TreeViewItems 进行 TAB?

php - 最后一个事件早于 X 天的 Mysql 返回 ID

JAVA 智能卡客户端身份验证 - 慢 "init keystore"

C# Task.Factory.StartNew 长时间运行

c# 在 OneNote 中打开 "Select location"窗口

c# - WPF 如何在代码中将网格行和列大小重置为 "*"

c# - 使用子集合更新 NHibernate 对象

c# - 如何检测鼠标是否位于上下文菜单上

wpf - 更改列表框中选定用户控件的背景颜色

php - array_merge 与 union 在 PHP 中的性能