Для получения данных от клавиатуры удобно использовать глобальный объект Key. Чаще всего используются два его метода
Кроме того, самый простой способ определить код экспериментально, использовав функцию getCode() в обработчике keyDown.
Коды некоторых специальных клавиш можно получить как свойства объекта Key. В первом примере мы будем при каждом нажатии клавиши выводить в окно Output ее код и состояния клавиш Ctrl, Shift и Alt (true нажата, false не нажата).
Изучим эти возможности на примере проекта «Воздушный шар». Он управляется клавишами-стрелками и перетаскивается мышкой. При нажатой клавише Ctrl скорость движения увеличивается. Чтобы проверить работу ролика, сначала щелкните на нем мышью.
Откройте файл PRACTICE\8\baloon.fla. Добавьте код, связанный с воздушным шаром:
onClipEvent (keyDown) { trace(Key.getCode()); trace(Key.isDown(Key.CONTROL)); trace(Key.isDown(Key.SHIFT)); trace(Key.isDown(Key.ALT)); }Проверьте работу клипа, нажимая на разные клавиши. |
Скорость движения запишем в переменную v, ее начальное значение зададим в обработчике load (за время одного кадра шар смещается на 3 пикселя в заданном направлении).
Добавьте новые обработчики событий для воздушного шара:
onClipEvent (load) { v = 3; } onClipEvent (enterFrame) { if (Key.isDown(Key.RIGHT)) { _x += v; } else if (Key.isDown(Key.LEFT)) { _x -= v; } }Аналогично запишите обработчики для клавиш-стрелок «вверх» и «вниз» (коды Key.UP и Key.DOWN). |
Теперь сделаем так, чтобы при нажатии клавиши Home шар возвращался в исходное состояние (где он был в начале). Для этого в обработчике события load надо запомнить его координаты в переменных x0 и y0, а при нажатии клавиши Home присваивать эти значения координатам клипа _x и _y.
Добавьте строчки в обработчик load: x0 = _x; y0 = _y;Измените обработчик события keyDown на такой: onClipEvent (keyDown) { if (Key.isDown(Key.HOME)) { _x = x0; _y = y0; } } |
trace("Ку-ку");в обработчик keyDown, мы обнаружим, что при нажатии клавиши Home этот обработчик не вызывается.
Дело в том, что мы запускаем клип из среды разработки, которая перехватывает некоторые клавиши, например, Enter и Home. При просмотре этого ролика в отдельном окне Flash-проигрывателя или в браузере все будет нормально.
Однако есть простой способ избавиться от этого неудобства.
Запустите ролик и отметьте флажок Disable Keyboard Shortcuts в меню Control в окне проигрывателя. Проверьте, реагирует ли теперь клип на нажатие клавиши Home. |
Добавьте в начало обработчика события enterFrame код
if (Key.isDown(Key.CONTROL)) { v = v0*3; } else { v = v0; }и измените первую строчку в обработчике load на v0 = 3; |
Самостоятельно сделайте так, чтобы воздушный шар опускался вниз, если не нажата ни стрелка «вверх», ни стрелка «вниз». Также нужно, чтобы он не мог улететь вниз за пределы экрана. |
Чтобы убрать стандартный курсор и потом восстановить его обратно, используем два метода объекта Mouse:
Перетащите на сцену клип Рука из библиотеки, дайте ему имя hand и добавьте такой код:
onClipEvent (load) { _visible = false; } onClipEvent(enterFrame){ _x = _root._xmouse; _y = _root._ymouse; } |
Если кнопка мыши нажата на клипе, заменяем курсор и начинаем перетаскивание клипа. При отпускании кнопки возвращаем все обратно.
Добавьте два обработчика к коду клипа Шар:
on (press){ startDrag (this); Mouse.hide(); _root.hand._visible = true; } on (release) { stopDrag(); Mouse.show(); _root.hand._visible = false; } |
Добавьте в самое начало обработчика enterFrame строчку
if ( _root.hand._visible ) return;Проверьте работу фильма и закройте документ. |
s = "123";
t = s + 45 + "6789";
trace ( t ); // получим "123456789"
Во второй строке число 45 было автоматически
преобразовано к символьной форме.
В следующем проекте мы построим небольшой редактор текста, который умеет делать выделенные буквы заглавными или строчными, считать количество символов и искать в тексте заданное слово.
Откройте файл editor.fla. Создайте новый слой Текст и разместите большое текстовое поле в середине сцены. Установите тип надписи Input Text (поле ввода), имя main и параметр Multiline (многострочный текст), как показано на рисунке ниже. |
Содержимое текстового поля это тоже строка, то есть, объект класса String. Она имеет имя text, это значит, что адрес текстовой строки поля main запишется как main.text.
Сделаем так, чтобы при нажатии кнопок и все буквы текста становились заглавными (или соответственно строчными).
Добавьте к кнопке код
on ( release ){ main.text = main.text.toUpperCase(); }а к кнопке код on ( release ){ main.text = main.text.toLowerCase(); }Проверьте работу кнопок. |
Добавьте в нижнюю часть сцены однострочный динамический текст (Dynamic Text, Single line)
с именем info. Для кнопки
введите обработчик события
on ( release ){ info.text = "Символов: " + main.text.length; } |
Объект Selection это выделенная часть текста в одном из полей ввода. Он связан с тем элементом, который в данный момент имеет фокус, то есть принимает команды от клавиатуры.
Методы объекта Selection:
Добавим возможность поиска слова в тексте.
Добавьте в верхнюю часть сцены (слева от кнопки ) однострочное поле ввода (Input Text, Single line) с именем find. |
Для кнопки
задайте ведите обработчик события
on (release) { if ( find.text == "" ) return; n = main.text.indexOf ( find.text ); if ( n < 0 ) info.text = "Ничего не найдено."; else { info.text = "Нашли в позиции " + n; Selection.setFocus ( "main" ); Selection.setSelection ( n, n + find.text.length ); } } |
Затем, с помощью метода indexOf ищем образец в тексте. Если такого слова нет, выводит сообщение об этом в информационную строку. Если есть, то устанавливаем фокус на поле main и выделяем найденное слово.
Используя методы объекта Selection, можно улучшить работу кнопок и : если что-то выделено, они будут менять только выделенную часть текста.
Сначала мы определим начало и конец выделенной части и запишем номера этих символов в переменные nStart и nEnd. Если они равны, то ничего не выделено и преобразуется весь текст. Если эти значения не равны, новая строка строится так: содержимое main.text «разрезается» на 3 части с помощью метода substring, ко второй части применяется метод toUpperCase.
Эта часть программы будет работать только для Flash Player версии 9 и выше, поскольку в ранних версиях во время щелчка по кнопке текстовое поле теряет фокус. |
Измените обработчик кнопки
на такой:
on (release) { nStart = Selection.getBeginIndex(); nEnd = Selection.getEndIndex(); if (nStart == nEnd) { main.text = main.text.toUpperCase(); } else { s = main.text; s = s.substring ( 0, nStart ) + s.substring ( nStart, nEnd ).toUpperCase() + s.substring ( nEnd ); main.text = s; } }Аналогично измените код кнопки . |
Обратите внимание, что при вызове substring(nEnd) второй аргумент не указан, то есть выделяется фрагмент с символа nEnd до конца строки.
Заметим, что алгоритм работает даже тогда, когда поле main не имеет фокуса ввода (и обе функции getBeginIndex и getEndIndex вернут -1).
col = new Color ( адрес клипа );
Таким образом, мы получаем доступ к цвету объекта.
Затем можно использовать два метода:
Чтобы удобно было разбираться в цветах, принято записывать их в шестнадцатеричной системе счисления, так что младшие две цифры это B, следующие две G, а две старших R. Например, для цвет 0x660000 имеем R=6616=102, G=B=0.
В проекте этого раздела мы будем управлять цветом логотипа фирмы AT&T с помощью кнопок в нижней части сцены.
Откройте файл att.fla. Выделите самую левую кнопку и перейдите на панель Properties.
В списке Color выберите вариант Tint
(цветовой оттенок), цвет с кодом #000033 и смешение
100% (полная замена исходного цвета).
|
Выделите первую кнопку и введите код обработчика, который вызывается при отпускании кнопки мыши:
on ( release ) { cLogo = new Color(_root.logo); cLogo.setRGB(0x000033); }Аналогично задайте параметры и обработчик второй кнопки с цветом 0x000066. Проверьте работу фильма. |
Конечно, можно применить те же шаги для остальных кнопок, но эту нудную работу можно значительно упростить, если использовать массивы и циклы.
Нумерация элементов массива с нуля непривычна для обычных людей, но широко используется в программировании (языки Си, JavaScript, Java, ActionScript). |
Массив из трех элементов можно объявить и заполнить так:
A = new Array(3); A[0] = 12; A[1] = 4.56; A[2] = "Ку-ку!";или так:
A = new Array (12, 4.56, "Ку-ку!");или так:
A = [12, 4.56, "Ку-ку!"];
При работе с массивами, как и с другими объектами
(кроме чисел, строк и логических переменных), есть один тонкий момент.
Рассмотрим пример кода:
A = [1, 2, 3];
B = A;
B[1] = 99;
trace ( A );
Здесь создается массив A, затем он копируется в массив
B. Потом изменяется B[1] и массив A
выводится в окно Output. Вроде бы массив A не
должен измениться, однако мы увидим в окне Output
строчку:
1,99,3Почему же изменился массив A? Дело в том, что оператор B=A НЕ создает новый массив, а просто копирует в B адрес массива A, то есть A и B обращаются к одной области памяти. Поэтому, изменив B, мы изменили и A. Чтобы действительно создать копию массива, нужно заменить оператор B=A на код
B = new Array(); for(i=0; i<A.length; i++) B[i] = A[i];Здесь используется встроенное свойство length объекта Array длина массива.
В нашем примере мы создадим массив, в котором будут храниться коды цветов всех кнопок.
Удалите ранее созданные обработчики. Создайте новый слой Программа и в первый кадр введите код,
заполняющий массив кодами цветов:
colors = [0x000033, 0x000066, 0x000099, 0x003300, 0x006600, 0x009900, 0x330000, 0x660000, 0x990000]; |
Слой Программа можно сразу же заблокировать, щелкнув по значку в столбце . Это позволит добавлять код ActionScript, но не даст случайно добавить что-то еще. |
Добавьте функцию, которая изменяет цвет логотипа в соответствии с цветом кнопки, на которой
щелкнули мышкой:
function changeColor() { c = new Color(this); col = c.getRGB(); cLogo = new Color(_root.logo); cLogo.setRGB(col); } |
Созданная функция пока не работает, поскольку мы не определили, в каких случаях она вызывается. Для того, чтобы она стала обработчиком события release некоторой кнопки, достаточно написать
Кнопка.onRelease = changeColor;
Далее мы с помощью цикла, в котором переменная i (номер кнопки) меняется от 0 до 8, настроим все кнопки сразу: перекрасим их в нужный цвет и добавим обработчик события.
Чтобы в цикле обращаться к кнопке по ее номеру, можно использовать специальную форму _root[имя]. Таким образом, _root["color0"] это то же самое, что и _root.color0, но преимущество первого метода в том, что имя кнопки можно построить динамически, во время выполнения, например, так:
_root["color"+chr(48+i)]Функция chr преобразует код символа в символ. Учитывая, что цифры 0-9 имеют коды 48-57, при i=2 получаем _root["color2"].
Чтобы эта идея сработала, кнопкам нужно дать соответствующие имена color0, color1 и т.д., что уже было сделано заранее (проверьте это на панели Properties, выделив какую-нибудь кнопку).
Добавьте к коду кадра 1 цикл: for (i=0; i<9; i++){ obj = _root["color"+chr(48+i)]; c = new Color(obj); c.setRGB(colors[i]); obj.onRelease = changeColor; }Проверьте работу фильма и сохраните его. |
Откройте файл PRACTICE\8\basketball.fla и посмотрите «внутрь» клипа, моделирующего мячик. |
Здесь использован переработанный пример из учебного курса фирмы Adobe, опубликованного на сайте www.intuit.ru. |
Этот клип содержит анимацию движения, во время которой мяч летит вниз, ударяется и возвращается в верхнее положение. Во время удара проигрывается звуковой фрагмент.
Наша задача сделать так, чтобы
Сначала научимся проигрывать звук из библиотеки и останавливать его в нужный момент.
Найдите звук hey.wav в библиотеке и нажмите на нем правую кнопку мыши. В контекстном меню выберите команду Linkage... (связывание), в появившемся окне отметьте флажки Export for ActionScript и Export in first frame, введите имя звука hey в поле Identifier. |
Флажок Export for ActionScript делает звук доступным из программы, мы будем обращаться к нему по имени hey. Флажок Export in first frame загружает звук вместе с первым кадром, таким образом, звук будет доступен с самого начала фильма.
Теперь надо
Выделите клип-мяч и добавьте в окно Actions следующий код:
onClipEvent (load) { snd = new Sound(); } onClipEvent (mouseDown) { snd.attachSound ("hey"); snd.start(0, 1); } onClipEvent (keyDown) { snd.stop(); }Проверьте работу фильма. |
При вызове метода start первое число обозначает время от начала звукового файла в секундах (0 с самого начала), а второй количество повторов.
Если проигрывать звук не с начала, после завершения звуковой дорожки будет проиграна начальная часть. |
С помощью вызова stopAllSounds(); можно прекратить проигрывание всех звуков сразу. |
Теперь надо сделать, чтобы мячик перемещался вместе с мышью и звук (внутри клипа-мяча!) изменялся соответственно его положению.
Прямоугольник, ограничивающий допустимую область для мяча, можно задать четырьмя числами:
Здесь учтено, что начало координат находится в левом верхнем углу сцены.
Чтобы «добраться» до звука внутри клипа, нужно указать адрес клипа при создании объекта Sound. Например, в коде самого клипа можно использовать this:
bounce = new Sound(this);
Для изменения громкости используется метод setVolume, в скобках нужно указать громкость звука в процентах от исходной. Будем считать, что на дальней границе области громкость составляет 50%, а на ближней 100%. Легко показать, что для произвольной точки с координатой y громкость (в процентах) можно вычислить по формуле:
vol = 50 + 50 * (y - t) / (b - t);
Будем считать, что так же изменяются и видимые размеры мяча, то есть свойства _xscale и _yscale.
Звуковой баланс регулируется с помощью метода setPan (set panoram установить баланс), в скобках нужно задать величину от -100 (левая граница зоны, только левый канал) до 100 (правая граница, только правый канал). Тогда величину баланса для точки с координатой x можно определить так:
pan = 200 * (x - c) / (r - l) ;где с середина прямоугольника, среднее арифметическое l и r:
c = (l + r) / 2;
Добавьте в обработчик события load строчки
bounce = new Sound(this); l = 60; r = 490; t = 245; b = 400; c = (l + r) / 2; |
Для перетаскивания мышкой будем использовать событие mouseMove (движение мыши). Если мышь находится в пределах разрешенной зоны, начинается перетаскивание, как только она вышла из зоны, перетаскивание прекращается. При перемещении мяча регулируется громкость звука и баланс.
Добавьте обработчик события mouseMove onClipEvent (mouseMove) { x = _root._xmouse; y = _root._ymouse; if (l < x && x < r && t < y && y < b) { Mouse.hide(); startDrag(this, true); vol = 50 + 50 * (y - t) / (b - t) ; bounce.setVolume(vol); this._xscale = vol; this._yscale = vol; pan = 200 * (x - c) / (r - l) ; bounce.setPan(pan); } else { Mouse.show(); stopDrag(); } }Просмотрите результат и сохраните фильм. |
Второй параметр при вызове startDrag, равный true, означает, что при перетаскивании точка регистрации клипа перемещается в точку, где находится курсор мыши.
Здесь использован переработанный пример из учебного курса фирмы Adobe, опубликованного на сайте www.intuit.ru. |
Создать новый объект класса Date можно так:
d = new Date(2007, 5, 11);
Первое число год, второе номер месяца, третье число.
Эта дата 11 июня 2007 года. Здесь нет ошибки, номера месяцев начинаются с
нуля, поэтому месяц 5 в программе Flash это июнь.
Если параметры не используются:
today = new Date();
создается объект с сегодняшней датой.
С помощью методов объекта Date можно определить год, месяц, число и день недели:
откройте файл PRACTICE\8\clock.fla. Добавьте динамические текстовые поля (Dynamic Text) для вывода дня недели, числа, месяца года так, как на образце. Дайте им имена day, date, month и year, установите выравнивание по центру, выберите цвет и размер шрифта. |
Добавьте слой Программа и в первом кадре введите код
stop(); today = new Date(); weekDays = ["воскресенье", "понедельник", "вторник", "среда", "четверг", "пятница", "суббота"]; months = ["января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"]; day.text = weekDays[today.getDay()]; date.text = today.getDate(); month.text = months[today.getMonth()]; year.text = today.getFullYear();Проверьте работу фильма. |
Затем в текстовые поля записываются данные сегодняшнего дня, причем некоторые из них выбираются из массивов.
С выводом времени дело обстоит несколько сложнее, его надо обновлять раз в секунду. Сначала добавим текстовое поле и напишем функцию, которая должна выводить в него время.
Добавьте текстовое поле под листом календаря и дайте ему кодовое имя time.
В код кадра 1 добавьте функцию
function showTime() { function str2 ( n ) { var s = String(n); if ( n < 10 ) s = "0" + s; return s; } today = new Date(); h = today.getHours(); m = today.getMinutes(); s = today.getSeconds(); time.text = str2(h) + ":" + str2(m) + ":" + str2(s); } |
В основной части функции создается новый объект Date, содержащий текущую дату и время. С помощью методов getHours, getMinutes и getSeconds из него извлекаются часы, минуты и секунды. Далее они переводятся в символьный вид с помощью функции str2 и объединенная строка записывается в свойство text поля time.
Все бы хорошо, но функцию showTime надо вызывать периодически с интервалом не менее 1 секунды. К счастью, в среде Flash есть такое средство.
Добавьте к коду кадра 1 строчку
setInterval ( showTime, 200 );
и проверьте работу клипа.
|
Добавьте на поле четыре надписи (Static Text): время, сек, повторить и раз, а также два поля ввода (Input Text) с именами alarmTime (время сигнала) и loops (повторы). Добавьте в нужное место кнопку Пуск из библиотеки. |
В кадр 1 слоя Программа добавьте присвоение начальных значений:
alarmTime.text = "10"; loops.text = "1"; |
Дайте звукам из библиотеки имена tick (тиканье) и alarm (будильник). Для этого надо выбрать пункт Linkage... из контекстного меню. |
t = getTimer();
записывает в переменную t количество миллисекунд,
прошедшее с начала проигрывания фильма. Для будильника нам нужна
разница между текущим временем и временем начала отсчета,
которое мы запомним в специальной переменной startTime.
В другой переменной, alarmOn будем запоминать состояний будильника (включен или выключен). Теперь можно написать код для кнопки: при ее нажатии включается будильник и запоминается время начала отсчета.
Добавьте код обработчика для кнопки: on (release) { clock.alarmOn = true; clock.startTime = getTimer(); } |
Остальная работа выполняется клипом clock: вращение стрелки, тиканье раз в секунду и выдача сигнала будильника.
Добавьте к клипу-секундомеру код обработчика enterFrame:
onClipEvent (enterFrame) { if ( !alarmOn ) return; t = Number(_root.alarmTime.text); diff = Math.round((getTimer()-startTime)/1000); if (hand._rotation != diff*6) { hand._rotation = diff*6; tick = new Sound(); tick.attachSound("tick"); tick.start(0,1); } if (diff == t) Alarm(); } |
В переменную t записывается числовое значение установленного времени, для перевода из символьной строки в число используется функция Number.
Разница между текущим и стартовым временем переводится в секунды из миллисекунд (делением на 1000) и округляется до ближайшего целого числа с помощью функции Math.round, которая относится к объекту Math (математика).
Если вспомнить, что за 1 секунду стрелка должна повернуться на 6(=360/60) градусов, то нужный угол поворота стрелки равен diff*6. Если стрелку надо «довернуть», изменяем ее свойство _rotation и 1 раз проигрываем звук tick из библиотеки.
Если разница diff совпала с установленным временем t, вызывается функция Alarm, которую мы сейчас напишем. В ней надо отключить будильник, вернуть стрелку в исходное положение и проиграть звук alarm из библиотеки нужное число раз.
Введите код обработчика собятия load для клипа:
onClipEvent (load) { function Alarm() { alarmOn = false; hand._rotation = 0; snd = new Sound(); snd.attachSound("alarm"); snd.start(0,_root.loops.text); } }Проверьте работу будильника. |
Добавьте динамический текст «Пора вставать!» ниже часов и дайте ему имя wakeup. Выберите шрифт и примените фильтры на ваш вкус. |
Добавьте в код кадра 1 слоя Программа строчку
wakeup._visible = false; |
Вспомним, что мы уже использовали средство, которое позволяет вызывать функцию периодически с заданным интервалом. Например, вращение некоторого клипа qq можно организовать так:
function rot() { qq._rotation += 10; } setInterval ( rot, 1000 );Через 1000 мс (или через 1 сек) будет вызываться функция rot, так что каждую секунду клип будет поворачиваться на 10 градусов.
Ссылку на интервал можно запомнить в переменной:
i = setInterval ( rot, 1000 );
Тогда для прекращения этих вызовов нужно вызвать функцию
clearInterval:
clearInterval ( i );
или просто удалить из памяти эту переменную:
delete i;
Теперь применим этот способ к нашему случаю.
Добавьте в конец функции Alarm строчки
_root.wakeup._visible = true; i = setInterval ( removeText, 2000 );После этой функции (внутри обработчика события load) добавьте еще одну функцию: function removeText() { _root.wakeup._visible = false; delete i; }Проверьте работу клипа и сохраните его. |
Каждая сцена это самостоятельный ролик. Сцены в фильме проигрываются одна за другой.
Выбрать нужную сцену для работы можно с помощью кнопки справа над рабочей областью или вызвав список сцен на панели Scene (клавиши Shift+F2 или меню WindowOther panelsScene). В нижней части этого окна есть три кнопки:
создать копию выделенной сцены; | |
создать новую сцену; | |
удалить выделенную сцену. |
Откройте панель Scene (сцены) и создайте новую сцену Загрузка, щелкнув по кнопке со знаком «плюс». Перетащите ее в самый вверх списка, чтобы эта сцена стала первой. Закройте окно Scenes. На панели Properties установите белый цвет фона. |
Создайте новый символ типа Movie Clip с именем Индикатор (клавиши Ctrl+F8). Нарисуйте узкий прямоугольник с черным контуром и заливкой синего цвета. |
Выделите только заливку и перенесите ее на новый слой. Преобразуйте заливку в символ Полоска типа Movie Clip и дайте ему имя bar (на панели Properties). |
Добавьте (внутри символа Индикатор) слой Текст и разместите на нем статический текст Загрузка (Static Text) и динамический текст 0% (Dynamic Text) с именем proc. |
Для определения доли уже загруженной части клипа будем использовать два метода монтажного стола _root:
Перейдите к редактированию сцены и добавьте в центр символ Индикатор из библиотеки. Выделите клип и
добавьте к нему обработчики событий
onClipEvent (load){ bar._xscale = 0; } onClipEvent (enterFrame){ done = _root.getBytesLoaded(); all = _root.getBytesTotal(); part = 100*done/all; // доля в процентах bar._xscale = part; proc.text = Math.round(part) + "%"; if ( done == all ) _root.nextFrame(); } |
Для того, чтобы округлить значение до целых процентов, используем функцию Math.round.
Если ролик полностью загружен, «отправляем» главный монтажный стол на следующий кадр командой nextFrame. Поскольку там только один кадр, происходит переход к следующей сцене.
При проверке ролика в локальном режиме (без Интернета) время загрузки ничтожно мало и мы не успеем увидеть работу загрузчика. Однако есть средство проверить и этот режим имитация загрузки на медленном канале.
Запустите ролик, нажав Ctrl+Enter. Выберите в меню окна проигрывателя пункт ViewDownload Setting56 K (имитация загрузки со скоростью 56 Кбит/c, модем). После этого нажмите Ctrl+Enter (меню ViewSumilate Download). Убедитесь в правильной работе индикатора загрузки и сохраните файл. |
Дополнительную информацию о скорости загрузки и размере каждого кадра в байтах
можно получить при выборе пункта меню
ViewBandwidth Profiler. |
Знакомство с ActionScript | Математика и физика |
© 2007 К. Поляков