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

Обновление класса Filereference в 10 плеере

В новой десятке класс Filereference стал более "безопасным". Теперь метод FileReference.browse() нельзя будет вызвать программно, а только в ответ на нажатие клавиатуры или мыши. В связи с этим возникнет необходимость переделывать флешовые аплоадеры для Flickr, SWFUpload и Wordpress.
Как говорят в Adobe, данная мера вызвана необходимостью повышения безопасности - якобы пользователя может ввести в заблуждение внезапно появившееся окошко и он случайно сохранит не то, что нужно:)
Источник

Во Flash-видео скоро появится новый тип метаданных

В скором времени Adobe Systems представит на обозрение новую фичу видео - voice-to-text. Это означает, что вся произносимая речь будет переведена в метаданные и внедрена в видео-ролик с помощью средств для редактирование видео от Adobe. Внедрение данной разработки окажет огромное влияние на индексацию видео-контента и видео-рекламу.

Jim Guerard, заведующий всем rich media в Adobe, говорит, что данный функционал мы сможем увидеть уже в этом году.

четверг, августа 14, 2008

Откуда у функции length?

На днях столкнулся с такой проблемой.
После переноса цикла в функцию, в последней остался параметр length, который был локально обозначен перед циклом и был успешно там забыт. Но ошибки компилятор не выдал и косяк не был замечен сразу. Потом я обратил внимание на этот загадочный length.
Откуда же он взялся?
А взялся он от функции и равен количеству аргументов, заданных в сигнатуре функции. Он отличается от arguments.length тем, что arguments.length равен реально переданному количеству аргументов. Например, если компилировать в standard mode:
function traceLength(x:uint, y:uint):void
{
trace("получено: " + arguments.length);
trace("ожидалось: " + traceLength.length); // или просто length
}

traceLength(3, 5, 7, 11);
/* output:
получено: 4
ожидалось: 2 */
Ссылка на доку

пятница, августа 01, 2008

Поддержка AMF cкоро будет в Zend Framework

Так называемый Zend_Amf_Server обеспечит поддержку формата AMF для Zend Framework. Участвовать в проекте будет Wade Arnold - человек, ведущий проект AMFPHP. Надеюсь эта новость оправдает тормоза в релизах AMFPHP, который завис на бете в сентябре 2007 года.

среда, июля 30, 2008

14 июля начато строительство моста ...

...между Adobe Air и Java под названием Merapi.
Merapi - это фреймворк, объединяющий оба типа приложений, запущенных на десктопе и выступающий так называемым мостом между ними. Взаимодействие реализовано с помощью класса merapi.Bridge, реализованного как для Air, так и для Java. С помощью Merapi Air-приложение может выступать интерфейсом к Java-приложению, что позволит расширить возможности приложения до бесконечности. В общем, кому интересно - добро пожаловать на сайт проекта.

вторник, июня 10, 2008

Small Worlds

Никогда особо не интересовался всякими онлайн-играми, но недавно пришло приглашение в бета-версию игры Small Worlds и, зарегистрировавшись там, я был мягко говоря поражен ее крутотой.

SmallWorlds - это виртуальный 3D мир, который создается самими игроками. Это флексовый проект, созданный студией Outsmart из Новой Зеландии. С серверной стороны используется Java. Также используется вебсервис Amazon’а Elastic Compute Cloud, также известный как EC2. Этот виртуальный сервер позволяет SmallWorlds масштабироваться на 1000 серверов в считанные минуты.

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



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



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



В планах на будущее:
  • куча опций для аватаров
  • API для Flash разработчиков
  • множество игр
  • виджеты

В общем лучше один раз увидеть, как говорится.

пятница, июня 06, 2008

Один ItemRenderer для нескольких колонок

Столкнулся с задачей отображения в DataGrid одинаковых по сути данных (UNIX_TIMESTAMP), к которым нужно применить ItemRenderer так, чтобы последний знал к какой колонке он применяется. Я нашел два способа это сделать и оба связаны с использованием свойства listData. Свойство listData имеют такие элементы как Text, Label, Button, CheckBox и т.п., то есть те, которые имплементируют интерфейс IDropInListItemRenderer. В данном случае в качестве ItemRenderer мне достаточно использовать Label. Если же необходим какой-нибудь контейнер в качестве рендерера, который не имеет свойства listData по-умолчанию, его необходимо реализовать своими силами.
Итак, первый способ - это назначать данные для рендерера в зависимости от индекса колонки таблицы. Приведу кусок кода:

<mx:Label xmlns:mx="http://www.adobe.com/2006/mxml">
...
override public function set data(value:Object):void
{
super.data = value;
var myListData:DataGridListData = DataGridListData(listData);
var colIndex:int = myListData.columnIndex;
switch (colIndex)
case 1: text = data.date1; break;
case 2: text = data.date2; break;
}
...
</mx:Label>

Здесь мы обращаемся к listData, кастим его к DataGridListData, получаем индекс колонки таблицы и в зависимости от индекса отображаем в колонках date1 или date2. Недостатком этого способа является то, что при добавлении новых колонок перед этими придется переделывать код рендерера и также нельзя перетаскивать колонки. Поэтому рассмотрим второй способ.

<?xml version="1.0" encoding="utf-8"?>
<mx:Label xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridListData;
[Bindable] private var formattedVal:String;

override public function set data(value:Object):void
{
super.data = value;
if (value)
{
var myListData:DataGridListData = DataGridListData(listData);
var dt:Date = new Date();
var cellVal:int = int(data[myListData.dataField]);
dt.time = cellVal*1000;
formattedVal = dateformatter.format(dt);
}
}
]]>
</mx:Script>
<mx:DateFormatter id="dateformatter" formatString="DD.MM.YY J:NN"/>
<mx:text>{formattedVal}</mx:text>
</mx:Label>

В данном случае мы обращаемся не к columnIndex, а к dataField, таким образом получая строку, в которой содержится название поля, из которого мы получаем данные. А с помощью data[myListData.dataField] мы получаем значение этого поля.

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

Пример динамического наложения двух mp3

Поигрался с примером Tinic Uro по поводу новых методов класса Sound, в частности, extract():
function extract(target:ByteArray,
length:Number,
startPosition:Number = -1 ):Number;

  • target - ByteArray, в который помещаются извлеченные сэмплы (samples);
  • length - количество сэмплов. Сэмпл содержит левый и правый каналы, каждый из которых представляет числа с плавающей точкой.
  • startPosition - позиция, с которой начнется извленение. Если она не указана, то извлечение будет идти с начала.
  • extract() - возвращает количество сэмплов, но оно может быть меньше запрошенной длины в самом конце звука.
Вот немного переделанный пример того, как можно наложить два звука друг на друга:


package
{
import flash.display.Sprite;
import flash.events.*;
import flash.media.*;
import flash.net.URLRequest;
import flash.utils.ByteArray;

public class SoundTest extends Sprite
{
private var mp3sound0:Sound = new Sound();
private var mp3sound1:Sound = new Sound();
private var dynamicSound:Sound = new Sound();
private var samples0:ByteArray = new ByteArray();
private var samples1:ByteArray = new ByteArray();

public function SoundTest()
{
mp3sound0.addEventListener(Event.COMPLETE, loadComplete0);
mp3sound0.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
//загрузка первого файла
mp3sound0.load(new URLRequest("sound0.mp3"));
}

private function loadComplete0(event:Event):void
{
mp3sound1.addEventListener(Event.COMPLETE, loadComplete1);
mp3sound1.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
//загрузка второго файла по событию загрузки первого
mp3sound1.load(new URLRequest("sound1.mp3"));
}

private function onIOError(e:IOErrorEvent):void
{
trace(e.text);
}

private function loadComplete1(event:Event):void
{
//начало динамического наложения звуков
dynamicSound.addEventListener("samplesCallback",samplesCallback);
dynamicSound.play();
}

private function samplesCallback(event:SamplesCallbackEvent):void
{
//установка массивов на нулевую позицию
samples0.position = 0;
samples1.position = 0;
var len:Number = 1000;
//извлечение сэмплов в массивы
mp3sound0.extract(samples0, len);
mp3sound1.extract(samples1, len);
//установка массивов на нулевую позицию
samples0.position = 0;
samples1.position = 0;
for (var c:int = 0; c < len; c++)
{
//получение значение каналов и их сложение
var left:Number = samples0.readFloat() + samples1.readFloat();
var right:Number = samples0.readFloat() + samples1.readFloat();
//запись значений в объект динамического звука
dynamicSound.samplesCallbackData.writeFloat(left);
dynamicSound.samplesCallbackData.writeFloat(right);
}
}
}
}

вторник, мая 27, 2008

Новые методы и свойства старых классов FP10

ByteArray
clear()
deflate()
inflate ()

Mouse
cursor

ContextMenu
clipboardMenu
clipboardItems
link

Capabilities
hasColorCorrection

ApplicationDomain
domainMemory
MIN_DOMAIN_MEMORY_LENGTH

NetStream
farID
farNonce
info
nearNonce
peerStreams
onPeerConnect()
play2()
DIRECT_CONNECTIONS

NetConnection
farID
farNonce
maxPeerConnections
nearID
nearNonce
protocol
unconnectedPeerStreams

FileReference
data
load()
save()

Sound
extract()
sampleData

Microphone
codec
encodeQuality
framesPerPacket

Event
CLEAR
COPY
CUT
PASTE
SAMPLE_DATA
SELECT_ALL

Stage
enableColorCorrection

MovieClip
currentFrameLabel

Graphics
beginShaderFill()
drawGraphicsData()
drawPath()
drawTriangles()
lineBitmapStyle()
lineShaderStyle()

DisplayObject
blendShader
rotationX
rotationY
rotationZ
z
globalToLocal3D ()
local3DToGlobal ()

BitmapData
histogram()

BlendMode
SHADER

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

вторник, апреля 29, 2008

Эффект Fade для текста без внедрения шрифта

Как известно, чтобы применить эффект Fade к тексту (плавное его появление и исчезновение), необходимо, чтобы соответствующий шрифт был внедрен в приложение. Но в результате размер приложения существенно увеличится. Чтобы избежать этого, но сохранить красоту эффекта, необходимо перед началом превратить текст в битмап с помощью пустого эффекта BlurFilter с нулевыми значениями:
private function addBlurFilter():void {
var bf:BlurFilter = new BlurFilter(0,0,0);
var myFilters:Array = new Array();
myFilters.push(bf);
label.filters = myFilters;
}
А потом уже запускать эффект Fade.
Есть еще один способ - применить эффект Dissolve. В отличии от Fade, который работает непосредственно с элементом, Dissolve создает непрозрачный прямоугольник над элементом и работает уже с ним. Но этот эффект хорошо смотрится только на белом фоне, так как иначе он будет виден поверх нашего объекта.
Отсюда

среда, марта 26, 2008

RubyIZUMI - опенсорсный RTMP сервер (MP4/H.264) для потокового Flash видео и аудио

Takuma Mori из Vixy.tv недавно зарелизил RubyIZUMI - открытый потоковый сервер (Ruby) для проигрывания H.264 видео.
Демо.

вторник, марта 25, 2008

Атрибуты метатега SWF

Официально опубликованы все атрибуты метатега SWF

[SWF width="#"
height="#"
widthPercent="#"
heightPercent="#"
scriptRecursionLimit="#"
scriptTimeLimit="#"
frameRate="#"
backgroundColor="#"
pageTitle="String"]

Напомню, что данный тег должен располагаться непосредственно перед определением AS-класса:

[SWF(width="1024", height="768", frameRate="31", backgroundColor="#000000")]
public class Main extends Sprite {...

четверг, марта 20, 2008

Повышение производительности AS3 приложений

Здесь представлены некоторые приемы, которые помогут повысить производительность наших приложений:

1) Создавайте константы для часто используемых объектов типа new Point(0,0) или new Rectangle(0,0,320,240):

//вызов 100000 раз: 75мс
new Point(0,0);
//или
private static const POINT:Point = new Point(0,0);
//8мс
POINT;


Быстрее на 838%

2) Сократите указания на статические члены классов. Вместо этого старайтесь использовать переменные пакета:
//15мс
SomeClass.somevar;
package somepackage{
public const somevar:int;
}
//8мс
somevar;

на 66% быстрее

3) Сохраняйте getter свойства в локальных переменных при их использовании более одного раза.

somesprite.graphics.clear();
somesprite.graphics.beginFill(0x000000);
somesprite.graphics.drawRect(0,0,10,10);
somesprite.graphics.endFill();

// лучше заменить на

var n:Graphics = somesprite.graphics;
n.clear();
n.beginFill(0x000000);
n.drawRect(0,0,10,10);
n.endFill();


4) Создавайте собственные reflection-методы вместо использования getDefinitionByName(getQualifiedClassName(object))
utils reflection
// 503мс
var someclass:Class = getDefinitionByName(getQualifiedClassName(someObject));
// getter reflection
public class SomeClass {
public function get reflect():Class {
return SomeClass;
}
}
// 9мс
var someclass:Class = object.reflect();

быстрее на 5489%

5) Страрайтесь использовать строгое типизирование

6) Приводите к нужным типам, например, при чтении из массива.
Быстрее будет обращаться к image

var image: BitmapData = images[index];
image.getPixel(x,y)
//чем к
images[index].getPixel(x,y);


7) Где возможно, используйте int вместо Number

8) Операторы побитового сдвига работают быстрее:

Побитовый сдвиг влево быстрее на 300% при умножении на любую степень двойки:

x = x * 2;
x = x * 64;
//равно:
x = x << 1;
x = x << 6;


Побитовый сдвиг вправо быстрее на 350% при делении на любую степень двойки:

x = x / 2;
x = x / 64;
//равно:
x = x >> 1;
x = x >> 6;


Извлечение компонентов цвета:

//24bit
var color:uint = 0x336699;
var r:uint = color >> 16;
var g:uint = color >> 8 & 0xFF;
var b:uint = color & 0xFF;
//32bit
var color:uint = 0xff336699;
var a:uint = color >>> 24;
var r:uint = color >>> 16 & 0xFF;
var g:uint = color >>> 8 & 0xFF;
var b:uint = color & 0xFF;


Объединение компонентов цвета:

//24bit
var r:uint = 0x33;
var g:uint = 0x66;
var b:uint = 0x99;
var color:uint = r << 16 | g << 8 | b;

//32bit
var a:uint = 0xff;
var r:uint = 0x33;
var g:uint = 0x66;
var b:uint = 0x99;
var color:uint = a << 24 | r << 16 | g << 8 | b;


9) Обмен значениями численных переменных без использования временной переменной:

var t:int = a;
a = b;
b = t;
//равно:
a ^= b;
b ^= a;
a ^= b;


Быстрее на 20%.

10) Инкремент/декремент.
Внимание: это пример понижения производительности, но зато есть возможность понизить читабельность кода для врагов:)

i = -~i; // i++
i = ~-i; // i--


11) Смена знака с помощью NOT или XOR (говорят на 300% быстрее):

i = -i;
//равно:
i = ~i + 1;
//или
i = (i ^ -1) + 1;


12) Подсчет остатка

Если делитель является степенью двух, то остаток можно подсчитать быстрее на 600% следующим образом:
остаток = делимое & (делитель - 1);

x = 131 % 4;
//равно:
x = 131 & (4 - 1);


13) Проверка на четность/нечетность:

isEven = (i % 2) == 0;
//равно:
isEven = (i & 1) == 0;


Быстрее на 600%.

14) Абсолютное значение. Версия 1 быстрее на 250%, чем Math.abs(), а версия 2 быстрее на 20%, чем версия 1.

//версия 1
i = x < 0 ? -x : x;
//версия 2
i = (x ^ (x >> 31)) - (x >> 31);


15) Сравнение двух числе на равенство знаков

eqSign = a * b > 0;
//равно:
eqSign = a ^ b >= 0;


На 35% быстрее.

16) Быстрое конвертирование цвета из R5G5B5 в R8G8B8

R8 = (R5 << 3) | (R5 >> 2)
G8 = (R5 << 3) | (R5 >> 2)
B8 = (R5 << 3) | (R5 >> 2)

17) a++ быстрее, чем a = a + 1 и т.п.

18) Умножение быстрее деления.

Лучше использовать a = b*.5 вместо a = b / 2

19) int(1.5) быстрее, чем Math.floor(1.5)
Аналогично int(1.5) + 1 быстрее, чем Math.ceil(1.5)

пятница, февраля 29, 2008

Улучшаем Flash 9 IDE

Lee Brimelow предлагает вашему вниманию три кастомные панельки для Flash IDE:
  • Event Generator - генератор событий. Необходимо выбрать мувиклип, открыть панель (Window > Other Panels), определить необходимые события, скопировать в буфер и потом вставить готовый код куда нужно. Это значительно облегчает монотонные записи добавления событий.
  • Калькулятор - считаем не выходя из любимой IDE.
  • Панель заметок позволяет легко сохранять интересные куски кода с названиями.
Также автор выложил видео Building Custom Flash Panels о том, как создавать собственные панели.

четверг, февраля 28, 2008

Использование RSL классов фреймворка и кэширование в плеере

Эта статья является вольным и неполным переводом статьи из хелпа по поводу использования RSL и кэширования плеера.

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

Чтобы не внедрять одни и те же классы на этапе компиляции, можно использовать внешние библиотеки классов (Runtime Shared Libraries или RSL) классов flex-фреймворка, то есть подгружать эти классы на этапе загрузки приложения. Существует два вида RSL классов фреймворка – подписанные и неподписанные. Подписанные RSL кэшируются плеером, доступ к ним возможен из любых приложений вне зависимости от доменов. Они не удаляются при очистке кэша браузера. Неподписанные RSL кэшируются браузером и могут использоваться только приложениями, которые имеют доступ к домену RSL.

Flash Player 9.0.115 поддерживает загрузку подписанных RSL классов фреймворка. Эти RSL имеют расширение SWZ, и только Adobe может их создавать. Для плееров версий ниже 9.0.115 будут автоматически загружаться запасные неподписанные RSL, если конечно они были определены при компиляции приложения.

Только приложения, скомпилированные с помощью Flex 3, могут использовать подписанные RSL.

Существующие RSL

Для SDK RSL классов фреймворка находятся в папке flex_sdk_dir/frameworks/rsls, для Flex Builder - flex_builder_dir/sdks/3.0.0/frameworks/rsls. Файлы именуются следующим образом – версия Flex плюс версия сборки компилятора. Следующие RSL классов фреймворка включены в продукты Flex:

  • framework_3.0.build_number.swz (подписанная RSL классов фреймворка)
  • framework_3.0.build_number.swf (неподписанная RSL классов фреймворка)
  • rpc_3.0.build_number.swz (подписанная RSL классов сервисов данных (data services)
  • rpc_3.0.build_number.swf (неподписанная RSL классов сервисов данных)
  • (Только для Flex Builder) datavisualization_3.0.build_number.swz (подписанная RSL классов визуализации данных)
  • (Только для Flex Builder) datavisualization_3.0.build_number.swf (неподписанная RSL классов визуализации данных)

Данные библиотеки уже оптимизированы.

Flex также включает некоторые SWC файлы, которые можно использовать как стандартные или кросс-доменные RSL. Эти библиотеки неоптимизированны и не подписаны. Они находятся в папке frameworks/libs: automation.swc и qtp.swc. Это классы для автоматизированного тестирования приложения.

Кэш плеера

По умолчанию, максимальный размер кэша плеера равен 20MB. После превышения этого размера кэш автоматически очищается от файлов, которые реже всего использовались. Очистка происходит, пока размер кэша не станет меньше 60%, то есть по умолчанию 12MB. С помощью Settings Manager можно регулировать место, отведенное под кэш плеера.

В следующей таблице показаны папки, в которых плеер хранит кэш:

Windows 95/98/ME/2000/XP - C:\Documents and Settings\user_name\Application Data\Adobe\Flash Player\AssetCache\

Windows Vista - C:\Users\user_name\AppData\Roaming\Adobe\Flash Player\AssetCache\

Linux - /home/user_name/.adobe/Flash_Player/AssetCache/

Mac OSX - /Users/user_name/Library/Cache/Adobe/Flash Player/AssetCache/

Использование RSL классов фоеймворка

Использовать RSL классов фреймворка просто:

  1. заходим в свойства проекта;
  2. Flex Build Path -> Library Path
  3. Раскрываем Flex 3 -> framework.swc -> Link type -> Edit
  4. Ставим в выпадающем списке RSL и добавляем (Add) 2 файла – framework_build_number.swz и framework_build_number.swf
  5. Теперь эти два файла сохранятся в вашем проекте

Кстати, размер пустого приложения при использовании внешних библиотек сократился со 150 Кб до 50, правда сама библиотека весит порядка 550Кб, но она сохраняется в кеше и грузится только один раз.

среда, февраля 27, 2008

Проект Open Flash Chart

Наткнулся на интересный проект - Open Flash Chart. Попросту говоря, это приятные на вид flash-графики, которые можно легко вставлять на свои страницы.
Проект в первую очередь разрабатывается для PHP, но есть версии и для Java, Perl, Python, Ruby and Rails и .NET (правда, не факт, что они будут той же версии, что и для PHP). В частности, для Ruby and Rails плагин, которые позволяет в два счета создать нужный график.
Кстати, использовать графики можно абсолютно бесплатно, но помощь приветствуется.

четверг, февраля 14, 2008

E4X запросы с учетом namespace'ов

Допустим у нас есть некий XML (например, rss поток):
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
<channel>
<item>
<title>News feeds from the BBC</title>
<description></description>
<link>http://news.bbc.co.uk/go/rss/-/1/hi/help/rss/3223484.stm</link>
<guid isPermaLink="false">http://news.bbc.co.uk/1/hi/help/rss/3223484.stm</guid>
<pubDate>Mon, 21 Aug 2006 08:34:42 GMT</pubDate>
<category>RSS</category>
<media:group>
<media:category>RSS</media:category>
<media:copyright>(C) British Broadcasting Corporation</media:copyright>
</media:group>
</item>
</channel>
</rss>
Чтобы получить данные тегов из пространства имен media необходимо поступить следующим образом:

1) создать пространство имен
var media:Namespace = new Namespace("http://search.yahoo.com/mrss/");

2) обращаться к необходимым узлам с использованием этого пространства имен
var copyright:String = xml.channel.item.media::group.media::copyright.text();

3) Ответ верный:
(C) British Broadcasting Corporation

пятница, февраля 01, 2008

Ошибка при отсутствии атрибута в XML

Возьмем простой xml типа

<data>
<row owner="Andrey"/>
<row owner="Peter"/>
<row/>
</data>


Нам необходимо получить все записи, у которых owner = "Andrey".
Делаем как всегда:

var res:XML = httpServ.lastResult as XML;
var rows:XMLList = res.row.(@owner=="Andrey");


Вылезает ошибка:

ReferenceError: Error #1065: Variable @owner is not defined.

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

1 способ:

var rows:XMLList = res.row.(attribute("owner")=="Andrey");

2 способ:

var xml:XMLList = res.row.(hasOwnProperty("@owner")==true && @owner=="Andrey");