当试图基于Silverlight设置对象时间/帧的动画时(与使用DoubleAnimation或Storyboard不同,例如不适合快节奏游戏),例如每帧移动一个特定方向的飞船,运动是跳跃的,不是很顺利。屏幕甚至似乎都在撕裂。
CompositionTarget和DistpatcherTimer之间似乎没有区别。 我使用以下方法(伪代码):
Register Handler to Tick-Event of a DispatcherTimer
In each Tick:
Compute the elapsed time from the last frame in milliseconds
Object.X += movementSpeed * ellapsedMilliseconds
这会导致运动平稳,对吧?但事实并非如此。 这是一个例子(控件:WASD和鼠标):Silverlight Game。 虽然我所描述的效果在这个样本中并不太普遍,但我可以向你保证,即使在画布上移动一个矩形也会产生一个跳跃的动画。
有人知道如何最小化这个。有没有其他方法可以使用Storyboards / DoubleAnimations来解决基于帧的动画问题?
编辑:这是一种快速而肮脏的方法,用最少的代码设置矩形动画(控件:A和D)Animation Sample
的Xaml:
<Grid x:Name="LayoutRoot" Background="Black">
<Canvas Width="1000" Height="400" Background="Blue">
<Rectangle x:Name="rect" Width="48" Height="48"
Fill="White"
Canvas.Top="200"
Canvas.Left="0"/>
</Canvas>
</Grid>
C#:
private bool isLeft = false;
private bool isRight = false;
private DispatcherTimer timer = new DispatcherTimer();
private double lastUpdate;
public Page()
{
InitializeComponent();
timer.Interval = TimeSpan.FromMilliseconds(1);
timer.Tick += OnTick;
lastUpdate = Environment.TickCount;
timer.Start();
}
private void OnTick(object sender, EventArgs e)
{
double diff = Environment.TickCount - lastUpdate;
double x = Canvas.GetLeft(rect);
if (isRight)
x += 1 * diff;
else if (isLeft)
x -= 1 * diff;
Canvas.SetLeft(rect, x);
lastUpdate = Environment.TickCount;
}
private void UserControl_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.D)
isRight = true;
if (e.Key == Key.A)
isLeft = true;
}
private void UserControl_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.D)
isRight = false;
if (e.Key == Key.A)
isLeft = false;
}
谢谢! 安德烈
答案 0 :(得分:3)
每1毫秒更新一次位置是过度的,因为silverlight根本不会快速更新屏幕。当您修改像这样的对象(或任何其他ui更新)的位置时,silverlight会将帧缓冲区标记为脏,然后它最终将重绘屏幕,但是它不会比MaxFrameRate
更频繁地重绘屏幕。 / p>
仅设置MaxFrameRate
:
Application.Current.Host.Settings.MaxFrameRate = 60;
这会将你的应用程序限制在每秒60帧,这应该足够了。
答案 1 :(得分:0)
不要将DispatchTimer用于动画。 Reasons for this。如果可以,请使用故事板或CompositionTarget.Rendering事件。