[英]Lagging when trying to create animation
我正在尝试使用一些物理逻辑创建一个下落的球,当我启动程序时,球以一种滞后且出乎意料的方式移动。
我正在使用 DispatcherTimer 类来绘制每一帧的球。
这是代码
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;
}
}
我的调度员计时器:
private DispatcherTimer SetTimer()
{
var timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(16);
timer.Start();
return timer;
}
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; }
难道是 wpf 渲染得不够快?
好的,我通过像这样添加到 dispatcherTimer 优先级来修复它
var timer = new DispatcherTimer(DispatcherPriority.Send);
这是一个替代实现。
这是一个快速而肮脏的概念证明。
主窗口:
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>
非常hacky的线程开始:
private void Window_ContentRendered(object sender, EventArgs e)
{
var mvm = this.DataContext as MainWindowViewmodel;
mvm.SpinUp();
}
视图模型(棱镜核心 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();
}
}
我正在使用异步等待而不是调度程序计时器。 这应该提供更一致的计时,因为使用的 tye 计时器比调度计时器更精确。 它也更容易阅读。
请注意,绑定值更改通知会自动编组到 ui 线程。
我已经硬编码了一些你想要计算一次的东西,比如重力加速度。
正如我上面提到的,这是非常脏的代码 - 但它给出了相当平滑的结果。 由于等待 1 秒,每次重复球都会挂在顶部。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.