wpf 渲染事件

代码

    private void MoveCarWindow_OnLoaded(object sender, RoutedEventArgs e)
    {
        this.lastRenderingTime = TimeSpan.Zero;

        // 订阅渲染事件, 在对象呈现到合成树之前即发生。
        CompositionTarget.Rendering += this.CompositionTargetOnRendering;
    }

    private void CompositionTargetOnRendering(object? sender, EventArgs e)
    {
        if (e is RenderingEventArgs args)
        {
            var currentRenderingTime = args.RenderingTime;
            var timeSpan = currentRenderingTime - this.lastRenderingTime;

            this.lastRenderingTime = currentRenderingTime;

            // 计算移动的向量
            var vector = this.CalculateDirectionVector();

            if (vector is { X: 0, Y: 0, } || double.IsNaN(vector.X) || double.IsNaN(vector.Y))
            {
                // 没有移动
                return;
            }

            // 根据是否按 j 设置速度 
            double speed = Keyboard.IsKeyDown(Key.J) ? 400 : 200;

            // 根据时间与速度计算出移动的距离
            var moveVector = vector * (speed * timeSpan.TotalSeconds);

            // 进行移动
            this.MoveCar(this.CarRectangle, moveVector);
        }
    }

    private Vector CalculateDirectionVector()
    {
        // 根据按下的按钮,计算出移动的向量
        var vectorys = new List<Vector>();

        if (Keyboard.IsKeyDown(Key.Up))
        {
            vectorys.Add(new Vector(0, 1));
        }

        if (Keyboard.IsKeyDown(Key.Down))
        {
            vectorys.Add(new Vector(0, -1));
        }

        if (Keyboard.IsKeyDown(Key.Left))
        {
            vectorys.Add(new Vector(-1, 0));
        }

        if (Keyboard.IsKeyDown(Key.Right))
        {
            vectorys.Add(new Vector(1, 0));
        }

        if (vectorys.Count == 0)
        {
            return new Vector(0, 0);
        }

        var sumVector = vectorys.Aggregate( new Vector(0, 0), (sum, it) => sum + it);

        // 因为多个方向的向量累加,所以这里需要归一化,变长度为1
        sumVector.Normalize();

        return sumVector;
    }

    private void MoveCar(Rectangle car, Vector moveVector)
    {
        if (car.Parent is not FrameworkElement parent)
        {
            return;
        }

        var width = parent.ActualWidth;
        var height = parent.ActualHeight;

        var margin = this.CarRectangle.Margin;

        // 因为 wpf 坐标与二维坐标系不同,需要做一下转换
        margin.Left += moveVector.X;
        margin.Top -= moveVector.Y;

        // 限制只在窗口内移动
        margin.Left = Math.Clamp(margin.Left, 0, width - car.ActualWidth);
        margin.Top = Math.Clamp(margin.Top, 0, height - car.ActualHeight);

        car.Margin = margin;
    }
上一篇
下一篇