简体   繁体   English

尝试创建动画时滞后

[英]Lagging when trying to create animation

I'm trying to create a falling ball with some physics logic, When I launch the program the ball moves in a laggy and unexpected way.我正在尝试使用一些物理逻辑创建一个下落的球,当我启动程序时,球以一种滞后且出乎意料的方式移动。

I'm using a DispatcherTimer class to draw the ball every frame.我正在使用 DispatcherTimer 类来绘制每一帧的球。

this is the code这是代码

        private void Draw(MyEllipse s)
        {
            var h = Canvas.GetTop(s.Ellipse);
            if (h >= cnvs.ActualHeight) //reachs the bottom
            {
                s.Velocity = s.Velocity * -1;
                s.YLoc = cnvs.ActualHeight - 1;

            }
            else //go down
            {
                s.YLoc = s.YLoc + s.Velocity;
                s.Velocity += PhysicsClass.Gravity;
            }
        }

My DispatcherTimer:我的调度员计时器:

        private DispatcherTimer SetTimer()
        {
            var timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromMilliseconds(16);
            timer.Start();
            return timer;
        }

Properties of MyElipse MyElipse 的属性

       private Ellipse ellipse;
        public Ellipse Ellipse
        {
            get { return ellipse; }
            private set { ellipse = value; }
        }

        public double XLoc
        {
            get { return Canvas.GetLeft(Ellipse); }
            set { Canvas.SetLeft(Ellipse, value); }
        }


        public double YLoc
        {
            get { return Canvas.GetTop(Ellipse); }
            set { Canvas.SetTop(Ellipse, value); }
        }


        public double Velocity { get; set; }

Could it be that wpf cannot render quick enough?难道是 wpf 渲染得不够快?

好的,我通过像这样添加到 dispatcherTimer 优先级来修复它

var timer = new DispatcherTimer(DispatcherPriority.Send);

Here's an alternative implementation.这是一个替代实现。

This is a quick and dirty proof of concept.这是一个快速而肮脏的概念证明。

Mainwindow:主窗口:

        SizeToContent="WidthAndHeight" 
        ContentRendered="Window_ContentRendered"
        >
    <Window.DataContext>
        <local:MainWindowViewmodel/>
    </Window.DataContext>
    <Grid>
        <Canvas x:Name="canvas"  Height="800" Width="800">
            <Ellipse Height="20" Width="20" Fill="Blue"
                     Canvas.Left="{Binding X}"
                     Canvas.Top="{Binding Y}"
                     />
        </Canvas>
    </Grid>
</Window>

Very hacky start of thread:非常hacky的线程开始:

    private void Window_ContentRendered(object sender, EventArgs e)
    {
        var mvm = this.DataContext as MainWindowViewmodel;
        mvm.SpinUp();
    }

Viewmodel ( prism core nuget ).视图模型(棱镜核心 nuget)。

public class MainWindowViewmodel : BindableBase
{
    private double x = 200;
    public double X
    {
        get => x;
        set => SetProperty(ref x, value, nameof(X));
    }
    private double y = 0;
    public double Y
    {
        get => y;
        set => SetProperty(ref y, value, nameof(Y));
    }
    private const double MAX_HEIGHT = 790;
    private double speed = 0;
    private double acceleration = 0.0982;
    private async void animateBall()
    {
        while(1==1)
        {
            while (y < MAX_HEIGHT)
            {
                speed += acceleration;
                Y += speed;
                await Task.Delay(20);
            }
            Y = 0;
            await Task.Delay(1000);
            speed = 0;
        }
    }
    public void SpinUp()
    {
        new Thread(() =>
        {
            animateBall();
        }).Start();
    }
}

I'm using async await rather than dispatcher timer.我正在使用异步等待而不是调度程序计时器。 This should give more consistent timings since tye timer used is more precise than dispatvher timer.这应该提供更一致的计时,因为使用的 tye 计时器比调度计时器更精确。 It's also easier to read.它也更容易阅读。

Note that the binding value change notification is automatically marshalled to the ui thread.请注意,绑定值更改通知会自动编组到 ui 线程。

I've hard coded some stuff you'd want to calculate once like the gravity acceleration.我已经硬编码了一些你想要计算一次的东西,比如重力加速度。

As I mentioned above this is pretty dirty code - but it gives reasonably smooth results.正如我上面提到的,这是非常脏的代码 - 但它给出了相当平滑的结果。 The ball kind of hangs up back at the top each repetition due to that 1 seconds await.由于等待 1 秒,每次重复球都会挂在顶部。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM