05 декабря 2008

Визуальные объекты

Flash технология поддерживает ряд встроенных визуальных объектов, но количество разновидностей ограничено, поэтому в большинстве случаев нужные элементы, например Graphics User Interface, создаются путем комбинирования нескольких "стандартный" объектов. Все стандартные объекты определяются в DefineXXX. К основным визуальным объектам можно отнести: Фигура (Shape), Морфируемая фигура (MorphShape), Статический Текст (Static Text), Динамический текст (Dynamic Text), Кнопка (Button), Видео (Video) и Спрайт (Sprite).


Обратите внимание, что нет объекта Изображение (Image). Чтобы отобразить изображение его необходимо использовать в качестве заливки для прямоугольной фигуры.


Уникальный идентификатор CharacterID


Каждый визуальный объект имеет свой уникальный CharacterID – число типа word , т.е. значение в диапазоне 0..$FFFF. Если вы самостоятельно создаете объекты, то должны позаботится о его уникальности. Уникальность необходима для того, чтобы плеер однозначно понимал какой объект использовать при обработке tagPlaceObject.


Когда необходимо «склеить» несколько SWF, то первая задача состоит в том, что необходимо обеспечить уникальность этих CharacterID, в противном случае некоторые объекты просто не будут отображаться. Для этого необходимо переопределить все значения в одной из SWF путем изменения значений на заведомо незанятое значение.


Имена объектов


Как я отмечал ранее, имя назначается экземпляру объекта в tagPlaceObject при этом указание CharacterID обязательно. Можно создать несколько экземпляров одного объекта с разными именами. Опять таки, при склеивании двух SWF необходимо обеспечить уникальность имен. Имена как правило используются в ActionScript для управления этими экземплярами, поэтому в случае переименования объектов необходимо сделать соответствующие корректировки в ActionScript.

16 ноября 2008

Кадр, сцена или список отображения

Как я отмечал ранее, отображение происходит когда в SWF встречается тэг ShowFrame. Для того, чтобы отобразить какой либо визуальный объект его сперва нужно описать (тэги с названиями DefineXXX), а затем поместить на нужную глубину при помощи тэгов PlaceObject. Размещать объект можно многократно, таким образом получается эффект клонирования. В зависимости от параметров тэга PlaceObject экземпляры (instance) визуального объекта могут выглядеть совершенно по разному. Отображаются экземпляры, до тех пор, пока не будут принудительно удалены тэгом RemoveObject. Это позволяет определять, размещать и удалять экземпляры объектов в разных кадрах.



Глядя на эту схему можно ответить на вопрос, какие объекты отображаются в определенном кадре - нужно составить список из всех PlaceObject, которые были до текущего кадра и убрать из этого списка те, какие были удалены тэгом RemoveObject. Нужно также учесть, что PlaceObject может иметь флаг PlaceFlagMove который указывает что занятую глубину нужно очистить, т.е. это аналог RemoveObject в одном тэге.


Обзор PlaceObject

Основной тэг, который используется при указании какой объект, где и как должен отображаться. По мере развития SWF формата в этот тэг добавлялись дополнительные параметры и сейчас существует три "редакции": tagPlaceObject, tagPlaceObject2 и tagPlaceObject3.


Основные параметры:


  • Depth - глубина, на которую помещается объект. Чем больше значение, тем «выше» изображение. Поскольку для этого параметра отводится 2 байта, то максимальное значение 65535. Для корректного отображение на глубине не должно быть других объектов, в противном случае нужно установить флаг PlaceFlagMove в true.
  • CharacterId - Идентификатор существующего объекта.
  • Name - имя экземпляра объекта. Имя может использоваться в ActionScript для программирования анимации и интерактивности.
  • Matrix - группа параметров для геометрической трансформации. Сюда входят TranslateX и TranslateY для указания положения (ноль в левом верхнем углу), ScaleX и ScaleY для уменьшения или увеличения, SkewX и SkewY для скоса и поворотов.
  • ColorTransform - группа параметров для цветовой трансформации. Сюда входят addR, addG, addB и addA для изменения цветовых составляющих путем добавления заданных величин, multR, multG, multB и multA для изменения цветовых составляющих путем умножения на заданные величины.

Устанавливая разные параметры в разных кадрах мы получаем анимацию. Например, изменяя значения Translate создается движение. Изменяя addA или multA создается эффект появления или исчезновения.

29 октября 2008

Временная диаграмма (TimeLine)

Flash-player воспроизводит SWF по кадрам. Это происходит когда flash-player встречает tagShowFrame, т.е. ни какие изменения в отображении нельзя увидеть пока не будет этого тэга. Частота отображения задается в заголовке файла величиной FPS. Умножив количество кадров на значение FPS можно вычислить длительность проигрывания swf.


Это в теории, но на практике все намного сложнее и вот почему.


Дело в том, что SWF может быть не простым фильмом, а сложным логическим сценарием с элементами интерактивности. Переход от кадра к кадру может происходить в произвольной последовательности, в том числе с остановкой на кадрах с целью ожидания реакции пользователя. Фактически, такие SWF являются вэб-приложениями.

Кроме того, в movie можно использовать специальные объекты Спрайты (Sprite), в терминологии Flash IDE их называют MovieClip. Спрайты имеют такую же структуру как SWF (набор тэгов) и свою временную диаграмму. Так вот, встречаются SWF с одним кадром в SWF, где вся анимация происходит в спрайтах.


И на последок. Иногда flash-плеер не успевает подготовить кадр для отображения. Как правило, это происходит когда в кадре выполнятся трансформация изображений или присутствуют многочисленные наложения масок друг на друга. В этих случаях обновления происходят заметно реже, чем указано в FPS.


Вывод. В большинстве случаев НЕЛЬЗЯ определить длительность SWF. В большинстве случаев НЕЛЬЗЯ перемотать SWF, например на 3-ий кадр, если вы не знаете структуру и сценарий movie. В большинстве случаев НЕЛЬЗЯ узнать, закончился ли проигрыватся SWF, поскольку "дейстивие" может происходить не в основной временной диаграмме, а в спрайтах.

08 октября 2008

Вступление. Структура SWF.

Думаю, что каждый был в неловкой ситуации, когда вам задают "неправильный" вопрос из-за того, что задающий не в теме вопроса. В такой ситуации не поймешь, с чего начинать отвечать, поэтому я начну... с самого начала.

Вступление

Когда мы говорим Flash, то можем подразумевать совершенно разные вещи даже в рамках терминов web-технологии. Чтобы не было путаницы, я буду использовать: 

  • Flash – технология web-анимации в целом;
  • Flash player – программа, библиотека ActiveX которая выполняет отображение flash;
  • Standalone Flash player – приложение (exe-файл), отображающее flash;
  • Flash IDE, Adobe Flash, Flash Professional – среда разработки, предоставляемая фирмой Adobe (ранее Macromedia);
  • FLA – проектный файл (исходный) анимации для Flash IDE;
  • Movie, мувик – цельная сущность web-анимации на этапе разработки;
  • SWF – непосредственно конечный файл анимации.

И так, когда мы открываем web-страницу, на которой находится flash анимация, в упрощенном варианте происходит следующее: интернет-браузер в html разметке обнаруживает вставку flash-анимации, создает объект flash-плеера и указывает ему какой файл нужно отобразить. Flash-плеер выполняет загрузку swf, и, если это возможно, начинает его отображать. Благодаря такому принципу работы flash-плеер может отображать так называемые прелоадеры (preloaders), воспроизводить потоковый звук и видео (как, например, YouTube) без полной загрузки самого swf.

Структура SWF

Формат файла описан в документе SWF File format specification, который можно загрузить с сайта Adobe.com. Обычно документация опаздывает от выхода новых версий flash-плееров до полугода. На момент написания данного текста уже выпущен 10-ый flash-player, но файл спецификации не обновлен и содержит описание только 9-ой версии. Почти про все, что я здесь буду писать, можно найти спецификации, но в том то и дело, что "почти все" :)

Базовая структура SWF не зависит от версии, поэтому SWF всегда имеет структуру Header + Body. Body в свою очередь состоит из записей, которые в терминологии спецификации называют тэгами (tags).


Для описания структуры данных я буду использовать синтаксис Object Pascal.

Header

Заголовок содержит основную информацию о SWF и ее можно описать так: 
TSWFHeader = packed record
  SIGN: array [0..2] of AnsiChar;
  Version: byte;
  FileSize: LongWord;
  MovieRect: TRect;
  FPS: word;
  FramesCount: word;
 end;

  • Первым параметром идет сигнатура SIGN. Значение CWS указывает, что данный файл упакован ZLib-компрессией, а FWS - нет.
  • Version – версия формата файла.
  • FileSize – размер в байтах НЕСЖАТОГО файла.
  • MovieRect – размер изображения на экране в твипсах (1px = 20twips). Учитывая эти единицы нужно отметить, что, фактически, SWF и графические объекты не могут быть больше, чем $ffff / 20 = 3276 px. 
    Я не встречал swf, в которых top-left значения больше или меньше 0, но задав эти значения в своих тестах убедился, что эти значения таки учитываются. 
    Стоит отметить, что указанный прямоугольник является «посадочным местом» которое отводится в браузерах. Если открыть swf в Standalone-плеере, то иногда можно увидеть "декорации за кадром".
  • FPS (frames per second) – значение в формате 8.8 fixed, т.е. для человеческого восприятия это значение Result := FPS shr 8 + (FPS and $FF) / ($FF+1);
  • FramesCount – количество кадров. Как правило, минимум один кадр всегда есть, но можно делать swf и без кадров, если этот файл служит как библиотека для других swf.

Компрессия в SWF

Для уменьшения размера файла Macromedia применила два подхода.
Первый заключается в том, что для сохранения чисел используется побитовая упаковка. Выглядит это примерно так. Допустим, нам нужно сохранить размер прямоугольника, т.е. четыре числа типа integer. При простой записи это будет 4 * 4 байта = 16 байт. При записи в swf в первые 5 бит записывается число бит, необходимое для кодирования самого большого значения, а затем эти 4 значения в битовом представлении с указанной длиной бит. Например, нужно сохранить координаты (0, 0 - 100, 100) в переводе на твипсы (0, 0 - 2000, 2000). В битовом представлении число 2000 = 11111010000 (11 бит + 1 для знака). Выходит (5 + 4 * 12) / 8 = 7 байт, что меньше почти в двое. 
Такой подход приводит к тому, что некоторые одинаковые тэги могут иметь разный размер. Это также относится и к Header.

Второй подход - это использование ZLib компрессии как в целом для всего swf, так и для отдельных тэгов. 

Когда файл компрессированный, то первые три параметра Header-а (это 8 байт) не упакованы, а остальные упакованы и это объясняет, почему нельзя одним методом Read считать только заголовок swf.