понедельник, 31 января 2011 г.

Протохаки

Последнее время по работе активно осваивал JS. И в процессе отходняка от взлома мозга и взрыва всех основательно прикипевших принципов ООП стали появляться вопросы.

Вопрос: вот есть AS3, он же вроде причёсанный Adobe'ом форк JS, а в основе JS лежит концепция prototype(а это клёвая штука! :)), а куда она делась в AS3? [Тут надо заметить, что AS2\1 я вообще знать не знаю и в глаза не видел].

Потом у меня образовался непредвиденный отпуск, и я от нечего делать начал ковыряться с Burrito-Hero-Android-iPhone и другими новоявленными интересностями во флеше.

Пишу я значит аппликуху, пишу, и тут натыкаюсь на задачу: хочется мне расширить класс Array нужным мне методом.

ООП-way: "наследуйся!".
JS-way:
Array.prototype.newMethod =
function() {blah-blah};



Вспоминаю свой Вопрос, гуглю - оказывается никуда ничего не делось, всё на месте, но нужно учитывать специфику. [А в AS2/1 так вообще, оказывается, прототипирование пышны м цветом цвело.]

Почитал, порадовался. Но. Adob'овцы настоятельно не советуют. Мол ООП наше всё и нефиг искать лёгких путей. Кроме того куча ограничений портящих всю малину. Более менее удобно prototype использовать для динамических классов:

var arr:Array = [1,2,3];
arr.checksumm();
или сразу [1,2,3].checksumm();
удобно?

Для не динамических классов, чтобы прорваться через компилятор приходится разыменовываться к Object, что уже съедает весь профит. Хотя нетипизированные переменные частично решают проблему:

var a = 5;
a.minutes().ago(); // вернёт время(Date) на a минут меньшее, чем
now
красиво?

А вот вариант когда использование prototype может быть реально полезно:
возвращаемся к нашему Array, которому хочется добавить метод. Не выёживаемся и идём ООП путём. А теперь начинаем оптимизировать, и приходим к выводу что надо бы вместо Array сделать Vector.<int> и сильно огорчаемся, узнав что от Vector.<*> отнаследоваться никак нельзя, final класс, все дела. Можно мутить врапперы-хелперы, а можно воткнуть метод через prototype и использовать так:

var b:Vector.<int> = new Vector.<int>();
b.push(1,2,3);
trace(Object(b).sum()); // =6!

профит!
Если кому интересно могу опубликовать здесь исходники, но вообще тут довольно внятно всё объясняется.

среда, 17 февраля 2010 г.

Сколько времени было потеряно!

Из серии "а мужики то не знают...". Оказывается условная компиляция в AS3 СУЩЕСТВУЕТ!
Сколько я убил времени на решение проблем, которые легко и непринужденно разруливаются с помощью старой, доброй, условной компиляции. Но в тот момент (три года назад) я нагуглил только то, что условной компиляции в AS НЕТ. Я не удивился, но огорчился. И с тех пор считал что её нет. А она, блин, уже есть(или была всегда?).

Зачем это надо? Первое и самое распространенное выкусывание из кода "отладочных" кусков. Чтобы при отладочной сборке этот код работал, а при релизной - нет. Второе и менее распространенное - когда один и тот же программный модуль имеет несколько различных вариантов использования. Например [что скоро станет сильно актуально] код, который должен компилиться под десктоп и под мобилу одновременно. Очевидно, что без модификации некоторых кусков кода это невозможно. И тогда можно будет помечать, что использовать под десктопом, а что под мобилой.

Пример использования:

в настройках компилятора пишем (Проект -> Свойства -> Компилятор Flex -> Дополнительные аргументы компилятора):

-define+=CONFIG::debugging,"false" -define+=CONFIG::release,"!CONFIG::debugging"

этим самым мы сказали компилятору что у нас будет две переменные условной компиляции:
CONFIG::debugging и CONFIG::release. Для CONFIG::debugging мы установили значение false. А переменную CONFIG::release мы задали как НЕ CONFIG::debug (логическое отрицание).

и далее кусок кода с использованием условной компиляции. Пусть это будет обработчик клика:

private function handlerClick(e:Event):void
{
CONFIG::debugging {
Alert.show("debug");
}
CONFIG::release {
Alert.show("rlease");
}
}


В зависимости от состояния переменных CONFIG::debugging и CONFIG::release обработчик будет скомпилен либо так:

private function handlerClick(e:Event):void
{
Alert.show("debug");
}

Либо так:

private function handlerClick(e:Event):void
{
Alert.show("release");
}

Сами переменные условной компиляции обзываются по правилу NAMESPACE::variable_name, где NAMESPACE и variable_name Вы вольны придумывать сами.

Пока я всё это писал mrDiestro прислал ссылку на сюда:
http://onenterframe.ru/2009/10/29/%D0%BC%D0%B0%D0%BA%D1%80%D0%BE%D1%81%D1%8B-%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%82%D0%BE%D1%80%D0%B0-actionscript/
и на сюда:
http://groups.google.com/group/ruflash/browse_thread/thread/eb97256b7ebfcd0
Т.е. тема обширно обсуждающаяся...а мужики то не знают...

ЗЫ:
Вопрос к знающим мужикам, как минимальными усилиями сделать два конфига для компилера(в flex builder ide) - дебаг конфиг и релиз конфиг, чтобы по кнопке Export Release подсасывался релизный конфиг, а при обычном билде - дебажный ?

пятница, 30 октября 2009 г.

Попугаи сопротивляются!!!

Признаюсь: в пылу осенней упячки я совсем почти забросил своих попугаев (портирование haxe+neash на WinMo). Уж и адоб собирается полноценный флекс под мобилы выпустить до нового года, и QT выпустило 4.6.beta типа тоже мега оптимизированную...

А у меня статус такой:
1. Собрал таки gc (garbage collector испльзуемый в недрах nekovm) под WinMobile.
2. Собрал саму nekovm под WinMo
3. Поковырялся над портированием UIComponent на haxe....там ооочень конечно много чего надо будет дописывать.

вот собственно и всё...теперь думаю чо дальше крячить hxcpp или sdl.

понедельник, 21 сентября 2009 г.

Странности больших чисел

Поспорили тут недавно с товарищем. Товарищ - жОский и многоопытный подмобило-геймо-писатель. Так сложилось, что посадили его в срочном порядке за флекс. И поставили задачу: отрисовывать 50.000 статических объектов. И он, ничтоже сумняшися, забубенил это самым ядерным способом. Понаписал кучу своих (а по сути абстрактно-платформенных) классов, которые в итоге всё дампят на главную битмапку. Я не сомневался что это будет работать быстро, я засомневался в целесообразности этого подхода относительно шейпов.(ну мы же цивилизованные люди, специально же для нас делали объектную модель и всё такое)

Стал ставить эксперименты. Флекс, аппликейшин, спрайт-родитель на весь экран и 50.000 дочерних шейпов. mouseChildren=false. Всё умерло. Машина - Windows7,8гигов памяти, 4 ядра. Заработало всё где-то на 30.000 шейпов. Добавил возможность драгать по экрану родительский спрайт. Умирает как только начинаешь драгать.Т.е. если тащить ме-е-едленно, то фпс приличный. А если дёргать резко, когда мышка постоянно над разными местами этого "борща" из шейпов скачет - всё, пиши пропало. Ставлю 10.000 шейпов - всё опять летает, с драгом. 57 Fps (из 60 возможных). Сделал 4 родительских спрайта, каждый на четверть экрана, в каждом по 10.000 шейпов. Т.е. в сумме на экране 40.000 шейпов. 57 fps.

Там в плеере где-то вшита константа? :))) Или алгоритм такой, что до 10.000 чайлдов он работает быстро-быстро, а потом, резко так, включается ЭКСПОНЕНТА? или чо аще? а?

вторник, 8 сентября 2009 г.

ComplexRectangle во Flex4

Разбираюсь с 4м Флексом. В FXG всё до боли аналогично Degraf'е. Но один из самых полезных для меня примитивов - RoundedRectangleComplex отсутствует как класс (прямоугольник у которого можно задавать отдельно радиус каждого уголка). Спасибо товарищу, спас! Спасибо ему огромное.

воскресенье, 6 сентября 2009 г.

Свобода попугаев. Часть 1.

Часть 1.
Рассказ о том, как я впервые компилил haxe-приложения в исполняемый файл(exe).
Дело было под Vista 32 bit.

  1. Сначала я скачал и установил haXe. По ходу установки соглашаемся на установку Neko. [под Windows7 64 bit устанавливаться он не захотел, а вот под Vista-32 встал нормально].

  2. Далее я поставил FlashDevelop

  3. На странице приветствия обнаружил New Project. Выбрал HaXe -> C++ Project. Ввёл имя проекта: MyTestProject. Поставил галку Create directory for project. Получил сгенерённую болванку проекта.

  4. Открывыю src/Main.hx. Вижу там функцию main. Пишу в неё:

    flash.Lib.Init("Test", 800, 600, false, true);
    flash.Lib.SetBackgroundColour(0xffffff);
    var sprite= new Sprite();
    sprite.graphics.beginFill(0x00ff00,1);
    sprite.graphics.drawRect(10,20,30,40);
    sprite.graphics.endFill();
    flash.Lib.current.addChild(sprite);
    flash.Lib.Run();

    При этом в импортах получилось два package:

    import cpp.Lib;
    import flash.display.Sprite;

    Жму F5. Получаю сообщение об ошибке: You can't access the flash package with current compilation flags (for flash.display.Sprite) . Хм. Грубо говоря это означает: "Фигли ты флэшовые пэкэджи используешь в нефэлшовом проекте". Та-ак. Сейчас буду давать адекватный, но ассимметричный ответ на данное заявление.

  5. Подключаю билиботеки neash и nme, которые будут "эмулировать" флэш плеер. Сначала устанавливаю их. Захожу в папку установки haxe (по умолчанию это Program files/Motion-Tween/haxe/) и запускаю оттуда haxelib.exe install nme. Потом haxelib.exe install neash. И в заключение haxelib.exe install hxcpp. Скачались и установились соответствующие библиотеки. Далее подключаю библиотеки к нашему проекту. Для этого захожу в FlashDevelop->Project->Properties->Compiler options. Тыкаю в Libraries и в открывшемся EditBox'е пишу две строки:

    neash
    nme


  6. Теперь торжественно сообщаю компилятору, что он был в корне неправ. В этом же диалоге (FlashDevelop->Project->Properties->Compiler options) в Additional compiler options пишу две строки:

    --remap flash:neash
    --remap neko:cpp


  7. Жму F5 с надеждой скомпилить-таки проект. Снова ошибка. Но в папочке ./bin/src нагенерировалась куча исходников. А что за ошибка? Не найден cl.exe? Ага, т.е. FlashDevelop попытался запустить внешний компилятор (у меня это Microsoft-компилятор от VisualStudio 2008), но так как окружение не настроено - из этого ничего не вышло. Будем настраивать.

  8. Настройка заключается в том, чтобы прописать в переменные окружения все пути для бинарников, инклюдов и библиотек необходимых для компиляции cpp приложения из командной строки. Самый простой вариант устроить это - залезть в файл vsvars32.bat (лежит в Program files/Miscrosoft Visual Studio 8(или 9)/Common7/Tools) и скопировать пути из строчек @set PATH=, @set INCLUDE= и @set LIB= в переменные среды PATH, INCLUDE и LIB соответственно (в Vista я это делал через Панель управдения->Система->Дополнительные параметры системы->Переменные среды)

  9. Вот оно! Вижу зелёный квадратик! Ура! :))



P.S.
Для тех у кого нету установленного VisualStudio, Exey в комментах запостил план Б. За что и выражаю ему благодарность.

пятница, 4 сентября 2009 г.

Свобода попугаев. Предисловие.

Приветствую всех!
Сегодня начал практически ковыряться в haXe и решил параллельно писать заметки по этому поводу.

Предисловие.

Вводную про haXe я давать не буду. Я лучше расскажу, что меня сподвигло на его изучение. Однажды, после долгих лет GUЯния на разных платформах, языках и фреймворках, я встретил Adobe Flex. С тех пор прошло уже два года. Тогда я только предполагал, что при всех своих недостатках Flash+Flex framework это лучшее, что есть для GUI-писателя. Сейчас я в этом уверен.

Мысль о вытаскивании Flash\Flex-приложения (в качестве красивой морды) за пределы его песочницы посещала меня давно, равно как и регулярно.(В предыдущих моих постах слышны отголоски этих посещений :)) Лейтмотивом мотивации являлось: "Какое было бы счастье забыть про Win32\MFC\wxWidgets\WinForms\Qt\Gtk\jQuery и прочее и прочее". И вот оно (счастье), кажется, медленно, но верно надвигается. Вы спрашиваете причём тут haXe?

А вот причём: ECMAScript-образный язык haXe (т.е. он похож на AS3\javascript) позволяет нам (кроме всего прочего) компилить один и тот же исходник как в swf, так и в executable файл. Специально подчеркну, что исполняемый файл получается путём совершенно легальной компиляции промежуточного cpp-кода, (полученного из haXe сорцов) и линковкой с библиотеками хакса(open-source между прочим). На данный момент библиотеки имплементированы для 4х разных платформ: Win32, Linux, Mac и (та-дам!) iPhone.
Приведу кусок haxe-кода:

class Application extends MovieClip
{
public var surface:Sprite;

public function new()
{
super();
surface = new Sprite();
this.addChild(surface);
timer = new Timer(50);
timer.addEventListener(TimerEvent.TIMER, handlerTimer);
surface.addEventListener(MouseEvent.CLICK, handlerClick);
sprite.graphics.beginFill(0x00ff00, 0.5);
sprite.graphics.drawEllipse(20, 30, 25, 35);
sprite.graphics.endFill();
trace(width);
}

Ничего не напоминает? :) Этот код може быть скомпилен в swf. И этот же код БЕЗ ИЗМЕНЕНИЙ компилится в EXE-шник (под виндой) и мало того, он ещё и работает! И для его работы никакой AdobeFlash-плеер не требуется! И в самом экзешнике ни про какого Adobe не знают и знать не хотят!!! Всё, здесь у меня начинается истерика:)).

Теперь можно задать такой вопрос: "Ну и чо? Ну есть, ну компилится, ну EXE-шник, а в чём радость-то ... profit где?!?". Нету! :) Пока - нету. Но есть мысли и я их хочу проверить, и если в том будет хоть капля смысла - реализовать. Вот парочка, в качестве затравки:


  • Портануть neash под WinMobile и посмотреть как оно будет вертеться там

  • Портировать на haXe (а значит и в native на разных плафтормах) его... FLEX SDK!




Кстати, если первое сложить со вторым, то получаем единственный вменяемый GUI фреймворк под WinMobile. Краткий обзор существующих там фреймворков: .NET CF+WinForms = 20 Mb DLLек и просто "никакая" кастомизация контролов. Qt=15 Mb DLLек и неюзабельные тормоза. Остальное - дикий и беспощадный хардкодинг. А в случае успеха затеи мы имеем 3 Mb DLLек и предположительно хорошее быстродействие(хотя тут конечно бабушка надвое)

Ну, это всё лирика. Переходим к практическим занятием. В следующей части расскажу как я настраивал FlashDevelop и окружение и как скомпилил первую пару swf-exe. Спасибо за внимание.