вторник, декабря 23, 2008

Сокеты, политика безопасности и SmartFox

Наконец-то я вплотную столкнулся с вопросом безопасности.
А собственно, когда настало время выложить многопользовательскую игру под SmartFox, я столкнулся со следующей проблемой: игра лежит на некотором доменном имени (somegame.ru). Сокетное соединение к SmartFoxServer (XX.XX.XX.XX:9339) просто не проходит:
"Ошибка: Запрос ресурса на xmlsocket://XX.XX.XX.XX:9339 источника запроса из h_ttp://somegame.ru.../Name.swf отклонен из-за отсутствия разрешений в файле политики."
"*** Нарушение безопасности изолированной среды *** Подключение к XX.XX.XX.XX:9339 прервано – нет разрешения от h_ttp://somegame.ru.../Name.swf".
Причем, при локальном запуске всё работает превосходно.

Долго я рыл статьи, форумы по кроссдоменным проблемам, особенности политики безопасности сокетных соединений, нашел много полезного:
External data not accessible outside a Flash movie's domain - общепознавательная статейка.
Про crossdomain.xml и как продолжение -
Security policy. Error #2044: Unhandled securityError:. text=Error #2048: Security sandbox violation. Поисследовал данные вопросы, ознакомился со статьей -
Setting up a socket policy file server.
Затем не обнаружив ничего подходящего, поискал аналогичные вопросы на ресурсе SmartFox:
bluebox problem, donot connect - имеют косвенное отношение к проблеме, но могут пригодиться.
Troubleshooting common runtime problems дает общее представление о проблемах связи и наводит на главную статью по теме:

Flash Security Policy guidelines.
После поверхностного ознакомления со статьей, у меня сразу закралось подозрение - я проверил файл конфигурации config.xml и в секции
PolicyAllowedDomains конечно же не обнаружил записи AllowedDomain, соответствующей нужного мне домена. Админы, включили какие угодно домены, но только не тот который мне был нужен.
Прописываем нужный домен, рестартуем сервер и мгновенно получаем соединение.
Проблема, к счастью, является простейшей. Получаем урок: прежде чем отчаиваться и глубоко вкапываться в интернет и документацию, хорошо для начала просто еще раз проверить конфигурацию сервера.

среда, декабря 17, 2008

Настройка стиля предзагрузчика Flex-приложения

Как-то я уже сталкивался с подобной задачей: Делаем прелоадер для Flex-приложения. Продолжение. AS3.
Сегодня мне просто нужно изменить стиль предзагрузчика - изменить цвет фона и панельки. Ничего дополнительно скриптовать просто не требуется.

Начнем с цвета фона - тут всё просто: В инете невооруженным взглядом по первой ссылке находим: Изменение цвета прелоадера flex приложения.
Ключевая строка: "на вкладке Flex Compiler дописать строку “-default-background-color #336699″ в Additional compiler arguments."

Хорошо бы теперь изменить внешний вид панельки. Точнее - хотя бы просто убрать надпись "Loading".
Поиски приводят нас в классу DownloadProgressBar. Собственно, в нем и находится всё управление нашей панелькой.
Ищем дальше. Это же наш старый знакомый! А настраивается он элементарно: всего в два действия. Или более углубленно: How to customize the standard Flex 2 loader.
Пробуем:

package display
{
import mx.preloaders.DownloadProgressBar;

public class CustomDownloadProgressBar extends DownloadProgressBar
{
public function CustomDownloadProgressBar()
{ super();
initializingLabel="Инициализация";
downloadingLabel="Загрузка";
}
}
}

* * *

<mx:application
preloader="display.CustomDownloadProgressBar"
>
. . .


Таким образом, мы заменили надписи меток.

Однако, скрыть совсем метку, используя showLabel=false; не получается. Так же не оказывают никакого влияния и все остальные параметры. Они корректно трейсятся, но не их изменение не влияет на внешний вид. По-видимому эти параметры задействуются в других случаях.

А вот MINIMUM_DISPLAY_TIME работает забавно - можно подольше подержать панель прелоадера на экране. Для тестов удобно. До этого, я перетаскивал во Flash CS и делал Simulate Download.

В общем, своей цели мы добились. На крайняк, можно просто установить initializingLabel=""; downloadingLabel="";. Кстати, извратиться и задать надписи с использованием HTML-разметки не получилось (строка выводится как есть).

вторник, декабря 16, 2008

Проблема отображения кириллицы в поле ввода при wmode="transparent"

Столкнулся со старинной проблемой Flash - Невозможность ввода кириллического текста при прозрачном фоне flash-объекта (wmode="transparent").

Пошуршав в Гугле, я выяснил:
Баг очень старый, решения его нет.
Или решения его достаточно сомнительны:
Ре-маппинг и хаки
Коррекция полученного от клавиатуры символа


В Adobe JIRA следующие упоминания этой проблемы:
Да что тут перечислять... Вот.

Кривые Безье. Подбираем движок. AS3

Передо мной стоит прозаичная задача - мини-редактор с использованием кривых Безье. Есть некая фигура, состоящая из кривых. Необходимо ее редактировать, путем изменении положения опорных точек.

Итак, прежде чем обратиться к таким авторитетным проектам как http://bezier.ru/, интересно было бы прогуляться по гуглу и посмотреть, что еще предлагают по этой теме.

Один из первых попавшихся - блог Paul Tondeur и его изыскания на эту тему: Drawing a cubic bezier curve using ActionScript3. Здесь можно ознакомиться с теоретической частью и изучить примерчик.

Дальше, получаем интересную статейку ссылкой с Drawlogic.com на labs.zeh.com.br: The search for the perfect bezier tweening syntax. Поиск решения создания пути перемещения при помощи кривых Безье. Особенно понравился пример с использованием Papervision3D - задается путь движения между фигурами.

Далее: Singularity представляет черезчур заумные классы с кучей примеров: Demos. Статья с описанием: AS 3 Parametric Curve Library.

Еще одна хорошая ссылочка: некий Cartogrammar представляет весьма доступный и очень простой в использовании класс CubicBezier.as. Здесь всего два статических метода, которые отрисовывают кривые разными способами. Кстати, очень даже заслуживает внимания. Пока ходил по ссылкам, натолкнулся на забавную демку как раз с использованием этого класса: AS3 Bezier blobs/metaballs

Интересный набор библиотек на Greensock: TweenLite, TweenMax, TweenFilterLite, TransformManager (AS3), TweenGroup. Не относится к кривым Безье (точнее их использует в некоторых случаях), но заставляет обратить на себя внимание.

Небольшое решение, которое может быть полезным: CurveToArray (AS3 class). На основании трех точек кривой Безье, выдает массив координат точек кривой.

Еще немного русскоязычного: Движение по кривой Безье.

А вот некий Flashgamer советует задвинуть "a couple good resources" и взяться все же за Degrafa. Ввиду "крупности" этого движка, оставим его на десерт.

Поглядим, таки, что нам предлагает наш http://bezier.ru/. Здесь множество документации на русском (что важно), обзорная демка и исходники. Скачать исходники можно при помощи SVN-клиента. - делаем СheckОut. Исходники по большей части представляют собой примеры использования, что конечно радует. В принципе писать тут нечего - сайт полон информации на русском, и если что, здесь же можно написать комментарий и получить ответ от хозяев. Надо просто попробовать.
Создаем проект AS3 в FD, кладем в него примеры, прописываем пути к библиотеке и компилируем. Ошибка: "Bezier.as(1488): col: 12 Error: Недопустимое присваивание переменной, которая определена как константа." Ну что ж делать, бывает. В строке "const limiter : Number = 20;" Меняем "const" на "var" и наслаждаемся демкой.
Кстати, исходный код просто перегружен ASDoc-комментариями (что, безусловно, является достоинством). Однако, ни на сайте, ни на Google Code я не смог найти ASDoc-документации Bezier. Странно...

Перейдем к Degrafa. Скачать ее можно на Google Code, но я, пожалуй, воспользуюсь SVN. Пришлось здорово повозиться, чтобы запустить примеры.
При использовании исходников, я вообще не смог избавиться от ошибок - что я не делал - везде вставала проблема некорректных namespace.
При использовании SWC, пример тоже выдавал кучу ошибок. Загвозка была в том, что в примерах указан namespace xmlns:degrafa="http://www.degrafa.com/2008", а нужно xmlns:degrafa="http://www.degrafa.com/2007".
Вывод по Degrafa - мощная и популярная система, но требует углубленного изучения.

Итак, вывод. Для себя я избрал три варианта:

  1. CubicBezier.as.
  2. Bezier.ru.
  3. Degrafa.

CubicBezier - вполне работоспособный, примитивный движок позволяющий рисовать кривые Безье с различными параметрами. Его можно сразу использовать "как есть", либо с необходимыми модификациями, которые внести совсем не сложно. Предварительного изучения не требует, для моей задачи подходит "на ура".
Bezier - Требует предварительного изучения, зато предоставляет широкий набор возможностей для решения большинства практических задач, связанных с кривыми Безье.
Degrafa - Мощный комплекс, позволяющий создавать графику декларативно, при помощи MXML. Для того, чтобы приступить к решению задачи, придется изрядно почитать документацию, которая имеется в изобилии, в формате ASDoc. За изучение есть смысл взяться, т.к. проект весьма перспективный и популяризирующийся. Однако, как всегда, под конец года времени нет, поэтому придется отложить. Но не надолго - ощутив вкус прелестей Degrafa, уже не хочется от него отказываться.

понедельник, ноября 17, 2008

Модульность Flex-приложения

Интересный вопрос был поднят недавно: Модульность приложения и размер swf. Ключевая фраза: "бред, закачивать классы, которые уже закачаны."
Тему раскрывает kuril:
"Все просто, сначала компилируется главное приложение с параметром - link-report=report.xml потом каждый модуль с параметром -load-externs=report.xml Таким образом классы которые уже имеются в главном приложении, не будут включены в модуль. http://livedocs.adobe.com/flex/3/html/help.html?content=modular_4.html"

вторник, ноября 04, 2008

Embed MovieClip не всегда дает MovieClip. AS3

Столкнулся с любопытной ситуацией (компиляция осуществляется Flex SDK 3, FlashDevelop):
Создаю клип в один фрейм. Объявляю его в Linkage как Base class = "flash.display.MovieClip".
Внедряю в код:
[Embed(source="Assets/screens.swf", symbol="SIntroScreen")]
public static var INTRO_CLASS:Class;

Пытаюсь работать с ним как с MovieClip:
var test:MovieClip = new Embeds.INTRO_CLASS();
Получаю исключение: "Type Coercion failed ..." Позвольте, позвольте!
Смотрим, что говорит нам describeType:
var test:DisplayObject = new Embeds.INTRO_CLASS();
trace(describeType(test));

А говорит он вот что (опускаю излишние подробности и заменяю треугольные скобки на квадратные):
[type name="classes::Embeds_INTRO_CLASS" base="mx.core::SpriteAsset" isDynamic="false" isFinal="false" isStatic="false"]
[extendsClass type="mx.core::SpriteAsset"/]
[extendsClass type="mx.core::FlexSprite"/]
[extendsClass type="flash.display::Sprite"/]
[extendsClass type="flash.display::DisplayObjectContainer"/]
[extendsClass type="flash.display::InteractiveObject"/]
[extendsClass type="flash.display::DisplayObject"/]
[extendsClass type="flash.events::EventDispatcher"/]
[extendsClass type="Object"/]
...

Так значит, при компиляции, однофреймовые MovieClip-ы без моего согласия (а может быть, согласно какому-то параметру по умолчанию), урезаются до Sprite-ов.
И верно, добавив еще один фрейм и скомпилировав, получаем:
[type name="classes::Embeds_INTRO_CLASS" base="mx.core::MovieClipAsset" isDynamic="false" isFinal="false" isStatic="false"]
[extendsClass type="mx.core::MovieClipAsset"/]
[extendsClass type="mx.core::FlexMovieClip"/]
[extendsClass type="flash.display::MovieClip"/]
[extendsClass type="flash.display::Sprite"/]
[extendsClass type="flash.display::DisplayObjectContainer"/]
[extendsClass type="flash.display::InteractiveObject"/]
[extendsClass type="flash.display::DisplayObject"/]
[extendsClass type="flash.events::EventDispatcher"/]
[extendsClass type="Object"/]
...

Вот такие чудеса творит оптимизация. В принципе, разумно конечно. Но только если знать про наличие такой фичи. В ином случае (как раз моем), добавочное время на разбор подводных камней обеспечено.

четверг, октября 30, 2008

Дублируем DisplayObject. AS3

Как известно, дублировать как в AS2 клипы уже нельзя - нет такого метода. Странно конечно, и зря. В шаблонной структуре приложения это было бы очень полезно.

Но в AS3 есть множество средств, которыми можно это сделать. Для начала, порыщем в Google.

Duplicate Movie Clip Action Script 3 (взято у Senocular, в котором есть этот исходник).
Этот метод уже стал классикой, судя по тому, как много на него ссылается блогов и форумов. Он также описан на Flashere. Идея такова: извлекается класс исходного дисплей-объекта var targetClass:Class = Object(target).constructor;, инстанцируется, и в него переносятся основные свойства исходного дисплей-объекта.

as3 duplicate DisplayObject. Здесь класс исходного дисплей-объекта получается аналогичным образом. Отличие лишь в том, что передаваемые свойства автоматически извлекаются посредством рефлексии - метода describeType.

Creating Class Instances from a DisplayObject in AS3. Здесь имя класса получается более хитрым способом - из строки, возвращаемой getQualifiedClassName. Затем, getDefinitionByName возвращает класс исходного дисплей-объекта.

Других, более вменяемых способов решения я пока не нашел. Почему "более вменяемых"? Да потому, что все эти способы имеют одно очень существенное ограничение. Они не дублируют произвольный дисплей-объект. То есть дублируемый объект должен обязательно иметь обозначенное в Linkage имя класса. Если мы протрейсим имя класса произвольного клипа, это будет MovieClip или SimpleButton, а инстанцируя их, мы получаем просто пустые клипы.

Таким образом, дублировать клип вышеперечисленными способами нельзя если клип не имеет имени класса в Linkage.
Это еще полбеды. Ведь мы всегда можем просто взять, да и указать это имя.
Но.
А если мы внедряем в наше приложение некий клип при помощи [Embed] , который в дальнейшем надо распарсить и что-то в нем дублировать?
Это что-то мы никогда не сможем дублировать, т.к. никакие Linkage-классы из внедряемой библиотеки не распознаются - они не переносятся в ApplicationDomain.

Кстати, интересное замечание по второму способу с рефлексией: describeType для объектов из внедряемой библиотеки выдает тэги описания свойств как "accessor", в то время как для объектов из подгруженной библиотеки - "variable".

Итак, вывод - универсального решения нет, и выход один - всё делать "ручками". Или я ошибаюсь?

* * *

Спасение пришло с другой стороны: Включение файлов в SWF в виде байтовой последовательности. Проблема внедряемых файлов будет устранена, остальное, в принципе решаемо.

* * *

Да, интуиция поискать по запросу loadBytes не подвела. Внедрил SWF вышеуказанным способом, загрузил через Loader.loadBytes. Отлично! Даже фреймовые скрипты работают. Всё как обычный Loader.load.

Единственная оговорка: Я загружаю классы в ApplicationDomain.currentDomain. При этом, параметр checkPolicyFile необходимо установить в false:
var context:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);

Еще раз спасибо Garbage Collector. Глядя на дату спасительного поста, я понимаю, что здорово отстаю :(.

среда, октября 29, 2008

Снимаем сливки с FlashGamm

Мы, кто поленился/не смог/не захотел поехать в Киев на Flash Game Meeting, грыз ногти и рвал волосы на голове от сознания собственного бессилия, затаив черную зависть, рассматривал отчеты и фотки с довольными и улыбающимися лицами, и выжидал, выжидал сглатывая слюну, когда же наконец поступит информация не про невообразимые впечатления, чудесную организацию и респекты, а про Flash, деньги и эти чертовы игры.

Теперь ликуйте! Читайте! Ха-хахаа! Вот они! Здесь! Доклады! Даа! Презентации! И мы станем участниками FlashGamm!

Презентация от Badimа.
Запоминаем: freeonlinegames.com, agame.com, gimme5games.com, yougame.com, flashgamelicense.com, mochiads.com, cpmstar.com, gamejacket.com, blog.elite-games.net. Ха-хаа! Теперь мы станем еще богаче!

Мало. Черт, мало! Подождем пока.

* * *

Вот, пошло-поехало! Сейчас посмотрим, чем они там занимались:
Презентация от Xitri: Использование флэш-игр в рекламе. Кто догадался в архивы их засовывать... Места на сервере что ль не хватает?
Игровой банер, честно говоря, странная идея для банера. Убедит в обратном? Смотрим.
Не, не убедил. Закон банера - заставить юзера кликнуть и впарить ссылку. Можно как-то еще использовать "следование за мышкой", но клик должен быть один, а про клаву я совсем молчу.
Хотя, для имиджевой рекламы, пожалуй, вполне сгодится. Пожалуй убедил. Еще бы послушать сам доклад, конечно...

Презентация от Mokus: Архитектура ММО на основе платформы Flash.
Немногословно... Не в пример предыдущей. Хоть бы аудио-треки прилагали, что-ли. Смотреть без объяснений бессмысленно.

Презентация от Ильи Курылева: Поиск инвестора под браузерную игру. Презентация очень вменяемая, представляю, какой интересный был доклад. Информация, на мой взгляд, очень ценная, хотя я в этой области совсем не ориентируюсь. Но общее представление и кучу незнакомых слов я получил. Спасибо! Про РБК сказано верно. Сейчас тут полный дурдом...

Презентация Ada Chen. Making Money From Web Games – The Pain Free Way. Представитель Mochi Media - компании, предоставляющей нам возможность зарабатывать на наших flash-творениях. Отпишем несколько названий: Armor Games, Crazy Monkey Games, Hallpass, AddictingGames, Kongregate, FlashGameLicense, Microsoft, King.com, MyGame.com, Shockwave, Meez, Candystand, MTV, IGA, Double Fusion, WildTangent, Nonoba, Mindjolt.

Презентация Семён Фриш: Флеш казино - интерфейс, игры, административная часть. Странная презентация - swf почти 3 Мб и всего несколько слайдов... В общем всё понятно. Без доклада имеет малую ценность. Да вообще, по мне, так делать казино - дело скучное и невысокоморальное.

Презентация от Стефан “memphys” Кейш: “Социальное волшебство”, или как продавать дороже. (Пока не смог посмотреть - закрыт доступ к rapidshare.com).

Пока всё что есть. Осталась Альтернатива и некий Tom Krcha.

* * *

Презентация Антона Волкова: Как сделать игру с помощью AlternativaPlatform. Да... Ребята хорошо подготовились. Презентация в html-формате. Текста почти нет, зато какие демки! И еще игра прилагается: ballance (подглючивает правда, но вообще, конечно, очень впечатляет).

понедельник, октября 27, 2008

Имитация воды

Сегодня на повестке дня - эффект имитации ряби на поверхности воды. Воду имитировать не так сложно, есть разные подходы.

С появлением фильтров эта задача стала еще проще. Если раньше рябь получали путем маскирования изображения мельчайшими полосами и многократного его дублирования, что дико нагружало процессор, то начиная с 8й версии, фильтр DisplacementMapFilter, легко позволяет искажать изображение, и получать эффектную анимацию воды.

Поглядим, какие эффекты делают наши коллеги:

Realistic Flash Water Effect - AS2. Вода получается сочетанием Bitmap.perlinNoise и DisplacementMapFilter. Вода смотрится вполне реалистично, если не считать недостатка отсутствия перспективы.
Кстати, мой коллега разрабатывал flash-заставку для Алых парусов. Он изначально сделал ставку на искажения водяной поверхности при помощи именно такого метода. Увы, требования заказчика по производительности были столь высоки, что эффект пришлось убрать... А было очень сильно сделано. К сожалению, фильтры на больших площадях очень медленны.

Здесь: Water effect, обошлись без фильтров и сделали всё масками. Смотрится конечно слабовато да и работы многовато. Но, для тех, кто не хочет дружить с flash-программированием, то вполне сойдет.
Сюда же отнесу и вот этот вариант: Flash Water Effects - пример для совсем начинающих.

Довольно продвинутый способ создания ряби, плюс имитация подводных каустиков: Water caustic effects with Flash/AS2. Демка смотрится довольно свеженько, но как-то не совсем реалистично. А всё из-за того, что карта подводных каустиков не генерируется, а является секвенцией. И сгенерирована она специальной программой, неким Caustics Generator. Что же, такой подход тоже имеет право на существование и, возможно, пожертвовав памятью на секвенцию карты, мы выиграем в производительности. А я думаю, что для того, чтобы на лету генерировать такую графику, ресурсов надо прилично, да и алгоритм еще поискать/разработать придется.

Смотрим далее: несравненный блог #Laboratory Andre Michelle и эффект Water. К сожалению, для него нет исходников. Приходится просто любоваться...

Продолжаем любоваться на воду: Rain Drop Water Effect. Сайт предлагает купить flash-компоненты с различными эффектами. Мы, безусловно, вежливо отказываемся и продолжаем рыскать.

Люди выкладывают исходный код на форумах: например, здесь - water effect. Правда нет демки, а прежде чем потратить время на проверку, хочется знать, ради чего. Пока пропустим, но будем иметь в виду.

По соседству лежит еще код: is this water effect possible in AS3? Он позволяет скрывать/появлять изображение с эффектом искажения. Как-то не очень...

Следующий претендент: Water ripples revisited (AS3-only version). Вот это то что надо! Есть Демка с "волнующейся" поверхностью и исходники. Думаю, здесь стоит остановиться и поэкспериментировать. О результатах обязательно отпишусь. Добавлю, что сам блог еще свежий, но пестрит очень любопытными демками с исходниками.

Попутно нашелся вот такой эффект: interactive water AS3 experiment. Из крана течет вода, которую мышкой можно потрогать. Выглядит интересно. Вообще, видно, что автор любит забавляться с партиклами и это у него хорошо получается.

Пока это всё, что я смог нарыть про эффект водяной ряби. Причем, помню, что видел еще что-то стоящее по этой теме, но, увы не смог найти. Буду рад помощи.

* * *

Вспомнил еще одну статью по анимации воды: Море воды - программная анимация и не только, и здесь же: Еще раз о воде - самый главный секрет. Очень полезные примеры имитации воды с помощью анимационных приемов и капельки программирования.

* * *

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

вторник, сентября 30, 2008

Физика и Flash

Ниже будет представлен небольшой обзор последних физических достижений в двумерном пространстве.
В процессе проведения небольшого обследования Google, я выявил несколько физических движков под AS3, а именно:

Итак, подробнее.



Fisix Engine. Старый, проверенный движок, на котором я сделал не один проект.

Достоинства: понятная и логичная структура пакетов и классов, стабильная физическая модель, наличие документации ASDoc, довольно богатый выбор примитивов, наличие контейнера-колеса, конвейера, других, "подготовленных" объектов, типа Bullet и Rope. Контроль "проникновения". Движок отлично заточен под производство игр с физикой. Дается много примеров.

Недостатки: разработка движка остановилась на версии 0.5 (alpha). У меня так же возникали проблемы с AngularConstraint (угловая связь объектов) - система уходила в разнос при попытке нарушения этой связи. На мой взгляд, все связи слишком "упругие". Даже те, которые должны быть жесткими. Еще один недостаток - отсутствие исходников. Предлагается скачать SWC. Это создает проблемы тем, кто хочет использовать движок из-под Flash CS3.

Итог: вполне стабильный рабочий движок, но изучать "загнувшийся" проект не имеет смысла.


APE. Такой же старый и забытый своими разработчиками движок.

Достоинства: простота и понятность движка. Он состоит всего из одного пакета, который содержит весь набор классов, который прямо скажем аскетичен.

Недостатки: разработка движка остановилась на версии 0.45 (alpha). Кроме того, я столкнулся с непонятным поведением объектов определенных обстоятельствах - когда сложные составные объекты с движущимися частями вдруг взлетают бешено размахивая своими оборванными деталями.

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

Основной недостаток рассмотреных выше движков - отсутствие полигональных примитивов. Если в Fisix есть какое-то упоминание о полигоне (как заглушка в API) и наличие полигональной поверхности FractalTerrain, то APE на это вообще не заморачивается.

Перехожу к мною не освоенным проектам. Начну с менее "раскрученного":



Foam. Попробуем его установить и потестить. Примеров в открытом виде нигде не видно. Качаем последнюю версию отсюда. Мда, последняя версия числится ноябрем прошлого года... Тоже не свежак. В архиве есть примеры! Пробуем установить и тестить. В архиве есть библиотека, документация и три примера.

Примеры откомпилировались и запустились без проблем. Только сразу не порадовала ресурсоемкость. Пример "ZeroGravityToyChest", даже без движения объектов, сразу съел одно ядро процессора. Второй пример "PerpetualFall" продемонстрировал более продвинутые возможности, но процессор грузил не менее активно. Однако, здесь мы видим полигональные фигуры! Третий пример демонстрирует реализацию вращения по орбите с использованием разных методов (Эйлера и Рунге-Кутта). Честно говоря, тут надо разбираться - по-видимому в примере заложена какая-то глубокая идея. Предполагаю, на основе данной физики можно смоделировать что-нибудь на подобии планетарной системы.

Поглядим на документацию. Не всё так гладко. Сжатые комментарии, сложные термины. Чтобы понять принципы движка, нужно изучить блог разработчика. Здесь есть заметки по теоретическим основам, примеры. Слабо реализована система событий.
Чтобы четко сформулировать достоинства и недостатки этого движка, нужно с ним поработать, а на первый взгляд, можно сказать следующее:

Достоинства: Физические тела реализованы при помощи полигонов, кривых Безье. Широкий выбор силовых воздействий и детекторов коллизий. Логичная структура пакетов.
Недостатки: Последнее сообщение в блоге производителя на тему FOAM датируется 27м ноября 2007. Это значит, что прежде чем браться за освоение этого проекта нужно поискать что-нибудь посвежее. Ресурсоемкость движка довольно высока.
Итог: Этот движок можно рекомендовать для решения каких-то специфических задач. Для игр я бы, наверное, не стал его использовать.



Box2DFlash. Этот движок - портация физического C++ движка Box2D на язык AS3.
При переходе на сайт проекта, перед нами возникает чудесная демка с двумя трупиками. При нажатии клавиш стрелок, демки сменяются. На момент написания этой статьи, здесь представлена версия Box2DFlashAS3 2.0.1. Демки показывает удивительные возможности движка. По производительности, опять разочарование. Движок стабильно съедает ядро процессора, несмотря на то, что на сцене нет никакого движения, а подвижные фигуры при полной остановке даже подкрашиваются. Если сравнить демки - шагающий механизм Theo Jansen, сделаный на box2Dflash с APE, первый съедает ресурсов вдвое больше (хотя, можно предположить, что это ненасытные набросаные под ногами колесики). Про Fisix можно сказать, что, сравнивая наглаз куклы с трупиками, он несколько экономичнее box2Dflash. Но это всё очень неточные оценки. Хорошо бы привести сравнительную оценку по решению одной и той же задачи.

Попробуем скачать и установить. Проект лежит здесь. архив содержит библиотеку, несколько служебных классов (кстати, здесь замерятель FPS, ограничитель фрейм-рейта (что это?), обработчик клавиатуры) и примеры. Документации нет! Точнее, здесь есть общее описание, но это не ASDoc... Смотрим исходники. Ну конечно... Какой уж тут ASDoc... Комментарии набросаны как попало. Ну хоть потестим примеры. Флашки компилируются и запускаются без проблем. Демка пожирает ресурсы так же безжалостно, как и на сайте. Однако, как только я создал проект во FlashDevelop и попытался его откомпилировать, вывалилась масса варнингов и несколько ошибок. В общем, разочарование. Вкратце, можно сказать, что:

Достоинства: Относительная свежесть движка (17 июня 2008). Впечатляющие возможности, продемонстрированные в демках, например полигональные физические тела. Больше сказать не могу - объяснение ниже.

Недостатки: Отсутствует документация ASDoc, код откомментирован не надлежащим образом. И довольно прожорлив он.

Итог: Мне думается, что работать с box2Dflash будет проблемматично: удобство работы с документацией является одним из решающих критериев освоения какого-либо продукта. Кроме того, Box2Dflash лучше подойдет для любителей Flash CS3 IDE.

Но не всё так плохо. Есть еще одна портация Box2D на AS3. И называется она:


Motor2. Как про него сказано на странице Google Code - основанный на импульсах твердотельный двумерный физический движок. Скачиваем последнюю версию: 0.8 бета. Датируется 4-м августа, ага - пока самая свежая из всех предыдущих. Смотрим архив - богатая комплектация - здесь есть SWC и исходники, большой набор примеров. Но вот документации ASDoc опять не вижу.
Установка. У нас есть два варианта - использовать SWC. Для этого, просто (для FlashDevelop) прописываем в Project -> Properties -> Compiler Options -> SWC Libraries полный путь к motor2.swc. Этого достаточно, чтобы откомпилировать примеры.

Однако, если мы хотим воспользоваться исходниками, не всё так просто. Нам необходимо скачать с сайта производителя библиотеку AS3 Data Structures For Game Developers (AS3DS). Это набор полезных алгоритмов и структур данных. Установим в Classpaths пути ко всем библиотекам - всё работает отлично. Пробежимся по исходникам. Наблюдается слабое ASDoc-комментирование. Значит есть вероятность, что документация существует.

Еще в начале года, в своей статье "motor2 development progress" автор писал, что он работает над документацией. Но, как видно, продвинулся он не сильно... Может попробуем сгенерировать ее сами, из того, что есть? Ох, боюсь ерунда получится... Мда, доки так и не захотели сгенерироваться. Из-за какой-то ошибки, ASDoc не хочет находить импорты некоторых классов, хотя они присутствуют и вполне корректны. Жаль.

Что ж, потестируем примеры. Они демонстрируют удивительное многообразие возможностей движка. Из всех движков, это, наверное самый мощный из всех рассмотренных. Здесь даже есть "плавучесть"! В демках со столкновениями, после полной остановки тел, ресурсоемкость реально падает почти в два раза. Здесь имеются составные тела, полигональные тела и многое другое... Потенциал можно оценить здесь: "Motor Physics released".

Достоинства: Свежий движок с богатыми возможностями и оптимальной ресурсоемкостью.

Недостатки: Отсутствует документация. ASDoc- и простое комментирование на минимуме. Дез комментариев и документации, разобраться в коде будет сложно.

Итог: Хочется испробовать движок в деле. Очень хочется. Если есть время на изучение структуры и функций классов, есть смысл заморочиться. У меня нет - буду ждать дальнейшего развития и использовать старые проверенные средства. Кроме того, раз движок еще не готов на столько, что нет даже элементарной документации - кто знает, какие баги могут вылезти в процессе его использования.


* * *

Итак, в качестве заключения, скажу, что несколько разочаровался. Хотелось найти что-то 1. совершенное и 2. готовое к применению. Первое - есть, и это Motor2. Второе - пока я рассматриваю только Fisix.

* * *

Из комментариев поступила еще одна ссылка на физический движок:

PopShapes. Демка обнадеживает. Полигоны, находящиеся в контейнере со стенками из кривых Безье. За одно это уже можно преклониться перед Andre. Он любезно предоставил исходный код, который мы немедленно качаем. С нетерпением импортируем тестовый flex-проект (кстати, FD на него ругается и не хочет импортить - просто вылетает по ошибке). после подцепления библиотек компилируем.

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

Итог: Здесь наверняка можно что-то позаимствовать, но, создается впечатление, что это небольшой кусок, самое начало какой-то большой разработки. Скорее всего, это основа какой-нибудь игры или в этом роде. В любом случае - не конечный продукт, удобный для пользования. Кроме того, если верить дате файлов библиотек, PopShapes - сильно устаревший движок.

* * *

Fisix конечно разочаровывает. Нельзя сделать даже прямоугольный объект - только путем сочетания поверхностей DynamicSurface. Но это имеет кучу недостатков - тонкая поверхность простреливается, и поверхность с двух концов скруглена, что мешает сделать острые углы. Я могу ошибаться, но подозреваю, что демка с ящиками, представленная на сайте, сделана с полноценной поддержкой полигонов, а выложенная библиотека намеренно урезана.

Не работают некоторые объявленные примитивы, конвееры, полигоны. Жесткие связи StickConstraint, всё равно растягиваются и сжимаются, что не позволяет сделать действительно жесткую конструкцию.

Единственный плюс - более-менее адекватная производительность. В процессе разработки, уже хотел было бросить Fisix и взяться за FOAM (документация по нему имеется и возможности приличные), но, решил, что пока обойдусь. В следующий раз, если ничего нового не появится или не выйдет что-нибудь типа документации к Motor 2, начну с FOAM.

* * *

Про конвейеры в Fisix я наврал - они не действуют на DynamicSurface, которая ложится на конвеер. Партиклы конвеер передвигает нормально.

* * *

Прозрение. Полез я от нечего делать в SVN движка APE... И расстроился...

В бранчах SVN лежит ряд версий движка. Некоторые из них, например, jim/ и rigidape/ содержат контент, пестрящий довольно аппетитными названиями: CollisionEvent.as, PolygonBody.as, RigidRectangle.as и т.п. Имеется apetest.swf. Конечно, документация по этим версиям отсутствует. Но код, в силу своей простоты, вполне понятен и разобраться можно. Другой вопрос - версии не являются релизными и их стабильность под вопросом. Но, думаю, попробовать их стоит.

Жаль, что я сразу не сообразил залезть в SVN. Проект, который я сделал на Fisix, имеет кучу недостатков, обусловленных именно возможностями движка.

* * *

Glaze. Прежде всего, спасибо Kuzyasun за наводку. Смотрим демку. Впечатляет! Гляжу на загрузку процессора и в голове крутится только одно слово: "КАК?!". Каждая из демок по-своему удивляет. Например, первая (вызывается по клавише "1") удивляет стабильностью - сложная конструкция из плашек стоит, не падает и лишь несколько плашек слегка колышется в начале. А 5-я демка вываливает на экран 500 полигонов. При этом, процессор загрузился всего менее чем на 30%.

Ну, а теперь попробуем ответить на мой риторический вопрос. Скачиваем код. Для этого нужно воспользоваться SVN-клиентом (без него не обойтись никак. Если не стоит - срочно ставьте: TortoiseSVN). Делаем чекаут по ссылке: http://glaze.googlecode.com/svn/trunk/

Документации нет. Смотрим код: плохо (да можно сказать, что совсем не) документирован. Пару раз проскочил ASDoc. Но, увы, только пару... Структура пакетов и классов вполне понятна и логична. Автор пишет, что в разработке было кое-что позаимствовано из APE и Chipmunk (движок физики под C).

Итог. Вполне свежий (в файлах SVN проскакивает дата 3.08.2008) очень мощный движок. Всё хорошо с динамикой, стабильностью и производительностью. Пока не всё ясно с обработкой событий, например, для выявления столкновений. Отсутствует комментирование и документация. Я думаю, что Glaze заслуживает того, чтобы с ним разобраться и попробовать его в деле.

* * *

Кстати, по теме физ-движков нашлось небольшое обсуждение: http://groups.google.com/group/glaze-engine/browse_thread/thread/7f4503fda8dc2726?pli=1.

понедельник, сентября 22, 2008

Ввод текста не в TextField: реально ли такое? AS3

Столкнулся со следующей проблемой:
Необходимо в некотором текстовом поле отобразить нажатый на клавиатуре символ.
Первая мысль - просто слушаем событие клавиатуры KeyboardEvent от, к примеру, Stage. Однако, событие имеет только два свойства, предоставляющих информацию о нажатом символе (не считая свойств, информирующих о вспомогательных клавишах): это charCode и keyCode. Из них, так или иначе, можно узнать, какая буква была нажата но - без учета текущего языка ввода! Как получить нужный символ с учетом текущей языковой версии ввода?
Идей решения этой проблемы я практически не нашел. Только здесь предлагается использовать невидимое текстовое поле с установленным на нем фокусе. Аналогичное решение предлагается здесь.
Порывшись в хелпе, в исходниках Flash/Flex-компонентов осуществляющих ввод текста, выяснилось, что всё сводится именно к TextField. Но в сам TextField, естественно, влезть невозможно.
Пока вижу единственный вариант - использовать TextField как источник введенного символа.
Хелп по этому поводу говорит: "Because mappings between keys and specific characters vary by device and operating system, use the TextEvent event type for processing character input." Но никто кроме TextField не умеет слушать событие TextEvent. То есть имеется подтверждение тому, что без текстового поля не обойтись.

Итак. Алгоритм таков (работает отлично):
Создаем TextField и куда-нибудь его вставляем. Делаем его невидимым - устанавливаем его свойство visible в false. Удивительно, но невидимые текстовые поля всё равно получают фокус! Не забываем установить type = TextFieldType.INPUT;
Подписываемся на прослушивание его события TextEvent.TEXT_INPUT. В обработчике этого события извлекаем нужный нам символ: event.text.charAt(0); и используем его как нам заблагорассудится. И не забываем при этом очистить поле.
Кроме того, подписываемся к this.someDisplayObject.stage на прослушивание события : KeyboardEvent.KEY_DOWN. В обработчике этого события мы устанавливаем фокус на наш невидимый TextField.

Решение, безусловно, выглядит как "заплатка". За то работает.
Если предполагаются другие интерактивные элементы, то нужно будет продумать систему отключения и включения нашей системы в зависимости от текущего фокуса ввода.

среда, сентября 10, 2008

Рефлексия и взрыв мозгов

Пост 360Flex SJ 2008 - Reflective Programming by Eric Ko натолкнул меня на мысль поближе познакомиться с рефлексией (или интроспекцией) в программировании. Привлекло меня, честно говоря, "красивое" незнакомое слово. Или любопытство.

Поискав в Гугле, стало ясно, что в рунете более распространен термин "интроспекция".

Что же это за зверь? Пишут всякое:

Например: В повседневной жизни, интроспекция - это проявление самоанализа. Интроспекция основывается на изучении собственных мыслей, ощущений, мотивов и поступков. Великий философ Сократ провел большую часть своей жизни, занимаясь самоанализом и призывая своих сограждан-афинян следовать своему примеру. Он даже утверждал, что для него самого "непроанализированная жизнь не стоит существования".
В случае программирования интроспекция означает возможность изучать что-либо, чтобы определить, что это такое, что оно умеет и что может делать. Интроспекция предоставляет программистам огромные гибкость и контроль. Если вы хоть раз работали с языками программирования, которые поддерживают интроспекцию, вы, возможно, испытываете схожие чувства: "непроанализированный объект не стоит воплощения".


Взрыв мозгов: Сложность разработки программного обеспечения обусловлена когнитивными и социальными аспектами профессии. ...

Прикладное применение рефлексии в .NET: NET Reflection представляет собой классический пример некоторой низкоуровневой библиотеки, которая может быть использована при решении прикладных задач. Что же это такое?Рефлексия (ударение на последнем "и", синоним слова интроспекция), или, по-английски, reflection - система, предоставляющая выполняемому коду информацию о нем самом (взрыв мозгов №2).

Тут тоже говорят: Интроспекция (англ. Introspection) - возможность определения типов и получения описаний (метаданных) типов и интерфейсов во время выполнения программы.

Вот тут мы натыкаемся на следы интроспекции в AS3: for…in теперь не выводит свойства и методы, объявленные в классе. Он выводит лишь динамические свойства объекта. В AS3 введен более продвинутый механизм интраспекции объектов, называемый describeType. Используйте describeType для интроспекции объектов в AS3.

Превосходно! Посмотрим ка Доки:
public function describeType(value:*):XML
Ах ну конечно! Это же та самая функция, которая выдает полное описание класса в виде XML.

Кроме того, хорошая статейка Performing object introspection открывает еще один полезный для интроспекции класс mx.utils.ObjectUtil.

Поняв, в принципе, о чем речь, вернемся к исходной статье. Здесь презентация. Кроме того, можно посмотреть статью ее автора - ActionScript - Reflective Programming.

В итоге, как же применить рефлексию на практике? Для себя я отложил два применения:

1-е очевидное: Мы имеем дело с закрытой библиотекой недокументированных классов и имеем возможность исследовать их свойства и методы.

2-е концептуальное: Если я не ошибаюсь, на рефлексии можно строить совершенно альтернативные механизмы, реализующие те же возможности, которые предоставляют наследование и композиция. Причем, как утверждает автор статьи, этот подход может дать более изящные решения.

В общем, почва для размышлений есть.

* * *

Еще одно интересное решение недавно появилось в обсуждениях - как раз на тему "Код изучает сам себя": Определение родителя класса. Хотя тема не совсем соответствует содержанию (скорее "Определение имени класса, который вызвал метод рассматриваемого класса"), решение очень любопытное:

Если в дебаговом плеере, то можно распарсить (new Error()).getStackTrace() и получить имя класса.

Денис Коляко

К сожалению, оговорка про "дебаговый плеер" накладывает существенное ограничение на использование этого подхода...

среда, августа 13, 2008

Ограничение в Input-TextField. AS3

Для того, что бы ограничить ввод, некоторые используют окно "Character Embedding" (кнопка "Embed"). Указав нужные диапазоны символов, мы не только ограничиваем внедрение шрифта, но и ограничиваем возможность ввода символов в строку.

Однако, это не всегда работает верно. Точнее, работает хорошо, но не предназначено для ограничения ввода символов. Вот пример, с которым я столкнулся. Я делаю Flex-компонент во Flash IDE и вставляю его в Flex-проект. Компонент содержит строку ввода с описанным выше ограничением шрифта (без некоторого диапазона символов). В свою очередь, Flex-проект уже содержит внедрение того же шрифта для своих нужд. Но только уже без ограничений (с наличием этого диапазона символов). В итоге, при конечной сборке проекта, строка ввода компонента беспрепятственно позволяет вводить все символы, не смотря на описанные выше ограничения. По всей видимости, шрифт, внедренный в компонент объединяется при компиляции с тем, что внедрен в Flex-проекте.

Для того, чтобы правильно ограничить ввод, в TextField предусмотрено свойство restrict.
Это строка, в которой можно указать как простую последовательность символов ("!#$%()*"), так и диапазоны символов ("0-9 A-Z a-z"). Символы, которые указаны в строке restrict можно будет вводить в поле ввода TextField. Ввод других символов будет запрещен. Для исключения символов из диапазона имеется спец-символ "^", после которого указывается исключаемый символ или диапазон символов. В хелпе про это всё хорошо написано.

Здесь есть один подводный камень. Если вы указываете в restrict диапазон в кириллице - обязательно обратите внимание на кодировку AS-файла, который содержит этот код. Если он не в кодировке UTF-8, то русские буквы в TextField вводиться не будут. Из-за такой мелочи можно убить много времени впустую.

среда, августа 06, 2008

Список без подсветки и выделения элементов. Flex

Элементарная задача - есть компонент список (в моем случае - это TileList). Его элементы (itemRenderer'ы) сами обрабатывают мышиные события наведения/нажатия. Нужно, чтобы сам компонент списка не делал никаких подсветок и выделений элементов.
Казалось бы - тривиальная задача. Ничего подобного.
Одними стилями этого не сделать, что лишний раз доказывает несовершенство механизма скинирования Flex.
Решение - создание потомка и перекрытие методов:
protected function drawSelectionIndicator(...) и protected function drawHighlightIndicator(...)
Код прилагается.

Посильную помощь в раскопках оказала статья: Flex Tutorial - Image ItemRenderer.

Не понимаю, почему в одних случаях модель цвета #RRGGBBAA реализована, а в других - только #RRGGBB? Ведь как было бы удобно просто задать стиль themeColor="#00000000" и не парить мозг?

четверг, июля 31, 2008

Прокол с микрофоном

Хотелось поиграться со спектром звука, снятого с микрофона. Сам класс Microphone ничего более-менее полезного не предоставляет. А SoundMixer на звуки от микрофона не реагирует.

Порыв интернет, нашел статейку "Sound Spectrum + Microphone = Disappointment", которая подтвердила мои опасения. Одно обнадеживает - 10й Flash будет поддерживать эту возможность.

А пока остается одно - сохранять запись на сервер, затем считывать и обрабатывать.
Как это сделать - разберемся позже.

* * *

И тут тоже подстерегает засада: в статье "SoundMixer.computeSpectrum + Microphone?" , в комментариях есть такая фраза: "Flash Media Server ... That's why the mic input and video input go into black boxes -- so you can't get the raw data from it and transmit or save the bytes. Otherwise there would be no need for Media Server. ... " Это значит, что нужен FMS или Red5. То есть задача усложняется на порядки. Эхх. Ждем Астру.

* * *

Кстати говоря, чтобы отправить звук с микрофона на сервер (лайвдоки) используется класс NetStream и метод public function attachAudio(microphone:Microphone):void.

вторник, июля 01, 2008

Апостроф и FlashDevelop|Flex SDK. AS3

Сегодня столкнулся с забавной проблемкой.
Проект FlashDevelop находится в папке, содержащей апостроф - символ " ' ": Children'sPortal.

В код включаю внешний SWF - пишется строчка:
[Embed(source="Assets/preloader.swf")].

Компилирую. Вылезает список ошибок:

Classes\myApplication___preloader_class.as(25): col: 43 Error: Syntax error: expecting rightparen before sPortal.
[Embed(_resolvedSource='.../Children'sPortal/.../Assets/preloader.swf', mimeType='application/octet-stream')]

. . .

Убираю апостроф - всё компилится.

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

среда, июня 18, 2008

Как получать сообщения от внедряемых/подгружаемых SWF. AS3

Например, есть у нас заставочка, которую мы подгружаем/внедряем в Flex-приложение.
Она долго проигрывается, и после ее завершения, мы хотим перейти, к примеру, на другой стейт. Но как поймать момент окончания заставки? А если нам надо как-то среагировать на ее команды в процессе воспроизведения? На ум приходит единственный вразумительный способ - генерировать события из заставки.
В простом случае, делается это всего одной строчкой:
this.dispatchEvent(new Event("Done"));
Но как, и кому подписываться на прослушивание этого события?
Да очень просто. В скрипте инициализации Flex-приложения вписываем:
this.addEventListener("Done", this.doneHandler, true);

Постараюсь пояснить происходящее:
При параметре useCapture, установленном в true, мы будем ловить наше событие на фазе захвата. На этой фазе, событие пройдет через всю цепочку дисплей-объектов, в которой сидит наш клип, до самого Stage.
Если мы не установим useCapture в true, то событие не будет обработано, т.к. событие, генерируемое из контейнера не имеет фазы target, а фаза bubbling отсутствует, т.к. мы генерируем событие с параметром по умолчанию bubbles=false.
Можно сделать наоборот - ловить событие на фазе bubbling. Тогда, при генерации события указываем bubbles=false, и получаем:
this.dispatchEvent(new Event("Done", true));
и
this.addEventListener("Done", this.doneHandler);

В процессе выяснений обстоятельств, я наткнулся на статейку: "Reader Question: Why isn’t event bubbling working" где хорошо разъясняется аналогичная ситуация.

Zinc 2.5 и Flex 3.0: Проблема со звуком

Имеется довольно крупный, офф-лайн проект - каталог недвижимости. Столкнулся со следующей проблемой:
Было необходимо вставить звуковое сопровождение. Нет проблем - создаем объект Sound, загружаем MP3-файл. Отлаживаем кнопку вкл/выкл звука. Всё работает как часы.
Загоняем всё это инковый гроб. Звука нет. Проверяем событие загрузки, трейсим загруженный объем звукового файла - всё отлично грузится и под zinc-ом. Но звука нет.
Тут уже начинает трясти, т.к. конец дня и домой хочется, а проект с утра сдавать.
И вот, пробую другой MP3-файл. Работает! А разница - первый был 5 Мб, второй - 680 Кб.
Итак, делаем вывод (предположительный) - Zinc (или система) ограничивает размер памяти выделяемой для нужд приложения. Причем как-то брутально - без предупреждений и исключений.

среда, июня 04, 2008

Flash CS3 + Flex Component Kit = Мистика

Вчера полдня потратили на решение такой проблемы:
В течение некоторого периода времени, разрабатывался набор Flex-компонентов с использованием Flash CS и Flex Component Kit 1.1.2 (это расширение идет в поставке Flex SDK 3. Кстати, лежит в папке ...Flex SDK/frameworks/flash-integration).
Всё было превосходно, мы отлаживали, обновляли их... до вчерашнего дня. Flash CS3 просто сломался.
Команда "Convert Symbol to Flex Component" отрабатывает успешно, SWC генерится, но всё это бесполезно.

Симптомы такие (касаются конечно только FLA-файла с компонентом):
  • Перестали работать тайм-лайновые скрипты ВООБЩЕ - в любом клипе.
  • Компоненты, которые получаются в результате публикации SWC Flex не видит.
  • Сначала символ компонента назывался "myButton". Позже, он был переименован с именем компонента "roomButton". Однако, иногда, имя символа (и класса) неожиданно опять слетает на старое без какой-либо закономерности.

Однако, при компиляции этого файла на другом компьютере, всё сразу чинится. И даже после пересохранения в какой-то момент починилось и на сломаном. Но не надолго.

Кроме того, FLA-файл был скопирован на удаленный компьютер. При открывании файла с удаленного компьютера и работе с этим всё работает корректно!

Не помогла даже переустановка Flash CS3!

Подробности: Компонент представляет собой клип с Base Class: mx.flash.UIMovieClip. В поле Class прописано имя класса, который управляет этим клипом и является потомком UIMovieClip.

понедельник, июня 02, 2008

AlternativaPlatform. Знакомство

Мы долго, с любопытством и восхищением, наблюдали за волшебством, которое творили наши Пермские коллеги. Они писали умные слова, которые мы привыкли встречать в описаниях 3D-ускорителей или настройках 3D-шутеров. Они выкладывали демки, которые не укладывалось в нашем 2D Flash-сознании и вызывали только один вопрос: "КАК?". Всё это казалось таким далеким, неосязаемым, недостижимым...

И вот, свершилось. Теперь можно просто зайти на сайт AlternativaPlatform, зарегистрироваться, скачать движок и просто пользоваться. Соблюдая, несомненно, лицензионное соглашение и правила этики.

Запомним это пророчество: "AlternativaPlatform.com — сеть уже не будет такой, как прежде ".

Итак, регистрируемся. Платформа делится на три части: Alternativa3d, AlternativaGUI, AlternativaCore. Пока доступен первый из них, его и качаем. Скачиваем архив и разархивируем его в предварительно созданную папку "Alternativa3D".

В обзоре Alternativa3d указывается, что на данный момент еще не все технические особенности внедрены. Самое вкусное оставленно на потом. Нам пока хватит и того что есть.

Идем в раздел документации. Но это сделать уже не так просто... 2 июня, к 11 часам сервер просто лежит. Еще 10 минут назад я спокойно обозревал сайт Альтернативы, но теперь, по всей видимости, придется прерваться. Интересно, это от наплыва посетителей или просто тех-проблемы?.. Не прошло и получаса, как сервер опять заработал и мы входим в раздел.

Здесь мы видим:

Уроки

1. Создаем во FlashDevelop новый "Default" проект, указываем в "Project > Properties... > Compiler Options > SWC Libraries":

  • Путь к файлам Alternativa3D/Alternativa3D.swc
  • Путь к файлам Alternativa3D/AlternativaTypes.swc
  • Путь к файлам Alternativa3D/AlternativaUtils.swc

2. Создаем файл HelloAlternativa3D.as, указываем ему "Always Compile" и копируем в него код примера.

3. Компилируем и запускаем. Всё работает без проблем, как и в примере на сайте. На первый взгляд всё просто. Побаловались с разными параметрами и почитали аннотации к коду. Примерно начинает складываться общая картинка. Любопытно было поэксперементировать с количеством сегментов куба. Первое желание - выставить их побольше и посмотреть, как это подвесит FP. Приятно удивило, что, к примеру, поставив их по 20 на каждое измерение, FP по началу явно подвис, но потом, видать, что-то сгенерилось и всё заработало достаточно быстро. Но 30 сегментов FP уже не стерпел...

По аналогии с первым смотрим два других урока. Писать тут особенно нечего - всё достаточно подробно изложено. Теперь от баловства надо переходить к делу. Только для начала нужно уточнить условия использования Alternativa3D в коммерческих целях.

В отличии от PaperVision3D, это не OpenSource, со всеми вытекающими последствиями. И значит открыт вопрос использования продуктов на базе альтернативы не в личных целях.

Ну вот, мы немножко пощупали (а сказать по честному, пока лишь едва ущипнули) этого мистического зверя, и хочется верить, что мы на нем еще ух как покатаемся!

пятница, мая 30, 2008

Хороший стиль Flex-программирования. ASDoc

Немного о комментировании/документировании в стиле ASDoc: ASDoc.

ASDoc

Комментирование свойств

Документируйте только первую функцию пары установщик/получатель (get/set). Пример объявления и документирования свойства:

/**
* @private
* The backing variable for the property.
*/
private var _someProp:Foo;

/**
* Place all comments for the property with the getter which is defined first.
* Comments should cover both get and set behavior as appropriate.
*/
public function get someProp():Foo
{
...
}

/**
* @private
*/
public function set someProp(value:Foo):void
{
...
}

Комментарии ASDoc применимы к тегам метаданных так же как и к другим элементам класса. Поэтому важно, чтобы комментарий относился к правильному элементу. Например, если свойство обозначено тегом Bindable, комментарий должен располагаться непосредственно перед функцией получателя (get), а не над метатегом Bindable:

можно:


[Bindable("somePropChanged")]
/**
* Comments for someProp
*/
public function get someProp():Foo

нельзя:
/**
* Comments for someProp
*/
[Bindable("somePropChanged")]

public function get someProp():Foo

Про документирование ASDoc можно посмотреть подробнее здесь.

PS: Ввиду уродского движка редактирования текста Blogger, местами поехали все пробелы в статье Хороший стиль Flex-программирования. Форматирование. Поэтому, лучше не надеяться на примеры кода, а читать текст.

Заключение

Цикл переводных статей про хороший стиль Flex-программирования еще не закончен. Через некоторое время я вернусь к этим статьям и, возможно, те правила, которые были отмечены автором как TBD будут опубликованы. На сегодня мы имеем достаточно информации, чтобы улучшить свой код. Будем надеяться, что с выходом Flash Player 10, новых SDK и т.п., правила сильно не изменятся.

Хороший стиль Flex-программирования. Форматирование

Здесь речь пойдет о том, как лучше оформлять файлы Flex-фреймворка. Статья Formatting.

Форматирование

Длина строки

Используйте перенос на следующую строку, если длина строки превышает 80 символов. Это дает следующие преимущества:

  • Разработчикам, у которых экран имеет малое разрешение, не потребуется горизонтально прокручивать длинные строки текста.
  • Можно комфортно сравнивать две версии программного кода, расположив два окна встык.
  • При показе кода на экране проектора, можно установить большой размер шрифта, и при этом не потребуется горизонтально прокручивать текст.
  • При печати, исходный код не будет обрезаться, или непредсказуемо переноситься.

Отступы

Используйте отступы в 4 пробела. Настройте редактор так, чтобы вместо символа табуляции вставлялись символы пробелов. Это необходимо для того, чтобы в код выглядел без искажений в программах с другой системой формирования отступов. Например Notepad отображает отступы в 8 символов.

Разделительные блоки

Код необходимо разбивать на разделы, а полученные разделы - озаглавливать. Для этого используйте большой и малый разделители.

Большой разделитель выглядит следующим образом:

//--------------------------------------------------------------------------
//
// Overridden methods
//
//--------------------------------------------------------------------------

Блок большого разделителя начинается с 4-го символа строки и заканчивается на 80-м. Текст начинается с 8-го символа.

Малый разделитель выглядит следующим образом:

//----------------------------------
// visible
//----------------------------------

Блок малого разделителя начинается с 4-го символа строки и заканчивается на 40-м. Текст начинается с 8-го символа.

Необходимо вставлять одну пустую строку до и одну после каждого разделителя.

Разделение блоков объявления

Используйте одну пустую строку для разделения блоков объявления констант, переменных, функций:
/**
* @private
* Holds something.
*/
var a:Number;
/**
* @private
*/
var b:Number

Метаданные

можно: Inspectable[a="1", b="2"]
нельзя: Inspectable[a=1 b=2]

Индексирование массивов

Не ставьте пробелы:
- до или после левой квадратной скобки,
- перед правой квадратной скобкой.

можно: a[0]
нельзя: a [ 0 ]

Расстановка запятых

После запятой, оставляйте один пробел. Это правило распространяется на список аргументов, элементы массива, свойства объекта.

Массивы

Ставьте один пробел:
- после левой квадратной скобки,
- перед правой квадратной скобкой,
- после каждой запятой.

можно: [ 1, 2, 3 ]
нельзя: [1, 2, 3] [1,2,3]

Исключение составляет только пустой массив:
можно: []
нельзя: [ ]

Если строка инициализации массива слишком длинна, разбивайте ее на несколько строк с выравниванием квадратных скобок:

static var numberNames:Array /* of String */ =
[
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine"
];

Объекты

Ставьте один пробел:
- после левой фигурной скобки,
- перед правой фигурной скобкой,
- после каждого двоеточия,
- после каждой запятой.

можно: { a: 1, b: 2, c: 3 }
нельзя: {a: 1, b: 2, c: 3} {a:1, b:2, c:3} {a:1,b:2,c:3}

Исключение составляет только пустой массив:
можно: {}
нельзя: { }

Если строка инициализации объекта слишком длинна, разбивайте ее на несколько строк с выравниванием квадратных скобок:

private static var TextStyleMap:Object =
{
color: true,
fontFamily: true,
fontSize: true,
fontStyle: true,
fontWeight: true,
leading: true,
marginLeft: true,
marginRight: true,
textAlign: true,
textDecoration: true,
textIndent: true
};

Функции

Пример форматирования:

var f:Function;
f = function():void
{
doSomething();
};

Объявление типов

Не ставьте пробелы до и после двоеточия, которое разделяет имя переменной, параметра, или функцию от типа.

можно: var n:Number;
нельзя:
var n : Number;
var n: Number;

можно: function f(n:Number):void
нельзя:
function f(n : Number) : void
function f(n: Number): void

Использование пробелов в операторах

Ставьте пробелы до и после оператора присваивания:
можно: a = 1;
нельзя: a=1;

Ставьте пробелы до и после инфиксного оператора:
можно: a + b * c
нельзя: a+b*c

Ставьте пробелы до и после оператора сравнения:
можно: a == b
нельзя: a==b

Не ставьте пробел между префиксным оператором и операндом:
можно: !o
нельзя: ! o

Не ставьте пробел между операндом и постфиксным оператором:
можно: i++
нельзя: i ++

Операторы

Начинайте каждый оператор с новой строки. Это дает возможность установить контрольную точку (breakpoint) на любой из операторов.
можно:
a = 1;
b = 2;
c = 3;
нельзя:
a = 1; b = 2; c = 3;

Всегда выравнивайте фигурные скобки блоков операторов:
можно:

function f():void
{
var n:int = numChildren;
for (var i:int = 0; i < n; i++)
{
if ()
{
x = horizontalGap * i;
y = verticalGap * i;
}
}
}

Нельзя:

function f():void {
var n:int = numChildren;
for (var i:int = 0; i < n; i++) {
if () {
x = horizontalGap * i;
y = verticalGap * i;
}
}
}

Объявление функций

Ставьте один пробел после каждой запятой. Никогда не ставьте пробелов после левой скобки и перед правой скобкой:
можно: f(a, b)
нельзя: f(a,b) f( a, b )

Если список параметров переносится на другую строку, перенесенные строки должны иметь отступ на уровне первого параметра после левой скобки. Можно располагать несколько параметров на одной строке, только если они умещаются. В ином случае, располагайте каждый параметр на отдельной строке. Если четный параметр не умещается, перенесите первый параметр на следующую строку с отступом на уровне начала имени функции.


public function foo(parameter1:Number, parameter2:String,
parameter3:Boolean):void

public function foo(parameter1:Number,
parameter2:String,
parameter3:Boolean):void

public function aVeryLongFunctionName(
parameter1:Number, parameter2:String,
parameter3:Boolean):void

Вызов функций

Ставьте один пробел после каждой запятой. Никогда не ставьте пробелов после левой скобки и перед правой скобкой:
можно: f(a, b)
нельзя: f(a,b) f( a, b )

Оператор if

Ставьте пробел между ключевым словом if и левой скобкой. Никогда не ставьте пробелов после левой скобки и перед правой скобкой:
можно: if (a < b)
нельзя:
if(a < b)
if( a < b )
if ( a < b )

Оператор for

Ставьте пробел между ключевым словом for и левой скобкой. Никогда не ставьте пробелов после левой скобки и перед правой скобкой:
можно: for (var i:int = 0; i < n; i++)
нельзя:
for(var i:int = 0; i < n; i++)
for( var i:int = 0; i < n; i++ )
for ( var i:int = 0; i < n; i++ )

Если описание цикла переносится на другую строку, перенесенные строки должны иметь отступ на уровне первого символа после левой скобки:


for (var aLongLoopVariableName:int = aLongInitialExpression;
aLongLoopVariableName < aLongUpperLimit;
aLongLoopVariableName++)

Оператор switch

Ставьте пробел между ключевым словом switch и левой скобкой. Никогда не ставьте пробелов после левой скобки и перед правой скобкой:
можно: switch (n)
нельзя:
switch(n)
switch( n )
switch ( n )

Комментарий

По всей видимости исходная статья находится на стадии разработки, т.к. под конец вылезло множество ошибок и обрывков фраз. Сделаю ревизию через пару месяцев.

В основном, всё логично и выполнимо. Последний FlashDevelop успешно реализует эти правила в своем автокомплите. Теперь стало ясно, почему они так резко изменили политику расстановки фигурных скобок функций, а именно, перенос левой фигурной скобки на следующую строку. Честно говоря, я с этим переносом намучался, поскольку при переходе на стиль форматирования FlashDevelop, я специально переучивался оставлять левую скобку на строке с определением функции. А тут вдруг огорошили... И опять возвращаться к прежнему формату.

Ну всё. Следующий проект начинаю правильно форматировать.

Кстати, о проектах, которые сделаны в старом (не по правилам) формате. Часто приходится к ним возвращаться, дорабатывать, улучшать. Но уже трудно работать по-старому. Как тут быть? На переформатирование времени тратить не хочется. Где взять такой реформатер??!

Пока для себя я держу правило - работать в контексте стиля программирования дорабатываемого кода. Мой это код или чужой - всё равно следовать правилам текущего документа.
Если проект важный, в итоге будет выделено время на рефакторинг и всё само собой встанет на места.
Если проект чужой - он, вероятно, попадет обратно к автору, а тот лучше поймет что ему делать со своими или не своими (но похожими :) ) каракулями.

Остался маленький "хвостик" про ASDoc, который мы сейчас и разберем.

четверг, мая 29, 2008

Хороший стиль Flex-программирования. Структура файла

Сегодня мы поговорим о том, как правильно организовать структуру файла Flex-фреймворка. Оригинальный текст: File Organization. По этой теме информации пока не много - большая ее часть в разработке.

Структура файла

Порядок организации файла следующий:

  • Блок Copyright
  • Объявление пакета package
  • Список объявлений import
  • Объявление use namespace
  • Метаданные класса
  • Объявление класса class
  • Инициализация класса extends
  • Список объявлений implements
  • Подключение файла Version.as
  • Список констант класса
  • Список "mix-ins"
  • Ресурсы, используемые классом
  • Переменные класса (static)
  • Свойства класса (static)
  • Методы класса (static)
  • Конструктор
  • Переменные
  • Переопределяемые свойства
  • Свойства
  • Переопределяемые методы
  • Методы
  • Переопределяемые обработчики событий
  • Обработчики событий
  • Вспомогательные классы, не входящие в пакет

Блок Copyright

Вставляйте в каждый .as-файл фреймворка блок copyright. Текст open-source copyright '2008 можно посмотреть здесь: Блок Copyright. Ширина блока - 80 символов.

Метаданные класса

Группируйте метаданные в разделы, в следующем порядке:

  • Events
  • Styles
  • Effects
  • Excluded APIs
  • Other Metadata

Вставляйте малый разделитель перед каждым разделом. (О большом и малом разделителях будет написано в следующей главе "Форматирование").

В каждом разделе располагайте метаданные в алфавитном порядке по имени name="...", а в разделе Other Metadata - по имени тега.

Код примера можно посмотреть здесь: Организация метаданных класса.

Подключение файла Version.as

В каждый класс необходимо подключать файл Version.as, содержащий объявление константы с номером версии static const VERSION:String:
include "../core/Version.as";

Список констант класса

Здесь объявляются статические константы static const.
ActionScript 3 не позволяет объявлять константы типов Array и Object. Такие константы необходимо объявлять как static var, но помещать в этот раздел, поскольку по своей сути они являются константами.

Список "mix-ins"

Здесь объявляются любые статические переменные типа Function, которые принимают ссылки на методы, но не объявляются в качестве методов. (Понятие mix-in я раскрыл так, как смог понять - возможно я ошибаюсь).

Свойства класса (static)

Здесь объявляются статические установщики и получатели (getter/setter) класса. Располагайте их в алфавитном порядке по имени свойства. Для каждого, используйте подзаголовок с именем свойства. Объявляйте сначала получатель, затем установщик.

Методы класса (static)

Здесь размещаются статические функции static function.

Переопределяемые свойства

Здесь объявляются переопределяемые нестатические установщики и получатели (getter/setter) класса. Располагайте их в алфавитном порядке по имени свойства. Для каждого, используйте подзаголовок с именем свойства. Объявляйте сначала получатель, затем установщик.

Свойства

Здесь объявляются новые нестатические установщики и получатели (getter/setter) класса. Располагайте их в алфавитном порядке по имени свойства. Для каждого, используйте подзаголовок с именем свойства. Объявляйте сначала получатель, затем установщик.

Переопределяемые методы

Здесь размещаются переопределяемые нестатические функции.

Методы

Здесь размещаются новые нестатические функции.

Переопределяемые обработчики событий

Здесь размещаются переопределяемые обработчики событий.

Обработчики событий

Здесь размещаются новые обработчики событий.

Комментарий

Я изменил порядок следования пунктов, так как они в оригинале расположены в абсурдном порядке:

  • Подключение файла Version.as
  • Список объявлений implements
  • Инициализация класса extends

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

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

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


пятница, мая 23, 2008

Хороший стиль Flex-программирования. Использование языка программирования

Продолжаем обозревать статью Flex SDK coding conventions and best practices.

Следующий подраздел: Language Usage.

Использование языка программирования

Здесь будут рассмотрены вопросы использования языковых конструкций ActionScript 3. Особое внимание мы уделим ситуацям, когда для выражения одной идеи существует несколько способов.

Параметры компиляции

Компилируйте проекты с параметрами -strict и -show-actionscript-warnings (они заданы по умолчанию в файле flex-config.xml).

API, базирующиеся на свойствах

Старайтесь применять API, которые базируются на свойствах а не на методах. Такой способ наиболее подходит для декларативного стиля программирования MXML.

Объявление типа

Указывайте типы для каждой константы, каждой переменной, каждого аргумента функции и ее результата. Даже если они не имеют типа, указывайте ":*":

Например:
можно: var value:*;
нельзя: var value;

Используйте наиболее подходящий для конкретной ситуации тип. Например, переменную цикла "for" лучше объявлять типом int а не Number, и, конечно, не Object или *. Другой пример: в mouseDownHandler необходимо объявить аргумент в виде event:MouseEvent, но не event:Event.

Используйте тип int для работы с целыми числами, даже если предполагается, что они будут только положительными. Тип uint используйте только для значений цветов RGB, битовых масок и в других значений, не предназначенных для вычислений.

Используйте тип * только в случае, если значение переменной может быть undefined. Но лучше всегда использовать вместо * тип Object, значение которого равно null, в случае, если объект не существует.

Если вы объявляете переменную типа Array, добавляйте комментарий /* of Тип */ непосредственно после слова Array, указывая тип элементов массива. Это важно, так как в будущих версиях ActionScript появятся типизированные массивы. (Интересно, такой синтаксис будет учитываться непосредственно компилятором, или это совет с расчетом на последующий рефакторинг кода?)

Например:
можно: var a:Array /* of String */ = [];
нельзя: var a:Array = [];
можно: function f(a:Array /* of Number */):Array /* of Object */ {...}
нельзя: function f(a:Array):Array


Литералы

undefined
Избегайте по возможности использования undefined. Единственный случай, когда это необходимо - использование переменных типа *.

int и uint
Никогда не используйте точку дроби в целочисленных значениях:
можно: 2
нельзя: 2.

В шестнадцатиричных числах всегда используйте "x" в нижнем регистре:
можно: 0xFEDCBA
нельзя: 0XFEDCBA

Всегда указывайте RGB-цвета в виде шестизначного шестнадцатиричного числа:
можно: private const BLACK:uint = 0x000000;
нельзя: private const BLACK:uint = 0;

При работе с индексами (например указатель на элемент в массиве), всегда используйте "-1" для обозначения отсутствия индекса.


Number
Если предполагается, что значение переменной будет дробным (обычный случай), инициировать его нужно с использованием точки дроби, после которой ставится дробная часть, либо, при ее отсутствии, нуль:
можно: alphaFrom = 0.0; alphaTo = 1.0;
нельзя: alphaFrom = 0; alphaTo = 1;

Но исключение для этого правила составляют пиксельные координаты, которые условно целые, хотя, в принципе, могут быть и дробными:
можно: var xOffset:Number = 3;
нельзя: var xOffset:Number = 3.0;

При использовании знака экспоненты, применяйте "e" в нижнем регистре:
можно: 1.0e12
нельзя: 1.0E12

Для Number используйте значение по умолчанию NaN - "не установлено".


String
Для обозначения строк всегда используйте двойные кавычки, даже если внутри строки присутствует символ кавычки:
можно: "What's up, \"Big Boy\"?"
нельзя: 'What\'s up, "Big Boy"?'

При использовании escape-последовательностей, спецсимвол "\u" указывайте в нижнем регистре:
можно: \u
нельзя: \U


Array
Используйте вместо new Array() литералы массива:
можно: [], [ 1, 2, 3 ]
нельзя: new Array(), new Array(1, 2, 3)

Используйте конструктор массива Array() только для определения массива заданного размера. Это важно, т.к. new Array(3) создает не [ 3 ], а [ undefined, undefined, undefined ].


Object
Используйте вместо new Object() литералы объекта:
можно: {}
нельзя: new Object(),

можно: {}, o = { a: 1, b: 2, c: 3 };
нельзя:
o = new Object();
o.a = 1;
o.b = 2;
o.c = 3;
или
o = {};
o.a = 1;
o.b = 2;
o.c = 3;



Function
Избегайте использования литералов функции для определения анонимных функций. Вместо этого, используйте методы класса или функции пакета.

При использовании литерала функции, обязательно указывайте возвращаемый тип, а последний оператор в теле функции заканчивайте символом точки с запятой ";":
можно: function(i:int):void { doIt(i - 1); doIt(i + 1); }
нельзя: function(i:int) { doIt(i - 1); doIt(i + 1) }


RegExp

Для определения регулярного выражения используйте представление в виде последовательности литералов, а не инстанцирование объекта RegExp с параметром String:
можно: var pattern:RegExp = /\d+/g;
нельзя: var pattern:RegExp = new RegExp("\\d+", "g");


XML и XMLList
Используйте представление в виде последовательности литералов, а не инстанцирование объекта XML с параметром String:
можно: var node:XML = <name first="Jane" last="Doe"/>;
нельзя: var node:XML = new XML("<name first=\"Jane\" last=\"Doe\"/>");

Используйте только двойные кавычки для определения значений аттрибутов тегов XML:
можно: var node:XML = <name first="Jane" last="Doe"/>;
нельзя: var node:XML = <name first='Jane' last='Doe'/>;


Class
Используйте полное имя класса (включающее имена пакетов) только в том случае, когда импортируется два класса с одним и тем же именем (но из разных пакетов), и необходимо разрешить конфликт имен:
можно:
import mx.controls.Button;
...
var b:Button = new Button();

нельзя:
import mx.controls.Button;
...
var b:Button = new mx.controls.Button();

Но в этом случае можно:
import mx.controls.Button;
import my.controls.Button;
...
var b:Button = new mx.controls.Button();



Выражения

Круглые скобки
При работе с операторами +, -, *, /, &&, , <, <=, >, >=, ==, и !=, не используйте круглые скобки там, где в этом нет необходимости:
можно: var e:Number = a * b / (c + d); var e:Boolean = a && b c == d;
нельзя: var e:Number = (a * b) / (c + d); var e:Boolean = ((a && b) (c == d));

Для остальных операторов, правила приоритета запомнить сложнее, поэтому в этом случае круглые скобки лучше использовать.


Приведение типов
Не сравнивайте переменную типа Boolean с "true" или "false". Она уже является первым или вторым.
можно: if (flag)
нельзя: if (flag == true)
можно: var flag:Boolean = a && b;
нельзя: var flag:Boolean = (a && b) != false;

Явно приводите к типу Boolean переменные типа int, uint, Number или String:
можно: if (n != 0)
нельзя: if (n)
можно: if (s != null && s != "")
нельзя: if (s)

Переменные типа Object можно приводить к типу Boolean неявно:
можно: if (child)
нельзя: if (child != null)
можно: if (!child)
нельзя: if (child == null)

Лучше использовать приведение к типу (кастинг), чем оператор "as". Оператор "as" используйте только в том случае, если при ошибке приведения к типу, вы хотите получить в результате значение "null", а не генерацию исключения:
можно: IUIComponent(child).document
нельзя: (child as IUIComponent).document


Сравнение
Старайтесь расставлять сравниваемые значения в естественном для прочтения порядке (более удобном для прочтения порядке):
можно: if (n == 3) // "Если n равно 3"
нельзя: if (3 == n) // "Если 3 равно n"


Операторы ++ и --
Если в какой-либо ситуации префиксная и постфиксная формы (оператор ставится до или после переменной) логически равнозначны, используйте постфиксную форму. Используйте префиксную форму только в том случае, когда требуется получить значение переменной до ее изменения.
можно: for (var i:int = 0; i < n; i++)
нельзя: for (var i:int = 0; i < n; ++i)


Тернарный оператор

Ипользуйте вместо if/else тернарный оператор в случае простых операций проверки, особенно, для проверок значений на null:
можно: return item ? item.label : null;
нельзя:
if (!item) return null;
return item.label;

Однако, нельзя использовать вложенные тернарные операторы в сложных логических цепочках:
можно:

if (a < b)
return -1;
else
if (a > b)
return 1;
return 0;
нельзя:
return a < b ? -1 : (a > b ? 1 : 0);


Оператор new
Всегда используйте круглые скобки после имени класса, даже если конструктор не требует аргументов:
можно: var b:Button = new Button();
нельзя: var b:Button = new Button;

Операторы

Всегда ставьте после операторов точку с запятой ";". ActionScript 3 не считает за ошибку отсутствие точки с запятой в конце оператора, но лучше не пользоваться этой особенностью:
можно:
a = 1;
b = 2;
c = 3;
нельзя:
a = 1
b = 2
c = 3


Директива include
Используйте include вместо #include. В конце ставьте точку с запятой, как и для других операторов:
можно: include "../core/ComponentVersion.as";
нельзя: #include "../core/ComponentVersion.as"

Всегда используйте относительные пути вместо абсолютных.


Директива import
Указывайте только те классы, интерфейсы и пакетные функции, которые используйте. Не используйте спецсимвол "*":
можно:
import mx.controls.Button;
import flash.utils.getTimer;
нельзя: import mx.core.*;


Директива use namespace
Избегайте ее использования. Вместо этого, используйте синтаксис "::" для каждого определения вне основного пространства имен:
можно:
import mx.core.mx_internal;
// Позже, в каком-либо методе...
mx_internal::doSomething();
нельзя:
import mx.core.mx_internal;
use namespace mx_internal;
// Позже, в каком-либо методе...
doSomething();


Оператор if
Если ветви оператора if/else не содержат более одного оператора, не заключайте эти операторы в блок фигурными скобками.
можно: if (flag) doThing1();
нельзя: if (flag) { doThing1(); }
можно:

if (flag)
doThing1();
else
doThing2();
нельзя:
if (flag) {
doThing1();
}
else {
doThing2();
}

Однако, если одна из ветвей содержит более одного оператора, заключайте в блоки все ветви:
можно:

if (flag) {
doThing1();
}
else {
doThing2();
doThing3();
}
нельзя:
if (flag)
doThing1();
else {
doThing2();
doThing3();
}

Если требуется проверка большого количества ошибок, используйте последовательность операторов if, которые осуществляют проверку и при ошибке, сразу возвращают результат и выходят из метода. При этом, поток выполнения проверки движется по странице вниз. В конце метода ставится возврат результата успешного прохождения проверки.
Не используйте вложенные тесты, при которых поток выполнения смещается поперек страницы:
можно:

if (!condition1)
return false;
...
if (!condition2)
return false;
...
if (!condition2)
return false;
...
return true;
нельзя:
if (condition1) {
...
if (condition2) {
...
if (condition3) {
...
return true;
}
}
}
return false;


Оператор for
Всегда заключайте тело цикла в болк фигурными скобками, даже если оно состоит только из одного оператора.
можно:

for (var i:int = 0; i < 3; i++) {
doSomething(i);
}
нельзя:
for (var i:int = 0; i < 3; i++)
doSomething(i);

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

var n:int = a.length;
for (var i:int = 0; i < n; i++) {
...
}
нельзя:
for (var i:int = 0; i < a.length; i++) {
...
}

Определяйте переменную цикла внутри круглых скобок оператора цикла, если она не определяется где-либо повторно:
можно: for (var i:int = 0; i < 3; i++)
нельзя:

var i:int;
for (i = 0; i < 3; i++) {
...
}


Оператор while

Всегда заключайте тело цикла в болк фигурными скобками, даже если оно состоит только из одного оператора:
можно:

while (i < n) {
doSomething(i);
}
нельзя:
while (i < n)
doSomething(i);


Оператор do
Всегда заключайте тело цикла в болк фигурными скобками, даже если оно состоит только из одного оператора:
можно:

do {
doSomething(i);
} while (i < n);
нельзя:
do
doSomething(i);
while (i < n);


Оператор switch

Заключайте тело каждого выражения case и default в болк фигурными скобками. Операторы break или return ставьте внутрь блока, а не после него. Если вы используете в блоке return, не ставьте после него break. Вариант default обрабатывайте так же как и case, вызов break из него так же обязателен:
можно:

switch (n) {
case 0: {
foo();
break;
}
case 1: {
bar();
return;
}
case 2: {
baz();
return;
}
default: {
blech();
break;
}
}
нельзя:
switch (n) {
case 0:
foo();
break;
case 1: {
bar();
}
break;
case 2:
baz();
return;
break;
default:
blech();
}


Оператор return

Не заключайте возвращаемое значение в круглые скобки:
можно: return n + 1;
нельзя: return (n + 1);

Вызов оператора return разрешается из любого места тела метода.

Объявления

Никогда не объединяйте несколько констант/переменных в одно объявление:
можно: var a:int = 1; var b:int = 2;
нельзя: var a:int = 1, b:int = 2;


Ключевое слово override
Там, где override необходимо, указывайте его до объявления спецификатора доступа:
можно: override protected method measure():void
нельзя: protected override method measure():void


Спецификаторы доступа

Всегда указывайте спецификаторы доступа везде, где это можно сделать. Никогда не используйте то, что по умолчанию, спецификатором доступа является internal.

Перед тем, как объявить какой-либо API как public или protected, как следует подумайте, действительно ли это нужно. Public и protected API нужно документировать в обязательном порядке. Кроме того, они должны поддерживаться в нескольких последующих релизах, прежде чем станут формально устаревшими.


Ключевое слово static
Там, где static необходимо, указывайте его после объявления спецификатора доступа:
можно: public static const MOVE:String = "move";
нельзя: static public const MOVE:String = "move";


Ключевое слово final

Там, где final необходимо, указывайте его после объявления спецификатора доступа:
можно: public final class BoxDirection
нельзя: final public class BoxDirection

Объявляйте все классы-каталоги ("enum classes") как final.
Также, объявляйте "базовые" свойства и методы (те, что начинаются с $) как final.


Константы

Все константы должны объявляться как static. Нет необходимости объявлять в классе динамические константы, поскольку всё равно все объекты этого класса будут хранить одни и те же значения:
можно: public static const ALL:String = "all";
нельзя: public const ALL:String = "all";


Переменные

Если переменную необходимо инициализировать каким-либо значением, делайте это сразу при объявлении переменной, а не в конструкторе:
можно: private var counter:int = 1;
нельзя:

private var counter:int;
...
public function MyClass() {
super();
...
counter = 1;
}


Локальные переменные

Объявляйте переменны непосредственно при их применении, или перед их первым использованием. Не объявляйте все переменные в начале функции:
можно:

private function f(i:int, j:int):int {
var a:int = g(i - 1) + g(i + 1);
var b:int = g(a - 1) + g(a + 1);
var c:int = g(b - 1) + g(b + 1);
return (a * b * c) / (a + b + c);
}
нельзя:
private function f(i:int, j:int):int {
var a:int;
var b:int;
var c:int;
a = g(i - 1) + g(i + 1);
b = g(a - 1) + g(a + 1);
c = g(b - 1) + g(b + 1);
return (a * b * c) / (a + b + c);
}

Объявляйте локальные переменные в функции только один раз. ActionScript 3 не поддерживает объявление локальных переменных с областью видимости в одном блоке:
можно:

var a:int;
if (flag) {
a = 1;
...
}
else {
a = 2;
...
}
нельзя:
if (flag) {
var a:int = 1;
...
}
else {
var a:int = 2;
...
}

можно:
var i:int;
for (i = 0; i < n; i++) {
...
}
for (i = 0; i < n; i++) {
...
}
нельзя:
for (var i:int = 0; i < n; i++) {
...
}
for (var i:int = 0; i < n; i++) {
...
}


Классы
Если класс наследуется от Object, не нужно указывать extends Object.

The only “bare statements” in a class should be calls to static class initialization methods, such as loadResources(). (Совсем ничего не понял в этой фразе).


Конструкторы
Если класс имеет какие-либо свойства или методы, необходимо написать конструктор. Обязательно вызывайте super(), даже если кроме него больше ничего нет.

Если в конструктор передаются аргументы, давайте им имена переменных, которым они передаются.
можно:

public function MyClass(foo:int, bar:int) {
this.foo = foo;
this.bar = bar;
}
нельзя:
public function MyClass(fooVal:int, barVal:int) {
foo = fooVal;
bar = barVal;
}

Не инициализируйте переменные класса в конструкторе. Делайте это при объявлении переменных. Это разрешается только в том случае, когда в наследуемых классах требуется переустановить значения переменных.

Послесловие

Далее перечислены темы, которые еще не в разработке:

  • Interfaces
  • Namespaces
  • Implementing properties
  • Metadata
  • Packages
  • Helper classes
  • Bare statements

Будем иногда заглядывать СЮДА и следить за продолжением.

Правила, конечно, порой спорные.
Например, инициализация переменных при их объявлении допустима только при работе с простыми значениями. [Например, инициализировав какую-либо переменную объектом {prop:1}, мы получим во всех объектах этого класса ссылку на один и тот же объект, но не клоны отого объекта.]

Еще пример - избавляться от лишних круглых скобок в вычислениях и логических выражениях. Не сильно я согласен с таким заявлением. Вообще, код лучше читается, когда он поделен на блоки. При многочисленных делениях и умножениях трудно будет потом разобраться что на что делется и множится... То же самое в логических выражениях.

Остальное, в принципе, вполне законно и приемлемо.
В следующий раз поговорим об организации файлов: File Organization.