Книги, научные публикации Pages:     | 1 |   ...   | 4 | 5 | 6 | 7 | 8 |

F L A S 100 советов и рекомендаций профессионала O'REILLY С&ППТЕР Шам Бхангал F L A S H H A C K S Sham Bhangal O'REILLT Beijing Х Cambridge Х ...

-- [ Страница 6 ] --

Зе Фернандо Оптимизация загрузки и использования №73 компонентов ТРЮК В комплект поставки Flash входит множество компонентов, предназначенных для решениях стандартных задач. Сведите к минимуму задержку, которая может возникнуть из-за них в начале SWF. Во многих Flash-презентациях (особенно коммерческих приложениях и роликах, имитирующих рабочую область других программ) используются стандартные элементы пользовательского интерфейса - кнопки, раскрывающиеся списки и т. д. Macromedia предоставляет их в виде готовых компонентов (рис. 9.11). Hi C e k B x hc o # R d Button ai o sn oe Хthree four five Рис. 9. 1 1. Стандартные компоненты пользовательского интерфейса !^Q gj Компоненты образуют особую категорию клипов, которые используются в качестве строительных блоков или предоставляют классы ActionScript, упрощающие реализацию расширенных интерактивных средств или взаимодействие между Flash и другими веб-технологиями. В процессе компиляции FLA в SWF Flash анализирует временную диаграмму и составляет список всех ресурсов в порядке их появления. Найденные ресурсы включаются в SWF в указанном порядке, что обеспечивает эффективную потоковую пересылку данных. Если ресурс не находится на временной диаграмме, он не включается в список, а следовательно, не экспортируется. Тем самым обеспечивается минимальный размер SWF-файла. Этот прием оптимизации работает неплохо. Но если ресурс или компонент используется в сценарии ActionScript, а не на временной диаграмме, возникают проблемы. Вы можете заставить Flash включать в SWF даже те ресурсы, которые не присутствуют на временной диаграмме, для этого в диалоговом окне Linkage Properties устанавливается флажок Export for ActionScript. Для компонентов этот флажок установлен по умолчанию, поэтому компоненты включаются Глава 9. Быстродействие и оптимизация в SWF даже в том случае, если они не используются на временной диаграмме. Если разместить компоненты на сцене (что приводит к их включению в библиотеку), а затем удалить их со сцены, компоненты останутся в библиотеке. Данный способ идеально подходит для включения необходимых компонентов в библиотеку. Тем не менее, не забывайте удалять неиспользуемые компоненты из библиотеки или сбрасывать флажки Export for ActionScript, иначе они будут включены в SWF даже в том случае, если эти компоненты не используются на временной диаграмме или ActionScript. Компоненты Flash MX 2004 (также называемые компонентами z>2) были серьезно усовершенствованы по сравнению с исходными компонентами Flash MX vl, но для их работы необходима загрузка 25-30 Кбайт дополнительного кода, выполняемая по умолчанию с первым кадром SWF. Для пользователей с медленными подключениями даже эта задержка может стать существенной. Избежать задержки с загрузкой нельзя, но можно выбрать момент, в который она произойдет. В окне File Х Publish Settings Х Flash выберите в списке ActionScript Version строку ActionScript 2.0 (компоненты v2 написаны на ActionScript 2.0). Щелкните на кнопке Settings рядом с раскрывающимся списком ActionScript Version (кнопка становится доступной после выбора ActionScript 2.0). В открывшемся диалоговом окне ActionScript Settings найдите текстовое поле Export Frame for>

Итоги Компоненты v2 поставляются вместе с Flash MX 2004, но, конечно, это не единственные компоненты, которые вы можете использовать в своих программах. Компоненты v2 ориентированы на веб-приложения в условиях высокой пропускной способности канала. В других ситуациях можно использовать компоненты Flash MX vl и даже другие компоненты от Macromedia или независимых фирм (например, компоненты Pocket PC).

ГЛЙВД IB ActionScript Трюки № 74- ActionScript определяет истинную мощь Flash. Без ActionScript возможности Flash ограничивались бы созданием тривиальной линейной анимации. С добавлением минимального кода ActionScript реализуются базовые средства управления (кнопки и активные зоны). Освоение нетривиальных возможностей ActionScript открывает доступ к таким возможностям, как создание локальных общих объектов (в просторечии - Flash-cookie). Без применения ActionScript не удастся создать Flash-сайт, который бы взаимодействовал с браузером, обменивался данными с серверными приложениями или загружал МРЗ-файлы. Многие новые средства Flash MX 2004 или Flash MX Professional 2004 реализованы в предположении, что разработчик владеет ActionScript. Даже те из них, которые не требуют опыта программирования (например, Behaviors и Timeline Effects), при определенном уровне владения ActionScript реализуются более гибко и лучше структурируются. Освоить анимацию на временной диаграмме несложно, но на то, что на ActionScript легко делается за считанные минуты или часы, при ручной реализации уходят дни и даже месяцы. А если дизайнер хочет, чтобы его приложение обладало улучшенной интерактивностью, содержало логику принятия решений или обменивалось данными с другими приложениями, ему не обойтись без изучения ActionScript. RIA-программирование, онлайновые игры, улучшенные графические интерфейсы - все это работает на базе сценариев. Хотя настоящая глава полностью посвящена ActionScript, сценарии в том или ином виде присутствуют практически в любом трюке книги. Так, в разделе Повышение быстродействия кода главы 9 рассматриваются проблемы оптимизации ActionScript. Кроме того, в книге представлены и другие трюки, относящиеся к быстродействию, - например, оптимизация байт-кода (см. трюк 100). Таким образом, один из путей изучения ActionScript - практические эксперименты с трюками и внесение в них всевозможных изменений. Кроме того, в предисловии обсуждается проблема преобразования ActionScript 2.0, широко использующегося в книге, в ActionScript 1.0.

Action Script Изменения в Flash M 2004 X Выход Flash MX 2004 принес большие изменения в жизнь пользователей Action Script. В область синтаксиса и структуры кода были внесены серьезные усовершенствования, упрощающие программирование больших приложений ActionScript, форматирование текста, а также расширенное управление потоковыми данными. Архитектура компонентов Flash была переработана таким образом, чтобы в ней использовались классы и новые возможности ActionScript 2.0, включая жесткую типизацию. Новые средства Flash MX Professional Slides и Forms позволяют вести разработку в парадигме визуального программирования стиля PowerPoint или Visual Basic с написанием минимального объема кода. Даже интерфейс среды разработки Flash MX 2004 может настраиваться при помощи программного интерфейса Flash JavaScript API (JSAPI). В разделе JSAPI Documentation документации Flash MX 2004 ( documentation/en/flash) приведены ссылки на документы, в которых объясняется, как создавать команды и инструменты для использования в среде разработки Flash. Более того, язык JSFL (Flash JavaScript) позволяет программировать операции в среде разработки. Полное описание JSFL выходит за рамки книги;

далее приводится короткий пример компиляции в режиме командной строки для Windows. Этот сценарий JSFL, написанный Колином Муком, создает файл.swf для каждого файла.fla в этом проекте:

/ Открыть файл. l / fa v r doc = f1.openDocument("fi1e:///с|/data/projects/pet/petsuppiies.fia"): a / Экспортировать. w / sf doc.exportSWF("file'7//c|/data/projects/pet/petsupplies.swf". true):

// Выход из среды разработки Flash M 2004 (необязательно). X fl.quit(false):

// Код exportPetSupplies.jsfl:

// Команда, выполняемая в командной строке из каталога /pet/: "c:\program files\macromedia\flash mx 2004\flash.exe" exportPetSupplies.jsfl Команда должна выполняться при закрытой среде Flash MX 2004. После выполнения команды в каталоге c:\data\projects\pet появляется откомпилированный ролик petsupplies.swf: И Flash MX 2004, и Flash MX Professional 2004 поддерживают ActionScript 2.0, но при этом также поддерживается синтаксис ActionScript 1.0 (версия компилятора ActionScript выбирается в списке File Х Publish Settings Х Flash Х ActionScript Version). Таким образом, разработчики могут сохранять верность ActionScript 1.0 или перейти на ActionScript 2.0, в большей степени приспособленный к объектно-ориентированным разработкам, по своему усмотрению.

Глава 10. ActionScript Новшества ActionScript в Flash Player Многочисленные расширения ActionScript в Flash Player 7 доступны для пользователей как ActionScript 1.0, так и ActionScript 2.O. Подробный список изменений приведен в электронной документации Flash (Help Х ActionScript Reference Guide Х What's New in Flash MX 2004 ActionScript). Вот лишь некоторые из них: Х обработка сообщений об ошибках в реальном времени с использованием класса Error, а также обработка ошибок конструкциями try/catch/finally и throw;

Х настройка контекстных меню Flash Player с использованием класса ContextMenu и нового свойства menu (классы Button, MovieClip и TextField);

Х поддержка события Mouse.onMouseWheel, обнаруживающего изменения в положении колеса мыши (только для системы Windows) и недокументированные средства обнаружения нажатия колеса мыши (см. трюк 62);

Х класс MovieClipLoader для создания предварительных загрузчиков (например, для вывода информации о ходе выполнения операции во время загрузки SWF-файла);

Х класс TextField.StyleSheet с поддержкой CSS;

Х поддержка формата SOAP, позволяющая Flash Player 7 работать с веб-службами на базе SOAP без установки на сервере Flash Remoting (готовые компоненты, обеспечивающие обмен данными в формате SOAP, входят только в комплект поставки Flash MX Professional 2004);

Х некоторые методы класса MovieClip, прежде всего методы управления глубиной getNextHighestDepthQ и getlnstanceAtDepth();

Х класс PrintJob, заметно упрощающий печать в Flash и предоставляющий больше возможностей контроля над печатным выводом, чем функции печати ActionScript 1.0. Большинство SWF-файлов в формате Flash Player 6 воспроизводится в Flash Player 7 без изменений. Тем не менее, в Flash Player 7 также появилась более жесткая политика междоменной безопасности (см. главу 12), которая может помешать просмотру некоторого содержания формата Flash Player 6 в Flash Player 7. Свойство System.exactSettings и метод System.allowlnsecureDomain() позволяют вернуть некоторые параметры доменной безопасности к менее жесткому уровню Flash 6, благодаря чему больше SWF-файлов формата Flash Player 6 будет работать в Flash Player 7. Хотя многие возможности Flash Player 7 также поддерживаются Flash Player 6.0.65 (часто встречается термин Flash Player 6r65), множество других возможностей в этой версии отсутствует. Для обеспечения максимальной совместимости (до тех пор, пока Flash Player 7 не появится на большинстве компьютеров) экспортируйте файлы Flash MX 2004 в формат Flash Player 6 (выполните команду File Х Publish Settings Х Flash и выберите в списке Version строку Flash Player 6, а затем установите флажок Optimize for Flash Player 6r65) - конечно, если в программе не используются специфические возможности Flash Player 7.

ActionScript ?_U Регистр символов и жесткая типизация ActionScript 2.0 позволяет задавать тип данных всех свойств, переменных, параметров и возвращаемых значений функций. Информация о типе данных используется компилятором для проверки типов. Иначе говоря, компилятор проверяет правильность типа только для тех данных, для которых он был указан. Кроме того, ActionScript 2.0 также учитывает регистр символов (см. в соответствии с предложенным стандартом ЕСМА-262 Edition 4 (ЕСМА 4). Эта тема подробно рассматривается по адресам mx2004/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context= =Flash_MX_2004 _Documentation&file=01_what.htm). Многие дизайнеры, не сведущие в программировании, полагают, что без жесткой типизации и учета регистра в ActionScript 2.0 вполне можно обойтись, на самом деле использовать эти возможности несложно, а они помогут предотвратить ошибки. Например, в ActionScript 1.0 переменной можно присвоить данные любого типа: answer = "Einstein";

Но где-то дальше на временной диаграмме будет ошибочно записана следующая команда: answer = 6: Числовое значение присваивается переменной, в которой, как предполагается, должен храниться текст - скорее всего, произошла ошибка. ActionScript 1.0 не обнаруживал подобные потенциальные ошибки и не мог предупредить о них программиста. Но при использовании жесткой типизации ActionScript 2.0 первая команда принимает следующий вид: var answer:String =."Einstein": После двоеточия указывается тип данных String. Это означает, что переменная answer должна содержать строку и не может принимать значения, относящиеся к другим типам данных. При определении типа данных перед именем переменной ставится ключевое слово var. Допустим, позднее на временной диаграмме встречается команда answer = 6;

При попытке откомпилировать FLA Flash выдает на панели Output сообщение об ошибке. Жесткая типизация помогает выявлять ошибки и создавать более надежный код. Тип данных проверяется на стадии компиляции и только в среде разработки. ActionScript поддерживает типизацию данных только в том случае, если в списке File Х Publish Settings Х Flash Х ActionScript Version была выбрана строка ActionScript 2.0. Но даже при использовании компилятора ActionScript 2.0 Flash не проверяет типы переменных, для которых не использовался синтаксис имя:тип. Это позволяет обновлять старые сценарии ActionScript 1.0 до ActionScript 2.0 без указания типов данных для всех переменных.

342 LiveDocs Глава 10. ActionScript Уследить за всеми новшествами Flash и ActionScript нелегко, поскольку из-за обнаружения новых ошибок и выхода обновлений документация иногда оказывается устаревшей (хотя при наличии подключения к Интернету Flash MX 2004 периодически спрашивает, не хотите ли вы загрузить обновленную документацию). Проект LiveDocs для Flash MX 2004 ( index.html), находящийся на ранней стадии своего существования, предоставляет пользователям доступ к полной документации Flash. На страницах LiveDocs отображаются комментарии других пользователей и имеется специальная кнопка, которая позволяет ввести ваши собственные комментарии по поводу содержимого страницы и его полезности. Особый интерес представляет словарь ActionScript - если у вас возникли проблемы с работой какого-либо фрагмента кода и найти ответ в документации Flash не удалось, попробуйте поискать в словаре.

ТРЮК Внешние редакторы сценариев Flash MX Professional 2004 содержит редактор, позволяющий редактировать внешние файлы, но в стандартном издании Flash MX 2004 такая возможность отсутствует. Использование внешнего редактора при написании кода ActionScript, JavaScript, XML или CSS сделает вашу работу более производительной.

№ Включение внешнего кода ActionScript (файлов с расширением.as) поддерживается со времен Flash 5. Как в Flash 5, так и в Flash MX внешние файлы ActionScript включаются директивой #include. В Flash MX 2004 и ActionScript 2.0 директива #include тоже поддерживается, но обычно можно обойтись и без нее. Далее приводится краткая сводка по использованию внешних файлов ActionScript. В ActionScript 2.0 определение класса (с ключевым словом>

Внешние редакторы сценариев Следующая команда ActionScript 2.0, конструирующая экземпляр класса Box оператором new, заставляет компилятор автоматически подгружать в SWF код из файла Box.as: var someVarBox = new BoxO;

Таким образом, в ActionScript 1.0 допускается размещение определений классов во внешних файлах.as, а в ActionScript 2.0 вы обязаны это делать. Компилятор ActionScript 2.0 ищет внешние файлы классов в списке каталогов классов или в пакете, заданном командой import. Добавление каталогов в список производится в диалоговом окне Edit Х Preferences Х ActionScript Х Language Х ActionScript 2.0 Settings (кнопка со значком + в секции>

344 :. Tc af a ф navigate Х function I Х Х Щ. p s r n ii n Х function 0 o Ta sa Х tХ л Щ f te es *Х function ja i V i e i ? af T x f cg au i о c l r n ii n Х function ii i ;

oTa sto Х ~И Щ, p p l t Te Х function ou el s Х at Х Глава 10. ActionScript populateEvents Х function ipg*lndx) i Х Х if ipage!p3gsind*nl.pUnk{0i t -IS ( tricoloi".unpO_mc*unRe!*ase л navigate, tricolor.stnpO mc.sm№arfC.!jrr><;

r Х1 true;

> if ipagлlpgлlndл>a.pUnm.}!-IS { tricoiur.stripl г If lpae*{pgelndл3.pUnkU! f- - 1 ! С true:

tricoto!".strip2_nx.:i'Si B.V!viO;

":;

f;

i' ХХ true: Х Х.mpopulatgEvents ХХ funttton О j Х Х builclcon ХХ function Cpaqelndex? { ХХ Х onTransition Х function 0 { Х erit * function ii { Рис. 1 0. 1. Редактор SciTEj Flash Процесс редактирования текста в SciTE|Flash достаточно очевиден, поэтому этот редактор прост и удобен в работе. Стоит особо выделить следующие полезные особенности: Х свертку программных блоков. Каждый блок помечен на левом поле охватывающей скобкой, в центре которой находится кружок со знаком + или ? (рис. 10.2). Щелкая на кружках, молено сворачивать и разворачивать отдельные блоки;

это очень удобно при работе с длинным модульным кодом - таким, как хранящиеся в файлах.as определения классов;

Х форматирование в синтаксисах других языков, кроме ActionScript. В частности, поддерживаются форматы CSS, HTML, JavaScript, XML и формат простого текста. Это позволяет создавать и редактировать все файлы с кодом, данными и параметрами конфигурации, задействованные в типичном проекте Flash. Синтаксис выбирается в меню Syntax (рис. 10.3). Х поддержку закладок для быстрого переключения между разными участками листинга (Ctrl+F2 - установка/сброс закладки для текущей страницы, F2 переход к следующей закладке, Shift+F2 - переход к последней закладке);

Х меню Edit позволяет закомментировать и снять комментарий с нескольких строк программы одной операцией. Также в меню Edit присутствует удобная команда поиска парной скобки для быстрого исправления ошибок с одной лишней или недостающей скобкой;

Х автоматическое заполнение (вообще говоря, эта возможность поддерживается панелью Flash Actions, но во внешнем редакторе она тоже не будет лишней);

Х если в момент закрытия приложения некоторые файлы оставались открытыми, SciTE|Flash автоматически откроет эти файлы при следующем запуске приложения (чтобы оценить эту возможность, нужно поработать с программой хотя бы неделю!);

Х переключение регистра (верхний, нижний, смешанный и т. д.).

Внешние редакторы сценариев p p as rents o u tE l ::

function {{>agelnd№(}'{ ипрсраЫ advents Х function У ( Х вой;

саг) 1 7 Ш iconTransХХ ftmotion SpagslndexH 3 lion Х* 1- ffi placeCon:ersl ХХХХ function С J 5 73 function S)| 18 о 9 stripEvent 2! @ stripCols -ХХfunction f i}i (unction^ Ш Ш strip-Pa^e ^function { H 2л Ш 3 2 3 nsvigatlonS3:!a ~ funcSonХ{) f 4 2: 4 S b to om top *o p p l t Tle -- (wtctiof) o uae i s Х uialeventsлfuncfion

if {jH^elpsstiffifexf^tUid^Oj Х - -1!-.( ' Х 'ХХ;

tricolor,strjpG_mc.0(sRete8*e ХХ navigate;

Х Х < ХХ n true;

:;

tncotor,sfrip1_rac.BnRetesse - navigate;

>} ! >tf (page|pagein:dexj.pLinStf2] fa -tj f >;

Х ttiootor,sSrip2_mc~3ftR*le33e л navijate;

ХХ tric^ar.sirip2_mc;

s-S!!Hs<;

s-S!".:.:.' ss- Х troe: Х ф 127 Щ unpapuiiateEvents- Х f u t K t i o n - ^ { buftiteon ХХ function i page index;

ХХ Х Рис. 10.2. Свертка программных блоков в SciTE| Flash CS S HM TL JavaScript Peri PHP Properties Python Text SL M Рис. 10.3. SciTE| Flash поддерживает синтаксис разных языков и файловых форматов Используя SciTE|Flash для написания кода ActionScript 1.0 (а также кода ActionScript 2.0 при использовании обновленных конфигурационных файлов с mizubitchy), сохраняйте свои классы ActionScript во внешних файлах с расширением.as. Чтобы протестировать сценарий, откройте новый документ FLA и свяжите с кадром 1 сценарий с директивой включения внешнего файла: #include "test.as" Глава 10. ActionScript Если в директиве указан относительный путь, компилятор Flash сам находит внешний файл.as (при условии, что он находится в одном каталоге с файлом.fla). Также можно указать абсолютный путь: #include "c:\Documents and Settings\Sham B\Desktop\test.as" Если вы пишете код для временной диаграммы, возможно, нужный код будет проще перенести операцией копирования/вставки, но применение директивы #include гарантирует, что при каждой перекомпиляции из внешнего файла.as будет извлечена новейшая версия определения класса. Более того, директива #include позволяет тестировать и отлаживать сценарии из SciTE|Flash! Чтобы перейти в Flash и просмотреть SWF в тестовом режиме, выполните команду Tools Х Test Movie в меню SciTE|Flash. Чтобы перенести результаты с панели Flash Output на панель вывода SciTE|Flash, выполните команду Tools Х Capture Output в меню SciTE|Flash. Flash входит в режим Test Movie, но не получает фокус и не разворачивается. Чтобы протестировать SWF одновременно с перенесением результатов, выполните команду Tools Х Test and Capture в меню SciTE|Flash. Окно SciTEjFlash остается на переднем плане, а среда разработки Flash входит в тестовый режим и разворачивается. Это мой излюбленный режим работы при написании длинных сценариев. SciTEjFlash также поддерживает интерфейс командной строки. Правая панель SciTE|Flash используется не только для вывода, но и для текстового ввода командной строки. Щелкните на правой панели, чтобы войти в режим командной строки, или нажмите клавиши Ctrl+F6, чтобы переключиться между режимом редактирования кода (левая панель) и командной строкой (правая панель). Комбинация клавиш Shift+F5 удаляет текст, находящийся на панели вывода. Например, чтобы протестировать SWF с сохранением выходных данных, введите в командной строке следующую команду: flush.exe-w Итоги Если вам потребуется быстрый и компактный внешний редактор для написания серьезных приложений, непременно опробуйте SciTE]Flash. Он покажется ослепительно быстрым всем, кто испытывает приступы клаустрофобии при работе с длинными сценариями на панели Flash Actions (механизм свертки SciTE|Flash помогает ориентироваться в больших сценариях). Однако SciTE|Flash гораздо компактнее внешнего редактора Dreamweaver, который явно избыточен для написания небольших фрагментов XML-кода. Конечно, существуют и другие внешние редакторы, кроме SciTE|Flash. К их числу принадлежат SE|PY ( - бесплатный редактор с открытыми исходными кодами, работающий на платформах Мае и Windows, и PrimalScript ( с минимальной ценой $179 (предоставляется 30-дневная бесплатная пробная версия без ограничения функциональности). Оба редактора обеспечивают автоматическое завершение кода ActionScript 2.09 и просмотр классов ActionScript 2.O.

О пользе жесткой типизации ТРЮК О пользе жесткой типизации В ActionScript 2.0 был включен механизм жесткой типизации для проверки ошибок, связанных с несоответствием типа переменной и ее значения. Жесткая типизация помогает разработчику проводить меньше времени за отладкой и больше Ч за созидательной работой.

№ В ActionScript 2.0 появился механизм жесткой типизации для выявления несоответствий в типах данных на стадии компиляции. Нужно ли использовать жесткую типизацию, если вы занимаетесь сценариями для компьютерных анимаций и не считаете себя асом от программирования, создающим объектно-ориентированные программы с применением классов? Мой ответ - решительное да. Важнейшими аспектами компьютерных анимаций являются скорость и чувствительность к действиям пользователя, поэтому все разработчики хотят как можно меньше времени проводить за отладкой и как можно больше - за созиданием. Жесткая типизация уменьшает количество проверок на стадии выполнения, что способствует повышению быстродействия, а проверка на стадии компиляции выявляет потенциальные ошибки, которые привели бы к незаметному нарушению работы программы в Flash MX. Таким образом, проверка типов ActionScript 2.0 повышает общую надежность кода, даже если программа довольно короткая и не использует объектно-ориентированные методы. Дополнительная проверка типов повышает вероятность того, что код будет правильно работать после успешной компиляции, и не ухудшает ее быстродействия (см. трюк 100).

Использование жесткой типизации Давайте на примере фрагмента кода ActionScript 2.0 посмотрим, как жесткая типизация работает при написании сценариев для компьютерной графики. function makeDot(cliprMovieClip):Void { // Создание точки в clip clip.lineStyledO. 0x0. 100);

clip.moveTo(0. 0): clip.lineTod. 0): } function mover():Void { } fnto cekiissedNme, lmtNme. ucin hcLmt(pe:ubr ii:ubr l w N m e,hg:ubr:ubr { o:ubr ihNme)Nme // С е а н п а л н я п и с п и о н в н и с к а м э р н мн арвеи р орксоеи ре каа i ( i i < low) | ( i i > h g ) { f lmt | lmt i h ) rtr -pe: eun sed } es { le rtr s e d eun p e :

// П р м щ н е т ч и ееееи ок this.sX = checkLimitsCthis.sX. this._x. 0. 550);

this.sY = checkLimitsUhis.sY. this._y. 0. 400);

this._x + this.sX;

= this._y + this.sY;

= Глава 10. ActionScript var ball:MovieClip: for (var i:Number = 0: i < 100: i++) { ball = this.createEmptyMovieClipC'dot" + i. i ) : ball._x = Math.randomO * Stage.width: ball._y = Math.randomO * Stage.height: ball.onEnterFrame = mover: ball.sX = Math.randomO * 8 + 2: ball.sY = Math.randomO * 8 + 2: makeDot(ball);

} Обратите внимание: объявление var balkMovieClip означает, что переменная ball является экземпляром класса MovieClip (то есть что ball принадлежит к типу MovieClipfc, поскольку объявление класса, фактически, определяет пользовательский тип данных с тем же именем). Объявление ball с типом MovieClip сообщает компилятору, что переменная должна содержать ссылку на клип. Позднее переменная ball будет использоваться для хранения ссылок на клипы, созданные во время выполнения программы функцией createEmptyMovieClip(): dotO, dot1 и т. д. Тип данных следует после двоеточия, и при каждом указании типа переменной ее имени должно предшествовать ключевое слово var. При попытке присвоить переменной значение, не являющееся ссылкой на клип: ball - 0;

ball = "dot+i";

компилятор Flash выводит на панели Output сообщение о несоответствии типов. На стадии разработки такие ошибки исправляются быстро и легко, тогда как без проверки типов вы будете смотреть на пустую сцену во время выполнения и гадать, в чем же дело. Также обратите внимание на то, что в приведенном примере функции и обработчики событий тоже типизированы. Функция, которая не возвращает никакого значения, объявляется с типом возвращаемого значения Void: function myName():Void { // Тело функции }:

Если функция вернет какое-нибудь значение (чего она делать не должна), Flash выведет сообщение об ошибке во время компиляции. Функция, которая вызывается с аргументами и возвращает значение, записывается следующим образом: function myName(argument:тип):возвращаемый_тип { II Тело функции return someValue: }: Если попытаться передать аргумент неправильного типа или если функция возвращает неправильный тип (то есть someValue не относится к возвращаемомутиny), Flash снова выводит сообщение об ошибке компиляции.

О пользе жесткой типизации Проверка типов позволяет компилятору Flash выявить многие ошибки, которые привели бы к проблемам во время выполнения. Жесткая типизация ActionScript 2.0 помогает локализовать ошибки на уровне кодового блока (например, функции или обработчика события) и предотвратить их распространение в другой код, из которого эти блоки вызываются.

Ограничения Не стоит полагать, что жесткая типизация быстро и легко применяется во всех случаях. Давайте рассмотрим некоторые ограничения проверки типов на стадии компиляции. Тип динамических свойств не проверяется. Так, в предыдущем примере свойства ball.sX и ball.sY объявляются без указания типа данных. При динамическом связывании пользовательских свойств с клипами на стадии выполнения ключевое слово var использоваться не может. Запрет на использование var также означает, что вы не сможете задать тип данных таких свойств. Более того, поскольку в нетипизированных переменных могут храниться данные произвольного типа, компилятор Flash не выдаст сообщение об ошибке для следующей команды (несмотря на то, что свойство ball.sX создавалось для хранения числовой, а не строковой информации): ball.sX = "cat";

Хотя в дальнейшем мы обращаемся к свойству ball.sX в виде this.sX внутри функции moverQ и передаем его функции checkl_imits() в параметре с именем speed, объявленным с типом Number, компилятор Flash не обнаруживает подобные косвенные ошибки. Нетипизированная переменная проходит все проверки без выдачи сообщений об ошибках. Чтобы использовать жесткую типизацию для проверки типов данных свойств, необходимо создать пользовательский класс. Далее в определении класса задаются типы всех свойств класса и свойств экземпляров. Например, сохранение следующего кода во внешнем файле Ball.as дает возможность создать пользовательский класс Ball, производный от MovieClip: // Этот код ActionScript 2.0 должен храниться во внешнем файле Ball.as>

var sY:Number;

} После этого в коде из предыдущего примера переменная ball объявляется с типом Ball вместо типа MovieClip: val ball:Ball:, При таком определении класса Flash проверяет типы свойств экземпляров (таких, как ball.sX и ball.sY). Условные команды затрудняют проверку типов. Flash поддерживает проверку типов только на стадии компиляции, поэтому проверяемый код во время проверки Глава 10. ActionScript не выполняется. По этой причине компилятор не может распознавать конструкции с условным выбором команд return. Например, в следующей команде if функция checkLimits() не вернет значения, хотя она объявлена с типом возвращаемого значения Number: function checkLimits(speed:Number. "limit:Number, low:Number. high:Number):Number { i f (false) { return -speed:

Ho Flash проверяет только тип выражения, следующего за ключевым словом return;

в данном случае выражение -speed не приводит к ошибке компиляции.

Итоги ActionScript 2.0 обладает средствами проверки типов, отсутствующими в Action Script 1.0. Эти средства не влияют на производительность на стадии выполнения и не конфликтуют со старым кодом ActionScript 1.0, не обновленным до версии 2.0. Механизм проверки типов выявляет ошибки, часто упускаемые программистами, и поэтому способствует написанию правильного, надежного кода. Хотя ActionScript 2.0 не выполняет проверку типов во время выполнения, а проверка типов на стадии разработки в некоторых ситуациях затруднена, применение жесткой типизации сэкономит немало времени и усилий разработчику любого уровня.

Кодовые подсказки Вывод подсказок на панели Flash Actions упрощает написание сценариев и предотвращает опечатки. Пользуйтесь подсказками, и вам не придется снабжать переменные суффиксами, обозначающими их тип данных. В Flash MX появилась система подсказок, отображаемых на панели Actions (F9). Кодовые подсказки отображаются в виде контекстного раскрывающегося списка с именами методов и свойств, соответствующих типу данных текущего объекта. Flash MX определяет тип данных объекта по суффиксу имени. Например, для активизации кодовых подсказок для экземпляра класса Color имя экземпляра должно заканчиваться суффиксом _color. При нажатии клавиши л. (точка) после идентификатора с суффиксом появляется кодовая подсказка (рис. 10.4). my color. gt G eR B getTransform st G eR B setTrsnsform Рис. 10.4. Раскрывающийся список кодовой подсказки заполняется в соответствии с суффиксом объекта (например, _color) Конечно, никому не захочется присваивать экземпляру цветового объекта имя myColor_color, а экземпляру звука - имя mySound_sound. Фирма Macromedia не Кодовые подсказки стала использовать эти суффиксы даже в большей части собственной документации. Более того, при использовании суффиксов разработчику приходилось запоминать суффиксы всех классов (_тс для класса MovieClip и т. д.). Одна из малоизвестных возможностей Flash MX - активизация кодовых подсказок без использования суффиксов, при этом тип переменной задается специальным комментарием. Например, следующий комментарий в следующей форме (точка с запятой обязательна) активизирует кодовую подсказку для идентификатора foo как для экземпляра заданного класса MovieClip: // MovieClip foo;

Тем, кто привык использовать суффиксы или комментарии для активизации кодовых подсказок, будет проще использовать как кодовые подсказки,/так и жесткую типизацию (трюк 75) в ActionScript 2.O. Указание типа данных через двоеточие (см. рис. 10.5) включает как жесткую типизацию, так и кодовые подсказки независимо от имени идентификатора или наличия у него суффикса. var myColor:Color = new Color (.};

rayCoIor. gt G eB R < g t r nf r eTa som \ st G eB R s t r nf r eTa som i Рис. 10.5. Кодовые подсказки в ActionScript 2.0 активизируются в соответствии с объявленным типом данных объекта Так что теперь вам не придется мучиться с суффиксами, чтобы использовать подсказки. Типы данных молено объявлять даже для имен экземпляров, задаваемых для клипов, текстовых полей и кнопок на панели свойств (помните, что кроме создания на программном уровне, эти ресурсы можно перетаскивать из библиотеки на сцену). Просто объявите тип данных клипа, текстового поля или кнопки директивой var (рис. 10.6). var myciip:MovieClip;

rayClip.

ф _accProps ф _aipha ||ip _currentframe $$ _dr&ptarзet ф _focusrect ф Jframesloaded Ш -height <з Jodoroot Ш rз !....-b,;

.:..

Ш Рис. 10.6. Объявление типов данных для имен экземпляров, определяемых на панели свойств для клипов, текстовых полей и кнопок Кодовые подсказки экономят время при использовании экземпляров классов (особенно MovieClip и Button), содержащих методы с длинными именами - такие, как createEmptyMovieClip().

352 ТРЮК Глава 10. ActionScript Клонирование объекта ActionScript копирует объекты не по значению, а по ссылке. Если вместо ссылки на оригинал потребуется создать независимую копию объекта, воспользуйтесь клонированием.

№ Для хранения данных в программах часто бывает удобнее использовать свойства одного объекта вместо набора независимых переменных, поскольку этот способ обеспечивает более формальный, структурный подход. Тем не менее, поведение объектов в некоторых ситуациях отличается от поведения простых переменных. Рассмотрим следующий фрагмент: var х = 5: var у = х;

trace(y);

х += 1;

trace(x);

trace(y);

// Вывод: 5 // Вывод: б // Вывод: Мы присваиваем х значение 5, присваиваем значение х переменной у, а затем увеличиваем х. После выполнения приведенного фрагмента переменная х равна 6, а значение у равно 5. Как и следовало ожидать, переменные не зависят друг от друга;

изменение х после выполнения команды присваивания var у = х;

не приводит к изменению у. Переменные, содержащие данные примитивных типов (например, числовые), копируются по значению, потому что ActionScript копирует значение переменной х на момент ее присваивания переменной у. Теперь попробуем выполнить аналогичную операцию с объектами: var objl = new ObjectO;

objl.prop = 5;

var obj2 = objl;

trace(obj2.prop);

// Вывод: 5 objl.prop += 1:

trace(objl.prop);

/ Вывод: 6 / trace(obj2.prop);

/ Вывод: б / На этот раз мы создали объект objl, включили в него свойство prop и присвоили объекту obj2. Привело ли это к появлению двух самостоятельных объектов? Сразу же после присваивания свойство obj2.prop равно 5, как и следовало ожидать. Но если увеличить objl.prop и проверить значения objl.prop и obj2.prop, выясняется, что они равны - свойства обоих экземпляров равны 6. Но почему это произошло? Казалось бы, даже после присваивания objl.prop значения б свойство obj2.prop должно было остаться равным 6? Дело в том, что мы создали не два самостоятельных объекта, а две ссылки на один объект. Обе переменные, objl и obj2, вместо примитивных данных (числа 6) содержат указатели на один блок данных объекта в памяти. Поскольку objl.prop и obj2.prop ссылаются на один и тот лее блок данных, изменения содержимого этого блока по любой из ссылок отражаются в обеих ссылках. Можно провести аналогию с созданием нескольких экземпляров клипа многократным размещением одного символа на сцене. Последующие изменения символа клипа в библиотеке отражаются на всех экземплярах. Впрочем, аналогия Клонирование объекта лишь приблизительная - экземпляры клипа зависят от символа в библиотеке, но остаются независимыми друг от друга. Изменения в свойствах экземпляра одного клипа не отражаются в других клипах, производных от того же символа. Сложные типы данных (такие, как объекты и массивы) копируются по ссылке. Они могут занимать много места в памяти, поэтому передача по ссылке получается более эффективной. Например, чтобы выполнить операцию с массивом, Flash передает только указатель на массив и обходится без копирования всех элементов. Но при таком способе копирования возникают проблемы, если вместо простой ссылки на оригинал вам нужна самостоятельная копия. Объект можно клонировать явным определением каждого свойства дубликата: Х var objl = new ObjectO;

objl.propl = 5: objl.prop2 = 12;

var obj2 = n w ObjectO;

e obj2.propl = objl.propl;

obj2.prop2 = objl.prop2;

trace(obj2.propl);

// В в д 5 ыо: oj.rp + 1 blpol = ;

trace(objLpropl): // В в д 6 ыо: trace(obj2.propl);

// В в д 5 ( н б!) ыо: ае Объекты objl и obj2, а также их свойства objl.propl и obj2.prop1 стали независимы друг от друга. Чтобы вместо ссылки на объект создавалась уникальная копия объекта, в класс Object можно включить дополнительный метод clone(). Следующий код написан на ActionScript 1.0, но он также будет работать в ActionScript 2.0: Object.prototype.clone = functionO { i f ( (typeof this) != "object" || (this instanceOf Button) || (this instanceof TextField) ) { // Для клипов, кнопок и текстовых полей возвращается исходная ссылка // (то есть эти типы не клонируются), return this;

} v r с = n w ObjectO;

a e f r ( a n i this) { o vr n v r о = this[n];

a i ( ( y e f o) = " b e t & f tpo = ojc" & !o i s a c O B t o | о i s a c O T x F e d ) { ( ntnef utn | ntnef etil) // С о с в т к е п е с а л е с б й о ъ к, вйто аж рдтвят оо бет \ // в п л и ь р к р и н е к п р в н е ыонт еусво оиоаи. } es { le // С о с в п и и и н х т п в к п р ю с п з а е и. вйта рмтвы ио оиутя о нчню // В п о и н м с у а э о с ы к н ф н ц ю M v e l p ртво че т сла а уки. oiCi. // B t o и и T x F e d. к т р е к п р ю с п с ы к. u t n л etil' о о ы о и у т я о с л е // п с о ь у д я н х н л з л г о с з а ь э р н о п е с а л н е оклк л и еья ек одт кане рдтвеи. с[п] = о : return с;

354 // Предотвратить использование метода clone в циклах for..in // и защитить его от удаления. ASSetPropFlags(Object.prototype.["clone"].5.1):

Глава 10. ActionScript Приведенный фрагмент включает в класс Object новый метод Object.clone(). Как и все классы ActionScript, он также работает с большинством классов, производных от Object. Тем не менее, этот код не пытается клонировать клипы, потому что встроенный метод MovieClip.duplicateMovieClipO уже умеет создавать независимые копии клипов. Хотя в методе clone() мы могли воспользоваться методом duplicateMovieClip() для клонирования вложенных клипов, обычно нежелательно дублировать клип только потому, что ссылка на него содержится в свойстве какого-то объекта. По тем же причинам не рекомендуется клонировать существующие текстовые поля или кнопки. На практике чаще встречается создание новых текстовых полей (например, методом MovieClip.createTextField())( нежели клонирование существующих полей. При наличии предыдущего определения метода clone() следующая команда создает независимую копию (то есть клонирует) obj1 и сохраняет ссылку на новый независимый объект в переменной obj2: obj2 = objl.cloneO;

Сравните с командой Obj2 = objl;

которая просто сохраняет в obj2 ссылку на тот же объект, на который ссылается objl. Обратите внимание: Х если метод cloneQ вызывается для одного из графических классов (клип, кнопка или текстовое поле), то вместо клонирования он возвращает ссылку на объект;

Х к объекту-клону присоединяются только перечисляемые свойства. В эту категорию входят свойства, которые обычно просматриваются в циклах for..in (то есть пользовательские свойства, определяемые разработчиком), но не стандартные свойства, определяющие внутренние механизмы работы класса;

Х недокументированный метод ASSetPropFlagsQ (см. трюк 82) защищает метод Object.clone() от удаления и исключает его из перебора в цикле for..in. Тестирование метода clone() выполняется следующим образом: // Создание тестового объекта, содержащего вложенный объект. obj = {name:"test". num:10. boo!:true. childObj:{childName:"original child name". childNum:5}. root:_root}: // Клонирование объекта cloneOfObj = obj.cloneO: II И м н н е з а е и в н в м о ъ к е зееи нчня оо бет c o e f b. h l O j c i d a e = " h n e c i d name": lnOOjcidb.h1Nm cagd hl // П о е к о ъ к о н н з в с м с ь рвра бетв а еаииот t a e " b. h l O j c i d a e = "+ o j c i d b. h l N m ) rc(ojcidb.hlNm b.hlOjcidae: t a e ' l n O O j c i d b. h l N m = "+ c o e f b. h l O j c i d a e : rcCcoefb.hlOjcidae lnOOjcidb.hlNm) Х Клонирование объекта Программа наглядно демонстрирует, что объект-клон и его вложенный объектсвойство существуют независимо от объекта-оригинала и его вложенного объекта. Метод clone() избавляет от необходимости вручную копировать свойства и пользовательские методы при создании новой копии объекта.

Клонирование в компьютерной графике Пусть меня назовут старомодным, но я все же предпочитаю рассматривать данные с визуальной точки зрения. По этой причине вашему вниманию предлагается следующий пример, наглядно демонстрирующий различия между клонированием и копированием по ссылке. Программа создает объект sData, который используется для управления несколькими полупрозрачными клипами, формирующими эффект частиц. Эффект формируется множеством идентичных клипов, каждый из которых представляет собой независимый экземпляр sData с собственной временной диаграммой. function animateC):Void { this.sData = sData.cloneO this._x = this.sData.x: this._y = this.sData.у: this.lineStyledO. 0x404040. 10);

this.moveTo(-0.5. 0): this.lineTo(0. 0);

this.onEnterFrame = functionO { this.sData._x += Math.randomO * this.sData.s - sData.s / 2;

this.sData._y += Math.randomO * this.sData.s - sData.s / 2;

this._x = this.sData.x: this._y = this.sData.y;

} var sData:Object = new ObjectO;

sData.x = 275;

sData.s = 4;

for (var i = 0: i < 500;

i++) { var dot:MovieClip = this.createEmptyMovieClipC'dot" + i. this.getNextHi ghestDepth());

dot.onEnterFrame = animate;

} В этом коде представлена стандартная методика копирования анимационных клипов по ссылке. Переменная dot содержит ссылку на экземпляр клипа dot/. Она всегда ссылается на клип, созданный в цикле, без создания дубликата этого клипа. Все клипы уникальны, поэтому каждый из них обладает независимым набором свойств, определяющих его размеры и позицию. Программа создает простейшую имитацию броуновского движения (случайного перемещения частиц) - рис. 10.7. Все 500 клипов независимы друг от друга.

Глава 10. ActionScript Рис. 10.7. Имитация броуновского движения из 500 клипов Если изменить первую строку функции animate() так, чтобы копирование осуществлялось по ссылке, а не посредством клонирования: this.sData = sData: результат будет совершенно иным (рис. 10.8).

Рис. 10.8. Замена клонирования простым копированием изменяет вид анимации В примере с независимыми объектами каждый клип обладал собственным объектом sData со своими координатами х и у, поэтому частицы двигались независимо. В новом варианте все частицы совместно используют один объект sData (то есть все локальные версии this.sData содержит ссылку на оригинал sData). Таким образом, изменение свойств sData по ссылке приводит к изменению свойств всех объектов this.sData. Вместо случайно распределенных частиц вы получаете нелепый комок, пляшущий по сцене. Все частицы ведут себя как составные части одного большого объекта, потому что их управляющие данные стали взаимосвязанными - частицы утратили свою индивидуальность.

Итоги Ссылки на существующие клипы часто используются в циклах, когда требуется обозначать разные клипы одним именем. Например, в следующем цикле ссылка должна указывать на текущий клип, только что созданный методом createEmptyMovieClip(). К новым клипам гораздо проще обращаться по имени myClip, чем писать код, который бы ссылался на них по конкретным именам экземпляров от clipO до clip9: for (i = 0;

i < 10;

i++) { var myC1ip:MovieClip = this.createEmptyMovieClipC'clip" + i. i ) : // Операции с текущим клипом по имени myClip myClip._rotation = 50;

} Иногда копирование по ссылке свидетельствует об ошибке са стороны программиста, который намеревался создать независимый объект. Метод Object.clone(), представленный в этом трюке, поможет легко создавать независимые объекты.

Тайм-аут по бездействию пользователя В компьютерной графике выбор между независимыми (уникальными) данными и ссылками на них позволяет создавать абсолютно непохожие эффекты с минимальными усилиями.

Грант Скиннер Тайм-аут по бездействию №78 пользователя ТРЮК В приложениях, критичных по быстродействию, не стоит тратить процессорное время на постоянные проверки действий пользователя. Создайте событие тайм-аута по бездействию, которое не будет мешать воспроизведению мультимедийной информации. Однажды мне заказали Flash-приложение для сбора информации, которое должно было работать на экранах, размещенных на спинках кресел в самолетах. Когда пользователь на некоторое время переставал работать с приложением, оно должно было переключаться на воспроизведение видеоролика. Но как только пользователь перемещал мышь или щелкал ее кнопкой, приложение должно было быстро вернуться в режим ввода данных. Я написал код, выявляющий бездействие со стороны пользователя, но без оптимизации этого кода видео воспроизводилось неравномерно. В Macromedia Director существует событие idle, инициируемое по бездействию и позволяющее использовать свободное время для полезных целей (например, для запуска фоновых задач). Flash-разработчики нередко повышают частоту смены кадров, пока у Flash остается свободное время (хотя его всегда меньше, чем в Director, потому что Flash обладает более низким быстродействием). Собственно, по этой причине в Flash отсутствует встроенное событие, которое бы инициировалось при отсутствии полезной работы. Пришлось крепко задуматься. Задача - создать событие, которое бы обнаруживало отсутствие взаимодействия с пользователем. При получении этого события приложение должно переключиться на выполнение других действий - скажем, запустить анимацию или выдать звуковое приглашение. В Director такие события называются событиями тайм-аута, но, как уже говорилось ранее, в Flash не существует встроенных средств для обнаружения бездействия пользователя. Пользователи часто оставляют Flash-сайты открытыми на время загрузки видео или звука и работают в другом окне браузера. Было бы неплохо, если бы вместо окна с надписью содержимое загружено SWF выдавал звуковую информацию о завершении загрузки. Или, скажем, в автоматическом киоске при отсутствии взаимодействия с пользователем по истечении периода тайм-аута SWF может запустить видеоролик для привлечения покупателей. Но как создать функцию обнаружения бездействия, которая бы не потребляла вычислительных мощностей во время общения пользователя с SWF? Самый очевидный кандидат для обнаружения пользовательской активности - событие onMouseMove (мышь в руке пользователя не может оставаться абсолютно неподвижной - если, конечно, пользователь не забывает дышать). Но во время активной Глава 10. ActionScript работы с приложением событие onMouseMove происходит слишком часто, и любые задержки в его обработке сказываются на быстродействии SWF. Следовательно, фоновому обработчику событий не стоит полагаться на это событие. Другой, более экономный способ выявления действий пользователя основан на создании двух интервальных таймеров: Х короткий интервал проверяет наличие действий пользователя каждые 1-2 с (недостаточно часто для снижения быстродействия);

Х длинный интервал (обычно от 15 до 120 с) задает продолжительность таймаута. Когда короткий интервальный таймер обнаруживает действие пользователя, длинный интервал сбрасывается. Эти два интервальных таймера срабатывают относительно редко по сравнению с такими событиями, как событие onEnterFrame, инициируемое для каждого кадра Flash. Мы пытаемся обойтись как можно меньшим объемом программного кода, чтобы избежать снижения быстродействия;

слишком большой объем фоновых вычислений замедлит работу Flash. Следующий короткий листинг демонстрирует работу схемы с двумя интервалами. Более короткий интервал выполняет минимальный объем кода (единственная команда if). Попробуйте снять комментарии с закомментированных команд trace() и посмотрите, какие действия выполняются в течение интервалов. Учтите, что команды trace() выполняются довольно медленно, поэтому в окончательной версии их присутствие нежелательно. function idleTimeO { // Воспроизведение анимации //traceC"playing the animation") gotoAndStop("attract"): } f n t o idles О { ucin // Проверить п р м щ н я м ш з п с е н е две с к н ы ееееи ыи а олди еуд if ( _ o t _ m u e + _root._ymouse) ! mousePos) { (ro.xos = // Е л п р м щ н я были, п р з п с и ь п о е к т й е а си ееееи ееаутт рвру амр //traceC"resetting"): gotoAndStopC'noAttract"): clearlnterval(idle): idle = setlntervaKidleTime. 28000);

//} else { / t a e ' o m v m n this period");

/rcCn oeet } // Сохранение ц л г числа, п е с а л ю е о п з ц ю м ш еоо рдтвящг оии ыи mousePos = _root._xmouse + _root._ymouse: } f n t o startldleO { ucin mousePos = -100000;

// И и и л з ц я ф к и н м з а е и м нцаиаи итвы нчне i l S m l = s t n e v l (idleS. 2000);

deape eltra } startldleO;

stopO;

Тайм-аут по бездействию пользователя Первый интервальный таймер idleSample проверяет позицию мыши каждые две секунды (перемещения мыши лучше идентифицировать именно так, а не в событии onMouseMove, потому что событие onMouseMove происходит довольно часто и может замедлить работу Flash-приложения). Если сумма координат изменилась по сравнению с предыдущим вызовом, значит, пользователь переместил мышь, поэтому мы сбрасываем другой, более длинный интервальный таймер idle. Если до истечения интервала тайм-аута (28 с) пользователь не взаимодействовал с приложением, выполняется функция idleTime(), которая активизирует воспроизведение с позиции attract (обычно при этом запускается рекламная анимация или видеоролик). При желании модифицируйте код таким образом, чтобы функция idleTimeQ запускала некую заставку, воспроизводимую в режиме ожидания, а функция idleSQ останавливала ее. Предыдущая программа выполняется до тех пор, пока по истечении 30 с (2000 + 28 000 мс) Flash не вызовет функцию idleTime() с переходом к кадру attract. Предполагается, что обработчик события onMouseMove для этого кадра прервет анимацию и запустит презентацию заново, когда пользователь щелкнет кнопкой мыши.

Итоги Для обеспечения оптимального быстродействия в Flash необходимо свести к минимуму выполнение фоновых операций на время воспроизведения материалов, требующих больших затрат ресурсов (видео, звук или сложная анимация). Это означает, что фоновые задачи должны быть хорошо оптимизированы. Код проверки бездействия пользователя, представленный ранее, выиолняется относительно редко, поэтому во время работы пользователя с сайтом он не замедляет воспроизведение основного содержания. Если пользователь на некоторое время перестает работать с программой, активизируется циклическое воспроизведение рекламного ролика или заставки. Такой режим работы хорошо подойдет для автоматизированных киосков: если взаимодействие с пользователем прекращается, Flash-ролик сбрасывается в начало. Не забудьте, что интервал тайм-аута (например, 30 с) должен быть длиннее любой анимации, которая, как предполагается, не требует ответных действий от пользователя. Возможно, вам придется увеличить интервал тайм-аута, чтобы сделать возможными вынужденные периоды бездействия, когда пользователь следит за работой приложения. Впрочем, если пользователю приходится пассивно ожидать в течение, скажем, 90 с и более, вместо простого увеличения интервала таймаута лучше пересмотреть структуру приложения. События нажатий клавиш также должны приводить к сбросу интервального таймера. Представьте, что пользователь вводит текст на форме, но не двигает мышь;

бесцеремонный переход к заставке весьма удивит его. Следовательно, если автоматический киоск оснащен клавиатурой, воспользуйтесь методом Key.addListener() для вызова обработчика onKeyDown, сбрасывающего интервал бездействия.

Глава 10. A t o S r p cincit Быстрый поиск в ActionScript Операции поиска в массивах и тексте из ActionScript выполняются относительно медленно. Небольшой фокус с переводом данных в строковый формат позволит ускорить реализацию поиска.

Хотя Flash Player 7 работает быстрее своих предшественников, операции с текстом и массивами все равно занимают много времени. В программной реализации поиска часто применяются циклы while и for. Но при многократном выполнении операций возникает проблема: Flash не является полноценным компилируемым языком. При публикации SWF-файла Flash преобразует сценарий ActionScript, приближенный к естественному языку, в байт-код, понятный для Flash Player. Таким образом, во время выполнения программы при каждой итерации цикла Flash Player приходится преобразовывать каждую строку байт-кода в исполняемые инструкции. Если исключить из цикла повторяющиеся операции, программа будет работать быстрее. В этом нетрудно убедиться на следующем примере, содержащем три реализации простого поиска в массиве: methodl = function () { // Последовательный поиск в массиве for (var i = 0: i

eun return false: }: method3 = function () { // П и к в м с и е с п е в р т л н м п е б а о а и м ос асв рдаиеьы рорзвне // э е е т в в строку. мно var s a c P s N m e = arr.join(" ").indexOf(nr.toString()) erho:ubr if ( e r h o ! -1) { sacPs = r t r true;

eun } r t r false: eun }: // С з а и м с и а с п с е о а е ь о т ю ч с л о 0 д 999. одне асв олдвтлнсь ие т о var a r A r y = new ArrayO: r:ra var e e : u b r = 1000: l mNme Быстрый поиск в ActionScript for (var i = 0 ;

i < el em;

i++) { arr.pushd): } // Случайный выбор искомого числа. var nr:Number = Math.floor(Math.random() * elem): trace("searching for:" + nr);

/ Тестирование м т д 1 / еоа var sT = getTimerO;

methodK): eT = getTimerO - sT: traceC'time method 1 : " + eT);

/ Тестирование м т д 2 / еоа var sT = getTimerO;

method20;

eT = getTimerO - sT;

traceC'time method 2 : " + eT);

var sT = getTimerO;

method30;

eT = getTimerO - sT: traceC'time method 3 : " + eT);

Сначала в программе создается массив с числами от 0 до 999. Затем выбирается искомое случайное число из интервала от 0 до 99): \/зг nr:Number = Math, floor (Math. randomO * elem);

Далее проводится тестирование трех функций поиска числа в массиве: method 1(), method2() и method3(). Первая функция, method1(), ограничивается простейшим поиском в цикле for. Она последовательно перебирает все элементы массива и сравнивает их с искомым числом. Если число будет найдено, функция возвращает true. Во второй функции, method2(), используется цикл for..in. Наконец, функция method3() обходится вообще без цикла. Вместо этого она генерирует строку из всех элементов массива, разделенных пробелами ("О 1 2 3 ? 997 998 999"), а затем ищет значение nr в сгенерированной строке. Сравнительное быстродействие определяется многократным выполнением функций. Программный хронометраж (см. трюк 69) помогает выявить многие проблемы. Самой быстрой оказывается третья функция, method3(), обеспечивающая постоянное низкое время поиска. Вместо циклического перебора элементов она преобразует данные в строковый формат и применяет к результату строковые методы Flash. Функция method3() содержит наименьшее количество команд, так как в остальных функциях используются циклы, поэтому она выполняется чуть быстрее других операций. Метод Array.join(), преобразующий содержимое массива в строку, выполняется довольно быстро, потому что он реализован на C++ - компилируемом языке, на котором написаны встроенные функции Flash. Методы классов String и Array, задействованные в данном трюке, показывают хорошее быстродействие в Flash Player 6 и 7. В предыдущих версиях Flash Player они работают медленнее.

Глава 10. ActionScript Приведенные ранее функции проверяют, входит ли целевое значение в массив, но не показывают, в какой именно позиции. Тем не менее, скорость поиска зависит от положения искомой величины в массиве. Реализация с циклом for работает быстрее, если искомое значение расположено ближе к началу массива: searching for: 153 time method 1 time method 2 time method 3 Если элемент находится в середине, первые два метода дают более или менее одинаковый результат: searching for: 418 time method 1 time method 2 time method 3 Если искомый элемент расположен близко к концу массива, вторая функция поиска работает быстрее первой. Дело в том, что циклы for..in просматривают свойства (элементы массива в данном примере) в порядке, обратном порядку их создания в объекте. Иначе говоря, перебор начинается с последнего элемента и постепенно передвигается к первому: searching for: 777 time method 1 time method 2 time method 3 Но во всех трех случаях третья функция поиска работает быстрее всего и обеспечивает постоянное время поиска. Если содержимое массива заведомо остается неизменным, для ускорения поиска молено сохранить результат join() во временной переменной и использовать ее в будущих операциях. Большой объем данных замедляет строковый поиск, и все же этот способ превосходит по скорости другие способы, если размер массива не превышает 10 000 элементов. Впрочем, если вам приходится выполнять поиск в наборах данных такого порядка, лучше выполнить его на удаленном сервере и вернуть результат - скажем, через Flash Remoting.

Итоги Циклы часто применяются для выполнения повторяющихся операций, но в Flash циклы приводят к большим затратам времени. Хорошее понимание сильных и слабых сторон всех трех типов поиска (последовательного перебора элементов, перебора свойств, поиска в строке без применения циклов) позволит вам создать оптимизированный код для любого конкретного приложения.

Материей предложен Эдвином Хейджменом Блокировка слоя actions ТРЮК Блокировка слоя actions ActionScript может размещаться практически в любой позиции временной диаграммы. Храните сценарии на специальном заблокированном слое actions, чтобы отделить код от ресурсов.

№ В анимационных приложениях течение времени представляется временной диаграммой. В начале каждого нового кадра Flash генерирует событие onEnterFrame. Схема выглядит абсолютно логично - до тех пор, пока в приложение не начинает добавляться программный код. В отличие от других сценарных языков с централизованным хранением сценариев, код Flash может связываться с любым ключевым кадром временной диаграммы, обычно в порядке выполнения. Некоторые разработчики собирают весь код ActionScript в кадре 1 главной временной диаграммы, но во многих проектах по крайней мере часть кода приходится связывать с другими кадрами. Иногда код даже связывается с кнопками и анимационными клипами на разных слоях. На длинной временной диаграмме с большим количеством слоев код постепенно распыляется, а это затрудняет отладку и сопровождение. Разработчикам часто приходится использовать Movie Explorer (Window Х Other Panels Х Movie Explorer) просто для того, чтобы найти нужный фрагмент кода! Чтобы не создавать себе лишних трудностей, присвойте первому слою временной диаграммы имя actions (или scripts) и связывайте все сценарии только с этим слоем. Хранение сценариев в отдельном слое способствует централизации кода (для хранения меток кадров, создаваемых на панели свойств, можно использовать этот же слой или создать отдельный слой labels). Вместо того чтобы связывать код непосредственно с кнопками и клипами на других слоях, задайте кнопке/клипу имя экземпляра на панели свойств. Далее код косвенно связывается с клипом по имени экземпляра. Код ActionScript должен размещаться в слое actions, а не в слое, содержащем клип, и не на временной диаграмме клипа. Например, создание ссылки на клип с именем экземпляра ballClip из кода слоя actions главной временной диаграммы с последующим заданием его координаты х выглядит так: var ballClip:MovieClip;

ball СИ p._x = 50;

Блокировка слоя Чтобы слой actions сохранял свою специализацию и использовался только для хранения сценариев, держите его постоянно заблокированным. Flash позволяет заблокировать любой слой временной диаграммы - для этого следует щелкнуть на точке в столбце с замком (рис. 10.9). Чтобы снять блокировку со слоя, щелкните на замке, обозначающем заблокированный слой (на рис. 10.9 слой Layer 2 заблокирован). Блокировка слоя не запрещает его редактирование, как можно было бы предположить, однако она не позволит добавлять объекты со сцены в заблокированный слой.

Глава 10. ActionScript Рис. 10.9. Чтобы заблокировать слой, щелкните на точке с столбце с изображением замка Даже после того как слой будет заблокирован, с ним возможны следующие операции: Х добавление ключевых кадров (сценарии присоединяются только к ключевым кадрам). Чтобы добавить ключевой кадр, выделите кадр заблокированного слоя и нажмите клавишу F6 (или выполните команду Insert Х Timeline Х Keyframe). Операция выполняется точно так же, как на любом незаблокированном слое;

Х присоединение и редактирование сценариев, связанных с ключевыми кадрами слоя, с применением панели Actions (F9);

Х вставка кадров на заблокированном слое. Чтобы вставить кадр, выделите один из кадров заблокированного слоя и нажмите клавишу F5 (или выполните команду Insert Х Timeline Х Frame). Операция выполняется точно так же, как на любом незаблокированном слое. Следующие кадры автоматически сдвигаются вправо. Итак, блокировка слоя actions предотвращает размещение на нем графических объектов или связывание символов с его ключевыми кадрами, в результате слой может использоваться только для хранения сценариев. Тем не менее, блокировка слоя не мешает добавлению и редактированию ключевых кадров и сценариев.

Итоги Никто не запрещает вам хранить код во внешних файлах с расширением.as. Более того, во многих ситуациях это даже рекомендуется делать вместо хранения всего кода в первом кадре временной диаграммы. Но в отдельных случаях такое решение оказывается непрактичным: Х создание больших анимаций с управлением временными диаграммами из ActionScript - таких, как The Goober Story ( Х тривиальное управление временными диаграммами. Например, создавать специальный класс для остановки клипа на кадре 12 было бы явным излишеством. Гораздо проще (и эффективнее) добавить операцию stop() в нужный кадр;

Х присоединение обработчика события к экземпляру клипа, не существующему в первом кадре. Невозможно связать обработчик события с экземпляром до того, как он будет существовать. Если анимационный клип не существует на временной диаграмме до кадра 34, то присоединить к нему обработчик события можно будет только в сценарии слоя actions в кадре 34, но не в кадре 33. Хотя все эти ситуации способствуют распылению кода, основной код все же может храниться в кадре 1 слоя actions - запишите все сценарии и обработчики событий в виде функций и вызывайте функции из нужных кадров. При такой схеме практически весь код ActionScript остается в кадре 1.

Отладка и трассировка ТРЮК Отладка и трассировка Функция trace() выводит текст на панели Output. Используйте ее для повышения эффективности отладки.

№ Отладчик (Window Х Development Panels Х Debugger и Control Х Debug Movie) помогает выполнять диагностику в реальном времени, и все же довольно часто бывает удобнее воспользоваться функцией trace() для вывода на панель Output. Однако следует помнить, что trace() выводит только одно выражение. Чтобы вывести больше данных, постройте более сложное выражение при помощи строковой конкатенации (оператор +). Допустим, нужно вывести текущие значения следующих переменных: var x:Number = 10: var у:Number = 20;

var z:Array = [10. 20. 30. 40];

var w:Object = {pi:10. p2:"hello". p3:true} Если переменные х и у определяют координаты графического объекта, уместно вывести их в одной строке в формате (х, у): traceC 1 (" + х + ". " + у + " ) " ) ;

Результат выглядит так: (10. 20) Чтобы разбить выводимые данные на несколько физических строк, воспользуйтесь несколькими командами trace() или служебной последовательностью \п. Так, фрагменты trace(" is: + x);

x trace(" is: " + У): У и t a e "x rc( x is: 10 у is: is: " + x + "\n" "y is: " + у + "\n");

выводят одинаковый результат:

Простая трассировка массива (то есть передача имени массива функции trace()) выводит список всех элементов массива. Так, для определенного ранее массива z команда trace(z) выведет список 10.20.30.40 Обратите внимание: элементы массива не разделяются пробелами. Чтобы результат выглядел более привлекательно, организуйте разделение при помощи метода Array.join(): trace(z.join(". " ) : Результат выглядит так: 10. 20. 30. 366 Команда trace(z.join("\n");

выводит элементы в разных строках: 10 20 30 Глава 10. ActionScript При работе с объектами для перебора перечисляемых свойств применяется цикл for.jn. Для предыдущего определения w фрагмент for (var i in w) { traceC'w." + i + " = " + w[1]): } выведет следующий результат: w.pl = 10 w.p2 = hello w.p3 = true Неперечисляемые свойства (например, встроенные свойства и методы, скрытые от ActionScript) можно вывести недокументированной функцией ASSetPropFlags() (см. трюк 82). Часто сценарий ActionScript делает не то, что требуется, и вы не можете понять, почему это происходит. Нередко причина кроется в недействительности экземпляра (вы думаете, что переменная содержит действительный клип или экземпляр объекта, а на самом деле в ней хранится мусор) из-за ошибки программирования или опечатки в имени экземпляра на панели свойств. К сожалению, если Flash Player не может выполнить операцию из-за недействительности экземпляра, он не выдает сообщений об ошибке. Диагностика таких проблем осложняется рядом факторов: Х обычно проблема возникает при динамическом создании клипов и в больших иерархиях временных диаграмм;

отладчик загромождается информацией, что затрудняет процесс диагностики;

Х даже если экземпляр отображается в отладчике, он может не существовать в начале кадра или область видимости переменной может отличаться от ожидаемой. Чтобы выявить подобные проблемы в отладчике, необходимо расставить точки прерывания и вручную выполнять код в пошаговом режиме, строка за строкой. Отладка такого рода занимает много времени. Чтобы проверить действительность экземпляра на момент использования, включите в программу отладочную команду trace() следующего вида: for (var i in this) { i f (i.indexOfC'myClip". 0) != -1) { trace(myClip._name + " is on timeline " + this):

Если экземпляр myClip виден на главной временной диаграмме, то на панели Output выводится строка myClip is on the timeline JevelO. В противном случае информация не выводится. Обратите внимание: выводимое сообщение содержит Отладка и трассировка подробную информацию о том, что и где было обнаружено, - верный признак грамотного подхода к отладке. Если ограничиться кратким сообщением found it!, через полгода вы и не вспомните, что оно означает. Также проследите за тем, чтобы команды trace() выводили разный текст, иначе вам будет трудно отличить, какой именно команде trace() было передано управление. Например, следующий фрагмент выводит информацию о типе аргумента incoming. Если incoming является объектом, выводится строка Incoming object in checkObject() is of type: object: function checkObject(incoming) { trace("Incoming object in checkObjectO is of type: " + typeof incoming);

} В сообщения trace() часто включаются префиксы, которые упрощают понимание логики и результатов: survey.fla > Starting up. xmlutils > Loaded. view > Loaded. Let's draw the display. display > Drawing.

Итоги Отладочная информация обычно выводится только на стадии разработки. Чтобы предотвратить вывод отладочной информации в работающем приложении, откройте диалоговое окно File Х Publish Settings Х Flash и установите флажок Omit Trace Actions. Flash игнорирует вызовы trace() при экспортировании, и результат будет таким же, как если бы все вызовы trace() в FLA были закомментированы. Для решения более сложных задач отладки и сокращения объема данных, выводимых командами traceQ, можно создать пользовательскую, централизованную функцию трассировки, исключаемую из окончательной версии сайта перед публикацией. В следующем листинге продемонстрирована простая схема изменения детализации отладочных сообщений. Сообщения ставятся в очередь функцией сТгасе {сообщение,приоритет). Если приоритет ниже пороговой величины verboseLevel, сообщение не отображается на панели Output. В следующем примере при нулевом значении verboseLevel выводятся оба сообщения, а если переменная verboseLevel равна 1, будет выведено только первое сообщение: сТгасе = function (message, priority) { i f (priority >= verboseLevel) { trace(message): } // Применение: verboseLevel = 1: cTraceCImportant message", 1);

// Сообщение выводится cTrace("Low-priority message". 0): // Сообщение не выводится Еще одно возможное усовершенствование - фильтрация сообщений. Например, при большом количестве ошибок было бы логично начать с исправления самых существенных проблем, а затем перейти к менее важным. Следующая программа Глава 10. ActionScript скрывает все сообщения с приоритетом, более низким, чем максимальный приоритет последнего сообщения. Фильтрация позволяет сосредоточиться на отладочной информации, которая с наибольшей вероятностью окажется актуальной для исправления ошибок. В следующем примере последнее сообщение остается скрытым, потому что ошибка, скорее всего, обусловлена сообщением с более высоким приоритетом. Допустим, сообщение с наивысшим приоритетом указывает на ошибку загрузки XML-файла. Менее важное сообщение В XML-файле обнаружены непредвиденные символы следует скрыть до того момента, когда XML-файл удастся загрузить: сТгасе = function (message, p r i o r i t y ) { i f ( p r i o r i t y >= verboseLevel) { verboseLevel = p r i o r i t y ;

trace(message): } // Применение: verboseLevel = 0: cTraceC'XML f i l e not loading". 2);

cTrace("Unexpected characters found in X L f i l e ". 1);

M Наконец, если тестирование должно осуществляться за пределами среды разработки (скажем, в браузере), отладочная информация может выводиться в текстовых полях. В следующем листинге диагностические данные перенаправляются в текстовое поле myText - предполагается, что поле уже существует на сцене (изменения выделены жирным шрифтом). Чтобы прекратить вывод отладочной информации, проще всего переместить текстовое поле на опорный слой: сТгасе = function (message, p r i o r i t y ) { i f ( p r i o r i t y > verboseLevel) { verboseLevel = p r i o r i t y : myText.text += messsage + "\n";

Недокументированные возможности №82 ActionScript ТРЮК Недокументированные возможности ActionScript интересны всем. В настоящем разделе рассматривается недокументированная область видимости _global. Нередко для решения какой-то важной задачи требуется перебрать свойства объекта. Допустим, вы хотите вывести значения свойств на панели Output для получения отладочной информации. Другой пример - декодирование неизвестных свойств объекта, возвращенного, скажем, при обращении к базе данных на сервере. Естественно, нам хотелось бы перебрать скрытые (недокументированные) свойства ActionScript и посмотреть, не найдется ли в них чего-нибудь интересного.

Недокументированные возможности ActionScript С точки зрения интерпретатора Flash базовый цикл ActionScript for..in означает следующее: Взять указанный объект и для каждого из его свойств (включая методы, хранящиеся в свойствах) выполнить тело цикла. Тем не менее, многие встроенные методы и свойства ActionScript по умолчанию исключаются из перебора в цикле for..in. Фирма Macromedia предполагает, что программиста интересуют объекты и свойства, созданные им в программе, а не те, которые заложены в основу работы ActionScript, поэтому встроенные свойства исключаются из перебора for..in. Недокументированная функция ASSetPropFlags() позволяет сделать видимыми даже те свойства и методы, которые обычно остаются невидимыми для перебора. Macromedia часто добавляет новую функциональность в обновленные версии своих программ. Например, многие возможности Flash Player 7 не документировались и не поддерживались официально (но работали!) в Flash Player 6.0.65.0. Каждый раз, когда Macromedia выпускает новую версию Flash Player (особенно на поздних стадиях жизненного цикла продукта), я проверяю, не появилось ли в ней чего-нибудь интересного. Как нетрудно догадаться по ее имени, функция ASSetPropFlags() позволяет задавать флаги защиты свойств из ActionScript. Флаги указывают Flash Player, должны ли соответствующие методы и свойства включаться в перебор for.Jn. Функция ASSetPropFlags() также позволяет запретить запись (или перебор) свойств и методов пользовательских объектов, чтобы предотвратить их случайную модификацию. Это особенно актуально для глобальных свойств распространяемых компонентов, чтобы предотвратить конфликты со сторонними компонентами, используемыми в том же SWF-файле. Давайте в общих чертах посмотрим, как же работает функция ASSetPropFlags(). Синтаксис вызова ASSetPropFlags(): ASSetPropFlадз(обьекг. свойства. маскаТгие, MacKaFalse) где: Х объект - объект или область видимости;

Х свойства - свойства/методы объекта, для которых вы собираетесь изменить флаги защиты. Специальный аргумент null означает все свойства;

Х маскаТгие - целочисленная битовая маска, определяющая флаги конфигурации. Значимыми являются три последних бита целого числа, представляющие (справа налево) флаги защиты от перезаписи, защиты от удаления и скрытия. Например, двоичное значение НО (06 в шестнадцатеричной записи, 6 в десятичной) защищает свойства, заданные вторым параметром, от записи и удаления, но перестает скрывать их при переборе;

Х MacKaFalse - другая целочисленная битовая маска, которая работает аналогично маскеТгие, но сбрасывает заданные флаги. MacKaFalse применяется до применения маскиТгие. На странице FlashCoders Wild ( Flags) имеется диаграмма с описанием различных битовых масок, используемых функцией ASSetPropFlags().

Глава 10. ActionScript Свойства/методы, которые мы хотим сделать видимыми, принадлежат к области видимости _global, содержащей все встроенные классы ActionScript. Таким образом, после выполнения следующей команды все классы ActionScript становятся полностью доступными для перебора: ASSetPropFlags(_global. null. 6. 1): Следующий фрагмент выводит список всех классов, найденных в открытой области видимости:

// Установить флаги защиты в _global равными 110(дв.). // чтобы сделать их доступными для перебора ASSetPropFlags(_global. n u l l. 6. 1);

// Составление списка объектов в _global for (thisObject in _global) { trace(thisObject): } Чтобы узнать, есть ли в этих классах что-нибудь интересное, мы последовательно переберем все их свойства. Если при поиске обнаружится свойство prototype, в котором хранятся методы и свойства класса (в ActionScript 1.0 и 2.0), мы переберем его содержимое:

// Установить флаги защиты в _global равными 110(дв.). // чтобы сделать их доступными для перебора ASSetPropFlags(_global. n u l l. 6. 1);

// Составление списка объектов в _global for (thisObject in _global) { ASSetPropFlags(_global[thisObject]. n u l l. 6. 1);

trace("\n" + thisObject): for (props in _global[thisObject]) { t r a c e r " + props): // Вывод содержимого prototype, i f (props == "prototype") { ASSetPropFlags(_global[thisObject].prototype, n u l l. 6, 1): for (protoChain in _global[thisObject].prototype) { traceC Х " + protoChain):

Если присоединить этот код к кадру 1 и протестировать ролик в Flash MX 2004, он выведет длинный список документированных классов с методами и свойствами (в книге он занял бы около 10 страниц). Далее приведен фрагмент списка для класса String: Srn tig foCaCd rmhroe poo rt constructor pooye rttp sbt usr slt pi sbtig usrn Недокументированные возможности ActionScript slice lastlndexOf indexOf concat charCodeAt charAt toLowerCase toUpperCase toString valueOf _proto constructor Как видите, сначала перечисляются методы и свойства классов, а за ними следуют методы и свойства экземпляров, объединенные в категорию prototype. Попробуем обратиться к методам и свойствам класса из функции traceQ и посмотрим, что они вернут. В следующем примере вызывается метод String.fromCharCode(), получающий один числовой аргумент (мы знаем об этом, поскольку метод fromChar Code является документированным): trace(String.fromCharCode(65));

// Вывод: А Однако в список также входят недокументированные классы: Cookie setCookie getCookie proto_ constructor Нам придется гадать, что представляет элемент списка - свойство или метод, а если метод - с какими параметрами он вызывается. Например, команда trace(Cookie.getCookieO): выводит следующее сообщение: Error opening URL "fi1e:///Сj/WINDOWS/PROFILES/SHAM^20B/ APPLICATIONX20DATA/MACROMEDIA/FLASHX20MXX202004/EN/ CONFIGURATION/Mmfdata/mmfdata3ff9fldf.xml" В сообщении говорится об ошибке открытия конкретного файла, хотя при вызове метода никакое имя не указывалось! Поэтому я попытался создать cookie методом Cookie.setCookie(): Cookie.setCookieC'footest data");

Далее последовал повторный вызов getCookie(): trace(Cooki e.getCooki e()): На этот раз ошибки не было! Напрашивалось логичное предположение, что метод setCookie() успешно сохранил файл, который искал метод getCookieQ. Я нашел файл mmfdata3ff9f1df.xml в каталоге, указанном в сообщении об ошибке, открыл его в текстовом редакторе - и действительно, файл содержал положенный текст: footest data Глава 10. ActionScript Но вызов trace(Cookie.getCookie());

ничего не выводил на панели Output, поэтому я проверил тип возвращаемого значения: trace(typeof Cookie.getCookieO): На панели Output появилась строка object. Значит, метод getCookieQ возвращает объект! Быстрый перебор в цикле for..in дал информацию о свойствах объекта: они совпадали со свойствами класса XML с добавлением еще нескольких свойств. Следующий листинг подтверждает, что объект является экземпляром класса XML (хотя более вероятно - пользовательским субклассом класса XML): Cookie.setCookieC'footest data"): result = Cookie.getCookieO;

trace (typeof result);

trace (result instanceof XML);

for (props in result) { trace(props);

} Декодирование структуры XML для получения исходного текста footest data, переданного при вызове setCookie(), остается читателю для самостоятельной работы. Счастливой охоты!

Итоги Конечно, недокументированные возможности Flash Player не документируются и не имеют официальной поддержки по вполне определенным причинам. Возможно, некоторые из них еще не прошли полноценного тестирования или не были реализованы в полном объеме. Нет гарантий, что недокументированные возможности сохранятся в будущих версиях Flash Player, поэтому пользоваться ими необходимо с осторожностью. Даже если они работают в конкретном браузере и на конкретной платформе, это еще не значит, что они будут работать везде.

ТРЮК Черный ход ASnativeO Каждый вызов метода ActionScript отображается по таблице на одну из внутренних функций, встроенных в Flash Player. Прямой доступ к таблице внутренних функций осуществляется недокументированным методом ASnative().

№ Flash Player поддерживает ряд методов, отсутствующих в API ActionScript. Эти функции не только не документированы, но даже не имеют имен! Они хранятся в таблице функций, а доступ к ним осуществляется по индексам. Недокументированная функция ASnativeO позволяет вызывать внутренние методы ActionScript, в том числе и те, которые не удается найти при помощи функции ASSetPropFlags() (см. трюк 82). Похоже, индексирование осуществляется по таблице с использованием двух индексов: ASnative(<3. Ь);

Нетривиальное применение операторов или в отдельных случаях - с передачей необязательного списка аргументов: ASnative(t3. b){args);

Индекс а - целое число, определяющее класс ActionScript;

индекс Ъ - целое число, определяющее метод класса, a args - один или несколько аргументов, связанных с этим методом. Например, индекс а = 200, соответствует классу Math, поэтому изменение индекса Ь открывает доступ к различным методам класса Math. Попробуйте выполнить следующий фрагмент:

trace(ASnative(200.0)(-4.567): / Вывод: 4 5 7 /.6 trace(ASnative(200.9)(144): / Вывод: 12 / По результатам тестов можно предположить, что ASnative(200,0) соответствует методу Math.abs(), a ASnative(200,9) соответствует методу Math.sqrt(). Все это, конечно, интересно, но зачем использовать малопонятные вызовы ASnativeQ для вызова документированных методов ActionScript? Большинство комбинаций (а, Ь) при вызове ASnativeQ в точности эквивалентны вызовам документированных методов документированных классов. Тем не менее, некоторые индексы не имеют явных аналогов в ActionScript, поэтому их вызов возможен только через черный ход ASnative(). Одним из таких примеров является вызов ASnative(800,&). Похоже, индекс 800 открывает доступ к функциям ввода/вывода, включая недокументированные методы класса Mouse (см. трюк 62).

Итоги Поиск недокументированных возможностей Flash Player до того, как Macromedia сообщит о них, превратился в любимую игру многих пользователей Flash. На странице FlashCoders Wiki ( приводятся подробнейший отчет о текущем состоянии дел, а также дополнительная информация о методе ASnativeQ и его параметрах.

Нетривиальное применение №84 операторов ТРЮК Недокументированные возможности ActionScript Ч не единственная благодатная почва для любопытных программистов. Оказывается, некоторым операторам ActionScript также можно найти нетривиальное применение.

Типичный разработчик решает 90 % своих задач при помощи 10 % возможностей ActionScript. Прочие возможности ActionScript используются очень редко или в крайне специфических ситуациях. Впрочем, некоторые средства ActionScript применяются редко лишь потому, что разработчики не умеют ими правильно пользоваться или не знают, как найти им неочевидные применения. В настоящем разделе описаны альтернативные способы использования некоторых команд и операторов ActionScript.

Глава 10. ActionScript Оператор вычисления остатка Оператор % возвращает остаток от целочисленного деления. Например, выражение 15%6 равно 3, то есть остатку от деления 15 на 6:

trace(15 % б):

/ Вывод: 3 / Для чего это нужно? Так как результат а%Ь никогда не бывает больше Ь, оператор % может использоваться для ограничения значений а интервалом от 0 до Ь. Следующая анимация помогает наглядно представить результат. Присоедините код к первому кадру нового ролика - и увидите, что центральная точка клипа ball никогда не выходит за линию х = 300. Функция clampQ, используемая как обработчик onEnterFrame для клипа ball, вычисляет горизонтальную координату ball по формуле (this._x+speed)%300. Следовательно, ball._x принимает значения из интервала от 0 до 300. function clamp():Void { this._x = (this._x + speed)*300: // Создание клипа ball var ball :MovieClip = this.createEmptyMovieClipC'ball", thi s.getNextHighestDepthC));

ball.lineStyle(20. 0x0. 100);

ball.lineToCO. 1);

ball._x = 0;

ball._y = 200;

// Создание линии t h i s. l i n e S t y l e ( n u l l. 0x0. 100);

this.moveToOOO. 190): this.lineTo(300. 210);

var speed = 4;

// Создание анимации ball.onEnterFrame = clamp;

Оператор % также может применяться для усечения величины до ближайшего числа, кратного заданному. Если х=а%Ь, то прибавление или вычитание х%Ь из х позволяет привести х к целому числу, нацело делящемуся на Ь. Следующие команды выводят 300 и 400 соответственно: х = 350;

trace(x - х$100): // Ближайшее меньшее число, делящееся на 100 traceCx + хЯЮО);

// Ближайшее большее число, делящееся на 100 В следующем примере этот прием используется для реализации перетаскивания мышью с привязкой к координатной сетке. Клип ball следует за мышью и автоматически выравнивается по координате, кратной 30 пикселам: ball.onMouseMove = function О { this._x = _xmouse -_xmouse%size;

this,_y = _ymouse -_ymouse%size: updateAfterEventO: }: size = 30:

} Нетривиальное применение операторов В файле dragger.fla на сайте книги этот код используется для создания набора мозаичных пластинок, которые могут располагаться только в фиксированных позициях вдоль сетки. Запустите пример и попробуйте перетаскивать мышью цветные квадраты - вы увидите, что они привязываются к ближайшему узлу сетки и плотно прилегают друг к другу, как показано в правой части рис. 10.10.

Рис.

10.10. Цветные квадраты автоматически выравниваются по сетке в процессе перетаскивания Возможные области применения выравнивания по сетке: Х Х Х Х головоломки, особенно игры типа л15 и мозаики;

игры жанра action со спрайтовой графикой;

настольные игры;

графические ОС-подобные интерфейсы (сайт выглядит как рабочий стол операционной системы, а для управления используются операции наведения, щелчки и перетаскивание).

Оптимизация интервальных проверок Метод Math.abs() возвращает абсолютное значение (модуль) выражения. Так, Math.abs(5) и Math.abs(-5) равны 5. Операция довольно простая, но на ее базе строится эффективная проверка принадлежности числа к заданному интервалу. Просто сдвиньте интервал так, чтобы его начальная и конечная точки имели одинаковые модули (например, -5 и +5 вместо 0 и 10). Традиционно в проверке верхней и нижней границ для координат. г и г / клипа было задействовано четыре условия. Чтобы сократить количество условий до двух, достаточно сдвинуть начало координат в центр сцены. Для стандартных размеров сцены (550 х 400) минимальное и максимальное значения координаты х равны -275 и 275 соответственно (вместо 0 и 550), а координата у лежит в интервале от -200 до 200 (вместо интервала от 0 до 400).

Глава 10. ActionScript Эффект оптимизации становится очевидным лишь в том случае, если операция должна выполняться действительно быстро, как в следующем примере. Мы устанавливаем таймер с интервалом 1 мс, чтобы Flash воспроизводил анимацию как молено быстрее. Оптимизированная интервальная проверка выделена жирным шрифтом. function animCtarget:MovieClip):Void { i f (Math.abs(target._x)>275) { target.xSpeed = -target.xSpeed;

} i (ahastre.y>0) { f Mt.b(agt_)20 t r e. S e d =- a g t y p e ;

agtype tre.Sed > tre.x+ tre.Sed agt_ = agtxpe;

tre.y+ tre.Sed agt_ = agtype: updateAfterEventO;

} // Создание клипов for (var i = 0: i < 20;

i++) { var ball :MovieClip = this.createEmptyMovieClipC'ball"+i. this.getNextHi ghestDepth());

ball.lineStyle(5. 0x0808AF. 100): ball ineTo(0. 1);

ball.xSpeed = Math.randomO * 10;

ball.ySpeed = Math.randomO * 10;

this["fastAnim"+i] = setlnterval(anim. 1. ball);

} // П л ч н е р з е о э р н о у е и амрв каа vrtm:tig = Saesaeoe a epSrn tg.elMd;

Saesaeoe = "xcFt;

tg.elMd eati" vr sit:ubr = Saewdh a WdhNme tg.it;

vr segtNme = Saehih;

a Hih:ubr tg.egt Saesaeoe = tm: tg.elMd ep // П р м щ н е н ч л к о д н т с е ы в ц н р ееееи ориа цн ет. ti.x = sit/;

hs_ Wdh2 ti.y= segt2 hs_ Hih/;

// Р з е к с е ы амта цн. ti.ietlCneie. 00 1 0 : hs1nSyeudfnd x. 0 ) ti.eiFlOFFF. 10;

hsbgniUxOAF 0) ti.oeo-Wdh s e g t.ti.ieosit. s e g t : hsmvT(sit. Hih) hslnT(Wdh Hih) ti.ieosit. -Hih) ti.ieo-Wdh -Hih) hslnT(Wdh segt. hslnTCsit. segt;

ti.nFl) hsediK;

Статическое изображение на рис. 10.11 не дает нормального представления о происходящем. На современном компьютере точки быстро передвигаются по сцене. При недостаточной частоте обновления монитора многие точки вообще будут незаметны, и вы увидите лишь след, остающийся за ними! На моем компьютере оптимизация интервальной проверки для клипов размером 5 пикселов приводила к ускорению анимации на 15-20%. Прирост скорости существенно зависит от производительности компьютера и сложности графики клипа (помните, что лузким местом по быстродействию обычно является перерисовка экрана, а не код).

Нетривиальное применение операторов Рис. 1 0. 1 1. Демонстрация оптимизированной интервальной проверки В следующем листинге методы Math.minQ и Math.max() отсекают значение переменной по границам интервала. Проверка условий отсутствует, значение просто загоняется в нужный интервал (предполагается, что начало координат не смещалось). Прием хорошо подходит для объектов с ограниченными перемещениями объекта - например, перемещения бегунка вдоль шкалы, но не для объектов, меняющих курс (например, прыгающего мяча). Предотвращение выхода за границу сцены реализуется так: function animCtarget:MovieClip):Void { target._x = Math.max (0. Math.min (target._x + target.xSpeed. 550)): target._y = Math.max (0. Math.min (target._y + target.xSpeed. 400)): updateAfterEventO;

} Или в более общем виде: function clip(input:Number, minVal:Number. maxVal:Number):Number { return Math.max (minVal. Math.min (input. maxVal)): } function anim(target:MovieClip):Void { target._x = clip (target._x + target.xSpeed. 0. 550);

target._y = clip (target._y + target.xSpeed. 0. 400): updateAfterEventO;

Инерционное движение с применением поразрядного сдвига Основной единицей измерения в Flash является твип (1/20 пункта). Flash позволяет определять расстояния в пикселах с точностью до 0,05 пиксела (меньшие Глава 10. ActionScript приращения игнорируются), поэтому вывод пиксела с координатами (10,5;

10,5) вполне допустим. Для вывода графики в позициях с дробными координатами применяется сглаживание. Размывка пиксела создает иллюзию его смещения, хотя схема адресации пикселов в видеоадаптере поддерживает только целочисленные позиции - например, (10;

10). К сожалению, эффект размывки приводит к потере детализации, поэтому графику лучше располагать с целочисленными интервалами. Инерционное движение (см. трюк 39) также входит в арсенал эффектов, часто применяемых в Flash. Однако стандартный алгоритм расчета инерции возвращает дробные значения в пикселах. Например, следующий фрагмент создает хорошо знакомый клип ball и анимирует его, имитируя инерционное движение к позиции мыши: inertia = function ():Void { this._x -= (this._x - _xmouse) / 4;

this._y -= (this._y - _ymouse) / 4;

trace(this._x);

}: // Создание клипа ball var ball :MovieClip = this.createEmptyMovieClipC'ball", this.getNextHi ghestDepth());

ball.lineStyle(20. 0x0. 100);

ball.lineTo(0, 1);

ball.onEnterFrame = inertia;

Ни одно из трассируемых значений (this._x) не является целым числом. Клип может выглядеть размытым, поскольку он позиционируется между границами физических пикселов. Другой типичный пример - добавление эффекта инерции в раскрывающиеся меню и полосы прокрутки часто приводит к утрате четкости текстом и нарушениям при выводе растровых шрифтов. Деление на 4 в предыдущем примере (это произвольное значение было выбрано лишь потому, что оно создает приятный эффект инерции на частоте смены кадров 18 fps, с которой я предпочитаю работать) можно заменить сдвигом вправо на два двоичных разряда: inertia = function():Void { this._x -= (this._x - _xmouse) 2;

this._y -= (this._y - _ymouse) 2;

trace(this._x) };

Операция >>2 означает, что биты операнда сдвигаются на 2 разряда вправо, что 2 эквивалентно целочисленному делению результата на 2, то есть 4. Сдвиг выполняется быстрее стандартного оператора деления ActionScript /, выполняющего вещественно деление. Теперь команда trace{) выводит только целочисленные значения, а анимация становится гораздо более четкой. Предполагается, что контент выравнивается по ближайшему пикселу (View Х Snapping Х Snap to Pixels), а размеры графических объектов кратны размерам пиксела (для этого следует задать целые значения свойств Width и Height на панели свойств).

Импортирование ASC-файлов как формата XML Итоги Как видите, у стандартных операторов ActionScript находится много неочевидных применений, которые часто превосходят типовые решения по компактности или скорости. Помните о них, если быстродействие действительно критично для вашего приложения.

Импортирование ASC-файлов №85 как формата XML ТРЮК Базовая загрузка текстовых файлов может осуществляться методами класса XML. Далее остается лишь разобрать единственный созданный узел XML. Распространенный формат XML применяется для отправки и получения данных от Flash Player. Для загрузки небольших объемов данных (или при отсутствии структурирования) также часто применяется класс LoadVars. Формат XML является фактическим стандартом в веб-дизайне и веб-технологиях, но многие приложения используют собственные форматы данных, не поддерживаемые Flash Player. Загрузка нестандартных данных в Flash обычно производится одним из двух стандартных способов: преобразованием данных в XML или разделением текста амперсандами (для LoadVars). В обоих случаях при обновлении исходных данных форматирование приходится выполнять заново, что снижает эффективность работы и повышает вероятность внесения ошибок во время преобразования. Другой, более эффективный путь - импортирование данных из формате исходного приложения. Настоящий раздел посвящен формату ASC, поддерживаемому многими приложениями.

Формат ASC Файл в формате ASC представляет собой последовательный ASCII-файл, содержащий серию строк с данными, разделенными пробелами. Каждая строка завершается символом новой строки (или другим ограничителем): data data data data data data data data data data data data data data data ASC и его аналоги обычно используются в качестве обобщенного формата, легко загружаемого в любое приложение. Во многих программах трехмерной графики имеются дополнительные модули экспортирования и импортирования ASC-файлов, хотя лишь немногие программы обладают интегрированной поддержкой AS С. ASC-файлы легко редактируются в любом текстовом редакторе: Х файл содержит простые ASCII-данные;

Глава 10. ActionScript Х в данных отсутствуют непечатаемые символы или служебные последовательности (управляющие коды);

Х данные структурируются в табличном виде, легко воспринимаемом человеком. Не путайте формат ASC со специализированным форматом ASC (ActionScript Communications), используемым Flash Communication Server MX. В этом трюке будет использоваться ASC-файл, созданный в 3D Studio Max. Как видно из листинга, он представляет собой простую таблицу данных: Ambient light color: Red= 0.0 Green= 0.0 Blue= 0.0 N m d object: "TorusOl" ae Tri-mesh. Vertices: 100 Faces: 200 Vertex l i s t : Vertex 0: X:-0.4 Y: 0.0 Z:61.1 Vertex 1: X:-0.4 Y:-11.8 Z:57.3 Vertex 98: Vertex 99: Face l i s t : Face 0: Smoothing: Face 1 Smoothing: X:-27.5 X:-33.4 A:0 E 1 A:0 1 Y:19.0 Z:38.5 Z:46. C:10 AB:0 ВС:1 CA:1 :1 BC:1 CA:

Face 198: A:99 B:0 C:9 AB:0 ВС:1 CA:1 Smoothing: 1 Face 199: A:99 B:90 C:0 AB:1 ВС:1 CA:0 Smoothing: 1 Данные определяют трехмерную фигуру - тор (рис. 10.12). Как же загрузить ASC-файл в Flash? Одно из самых простых (хотя и неочевидных) решений заключается в том, чтобы заставить Flash интерпретировать файл как данные в формате XML. Поскольку в действительности файл не содержит XML-кода, Flash считает, что в нем определяется только один узел - строка с полным содержимым файла. Для разбора этой строки используются стандартные строковые функции (вместо функций разбора узлов XML).

Рис. 10.12. Тор в 3D Studio Max Импортирование ASC-файлов как формата XML Импортирование и разбор ASC-файла Функции handlelncomingO и readXMLStartQ в следующем листинге заставляют Flash загрузить ASC-файл как файл в формате XML. Если загрузка проходит успешно, содержимое файла помещается в строку my3dFile. Мы знаем, что каждая строка ASC-файла содержит взаимосвязанные данные и заканчивается символом перевода строки (\п или Key.ENTER в Flash). Чтобы разбить ASC-файл на отдельные строки, мы просто перебираем файл и ищем очередное вхождение \п. Функция String.split() не используется, потому что мы все равно будем перебирать массив в поисках интересующих нас данных. Функция readASCO разделяет ASC-файл на строки и сохраняет их в массиве с именем shape. handleIncoming = function (success) { i f (success) { readXMLstartO: } readXMLstart = function () { my3dFile = xObj.firstChild.nodeValue;

readASCO: }: r a A C = functionО { edS v r o n e : u b r =0 a ldxNme : v r г n e : u b r =0 a IdxNme ;

v r el em: S r n = "";

a tig w i e ( l d x ! -1) { hl rne = r n e = m 3 F l. n e 0 ( \ " olndex): ldx ydieidxf"n. e e = m 3 F l. u s r n ( I d x rlndex);

lm ydiesbtigone. // П о у к е д п л я м е с р к ( л н м н е 3 с м о о ) рпсам оонеы тои диа ее 0 и в л в i ( l m l n t > 30) { f ee.egh s a e s a e l n t ] =e e : hp[hp.egh lm } o n e = r n e +1 ldx ldx ;

} var xObj:XML = new XMLO: var my3dFile:String = n w StringO: e var shape:Array = new ArrayO: xObj.onLoad = handlelncoming;

xObj.load("torus.asc");

Метод String.substring() просматривает содержимое my3dFile и извлекает символы между начальной позицией первого необработанного символа olndex и позицией следующего перевода строки rlndex: rlndex = my3dFile.indexOf("\n". olndex);

elem = my3dFile.substring(oIndex. rlndex): Значение rlndex определяется поиском следующего вхождения \п с использованием метода String.indexOf(). Программа узнает о достижении конца ASC-файла, когда метод String.indexOf() возвращает -1 - признак того, что искомая строка не найдена.

Глава 10. ActionScript Некоторые строки ASC-файла не представляют для нас интереса (например, потому что вместо описаний точек и линий в них содержится другая информация). Прежде чем считать текущую строку действительной, необходимо избавиться от таких строк по некоторому критерию. В нашем случае, если длина строки превышает 30 символов, данные считаются действительными и сохраняются в массиве shape: i f (elem.length > 30) { shape[shape.length] = el em;

} На рис. 10.13 изображены первые 10 элементов массива shape, сгенерированного этой программой. Вскоре из массива будут отфильтрованы все элементы, не содержащие информации о вершинах.

а !Х Х I о t !г ;

!Х Х !" :... ;

..

з 4 E 6 7 g ;

"Ambient itght cofor №ed= 0Л Green= S.S Bbл= O.OV* r r - e h Vertices;

1лS Facess 200\r* ms Vertex D. X--0 4 У 3.S Z:4J.iV 'Vertex is Х -3.4 Yi-114 2s57^,r* /erte> 2:

- :-:.4 У;

-19Л 2;

4?.3\r" |*Verts3<3: X:-0.4 Y:-I9.S 2i34,9\r* 1 "Vertex 4: X;

-0.4 Ys-1141 Z:24.3\r* "Vertex S: X 34 " O.S Ii21.!\r" i "Verts* 6;

X:Q4 Y;

li.S Z:24,9V :-, i*Vertex7: Xi-0.4 Y:19.S Zi343\r' 10.13. Первые 10 элементов массива shape Рис.

Разбор строк в ASC-файле В общем случае требуется сохранить не строку, а содержащиеся в ней данные. Учитывая, что ASC-файл описывает трехмерную фигуру, мы хотим извлечь информацию о координатах вершин. Типичная строка с описанием трехмерной точки выглядит примерно так: Vertex 98: Х:-27.5 Y:19.О Z:38.5 Можно сделать следующие предположения: Х все строки, содержащие информацию о вершинах, имеют длину не менее 30 символов и начинаются с префикса Vertex;

Х внутри строки значению координаты х предшествует подстрока X: (то же для координат у и z). Остается реализовать эти правила на программном уровне. Чтобы узнать, содержит ли текущая строка информацию о вершине, мы проверим, начинается ли она с буквы V: i f (elem.substrings, 1) == "V") { Если условие выполняется, в оставшейся части строки ищутся смещения подстрок X:, Y: и Z: posX = elem.indexOfC'X:". 0);

posY = elem.indexOf("Y:". posX): posZ = elem.indexOfC'Z:". posY);

Импортирование ASC-файлов как формата XML Вообще говоря, в нашем примере эти смещения одинаковы для всех строк, начинающихся со слова Vertex, но выполнение этого условия не гарантировано, поэтому мы ищем начальные позиции данных и не пользуемся никакими предположениями. По найденным смещениям из строки извлекаются координаты х, у и z. Начальное смещение увеличивается на 2, чтобы в подстроку не вошел префикс из буквы и двоеточия:

рХ = Number(elem.slice(posX + 2. posX + 6 ) ) : pY = Number(elem.slice(posY + 2, posY + 6));

pZ = Number(elem.slice(posZ + 2, posZ + 6));

Наконец, точка (х, у, z) создается в виде структурированного объекта Flash. Позднее объект может использоваться в ActionScript для построения трехмерной фигуры (см. трюк 37). В данном случае координаты точки добавляются в виде свойств элемента массива shape (рис. 10.14): shape[sPointer] = n w ObjectO: e shapeCsPoi nter].x = pX;

shape[sPointer].y = pY;

shape[sPointer].z = pZ;

Рис. 10.14. Координаты трехмерных точек в свойствах элементов массива shape Далее приводится полный код извлечения координат точек из ASC-файла, созданного в 3D Studio Max: handleIncoming = function (success) { if (success) { readXMLstartO;

} readXMLstart = function О { my3dFile = xObj.firstChild.nodeValue;

readASC();

}: readASC = functionO { var olndex:Number = 0;

var rlndex:Number = 0;

var elem:String = "": var posX:Number = 0;

var posY:Number = 0: var posZ:Number = 0;

while (rlndex != -1) { 384 rlndex = my3dFile.indexOf("\n". olndex): elem = my3dFile.substring(oIndex. rlndex): i f (elem.length > 30) { i f (elem.substring^. 1) == "V") { posX = elem.indexOfCX:". 0): posY = elem.indexOfC'Y:". posX);

posZ = elem.indexOfC'Z:". posY);

p = Number(elem.slice(posX + 2. posX + 6)) X p = Number(elem.slice(posY + 2. posY + 6)) Y pZ = Number(elem.slice(posZ + 2. posZ + 6)) shape[sPointer] = new ObjectO;

shape[sPointer].x = pX;

shape[sPointer].y = pY: shape[sPointer].z = pZ;

} olndex = rlndex + 1;

Глава 10. ActionScript } } var xObj:XML = new XMLO: var my3dFile:String = new StringO;

var shape:Array = new ArrayO;

var sPointer:Number = 0;

xObj.onLoad = handlelncoming;

xObj.load("torus.asc"): Читатель может ознакомиться с полной версией этого приложения, написанной Эдвином Хейджменом, в разделе Experiments сайта Полная версия строит по точкам интерактивное трехмерное изображение (рис. 10.15).

Рис. 10.15. Описание трехмерной фигуры, импортированное из ASC-файла в Flash Итоги По мере того как Flash завоевывает все большую популярность как универсальная мультимедийная веб-платформа, все чаще возникает задача импортирования данных в SWF из других приложений, в том числе и не связанных с Веб. Даже Импортирование ASC-файлов как формата XML если данные не соответствуют формату XML, для их загрузки можно воспользоваться классом XML (Flash не следит за тем, чтобы файл, интерпретируемый как XML-код, действительно был структурирован в этом формате). Этот прием хорошо подходит для импортирования структурированных текстовых файлов в формате, не поддерживаемом Flash, потому что в распоряжении программиста оказываются многие функциональные средства класса XML, в том числе и выдача события onLoad после завершения загрузки. Низкоуровневый формат ASC особенно упрощает импортирование в SWF данных, не предназначавшихся для Flash (таких, как описания трехмерных фигур или наборы записей баз данных). Это также дает некоторые преимущества по сравнению с преобразованием данных в формат, напрямую поддерживаемый Flash (например, XML). Не старайтесь всегда преобразовывать все данные в XML. Лишние преобразования только усложнят вашу работу при обновлении данных исходным приложением.

Эдвин Хейджмен ГЛАВА Интеграция с браузером Трюки № 86- С первых дней своего существования технология Flash был тесно связана с веббраузерами. Правда, Flash позволяет создавать специальные приложения, использующие Standalone Player для воспроизведения SWF-файлов, и все же большая часть Flash-контента просматривается через веб-браузеры благодаря вездесущему модулю Flash Player (в Internet Explorer для Windows он реализован в форме элемента ActiveX). Как ни странно, отношение многих пользователей к Flash (как хорошее, так и плохое) часто строится на неправильных представлениях. Многие веб-разработчики и пользователи толком не понимают, как Flash работает с браузерами. В этой главе показано, как Flash интегрируется со стандартными средствами браузера (например, кнопкой возврата - см. трюк 94) или поисковыми системами вроде Google. Кроме того, здесь рассматривается оригинальный способ проверки браузерного модуля Flash Player (см. трюк 87). Если Flash Player установлен, он периодически проверяет наличие обновлений на сайте macromedia.com. Как говорится в документации Macromedia Flex Managing Flash Player Auto-Update ( macromedia.com/flex/1/flex_docs/wwhelp/hhwimpl/common/html/wwhelp.htm?context = =Flex_Documentation&file=38_dept42.htm#wp154069), конфигурация автоматического обновления задается в файле mms.cfg в домашнем каталоге пользователя или посредством настройки параметров, о которых пойдет речь далее. Безопасность и конфиденциальность сыграли важную роль в принятии Flash как платформы распространения контента. Большинство разработчиков знают о контекстном меню Flash, вызываемом щелчком правой кнопки мыши (Windows) или щелчком с кнопкой 8 (Мае). Важнейшая команда этого меню, Settings, открывает диалоговое окно параметров Macromedia Flash Player. На вкладках этого окна настраиваются параметры конфиденциальности, локального хранилища, микрофона и камеры. Но лишь немногие разработчики (и еще меньше пользователей) знают о существовании дополнительных параметров Flash Player, настраиваемых только через веб-сайт Macromedia. Пользователи могут вызвать Settings Manager ( settings_manager.html) кнопкой Advanced на вкладке Privacy. На сайте Macromedia Интеграция с браузером пользователь может настроить дополнительные параметры конфиденциальности, хранения данных, безопасности и оповещений об обновлениях. За последние годы с выходом новых версий браузеров для основных операционных систем стандарты браузеров и их взаимная совместимость часто изменялись. Тем не менее, юридические факторы часто возобладают над технологическими. Компания EOLAS (Embedded Objects Linked Across Systems) обладает рядом патентов на воспроизведение содержания в браузере. Возможно, вы слышали о судебном иске, в результате которого Microsoft было запрещено автоматически запускать свою реализацию Flash Player в виде элемента ActiveX из Internet Explorer. На момент написания книги Microsoft выиграла фазу предварительных переговоров по объявлению патента недействительным, но судебный процесс еще идет. Последние новости по этому поводу от EOLAS можно найти по адресу Поиск по ключевому слову EOLAS на сайте даст новую информацию о недавних слушаниях по поводу Internet Explorer от Microsoft. Последствия этой тяжбы для программистов Flash и других мультимедийных платформ обсуждаются по адресу Пока неизвестно, останется ли победа за Microsoft - вероятно, так оно и произойдет. Но даже если выиграет EOLAS, мы разработали возможное обходное решение (хотя здесь оно и не реализовано). Темой патентной заявки являются модули, плотно интегрированные с браузером. Когда на странице обнаруживаются теги и , требующие загрузки внешнего содержания (например, SWF), процесс загрузки Flash Player в основном прозрачен для пользователя и разработчика. Если патент EOLAS будет подтвержден, a Microsoft не купит лицензию на него, Microsoft будет запрещено напрямую загружать модуль Flash Player в Internet Explorer. Возможное решение - загрузка внешнего содержания с использованием немодульных технологий (например, JavaScript). Впрочем, ради удобства и здравого смысла будем надеяться, что до этого все же не дойдет. Конечно, область применения Flash Player не ограничивается веб-браузерами. Существуют версии Flash Player для PocketPC, для сотовых телефонов, а также специализированные версии для ряда других устройств (см. com/devnet/devices). Учтите, что версия Flash Player, поддерживаемая большинством мобильных или автономных устройств, отстает от последней версии Flash Player для веб-браузеров настольных систем. Большинство версий Flash Player для других устройств поддерживает функциональность Flash 4, 5 или 6, тогда как последней версией Flash Player для Macintosh и Windows является Flash Player 7.. Исходные тексты среды разработки Flash закрыты, но формат SWF является открытым. Независимые разработчики могут получить бесплатную лицензию на файловый формат Flash SWF (за дополнительной информацией обращайтесь по адресам и open/licensing). Неудивительно, что многие программы сторонних разработчиков воспроизводят SWF-файлы в нестандартных условиях или позволяют генерировать SWF без применения среды разработки Flash (см. трюк 29).

388 ТРЮК Глава 11. Интеграция с браузером Решение проблем совместимости Стандартный процесс построения Flash-сайта не обеспечивает максимального уровня совместимости. Проблема решается внесением небольших изменений в HTML.

№ По данным W3Schools ( более 80% пользователей Веб использует Internet Explorer (версии 5 и выше). В то же время, проведенный Macromedia опрос показал, что у более 93 % пользователей установлен Flash Player 6 или более поздней версии ( com/software/player_census/flashplayer/version_penetration.html). Но несмотря на это мы должны как можно корректнее обходиться с пользователями, работающими в разных конфигурациях. Пользователи с претензиями гораздо заметнее пользователей без претензий. А это значит, что ничтожное меньшинство посетителей сайта (скажем, 5%), которым без всякой причины было отказано в доступе, могут выдавать 100% отзывов о работе сайте (причем все отзывы будут негативными). В реальной жизни один недовольный клиент редко компенсируется одним довольным клиентом, а уровень недовольства выше двухтрех процентов отпугивает многих заказчиков. Следите за текущей статистикой пользователей Веб. Например, W3Schools ( /www.w3schools.com/browsers/browsers_stats.asp) публикует ежемесячную статистику по использованию браузеров, а thecounter.com ( stats) собирает аналогичную статистику по огромному количеству своих ежедневных посетителей (чтобы получить распределение по типам браузеров, щелкните на названии месяца, а затем - на ссылке Browsers в правой части вебстраницы). Помните, что статистика не дает должного представления о количестве жалоб от пользователей, не сумевших попасть на ваш сайт.

Проверка поддержки Flash Наилучшие впечатления от использования сайта достигаются в том случае, если сайт распознает ресурсы, доступные на компьютере пользователя, и выводит контент, адаптированный для этой системы (или сообщает пользователю, что необходимо для полноценного просмотра). Едва ли не каждый разработчик, занимавшийся этой задачей, разработал собственный метод для проверки поддержки Flash. Вот лишь некоторые наиболее популярные средства: Х Х Х Fpi (Flash Plugin Inspector) Колина Мука - detection/moockfpi;

Web Monkey, Detecting Plugins - 40/index3a.html?tw=programming;

O'Reilly WebDev Center - 20/plugin_detection.html.

В трюке 87 описан бесплатный анализатор модуля Flash, реализованный на JavaScript.

Решение проблем совместимости Тестирование в различных браузерах Вопреки некоторым сообщениям, в одной системе можно установить несколько разных браузеров и даже запускать их одновременно. Например, на моем компьютере установлены Internet Explorer, Netscape Navigator, Opera и Mozilla (рис. 11.1).

mozilla Рис. 1 1. 1. Система Windows XP с несколькими одновременно работающими браузерами (слева направо): Internet Explorer, Netscape Navigator, Opera (бесплатная версия) и Mozilla Проблема, чаще всего возникающая при установке нескольких браузеров на один компьютер, связана с борьбой за звание браузера по умолчанию. Выберите пользовательский вариант установки, отключите режим использования браузера по умолчанию - и все должно быть нормально. Также присмотритесь к дополнительным компонентам, которые часто пытаются устанавливать новые браузеры. Обычно при установке рекомендуется отключать все компоненты, кроме базового браузера, если только вы не хотите заодно сменить почтовый клиент, интернет-пейджер и проигрыватель МРЗ. Netscape Navigator особенно усердствует в этом отношении, поэтому при его установке всегда отдавайте предпочтение выборочному варианту установки. Также остерегайтесь автоматизированных обновлений Internet Explorer, которые могут, скажем, заодно обновить Windows Media Player. Наличие нескольких браузеров является обязательным требованием для всех веб-дизайнеров, но оно особенно важно для Flash-сайтов, потому что вы должны проверить, что случится при отсутствии правильной) модуля. Лично я всегда слежу за тем, чтобы по крайней мере в одном браузере из тестового набора модуль Flash Player отсутствовал, а в большинстве браузеров была установлена самая распространенная версия Flash Player, которая не всегда совпадает с последней. По этой причине на моих компьютерах чаще устанавливается Flash Player 6, потому что на момент написания книги (июнь 2004 года) Flash Player еще не получил повсеместного распространения. Бесплатное приложение Flash Plugin Switcher позволяет легко и быстро сменить версию модуля Flash Player в некоторых браузерах (см. трюк 88). В Интернете Глава 11. Интеграция с браузером также можно найти старые версии модулей Flash, позволяющие легко переключиться на нужную версию Flash Player для Windows/Mac. Версии Flash Player существуют и для других операционных систем, включая Linux и OS/2. Их можно найти на странице download/alternates. Также стоит упомянуть и о таком полезном браузере, как Any Browser. Эта утилита эмулирует предельно упрощенный, минимальный браузер (HTML 3.2 с поддержкой таблиц, но без поддержки Flash и JavaScript). Хотя AnyBrowser не позволяет отображать содержание Flash, это хороший инструмент для тестирования худшего случая (отсутствие поддержки Flash). Если веб-страница способна сообщить пользователю о возникших проблемах и подсказать действия, которые нужно выполнить в браузере, вы идете по правильному пути! Если вас заинтересует AnyBrowser, щелкните на ссылке Site Viewer на сайте /www.anybrowser.com и найдите ссылку.

Проверка совместимости с поисковыми системами На сайте AnyBrowser также размещена полезная утилита, при помощи которой можно узнать, как ваш сайт будет восприниматься автоматическими сборщиками информации поисковых систем. Откройте главную страницу AnyBrowser и щелкните на ссылке Engine View. Простейший способ включения текста, читаемого поисковыми системами, - размещение его в поле комментария тега