вторник, сентября 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() и получить имя класса.

Денис Коляко

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