среда, 6 апреля 2011 г.

Chapter 4 - Создание SnowStorm приложения. Добавление анимации

Для реализации анимированных частей этого примера, мы должны сделать две вещи:
- Периодически добавлять ряд новых снежинок в верхней части сцены
- Периодически перемещать все существующие снежинки вниз и удалять те, которые достигают нижней части сцены.
В Swing приложении, вы бы перевели требование для периодических действий в метод, который вызывается по истечении таймера. JavaFX имеет гораздо более гибкие функции, которые могут быть использованы для реализации периодического действия, называемые временной шкалой или таймлайном (timeline). В самом общем виде, таймлайн состоит из ряда ключевых кадров, которые реализуются в определенное время. Для полного обсуждения таймлайнов и ключевых кадров, см. главу 18, "Анимация". В этой главе мы используем таймлайн в качестве средства выполнения некоторого кода с регулярными интервалами.

Добавление новых снежинок

Так как снежинки появляются в сцене, они должны быть узлами.Самый простой способ создания снежинки в форме узла это использование маленького белого круга, так что каждая снежинка будет экземпляром класса javafx.scene.shape.Circle.Нам нужно хранить ссылку на каждую снежинку, которую мы создаем, что всегда знать, как много их есть и что бы иметь возможность их перемещать вниз по экрану.Для этого мы создаем переменную последовательности называемую
snowflakes в которую каждая снежинка будет добавлена:

// Снежинки
var snowflakes:Circle[];

Как часто мы должны создавать новые снежинки? Ответ на этот вопрос не простой. Если мы создаем снежинки слишком часто, или если мы создаем их слишком много, мы можем обнаружить, что приложение тратит слишком много времени на их анимацию и это может показаться пользователю тормозящим. Если мы не создаем достаточно снежинок, эффект метели может быть потерян.Мы также должны иметь в виду, что это приложение может быть использовано на мобильном устройстве, которое имеет ограниченные вычислительные мощности. Для этого примера, мы принимаем компромисс и будем создавать 5 новых снежинки каждые 500 миллисекунд, поэтому нам нужно настроить таймлайн, который выполняет код для создания снежинок два раза в секунду.
Вот код, который определяет количество создаваемых снежинок, объявляет таймлайн и запускает его таймер.Добавьте этот код в конце файла SnowStorm.fx:



Переменная объявленная на второй строке является литералом со значением 500ms.Это пример литерала времени, и он вычисляет в экземпляре класса javafx.lang.Duration, представляющего интервал времени в 500 миллисекунд. Компилятор распознает синтаксис литерала времени, генерирует код для создания соответствующего объекта Duration, и делает вывод, что это тип переменной newSnowTime. Как вы увидите в главе 18, вы можете использовать этот синтаксис для указания продолжительности в часах, минутах, секундах и миллисекундах, и вы также можете выполнять арифметические операции над объектами Duration.
Код в строке 8 создает и инициализирует генератор случайных чисел, которые мы используем при добавлении и перемещения снежинок. Random это Java класс в пакете java.util. Мы также могли использовать функцию ranom() из пакета javafx.util.Math (см. главу 12, "Платформа API"), но не методом похожего названия из класса java.lang.Math, потому что он не доступен на мобильных устройствах.
Код на строках с 11 по 19 создает таймлайн, который является экземпляром класса javafx.animation.Timeline. В общем, таймлайн будет иметь несколько ключевых кадров, каждый из них указывает промежуточное состоянии анимации/действия, которые должны быть выполнены в указанное время относительно точки, в которой начинается анимация. В этом случае, мы должны сделать только одну вещь, так что нам понадобится всего один ключевой кадр.
KeyFrames переменная содержит экземпляр класса javafx.animation.KeyFrame для каждого ключевого кадра на временной шкале. Здесь есть только один ключевой кадр, который будет выполнен спустя 500 миллисекунд. Этот временной интервал задан в качестве значения переменной time в строке 15, а код, который будет выполнен содержится в функции addNewSnow(), который присваивается переменной action объекта KeyFrame на строке 16. Обратите внимание, что мы еще не объявили функцию с именем addNewSnow(), предыдущий код еще не будет компилироваться.
Это может показаться странным, что вы можете назначить имя функции переменной таким образом, потому что аналогичной концепции в Java нет. Это возможно сделать это на других языках, в том числе C и C++, где указатели на функции могут быть сохранены в переменных или переданы в качестве аргументов вызова функции. В отличие от Java, JavaFX поддерживает функции первого класса типа, что означает, что вы можете объявить переменную с типом функции, вы можете прочитать и присвоить такой переменной, вы можете вызвать функцию через функцию переменной, вы можете передать функции в качестве аргумента другой функции, и вы сможете вернуться из функции в функцию. Вы можете найти подробности в главе 6, "Выражения, функции и литералы объектов".
Значение Timeline.INDEFINITE назначается переменной repeatCount в строке 12, единственный ключевой кадр в этой строке будет повторяться бесконечно, пока не будет явно остановлено или пока не произойдет вход из приложения.Как результат, приложение постоянно создает новые снежинки.
Таймлайн не запускается без спроса так что мы не вызываем его на 20 строке вызывая его функцию play().
Теперь давайте посмотрим на реализацию функции addNewSnow().Добавьте следующий код в конец файла SnowStorm.fx и нажмите Ctrl-Shift-I (в NetBeans) или Ctrl-Shift-O (в Eclipse) для автоматического добавления строк импорта классов, которые используют анимацию:



Целью этого кода является добавление новых снежинок вверху сцены.Мы хотели бы эти снежинки, довольно случайно размещались и не группировались слишком тесно.Для достижения этой цели, мы делим ширину сцены в примерно snowFlakesPerLine разделов, а затем помещаем одну снежинку в каждом.Переменная sectionWidth объявленная в строках 3 и 4 устанавливается равной ширине каждого из этих разделов, на основе фактической ширины сцены и количества требуемых снежинок. Например, если сцена имеет 500 пикселей в ширину и snowFlakesPerLine имеет значение 5, sectionWidth будет 100, и там появится одна новая снежинка примерно раз в 100 пикселей по всей сцене.
Снежинки создаются в цикле на строках с 5 по 16.Как вы можете видеть, оператор for JavaFX мало отличается от своего аналога Java (подробности см. в главе 8, "Управление программным потоком").Синтаксис [0 ..

for (i = 0; i < snowflakesPerLine; i++)

В теле цикла, мы вычисляем координату х одной из снежинок, используя переменную цикла i представляя число секции, которая содержит эту снежинку.Х координата начала раздела (i * sectionWidth).Вы можете легко увидеть, что это правильно, потому что если sectionWidth имеет значение 100, X координата левого раздел должна быть равна 0, что в следующем разделе должно быть 100, следующий будет 200, и так далее.В разделе, мы хотим, чтобы снежинка размещалась случайно, поэтому мы добавляем к х координате смещение, получаемое из генератора случайных чисел, в диапазоне от 0 до sectionWidth.
Строки с 7 по 13 создают узел круга, представляющий снежинку.Чтобы нарисовать круг, необходимо указать положение его центра, радиус и цвет. Здесь х координаты центра значение только рассчитывается, у координата всегда равна нулю, так что снежинка появляется в верхней части сцены, радиус фиксируется на 2 пикселя, и его цвет белый (как и подобает снежинке!) Кэш переменной, установленный на строке 11, оптимизирует производительность, что позволяет среде хранить и повторно использовать копию пикселов, которые представляют круг так, чтобы они не перерисовывались с нуля каждый раз. Для таких простыхи малых формы это, вероятно, не будет иметь большой разницы, но для больших форм, используя этот параметр можно сэкономить значительное количество времени на рендеринге.
Создав снежинка и определив, где она должна появиться, мы добавим её на сцену, вставив его в последовательность content, как показано на строке 14.Оператор import JavaFX добавляет объект (в данном случае, снежинка) в конец последовательности (здесь, переменная content сцены). Сцена отображает узлы из её content, начиная с первого элемента последовательности и заканчивая последним.Результатом является то, что узлы, которые появляются позже в последовательности рисуются перед более ранними. Потому что фоновое изображение является первым узлом в сцене, снежинки будут полностью отображаться перед ним, что создаст нужный эффект. По той же причине, снежинки будет также рисоваться перед текстом, который является вторым элементом в последовательности.Это приемлемо, но требуется немного больше программирования, вы разместите снежинки за текстом.Оставим это упражнение для вас, как только вы прочитаете главу 7, "Последовательности".
Наконец, в строке 14, мы также добавим каждый узел круга к последовательности snowflakes.Мы делаем это так, что код, который перемещает снежинки, который показан в следующем разделе, позволяет легко их найти.Мы также используем эту последовательность в разделе "Подсчет Снежинок", далее в этой главе.
Если вы запустите пример на данный момент, вы должны увидеть новые снежинки накапливаемые в верхней части фонового изображения и с течением времени, всё в верхней строке будет заполнено. Наша следующая задача организовать падение снежинок на землю.

Комментариев нет:

Отправить комментарий