Главная » Silverlight » Анимация на основе кадров

0

Наряду с анимацией на основе свойств, платформа Silverlight предоставляет спосо­бы создания анимации на основе кадров с использованием только кода С#. Для их реа­лизации нужно лишь задать реагирование на статическое событие CompositionTarget. Rendering для извлечения содержимого для каждого кадра. Это довольно низкоуровне­вый подход, и применять его рекомендуется, только если стандартная модель анимации на основе свойств не подходит для решения сложной задачи, такой как создание про­кручиваемых игр, имитация физических эффектов, моделирование столкновения ча­стиц (снежинок, пузырьков) и т.д.

Базовая методика анимации на основе кадров несложная. Нужно всего лишь под­ключить обработчик к событию CompostitionTarget .Rendering. После этого надстрой­ка Silverlight будет непрерывно вызывать данный обработчик. Если код прорисовки вы­полняется достаточно быстро, Silverlight может вызывать обработчик 60 раз в секунду. В обработчике события прорисовки можно создавать и настраивать элементы окна, од­нако всю эту работу необходимо проделать вручную. По завершении анимации отклю­чите обработчик.

На рис. 10.14 показан простой пример, в ко­тором окружности случайным образом падают на дно контейнера Canvas. Скорость их разная (она определяется с помощью генератора слу­чайных чисел), однако ускорение всех окружно­стей одинаковое. Анимация завершается, когда все окружности упадут на дно.

В данном примере окружности создаются элементами Ellipse. Пользовательский класс Ellipselnfо содержит ссылку на эллипс и от­слеживает скорость эллипса вдоль оси Y. Вы легко можете расширить класс Ellipselnfo, за­дав отслеживание скорости вдоль оси X, ускоре­ния эллипса и т.д.

public class Ellipselnfo

{

public Ellipse Ellipse get; set;

public double VelocityY get; set;

public Ellipselnfo(Ellipse ellipse, double velocityY)

Рис. 10.14.

VelocityY = velocityY; Ellipse = ellipse;

Приложение создает экземпляр объекта Ellipselnfo для каждого эллипса и со­храняет все экземпляры в коллекции. В полях на уровне окна хранятся параметры, необходимые для управления перемещением каждого эллипса. Эти параметры легко конфигурировать.

private List<EllipseInfo> ellipses = new List<EllipseInfo>();

private double accelerationY = 0.1; private int minStartingSpeed = 1; private int maxStartingSpeed = 50; private double SpeedRatio = 0.1; private int minEllipses = 20; private int maxEllipses = 100; private int ellipseRadius = 10; private SolidColorBrush ellipseBrush = new SolidColorBrush(Colors.Green);

При щелчке на кнопке Пуск коллекция очищается, а обработчик подключается к событию CompositionTarget .Rendering.

private bool rendering = false;

private void cmdStart_Clicked(object sender, RoutedEventArgs e)

{

if (!rendering) {

ellipses.Clear (); canvas.Children.Clear();

CompositionTarget.Rendering += RenderFrame; rendering = true;

} }

Если эллипсы не существуют, код прорисовки автоматически создает их. Приложение создает случайное количество эллипсов (от 20 до 100) и присваивает им одинаковые размеры и цвет. Эллипсы размещаются вдоль верхней границы контейнера Canvas. Вдоль оси X они размещены случайным образом. Каждый получает случайную началь­ную скорость.

private void RenderFrame(object sender, EventArgs e)

if (ellipses.Count == 0) {

// Начало анимации; создание эллипсов

int halfCanvasWidth = (int)canvas.ActualWidth / 2;

Random rand – new Random();

int ellipseCount = rand.Next(minEllipses,maxEllipses+1);

for (int і = 0; і < ellipseCount; i++) {

// Создание эллипса Ellipse ellipse = new Ellipse (); ellipse.Fill = ellipseBrush; ellipse.Width = ellipseRadius; ellipse.Height = ellipseRadius;

// Размещение эллипса

Canvas.SetLeft(ellipse, halfCanvasWidth +

rand.Next(-halfCanvasWidth, halfCanvasWidth)); Canvas.SetTop(ellipse, 0) ; canvas.Children.Add(ellipse);

// Отслеживание эллипса

Ellipselnfo info = new Ellipselnfo(ellipse, speedRatio * rand.Next(minStartingSpeed, maxStartingSpeed)); ellipses.Add(info);

}

)

Если эллипсы уже существуют, код анимирует их. Каждый эллипс перемещается с помощью метода Canvas . SetTop (). Скорость перемещения каждого эллипса опреде­ляется значением VelocityY.

else {

for (int і = ellipses.Count-1; і >= 0; і—) {

Ellipselnfo info = ellipses[і];

double top = Canvas.GetTop(info.Ellipse);

Canvas.SetTop(info.Ellipse, top + 1 * info.VelocityY);

Для повышения производительности эллипс удаляется из коллекции, как только он достигнет дна контейнера Canvas. Удаленный эллипс не нужно больше обрабатывать. Чтобы при удалении не потерять позицию в коллекции, код проходит по ней в обратном направлении: с конца в начало.

Если эллипс еще не достиг дна, код увеличивает скорость. Можно также вычислять скорость в зависимости от расстояния эллипса до дна, тогда будет создан эффект маг­нита, притягивающего эллипсы.

if (top >= (canvas.ActualHeight – ellipseRadius*2)) {

// Этот эллипс достиг дна, поэтому // его анимация прекращается ellipses.Remove(info)?

}

else {

// Увеличение скорости

info.VelocityY += accelerationY;

}

И наконец, когда все эллипсы удалены из коллекции, обработчик события отключа­ется, позволяя анимации завершиться.

if (ellipses.Count == 0) (

// Завершение анимации;

// вызывать обработчик больше нет необходимости, // поэтому он отключается

CompositionTarget.Rendering -= RenderFrame; rendering = false;

}

}

}

}

Вы можете расширить приложение, заставив эллипсы отталкиваться друг от друга, рыскать по сторонам и т.д. Методика та же, нужно лишь вычислять скорости по обеим осям с помощью более сложных формул.

При создании анимаций на основе кадров необходимо учитывать, что они зависят от времени. Это приводит к тому, что на более быстродействующем компьютере ани­мация выполняется быстрее вследствие более высокой частоты кадров. В результате событие CompositionTarget.Rendering генерируется чаще. Для нивелирования этого эффекта нужно добавить код, принимающий во внимание текущее время.

Источник: Мак-Дональд, Мэтью. Silverlight 3 с примерами на С# для профессионалов. : Пер. с англ. —- М. : ООО «И.Д. Вильяме», 2010. — 656 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии