При попытке ко времени/кадру одушевленных объектов, базирующемуся в Silverlight (в отличие от использования чего-то как DoubleAnimation или Раскадровка, которая не подходит, например, для быстрых измеренных шагами игр), например, перемещая космический корабль в конкретное направление каждый кадр, перемещение является нервным и не действительно гладким. Экран даже, кажется, рвется.
Кажется, нет никакого различия между 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. Хотя эффект, который я описал, не слишком распространен в этом образце, я могу уверить Вас, который, даже перемещая единственный прямоугольник через холст производит нервную анимацию.
Делает у кого-то есть идея, как минимизировать это. Там другие подходы к к покадровой анимации кроме использования Storyboards/DoubleAnimations, который мог решить это?
Править: Здесь быстрый и грязный подход, анимируя прямоугольник с минимальным кодом (Средства управления: A и D) Образец Анимации
Xaml:
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;
}
Спасибо! Andrej
Обновление позиции каждые 1 миллисекунду - это излишество, потому что silverlight просто не будет обновлять экран так быстро. Когда вы изменяете положение объекта подобным образом (или любое другое обновление пользовательского интерфейса), silverlight помечает фреймбуфер как грязный и в конечном итоге перерисовывает экран, однако он не будет перерисовывать экран чаще, чем MaxFrameRate
.
Чтобы установить MaxFrameRate
, просто:
Application.Current.Host.Settings.MaxFrameRate = 60;
Это ограничит ваше приложение 60 кадрами в секунду, что должно быть более чем достаточно.