Внимание! Для работы с этим уроком
необходимы учебные файлы, которые Вы можете
загрузить
здесь.
Часть проекта Make My Day, который мы с вами
построим в этом уроке.
Использование отсчета времени во FLASH
Для измерения времени во
Flash-проектах имеется несколько методов.
Наиболее употребительны следующие:
- Объект Date. Встроенный объект
Flash; позволяет работать с датами (день,
месяц, год).
- Функция getTimer(). Специальная
функция Flash; позволяет вести отсчет
времени в миллисекундах.
- Кадры. Кадр – наиболее
употребительная "единица времени" во Flash,
ведь именно отсчет кадров лежит в основе
воспроизведения анимаций, звуков,
видеороликов и т.п. Перемещение от текущего
кадра к следующему (или предыдущему)
представляет собой развитие проекта во
времени (в прямом или обратном направлении).
Используя эти элементы, вы можете
снабдить свой проект следующими возможностями:
- Проигрывание в прямом или обратном
направлении, в зависимости от действий
пользователя
- Реакция проекта на текущую дату, время
или номер кадра
- Отображение информации о ходе загрузки
(например, в процентах)
- И многое другое
В ActionScript имеется еще один
специальный инструмент –
setInterval(), позволяющий вызывать
какую-либо функцию раз за разом с определенным
интервалом (измеряемым в миллисекундах). Для
примера рассмотрим такой скрипт:
function rotateClip() {
myMovieClip._rotation += 10;
}
setInterval (rotateClip, 1500);
В первых трех строках описана
функция. Затем следует действие
setInterval(),
вызывающее функцию
rotateClip() каждые полторы секунды (1000
миллисекунд = 1 секунде).
Если вызываемой функции требуется
передать значения аргументов, они просто
добавляются в качестве параметров действия
setInterval():
setInterval (updateMessageFunction, 2000, "Hello", arg2, arg3);
Действие
setInterval() можно включать и отключать
– для этого следует "присвоить" ему имя
переменной, как в этом примере:
myVariable = setInterval (rotateClip, 1500);
Тем самым имя
myVariable
назначается данному действию
setInterval().
Теперь, чтобы прекратить выполнение действия
setInterval(),
достаточно использовать следующую команду:
delete myVariable;
Действие
setInterval() можно инициировать в любое
время, например, вставив его вызов в какую-либо
функцию. В следующем уроке мы с вами применим
это действие для создания вращающихся рекламных
баннеров.
Определение текущего времени и даты
Все мы пользуемся календарем;
многие вообще не представляют себе, как можно
без него обойтись – ведь нужно планировать свои
дела на будущее и т.д.. Во Flash информация о
календарной дате тоже может пригодиться – чтобы
показать ее пользователю, или выполнить в
определенный день некие специфические действия,
или создать таймер обратного отсчета, да мало ли
для чего еще.
Чтобы использовать во Flash
календарную дату, необходимо создать экземпляр
объекта Date:
myDate = new Date(year, month, date);
Эта строка скрипта создает новый
объект Date под
именем myDate.
Параметры в скобках связывают этот объект с
определенной датой. Например:
myDate = new Date(66, 6, 27);
Этим скриптом будет создан новый
объект Date,
связанный с 27 июля 1966 года. Первый параметр
определяет год, второй – месяц, третий – день.
Кстати, не удивляйтесь, тут нет никаких
опечаток, хотя июль – седьмой месяц, а в скрипте
указано 6. Дело в том, что в ActionScript месяцы
и дни недели обозначаются числами, причем
нумерация начинается с нуля. Таким образом,
январь – "нулевой" месяц, февраль – "первый",
март – "второй", и так до "одиннадцатого" –
декабря. Подобным же образом, неделя начинается
с "нулевого" дня – воскресенья, затем идет
понедельник и так далее. В следующем упражнении
мы продемонстрируем, в чем состоит удобство этой
системы нумерации.
Примечание Числа месяцев и
годы имеют истинные значения. Так, 66
соответствует 1966 году, а 27 – 27-му дню
месяца.
Совет Список параметров
создаваемого объекта можно продолжить, указав
час, минуту, секунду и миллисекунду, если в
вашем приложении нужна такая точность.
Если нужно создать объект Date,
содержащий текущую дату и время (по системным
часам компьютера), достаточно просто не
указывать параметры, оставив скобки конструктора
объекта пустыми. Например:
myDate = new Date();
После того, как объект
Data создан, можно
извлечь из него любую информацию о хранящейся в
нем дате при помощи соответствующих методов.
Возьмем предыдущий пример – объект, содержащий
текущую системную дату. Чтобы выяснить, какой
сейчас месяц, мы используем следующий синтаксис:
currentMonth = myDate.getMonth();
После выполнения этой строки
переменная currentMonth
получит числовое значение, например, 5 – это
будет означать месяц июнь. Чтобы узнать день
недели, используем другой метод:
currentDay = myDate.getDay();
После выполнения этой строки
переменная currentDay
получит числовое значение, например, 4, что
соответствует четвергу.
Примечание Проект может
содержать несколько объектов
Data,
предназначенных для разных целей.
В следующем упражнении мы создадим
объект Data и
применим различные методы для отображения
текущей даты на экране.
- Откройте файл makeMyDay1.fla из папки
Lesson15/Assets.
Этот проект состоит из двух сцен –
Alarm и Messages. В этом упражнении мы будем
работать исключительно со сценой Alarm, и
сосредоточимся на календаре, расположенном в
левой половине. Правой половиной займемся в
следующем упражнении. Слои в этой сцене
называются в соответствии с содержимым.
Непосредственно под надписью
"Today is:" вы видите четыре текстовых поля.
Называются они (по порядку сверху вниз)
currentDay, currentMonth,
currentDate и
currentYear. В этих полях будут
динамически отображаться составляющие текущей
даты:
- currentDay. Будет показывать
текущий день недели (например, "Saturday").
- currentMonth. Будет показывать
текущий месяц (например, "April").
- currentDate. Будет показывать
текущее число месяца (например, "27").
- currentYear. Будет показывать
текущий год (например, "2002").
В каждом поле стиль текста будет
разным, чтобы наш календарь выглядел красиво.
- Откройте инспектор Параметры
(Property), выделите верхнее текстовое поле
– currentDay. Нажмите в инспекторе Параметры
кнопку Символ (Character), чтобы отобразить
диалоговое окно Свойства символов (Character
Options).
В самом низу этого окна вы видите
бессмысленный набор букв. Эти буквы – набор
символов, специфическое начертание которых мы
хотим внедрить в фильм для этого поля. Названия
всех дней недели состоят только из букв, которые
здесь перечислены. Это текстовое поле будет
содержать динамически генерируемый текст, и
внедрение шрифта позволит отображать текст в
этом поле со сглаживанием граней.
Для прочих текстовых полей
календаря тоже указан тот или иной внедряемый
набор символов (в зависимости от того, что
должно отображать каждое поле).
- Откройте панель Действия, выделите
кадр 1 слоя Actions и введите следующий
скрипт:
stop();
today = new Date();
Первое действие воспрещает
дальнейшее воспроизведение монтажного стола до
особых на то указаний.
Следующая строка скрипта создает
новый объект Date
под именем today,
как только начнется воспроизведение фильма.
Поскольку в скобках мы не указали особых
значений параметров, этот объект
Data будет
содержать текущую системную дату на компьютере
пользователя (на момент воспроизведения фильма).
- В конец текущего скрипта добавьте
следующие две строки:
nameOfDays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
nameOfMonths = ["January", "February", "March", "April", "May", "June", "July", "August",
"September", "October", "November", "December"];
Первая строка создает массив под
названием nameOfDays;
вторая строка – массив
nameOfMonths. Каждый массив содержит
набор строковых значений, представляющих собой,
соответственно, названия дней недели и месяцев.
Для чего нужны эти массивы? Ну, это ведь люди
называют дни и месяцы разными словами, а
ActionScript – нет, он знает их только под
номерами. Как вы вскоре увидите, с помощью
простого трюка мы заставим наш проект превратить
эти номера дней и месяцев в привычные нам
названия.
- В конец текущего скрипта добавьте
следующую строку:
currentDay.text = nameOfDays[today.getDay()];
Этим действием мы выводим
информацию в текстовом поле
currentDay.
Поясним, как это получается.
С помощью метода
getDay() (в
квадратных скобках) мы определяем день недели
даты, хранящейся в объекте
today. Этот метод
возвратит некое значение от 0 до 6 (напомним, 0
соответствует воскресенью, 6 – субботе).
Допустим, метод вернул значение 3; это значение
подставляется вместо выражения в квадратных
скобках, и мы получает такую строку:
currentDay.text = nameOfDays[3];
Как видите, в поле
currentDay будет
отображено значение элемента с индексом 3
массива nameOfDays,
то есть строковое значение "Wednesday". Как
видите, мы, зная, что метод
getDay() выдает
числовые значения от 0 до 6, создали на
предыдущем шаге массив, элементами которого
являются названия дней недели, причем этих
элементов имеют индексы тоже от 0 до 6.
- Добавьте в конец текущего скрипта
следующую строку:
currentMonth.text = nameOfMonths[today.getMonth()];
Этим действием мы выводим
информацию в текстовом поле
currentMonth.
Принцип действия тот же, что и на предыдущем
шаге – метод getMonth()
выдает некоторое числовое значение от 0 до 11,
из массива nameOfMonths
берется строковое значение элемента с
соответствующим индексом.
- Добавьте в конец текущего скрипта
следующую строку:
currentDate.text = today.getDate();
Это действие выводит информацию в
текстовом поле
currentDate. Здесь использован метод
getDate(),
возвращающий числовое значение от 1 до 31,
соответствующее числу месяца для даты,
хранящейся в объекте
today. В данном случае нам требуется
именно число, поэтому никакого массива для
преобразования номера в строку здесь не нужно.
- Добавьте в конец текущего скрипта
следующую строку:
currentYear.text = today.getFullYear();
Это действие выводит информацию в
текстовом поле
currentYear. Здесь использован метод
getFullYear(),
возвращающий числовое значение, соответствующее
году даты, хранящейся в объекте
today (например,
2002). В данном случае опять нас вполне
устраивает число, и массива для преобразования в
строку не требуется.
- Командой Управление > Проверить фильм
(Control > Test Movie) запустите тест
проекта.
Как только фильм запустится,
текстовые поля календарного листка на экране
заполнятся информацией, соответствующей
сегодняшней дате.
- Закройте тестовый фильм и сохраните
ваш проект под именем makeMyDay2.fla.
Мы продолжим работу с этим
проектом в следующем упражнении урока.
Отсчет времени
Функция
getTimer() возвращает время (в
миллисекундах), прошедшее с момента запуска
фильма. Если, к примеру, на момент вызова этой
функции фильм воспроизводится уже шесть секунд,
то скрипт
playBackTime = getTimer();
присвоит переменной
playBackTime
значение 6000 (1000 миллисекунд в каждой
секунде). Это – точное время, отсчитываемое по
системным часам пользовательского компьютера;
оно не зависит ни от частоты кадров фильма, ни
от быстродействия процессора, ни от того,
воспроизводится ли фильм или стоит на одном и
том же кадре. Подчеркнем, что функция возвращает
время, прошедшее с момента запуска всего фильма,
а не отдельных монтажных столов.
Промежуток времени между двумя
событиями внутри фильма все же можно измерить.
Для этого следует в нужный момент присвоить
какой-либо переменной значение, возвращенное
функцией getTime(),
а потом сравнить с этой переменной новое
значение, возвращенное функцией. Поясним это на
следующем примере:
// Скрипт для кнопки A
on (release) {
startTime = getTimer();
}
// Скрипт для кнопки B
on (release) {
nowTime = getTimer();
if (nowTime – startTime < 1000) {
message.text = "Вы нажали кнопку слишком быстро";
} else {
message.text = "Слишком поздно";
}
}
Здесь, если нажата и отпущена
одна из кнопок (кнопка A), фиксируется стартовая
точка отсчета времени. Когда нажата и отпущена
кнопка B, время снова фиксируется. Условный
оператор определяет, больше или меньше секунды
прошло между двумя этими моментами, и выполняет
соответствующее действие. Сходным образом можно
реализовать для одной кнопки обработку двойного
щелчка – следующий скрипт будет выполнять
действия только в том случае, если второй щелчок
на кнопке произошел не позднее, чем через
полсекунды после первого:
on (release) {
if (getTimer() – lastClick < 500) {
// Действия
}
lastClick = getTimer();
}
Используя функцию
getTimer()
совместно с событием
enterFrame и условными операторами, можно
создать механизм выполнения тех или иных
действий в определенное время – независимо от
монтажного стола и с большой точностью отсчета.
Возьмем такой пример:
onClipEvent (enterFrame) {
if (getTimer() > 5000) {
// Действия
}
if (getTimer() > 10000) {
// Действия
}
if (getTimer() > 15000) {
// Действия
}
}
Этот скрипт будет выполнять
действия каждые пять секунд по ходу
воспроизведения фильма – зачастую это
единственный способ, если требуется точный
отсчет времени.
В следующем упражнении мы с вами,
используя функцию
getTimer(), создадим таймер-будильник.
Примечание Функцию
getTimer() можно
найти в списке инструментов панели Действия в
разделе Functions.
- Откройте файл makeMyDay2.fla из папки
Lesson15/Assets.
Мы продолжаем работу над
проектом, начатым в предыдущем упражнении.
Напомним, что в этом файле имеется две сцены,
Alarm и Messages. Как и в предыдущем упражнении,
сейчас мы будем работать только со сценой Alarm,
только на сей раз сосредоточимся на правой
половине экрана. Здесь, в правом верхнем углу,
имеется три текстовых поля:
minutesToAlarm,
secondsToAlarm и
numberOfLoops (сверху вниз). Это
текстовые поля для ввода; первые два
предназначены для установки времени, по
прошествии которого должен сработать будильник,
третье будет определять, сколько раз будильник
должен прозвонить.
Ниже этих текстовых полей
находится кнопка Start, которой будет
запускаться таймер/будильник.
Под этой кнопкой расположен
экземпляр фильма-символа под названием
clock, содержащий
движущиеся элементы (подобно настоящему
секундомеру). Давайте познакомимся с ним
поближе.
- Двойным щелчком на экземпляре клипа
clock откройте его для редактирования на
месте.
Монтажный стол этого клипа
состоит из двух слоев: слой Clock содержит общее
графическое оформление, а в слое Hands находится
три экземпляра клипов, представляющих элементы
циферблата. Один из этих экземпляров,
secondHand,
представляет секундную стрелку часов; она будет
вращаться при запущенном таймере.
Непосредственно под этим экземпляром находится
второй экземпляр –
minuteHand; это будет минутная стрелка.
Третий экземпляр клипа выглядит как маленькая
красная метка в верхней части циферблата. Этот
экземпляр называется
alarmHand, эта метка переместится на
сколько-то делений после установки и запуска
таймера.
- Вернитесь на основной монтажный стол.
Откройте панель Действия, выделите кнопку
Start и введите следующий скрипт:
on (release) {
clock.alarmOn = true;
clock.startingTime = getTimer();
}
Когда эта кнопка будет нажата и
отпущена, будут присвоены значения двум
переменным в экземпляре клипа
clock. Как вы
вскоре увидите, то, что переменная
alarmOn получила
значение true,
будет знаком к "включению" скрипта,
присоединенного к этому экземпляру. Переменная
startingTime
получает возвращенное функцией
getTimer()
значение, равное числу миллисекунд, прошедших с
момента запуска фильма. Фиксация точного времени
запуска таймера – важнейший момент для этой
части нашего проекта, и сейчас вы в этом
убедитесь.
- Выделите экземпляр клипа clock и
введите в панели Действия следующий скрипт:
onClipEvent (enterFrame) {
if (alarmOn) {
}
}
В этом скрипте условный оператор
проверяет значение переменной
alarmOn каждый
раз, когда происходит событие
enterFrame. Как вы
помните, на предыдущем шаге мы
запрограммировали, что при нажатии на кнопку
Start эта переменная получает значение
true. На
нескольких следующих шагах мы добавим действия в
этот условный оператор, и действия эти будут
выполняться только в том случае, если
alarmOn равно
true. Действия
будут перемещать стрелки часов и подавать сигнал
в нужный момент. Таким образом, кнопка Start
запускает таймер.
- Внутрь условного оператора вставьте
следующую строку:
totalTimeToAlarm = (Number(_root.minutesToAlarm.text) * 60) + Number(_root.secondsToAlarm.text);
Вы помните, что в нашей сцене
имеется одно текстовое поле для ввода минут, и
другое – для ввода секунд. Оба они нам
понадобятся, чтобы определить, через какой
промежуток времени должен сработать будильник.
Во введенной нами строке общее время получается
так: число минут, введенное в соответствующее
поле, умножая на 60, превращаем в число секунд,
а то, что получилось, прибавляем к числу секунд,
введенное в другое поле.
(Number(_root.minutesToAlarm.text * 60)) складываем с
(Number(_root.secondsToAlarm.text)) и получаем значение totalTimeToAlarm.
В обеих частях выражения мы
применили функцию
Number() – ради уверенности, что значения
minutesToAlarm.text
и secondsToAlarm.text
будут восприниматься как числовые, а не
строковые. Сейчас мы поясним, почему это
необходимо. Возьмем пример. Предположим,
пользователь ввел в текстовое поле
minutesToAlarm
число 5, а в текстовое поле
secondsToAlarm –
число 37. С этими значениями наше выражение
будет выглядеть так:
(Number("5") * 60) + Number("37")
Как видите, введенные значения
изначально трактуются как строковые, а в этом
случае у нас не получилось бы никаких
математических вычислений. Однако с помощью
функции Number()
мы преобразуем эти значения в числовые, и
выражения принимает такой вид:
(5 * 60) + 37
Примечание Значение
свойства text
текстового поля всегда считается строкой,
поэтому для математических операций следует
преобразовывать их в числа.
В минуте 60 секунд, поэтому
введенное число минут мы умножаем на 60. В нашем
примере получится 300. Это число мы прибавляем к
введенному числу секунд, и получаем 337 (секунд)
– это значение и присваивается переменной
totalTimeToAlarm.
В дальнейшем мы будем сравнивать с этим
значением число секунд, прошедших с момента
запуска таймера. Как только число прошедших
секунд превысит это значение, скрипт будет
знать, что пора включать звуковой сигнал.
Совет Наш таймер мог бы
прекрасно работать в том случае, если бы мы
установили значение
totalTimeToAlarm единожды, однако мы
поместили эту строку скрипта в обработчик
события enterFrame,
и значит, значение этой переменной может
обновляться, если надо, 24 раза в секунду
(частота кадров в нашем фильме). Это дает
пользователю возможность динамически менять
настройку таймера (вводить другое число минут и
секунд), даже если таймер уже запущен, и
значение totalTimeToAlarm
будет при этом автоматически обновляться.
- Сразу после строки скрипта,
добавленной на предыдущем шаге, добавьте
следующую строку:
secondsElapsed = Math.round((getTimer() – startingTime) / 1000);
Для нас очень важно отслеживать
время, прошедшее с момента, когда пользователь
нажал кнопку Start и активировал таймер. Это и
делает данная строка скрипта. Вычисления
производятся следующим порядком:
Текущее время, полученное с
помощью функции
getTimer() (проверяется 24 раза в
секунду, поскольку эта строка скрипта
выполняется обработчиком события
enterFrame),
вычитается из значения переменной
startingTime:
getTimer() – startingTime
Как вы помните, переменная
startingTime
содержит время, прошедшее от начала фильма до
нажатия кнопки Start. Постоянно проверяя текущее
время и сравнивая его с этим значением, скрипт
определяет, сколько прошло от нажатия кнопки
Start до текущего момента. Эта часть выражения
дает результат в миллисекундах, ну, например,
29349. Разделив это число на 1000 (следующая
часть выражения),
/ 1000
Мы получаем число прошедших
секунд – 29,349. Последняя часть выражения
округляет это значение до целого числа:
Math.round()
В конце концов, переменной
secondsElapsed
присваивается значение 29. Следует помнить, что
это значение будет увеличиваться при каждом
выполнении скрипта (ведь время идет). При этом
увеличение будет происходить только в целых
числах – 29, 30, 31 и так далее. Новое значение
мы будем получать каждую 1/24 секунды – именно с
такой частотой будет выполняться эта строка
скрипта.
Итак, у нас есть две переменные,
необходимые для остальных действий данного
скрипта.
- Сразу после предыдущей строки скрипта
добавьте следующую:
alarmHand._rotation = totalTimeToAlarm / 10;
Как вы помните,
alarmHand – это
имя экземпляра клипа – красной метки внутри
экземпляра клипа clock,
показывающей на циферблате часов момент
срабатывания сигнала. Эта строка скрипта
поворачивает alarmHand,
устанавливая в нужное положение. Например, если
сигнал должен прозвучать через 20 минут,
alarmHand
необходимо повернуть так, чтобы красная метка
оказалась напротив 20-минутной отметки на
циферблате. Посмотрим, каким же образом это
получается.
Полный круг составляет 360
градусов. Наш циферблат разделен на 60 минутных
отметок, отсюда мы получаем, что одной минуте
соответствует поворот на 6 градусов (6 x 60 =
360). Таким образом, чтобы установить метку на
20-минутную отметку, необходимо повернуть
экземпляр клипа alarmHand
на 120 градусов (6 градусов в минуту x 20
минут). Выражение, присваивающее значение
переменной
totalTimeToAlarm (шаг 5) пересчитывает 20
минут в 1200 секунд. Теперь мы делим это число
на 10, и получаем 120 – именно на столько
градусов нам нужно повернуть
alarmHand, чтобы
отметить 20 минут.
- Сразу после предыдущей строки скрипта
добавьте следующие строки:
secondHand._rotation = secondsElapsed * 6;
minuteHand._rotation = secondsElapsed / 10;
Эти две строки вращают экземпляры
клипов secondHand
и minuteHand,
основываясь на постоянно обновляющемся значении
secondsElapsed.
Логика здесь та же, что и на предыдущем шаге –
круг состоит из 360 градусов, наш циферблат
имеет 60 делений, по 6 градусов на каждую минуту
или секунду. За каждую прошедшую секунду
секундная стрелка должна переместиться на 6
градусов. Поэтому первое действие добавленного
нами скрипта поворачивает экземпляр клипа
secondHand на
значение secondsElapsed,
умноженное на 6. Таким образом, через одну
секунду он повернется на 6 градусов, через две –
на 12, и так далее, создавая эффект движения
секундной стрелки на настоящих часах. С минутной
стрелкой дело обстоит несколько иначе. Минутная
стрелка на часах проходит 1/60 того пути, что
прошла секундная. Например, за 60 секунд
секундная стрелка проходит полный круг. Минутная
стрелка к этому моменту должна пройти по
циферблату только 6 градусов, указывая, что
прошла одна минута. Поэтому второе действие в
нашем скрипте поворачивает экземпляр клипа
minuteHand на
значение secondsElapsed,
деленное на 10. Так, если прошло 60 секунд, это
выражение даст результат 6 – на столько градусов
и переместится
minuteHand.
- Сразу после предыдущей строки скрипта
добавьте условный оператор:
if (secondsElapsed == totalTimeToAlarm) {
activateAlarm();
}
Этот условный оператор,
выполняемый 24 раза в секунду (как и прочие
действия этого скрипта), сравнивает значение
secondsElapsed со
значением
totalTimeToAlarm. Если эти значения равны
– значит, пора подавать звуковой сигнал, и
оператор выполняет соответствующее действие.
Действие это заключается в вызове функции
activateAlarm().
Функцию мы сейчас опишем.
- В самый конец текущего скрипта
добавьте следующее:
onClipEvent(load) {
function activateAlarm() {
alarmOn = false;
secondHand._rotation = 0;
minuteHand._rotation = 0;
alarmHand._rotation = 0;
alarmSound = new Sound();
alarmSound.attachSound("annoying");
alarmSound.start(0, _root.numberOfLoops.text);
}
}
Этим скриптом, сразу после
загрузки экземпляра клипа
clock, будет описана функция
activateAlarm().
Функция первым делом присваивает
alarmOn значение
false. Тем самым
будет "отключен" скрипт, связанный с событием
enterFrame, и
таймер остановится. Три следующих действия
функции возвращают все стрелки часов на нулевую
отметку. После этого создается новый объект
Sound под именем
alarmSound. Этот
объект будет представлять собой, как вы
понимаете, сигнал будильника. Следующее действие
присоединяет к созданному объекту
Sound файл
звукозаписи из библиотеки, который называется
"annoying".
Последним действием, с помощью метода
start(),
запускается воспроизведение звука. Первый
параметр определяет, с какой секунды звукозаписи
должно начаться воспроизведение, второй параметр
– сколько раз следует повторить звукозапись. Мы
хотим воспроизводить звукозапись с самого
начала, поэтому в качестве первого параметра
указываем 0. Значение второго параметра будет
зависеть от числа, которое ввел пользователь в
текстовое поле
numberOfLoops на основном монтажном
столе.
- Командой Управление > Проверить фильм
(Control > Test Movie) запустите тест
проекта.
Когда фильм запустится, введите в
текстовые поля для таймера соответствующие числа
и нажмите кнопку Start. Часовые стрелки придут в
действие. Когда наступит время подачи сигнала,
таймер остановится, стрелки встанут на ноль, и
раздастся звуковой сигнал, который будет
повторяться столько раз, сколько вы указали в
поле numberOfLoops.
- Закройте тестовый фильм и сохраните
ваш проект под именем makeMyDay3.fla.
Вы убедились, что функция
getTimer() играет
важнейшую роль там, где требуется точный отсчет
и измерение времени.
Мы продолжим работу над этим
проектом в следующем упражнении.
Управление скоростью и направлением
воспроизведения монтажного стола
В нормальной ситуации монтажный
стол фильма проигрывается в прямом направлении и
со скоростью, определяемой значением
fps (кадры в
секунду), указанным в настройках параметров
фильма. Однако вы можете сами управлять как
направлением, так и скоростью воспроизведения
монтажного стола при помощи ActionScript.
Фактически, комбинируя обработку события
enterFrame с
различными элементами ActionScript, вы можете
получить практически абсолютный контроль над
монтажным столом вашего проекта.
Здесь первым делом нам с вами
следует поговорить о таких методах объекта
MovieClip, как
nextFrame() и
prevFrame(). C их
помощью можно перемещать монтажный стол к
следующему или предыдущему кадру:
on (release) {
myMovieClip.nextFrame();
}
или
on (release) {
myMovieClip.prevFrame();
}
Присоединив такие скрипты к
кнопкам, мы получим кнопки навигации,
обеспечивающие продвижение по монтажному столу
вперед или назад, по одному кадру за каждое
нажатие кнопки.
Нельзя не упомянуть о таком
свойстве монтажного стола, как
_currentframe
(свойство только для чтения). Его значение – это
номер кадра, на котором в данный момент
находится курсор воспроизведения. Например,
предположим, что основной монтажный стол
воспроизводится, тогда следующий скрипт поместит
в переменную whereWeAre
числовое значение, соответствующее номеру
текущего кадра:
whereWeAre = _root._currentfame;
Используя это свойство вместе с
условным оператором, можно определить, например,
находится ли курсор воспроизведения внутри
некоего диапазона кадров, и предпринять
соответствующие действия:
onClipEvent (enterFrame) {
if (_root._currentframe >= 50 && _root.currentframe <= 100)
// Выполнить эти действия
}
}
В этом скрипте действия в теле
условного оператора выполняются только в том
случае, если курсор воспроизведения основного
монтажного стола находится между 50-м и 100-м
кадрами.
А если использовать свойство
_currentframe
вместе с действием
gotoAndPlay(), то можно управлять и
направлением, и скоростью воспроизведения
монтажного стола. Возьмем такой пример:
_root.gotoAndPlay(_currentframe + 10);
Эта строка приведет к тому, что
курсор воспроизведения основного монтажного
стола "перепрыгнет" на 10 кадров вперед от
текущей позиции. Точно так же можно
переместиться по монтажному столу на 10 кадров
назад:
_root.gotoAndPlay(_currentframe - 10);
Как вы увидите в этом упражнении,
используя для выполнения подобной строки скрипта
событие enterFrame,
можно запрограммировать кнопки "перемотки"
вперед и назад.
- Откройте файл makeMyDay3.fla из папки
Lesson15/Assets.
Мы продолжаем работу над
проектом, начатым в предыдущем упражнении. На
сей раз мы будем работать по большей части со
сценой Messages. Однако сначала нужно обеспечить
в нашем проекте саму возможность перехода к этой
сцене. Для этого у нас предназначена кнопка с
надписью "Get phone messages" (в левом верхнем
углу сцены Alarm). Давайте напишем скрипт для
этой кнопки.
- Откройте панель Действия, выделите
кнопку "Get phone messages" и введите такой
скрипт:
on (release) {
nextFrame();
}
Когда пользователь нажмет и
отпустит эту кнопку, основной монтажный стол
продвинется на один кадр вперед. А поскольку в
этой сцене всего один кадр, следующим кадром
будет считаться следующая сцена. Таким образом,
это действие переместит монтажный стол к сцене
Messages, с которой мы дальше и будем работать.
- Откройте панель Сцена (Scene) и
выберите из списка сцену Messages, чтобы
отобразить ее в среде разработки.
Эта сцена состоит из четырех
слоев. Слой Background содержит общее
графическое оформление. В слое Buttons находятся
четыре кнопки: Play, Stop, FF и Rew. Слой
Flashing Indicator содержит экземпляр клипа,
изображающего светящуюся цифру 4. В слое Sound
Clip находится пустой (в смысле графики)
экземпляр клипа – он располагается чуть выше
сцены, слева. Имя этого экземпляра –
messages, и сейчас
мы познакомимся с ним поближе.
- Двойным щелчком на экземпляре клипа
messages откройте его для редактирования на
месте.
Монтажный стол этого клипа
состоит из двух слоев – Sound Clips и Actions.
Кадр 1 слоя Actions содержит действие
stop(),
предотвращающее самопроизвольное проигрывание
этого монтажного стола. В слое Sound Clips
находится серия потоковых звуковых клипов,
занимающих в общей сложности 700 кадров (можете
вручную протащить курсор воспроизведения и
послушать эти клипы). В этом упражнении мы
запрограммируем на основном монтажном столе
кнопки, которые позволят пользователю
перемещаться по данному монтажному столу вперед
и назад.
- Вернитесь на основной монтажный стол.
Выделите экземпляр клипа messages и введите
в панели Действия следующий скрипт:
onClipEvent (enterFrame) {
if (action == "ff") {
gotoAndStop (_currentframe + 3);
} else if (action == "rew") {
gotoAndStop (_currentframe - 10);
} else if (action == "play") {
play();
} else if (action == "stop") {
stop();
}
}
Этот скрипт выполняется
обработчиком события
enterFrame, а значит, условный оператор
будет 24 раза в секунду анализировать значение
переменной action
и выполнять те или иные действия. А значение
этой переменной, как вы вскоре увидите, будет
меняться при нажатии кнопок Play, Stop, FF и
Rew.
Первая часть условного оператора
гласит, что если переменная action имеет
значение "ff" (она получит его при нажатии
кнопки FF), текущий фильм (то есть клип
messages) должен перейти на три кадра
вперед от текущего положения и остановиться.
Учитывая, что этот скрипт выполняется 24 раза в
секунду, вы поймете, что пока
action равно "ff"
(то есть, пока нажата кнопка FF), монтажный стол
будет продвигаться вперед, прыгая через три
кадра, имитируя процесс "быстрой перемотки"
вперед.
Следующая часть условного
оператора имеет эффект прямо противоположный.
Здесь говорится, что если
action имеет значение
"rew" (так будет
при нажатии кнопки Rew), текущий фильм должен
переместиться на 10 кадров назад от текущего
положения и там остановиться. Опять же,
поскольку этот скрипт выполняется 24 раза в
секунду, пока action
равно "rew" (пока
нажата кнопка Rew), монтажный стол будет
продвигаться назад, прыгая через 10 кадров, что
даст эффект "быстрой перемотки" назад.
Третья часть условного оператора
гласит, что если action
имеет значение "play"
(это значение переменная может получить при
щелчке на кнопке Play либо в момент отпускания
кнопок FF и Rew), фильм просто начинает
проигрываться с текущего кадра.
Последняя часть условного
оператора выполняется, если
action имеет
значение "stop"
(если нажата и отпущена кнопка Stop). В этом
случае воспроизведение текущего фильма
останавливается.
А теперь давайте займемся нашими
кнопками.
- Выделите кнопку Play и введите в
панели Действия следующий скрипт:
on (release) {
messages.action = "play";
}
Если пользователь нажмет и
отпустит эту кнопку, переменная
action (на
монтажном столе messages)
получит значение "play".
В результате присоединенный к этому экземпляру
скрипт (описанный на предыдущем шаге) выполнит
соответствующее действие.
- Выделите кнопку Stop и присоедините к
ней следующий скрипт:
on (release) {
messages.action = "stop";
}
Когда пользователь нажмет и
отпустит эту кнопку, переменная
action (на
монтажном столе messages)
получит значение "stop".
В результате присоединенный к этому экземпляру
скрипт (описанный на шаге 5) выполнит
соответствующее действие.
- Выделите кнопку FF и присоедините к
ней следующий скрипт:
on (press) {
messages.action = "ff";
fastSound = new Sound();
fastSound.attachSound("rewind");
fastSound.start(0, 50);
}
on (release) {
messages.action = "play";
fastSound.stop();
}
Для этой кнопки обрабатываются
два события: нажатие и отпускание. Когда
пользователь нажмет кнопку, переменная
action (на
монтажном столе messages)
получит значение "ff", и присоединенный к этому
экземпляру скрипт (описанный на шаге 5) выполнит
соответствующее действие. Но это не все. Для
имитации звука перемотки создается объект типа
Sound, к нему
присоединяется библиотечный файл звукозаписи
"rewind", после
чего этот звук воспроизводится, повторяясь 50
раз.
Примечание Для простоты мы
использовали звук
"rewind" для имитации звука перемотки и
вперед (здесь), и назад (на следующем шаге) –
ведь и в действительности эти звуки похожи.
- Выделите кнопку Rew и присоедините к
ней следующий скрипт:
on (press) {
messages.action = "rew";
fastSound = new Sound();
fastSound.attachSound("rewind");
fastSound.start(0, 50);
}
on (release) {
messages.action = "play";
fastSound.stop();
}
Эта кнопка работает точно так же,
что и предыдущая, за исключением того, что здесь
переменной action
присваивается значение
"rew".
- Командой Управление > Проверить фильм
(Control > Test Movie) запустите тест
проекта.
Когда фильм запустится, нажмите
кнопку "Get phone messages", чтобы перейти к
следующей сцене фильма. В появившейся новой
сцене попробуйте, нажимая разные кнопки,
управлять проигрыванием экземпляра клипа
messages. При
нажатой кнопке FF монтажный стол будет быстро
"перематываться" вперед, при нажатой кнопке Rew
– назад (это можно понять по тем звуковым
клипам, которые будут воспроизводиться после
"перемотки").
- Закройте тестовый фильм и сохраните
проект под именем makeMyDay4.fla.
Кнопки управления
воспроизведением, подобные тем, что мы создали,
могут найти самое широкое применение – не только
при потоковом воспроизведении звукозаписей (как
у нас), но и в любом проекте, содержащем сотни
кадров.
Отслеживание процессов воспроизведения и
загрузки
Число кадров в фильме и размер
входящих в его состав файлов определяют общую
длину фильма и размер SWF-файла – этот факт
станет очевидным, если даже просто взглянуть на
главный монтажный стол фильма. Общее число
кадров в фильме представлено значением свойства
_totalframes. Так,
если основной монтажный стол содержит 400 кадров
(в одной сцене или нескольких), мы могли бы
установить это следующим образом:
_root._totalframes = 400;
Это свойство можно использовать в
скриптах, чтобы определить общую длину фильма (в
кадрах).
Примечание Свойство
totalframes имеет
атрибут "только для чтения", то есть его
значение автоматически устанавливает Flash
(подсчитывая общее число кадров на монтажном
столе). Поэтому даже не пытайтесь сами изменить
значение этого свойства – это невозможно!
Итак, зная это значение, мы можем
использовать его, вместе с другими свойствами
фильма, для контроля хода воспроизведения или
загрузки. Например, сравнивая значение свойства
_totalframes со
значением свойства
_currentframe, мы можем определить,
сколько осталось до конца фильма:
framesLeft = _root._totalframes - _root._currentframe;
message.text = "До конца осталось " + framesLeft + " кадров."
Поскольку Flash основан на
потоковой технологии, процесс просмотра
(воспроизведения) SWF с вебсайта происходит кадр
за кадром по мере загрузки. Еще одно свойство,
_framesloaded,
содержит общее число уже загруженных кадров.
Значение этого свойства можно сравнить со
значением свойства
_totalframes, чтобы получить информацию о
ходе загрузки. В следующем упражнении мы
продемонстрируем создание индикатора выполнения
(будем называть его предзагрузчиком),
показывающего процент загруженных кадров.
- Откройте файл preloader1.fla из папки
Lesson15/Assets.
Этот проект состоит из двух сцен:
Preloader и Content. Сцена Content содержит
несколько слоев графики и анимации, которые
нужны нам просто для демонстрации работы
индикатора-предзагрузчика. Вся наша работа в
этом упражнении будет происходить в сцене
Preloader, которая состоит из трех слоев:
Background, Preloader и Actions. Слой Background
содержит фон – квадрат, залитый радиальным
градиентом. Слой Actions содержит действие
stop(),
предотвращающее самопроизвольное проигрывание
монтажного стола. Слой Preloader содержит два
элемента: надпись "now
loading…" и экземпляр клипа под названием
preloader,
состоящий из элементов, которые должны
показывать ход загрузки. Давайте познакомимся с
этим экземпляром поближе.
- Двойным щелчком на экземпляре клипа
preloader откройте его для редактирования на
месте.
Монтажный стол этого клипа
состоит из четырех слоев, названных в
соответствии с их содержимым. Наиболее важными
на этом монтажном столе являются два элемента:
текстовое поле под названием
info,
расположенное в слое Text,
и анимацию (с построением промежуточных
изображений) в слое Amount. Анимация
представляет собой 100-кадровый индикатор
выполнения – от 0 до 100 процентов. Наш скрипт
будет, среди прочего, продвигать этот монтажный
стол от кадра к кадру по мере загрузки кадров
основного фильма. В результате будет "двигаться"
и индикатор выполнения.
- Вернитесь на основной монтажный стол.
Откройте панель Действия, выделите экземпляр
клипа preloader и введите такой скрипт:
onClipEvent (enterFrame) {
framesLoaded = (Math.ceil (( _parent._framesloaded / _parent._totalframes) * 100));
gotoAndStop (framesLoaded);
info.text = framesLoaded + "% completed";
if (framesLoaded >= 90) {
_root.gotoAndPlay (2);
}
}
Выполнение этого скрипта будет
происходить с наступлением события
enterFrame (24
раза в секунду), то есть он будет немедленно
реагировать на изменения, происходящие в
процессе загрузки, точно отображая его ход на
экране.
Первым делом этот скрипт
определяет процентное отношение загруженных
кадров к общему их числу. Это число округляется
до целого в большую сторону, и то, что
получилось, присваивается переменной
framesLoaded.
Рассмотрим это выражение по порядку его
выполнения.
_parent._framesloaded / _parent._totalframes
В этой части выражения берется
число уже загруженных кадров главного монтажного
стола и делится на общее число кадров главного
монтажного стола.
Примечание Поскольку этот
скрипт присоединен к экземпляру клипа
preloader, который
находится на главном монтажном столе, мы
использовали для указания на главный монтажный
стол адресную ссылку
_parent. Благодаря этому клип
preloader можно
без всяких изменений вставить и в любой другой
проект.
Для примера предположим, что
фильм содержит 735 кадров, из которых 259 уже
загружено. В этом случае данная часть выражения
получится такой:
259 / 735
В результате получится 0,3523. На
следующем этапе выражения этот результат
умножается на 100:
* 100
В результате получаем 35,23. И
наконец, с помощью метода
Math.ceil() это значение округляется до
целого числа в большую сторону, и переменной
framesLoaded присваивается значение 36.
Напомним, что этот скрипт выполняется 24 раза в
секунду, это число будет увеличиваться по мере
загрузки фильма.
Совет Свойства
_framesloaded и
_totalframes,
примененные в этом скрипте, можно заменить
методами объекта
MovieClip – getBytesLoaded() и
getBytesTotal(),
если вы хотите, чтобы индикатор выполнения вел
отсчет, основываясь на реально загруженных
байтах, а не кадрах. Иногда такой способ
предпочтительнее, поскольку кадр будет считаться
загруженным (и индикатор продвинется) только
после того, как будут загружено все, что в кадре
содержится. Поэтому, если в процессе загрузки
будут встречаться сложные, многобайтные кадры,
индикатор будет приостанавливаться на заметное
время, продвигаться рывками. Если же отслеживать
загрузку по байтам, то индикатор будет двигаться
гладко, ведь данные о загрузке байтов данных
обновляются гораздо чаще (с каждым загруженным
байтом). На CD вы найдете бонусный файл,
демонстрирующий именно такой индикатор.
Вернемся к нашему скрипту. Второе
действие отсылает текущий фильм к кадру, номер
которого равен значению
framesLoaded. Поскольку текущий фильм
содержит анимацию, изображающую заполняющийся
слева направо индикатор выполнения, получается,
что это действие управляет движением индикатора.
С увеличением значения
framesLoaded заполняется индикатор.
Следующее действие скрипта
отображает текст в поле
info. Здесь значение
framesLoaded
соединяется со строкой "% completed". Если
framesLoaded имеет
значение 36, то получится "36% completed".
Последняя часть этого скрипта –
условный оператор, определяющий момент, когда
работу предзагрузчика следует завершить. Если
значение framesLoaded
больше или равно 90, главный монтажный стол
должен перейти к кадру 2 (которым на самом деле
будет сцена Content) и оттуда продолжить
воспроизведение фильма.
Совет Значение 90 в этом
условном операторе легко можно заменить любым
другим – все зависит от того, в какой момент вы
хотите прекратить работу предзагрузчика и
запустить основной фильм.
- Командой Управление > Проверить фильм
(Control > Test Movie) запустите тест
проекта. Когда тестовый фильм запустится,
выполните команду меню Отладка > 56K (Debug
> 56K), а затем команду Вид > Показать поток
(View > Show Streaming).
Так мы сможем получить достаточно
точную симуляцию загрузки фильма через модем на
скорости 56K, и сможем увидеть работу нашего
предзагрузчика. По мере загрузки фильма вы
увидите, как обновляется процент загрузки и
движется индикатор выполнения. Как и было
сказано на предыдущем шаге, индикатор
продвигается до 90 процентов, после чего
монтажный стол перемещается к сцене Content и
проигрывает фильм дальше.
- Закройте тестовый фильм и сохраните
проект под именем preloader2.fla.
Упражнение закончено.
|