アーカイブ

‘Flash (ActionScript)’ カテゴリーのアーカイブ

ActionScript 上で DOM 操作を行う

unbland as3 library の機能で ActionScript 上で JavaScript の DOM 操作やイベントハンドリングを行う機能があります。そんな機能の紹介です。

ActionScript
package {

import flash.display.Sprite;
import org.unbland.core.events.JSEvent;
import org.unbland.core.external.JavaScript;
import org.unbland.core.external.JSObject;

public class Example extends Sprite
{
    public function Example():void
    {
        // JS が利用できない環境なら終了
        if (!JavaScript.enabled) {
            return;
        }

        // JavaScript.proxy で JS 操作用のオブジェクトを取得
        var document:JSObject = JavaScript.proxy.document;
        var body:JSObject = document.body;

        // 最初は赤色に
        body.style.backgroundColor = "#FF0000";

        // ドキュメント領域をクリックしたらイベントを発生させる
        document.addEventListener(JSEvent.CLICK, function (e:JSEvent):void
        {
            // イベントが発生したら黄色に
            body.style.backgroundColor = "#FFFF00";

            // イベントの詳細情報をアラート
            var temp:String = "";
            for (var key:String in e.info) {
                temp += "key : " + key + " / value : " + e.info[key] + "\n";
            }
            JavaScript.alert(temp);
        });
    }

}

}

自作ライブラリを公開しました

2009 年 4 月 1 日 muta244@admin コメント 4 件

アイキャッチ画像

※ 09.04.16 追記:
バージョンアップしました。くわしくは “自作ライブラリのスクロールペインをバージョンアップ” をご覧下さい。

Bitbucket に自作ライブラリを一挙に公開しました。unbland as3 library といいます。現在開発中ではありますが、公開記念に UI 作成用のクラスを紹介したいと思います。

スクロールペインのデモ(※ 要 FlashPlayer 9)

「コンポーネントを使えば?」なんて声が聞こえてきそうですが、標準のコンポーネントはスクロールのイージングに対応していなかったり、スキンのカスタマイズがものすごく面倒くさかったり、拡張性が低かったり、バグが多かったりと問題が多い(扱ったことがある方なら分かって頂けるかと思います)ので自分で実装してみました。

出来るだけ拡張性を持たせ、且つ見た目のカスタマイズなどが簡単に行えるように作成しているつもりです。具体的には、Flash IDE 上でデザインしたオブジェクトにインスタンス名を付け、抽象クラスを継承させたクラスで各種設定を記述するだけで簡単に作成出来ます。

その他にも色々な機能を実装していますので、興味の有る方は unbland as3 library Wiki をご覧になって遊んでみて下さい。サンプルなんかも置いています。今後は TextInput, TextArea, ComboBox など、最近の Flash 案件で良く使うようになってきた UI については実装していきたいなーと思っています。

Wonderfl が面白い

kayac さんが Wonderfl というサービスをリリースしていたのですが、これがかなり面白い。サーバー上で書いた ActionScript がそのままリアルタイムでコンパイルされて表示されるので、かなりのお手軽さ。試しに自分も前に作った 3D ドーナッツを投稿してみました。ここから。ブログパーツにまで出来ちゃうから、ちょっと試してみたい時にも気軽に使えますね。ただ、環境によって BitmapData のエラーが出るのは FlashPlayer の所為?

ちなみにブログパーツ↓

カテゴリー: Flash (ActionScript) タグ:

ActionScript 3 で抽象クラス

Java でいう abstract 修飾子がないので疑似実装するしかないですが、今までは getQualifiedClassName() 使ってクラス名を取得後、文字列で判別してました。でも前回のエントリーで constructor プロパティの有用性を知ったので、こちらを使っての実装法を考えてみました。

※ 09.04.09 追記:
Proxy を継承したクラスのインスタンスの場合で constructor プロパティを呼び出した場合、Object#constructor でなく Proxy#getProperty が優先的に呼ばれるので注意が必要です。Proxy クラスを継承したクラスには constructor のゲッターで自クラスの参照を返すことでこの問題を回避出来ます。

ActionScript
// AbstractClass
package
{
    public class AbstractClass
    {
        public function AbstractClass():void
        {
            if (Object(this).constructor == AbstractClass) {
                throw new Error("このクラスは抽象クラスなので直接インスタンス化できません.");
            }
        }
    }
}

// SubClass
package
{
    public class SubClass extends AbstractClass
    {
        public function SubClass():void
        {

        }
    }
}

こんな感じにしておけば、new AbstractClass() だとエラーになりますが、new SubClass() だとインスタンス化できます。className プロパティとかを実装したいのであれば、やっぱり getQualifiedClassName() を使わないといけませんが、そうでなければこの方法で十分な気がします。

この方法を考えてる時に constructor プロパティの取得法がいまいち分からなかったんですが、seyself さんから教えていただきました。ありがとうございます。

ActionScript 3 での色々な文字列の扱い方

2008 年 10 月 28 日 muta244@admin コメント 8 件

ActionScript 内で JavaScript を操作する時には ExternalInterface を使いますが、複雑なことをする時にはどうしても以下のような感じになります。

ActionScript
ExternalInterface.call(
    "function ()" +
    "{" +
        "var temp = 'test';" +
        "temp += 'string';" +
        "alert(temp);" +
    "}"
);

これだと文字列の連結が多すぎで分かりにくくなってしまうんですが、ActionScript は CDATA セクションを文字列として扱うためこんなやり方もあります。

ActionScript
ExternalInterface.call(<![CDATA[
    function ()
    {
        var temp = "test";
        temp += "string";
        alert(temp);
    }
]]>);

カテゴリー: Flash (ActionScript) タグ: ,

AS3 での Singleton パターン実装

2008 年 10 月 23 日 muta244@admin コメント 4 件

AS3 での Singleton パターン実装はなかなか面倒くさいやり方が多いですが、ちょっとシンプルな実装法を思いついたので紹介します。

ActionScript
package
{
    public class Singleton
    {
        private static var _instance:Singleton = new Singleton();

        public function Singleton():void
        {
            if (_instance)
            {
                throw new ArgumentError("Singleton クラスは外部からインスタンス化できません.");
            }
        }

        public static function get instance():Singleton
        {
            return _instance;
        }
    }
}

※ 08.10.23 追記:
コンストラクタ内部で _instance = this をしていましたが、コメントを受けて修正しました。

内部で最初に new してしまっておくだけなんですが、今まで思いつきませんでした。問題になりそうな点があったらコメントお願いします。

FlashDevelop on Mac (Linux) の可能性が出てきた?

ネットサーフィン(って最近聞かないですね)してたら気になる情報が。

Mono 2.0 がリリースされたことにより FlashDevelop on Mac (Linux) の可能性が出てきたっぽいです。要は FlashDevelop は .NET で作られてるので、Mac 上で .NET が動かせる Mono により移植出来るようになったと。実際に Linux 上で動いている FlashDevelop の画像もあるので期待出来そうですね。

ただ、最初のリンク内で FlashDevelop 開発者の Mika さんがコメントされているように、肝心な構文解析やエディタ部分のエンジンが .NET ではないため、そこの移植はセカンドチーム(募集中?)次第みたいです。

エディタの善し悪しで作業効率が全然違うので、FlashDevelop on Mac が出来たら FlashDevelop on VMWare Fusion なんかとっととサヨナラするぐらい個人的にはテンション上がります。最後に、りちゃさん情報ありがとうございました!

カテゴリー: Flash (ActionScript) タグ:

Pixel Bender で放射状ブラー(ズーム&回転)

困った beinteractive さんの発言を受けて Pixel Bender で放射状ブラーを作ってみました。パラメータいじれるようにと思って Flex Builder に初挑戦してみたんですが、これのせいで余計に時間が掛かってしまった・・・。

放射状ブラーのデモ
放射状ブラーのデモ(※ 要 Flash Player 10)

関連ファイルはスパークプロジェクトの RadialBlur に一式上げてます。簡単に説明をすると、対象のピクセル間近 9 つのポイントをサンプリング&加重移動平均法を使って平滑化し、ピクセル色として適用しています。Pixel Bender はループ処理とか関数が使えない(Flash Player 向けの場合)ので、同じような文章が並んでかなり不格好ですが・・・。Pixel Bender の更なるバージョンアップに期待。

あと、Saqoosha さんも同じ事に挑戦されてました。違うアプローチで面白い。

カテゴリー: Flash (ActionScript) タグ:

[Flash Player 10 #7] シェーダ (Pixel Bender) を使った頂点計算の最適化 2

2008 年 5 月 29 日 muta244@admin コメント 4 件

前回のエントリーでは複雑なことをしてシェーダにデータを渡そうとしていましたが、Saqoosha さんからコメント欄で教えていただいた boostworthyisryantaylor というサイトの情報(ShaderJob クラスなど)を元に、シェーダでの頂点情報の計算に成功しました。

フレームレートが 20 を切る分割数を計測(Z ソートは今回無し)

従来の通りの頂点計算 => 分割数 75、頂点数 5625
シェーダを使った頂点計算 => 分割数 80、頂点数 6400

こんな感じで、望んでいたような劇的な変化はありませんでした。自分の環境は普通の MacBook ですので GPU は搭載されていませんが、GPU がある環境では wmode を gpu とかにすれば結果は変わってくるんでしょう。試してないですが。

従来の通りの頂点計算デモはこちら
シェーダを使った頂点計算デモはこちら

※ 要 Flash Player 10
※ 左右キーで分割数、上下キーで視野角を変更できます。

boostworthyisryantaylor さんでも書かれているように、現在はバグなのか、ShaderInput に Vector.<number> を渡すとエラーになるので ByteArray で渡しています(ドキュメントでは渡せると書いてあります)。この問題が直れば幾分は良くなるでしょうが、あまり期待はできないのかも。引き続き、調査は続けていくつもりです。とりあえずは Vector.<number> が渡せるようになるのを待つつもりですが。

http://www.libspark.org/svn/as3/Astro/VertexShader_01/

に今回のコードを上げましたので必要な方はチェックアウトしてください。

[Flash Player 10 #6] シェーダ (Pixel Bender) を使った頂点計算の最適化 1

2008 年 5 月 28 日 muta244@admin コメント 2 件

3D でボトルネックになるのは描画と頂点情報の計算などです。描画については drawTriangles という便利なメソッドがあるのでまだ良いとして、頂点情報については for で回して計算するのが常套手段ですが、最近はシェーダ(Pixel Bender)を使っての最適化に挑戦しています。

‘08 5.29 追記:
Saqoosha さんからコメント欄で頂いた情報を元に新しいエントリーを投稿しました。このエントリーでしているような複雑なことをしなくても、シェーダにデータを渡せますのでそちらを参照ください。
—–

そのためにまず必要になるのが、どのようにシェーダ側にデータを渡すかというところ。シーンの行列などはパラメータで渡せるのですが、頂点の情報量は不定のためパラメータとしては渡せません(そもそも、シェーダは Flash 用に書き出す設定では配列に対応していませんし)。ですので、ピクセルに頂点座標を埋め込もうとしたのですが、これも中々うまくいかず、現状はここで止まってます。

流れを追って説明すると以下のような感じ。

1. Flash 側 − ビットマップに頂点情報を埋め込む。

浮動小数点数な頂点情報を、ビットマップに 15.15 形式の固定小数点数な uint(32 bit) として埋め込む。(ビットマップに書き込む際にアルファ値が 0 だと他の色情報まで 0 になってしまうため、32 bit 目は 1 で固定。また、31 bit 目は正負を表すために 15.15 形式)

例えば {x:100, y:0, z:0} の頂点一つのデータを埋め込むコードは以下。

ActionScript
var vector:Vector. = Vector.([
    // 100 &lt;&lt; 15 | 0x80000000 でも良い。
    // ただ、ビット演算は計算によってはオーバーフローを起こすので注意。
    // ちなみに 0x80000000 は 32 bit 目を 1 にするため。
    100 * 0x8000 + 0x80000000, 0, 0
]);
var data:BitmapData = new BitmapData(3, vector.length / 3);
data.setVector(data.rect, vector);

2. シェーダ側 − ピクセルから頂点情報を抜き出す。

シェーダ側でピクセルをサンプリングすると float4(a, r, g, b) の形になるので、これをもう一度固定小数点数に戻す。ただし、Pixel Bender の int 型は 16 bit なので float 型で取り扱う。

コードは以下。

ActionScript
// BIT_24 は 16777216.0、BIT_16 は 65536.0、BIT_08 は 256.0 をそれぞれ定数化したもの
pixel4 tmp = sampleNearest(src, outCoord());
float n = floor(tmp.a * 255.0) * BIT_24
        + floor(tmp.r * 255.0) * BIT_16
        + floor(tmp.g * 255.0) * BIT_08
        + floor(tmp.b * 255.0);

3. シェーダ側 − 頂点情報を計算。

パラメータで受け取った行列などを元に、頂点情報を計算する。ここは実際には試していないが、大した問題ではないはず。

4. シェーダ側 − ピクセルに埋め込むために各色情報を分解。

Pixel Bender はビット演算が行えないため、乗算・除算を使って分解します。

コードは以下。

ActionScript
float a = floor(n / BIT_24);
float r = floor(n / BIT_16) - (a * BIT_08);
float g = floor(n / BIT_08) - (a * BIT_16 + r * BIT_08);
float b = floor(n         ) - (a * BIT_24 + r * BIT_16 + g * BIT_08);

いま、つまづいているのがまさにここ。例えば、n が 4294770688.0({a:255, r:253, g:0, b:0})の時は誤差が生じて r 成分が 254 になってしまいます。試しに、ActionScript で同様のコードを実行しても誤差は生じず・・・。

同様のコード。

ActionScript
var BIT_24:Number = 16777216.0;
var BIT_16:Number = 65536.0;
var BIT_08:Number = 256.0;

var BYTE:Number = 255.0;

var dst:Object = {a:255/255, r:253/255, g:0/255, b:0/255};

var n:Number = Math.floor(dst.a * BYTE) * BIT_24
             + Math.floor(dst.r * BYTE) * BIT_16
             + Math.floor(dst.g * BYTE) * BIT_08
             + Math.floor(dst.b * BYTE);

trace(n); // 出力 =&gt; 4294770688

var a:Number = Math.floor(n / BIT_24);
var r:Number = Math.floor(n / BIT_16) - (a * BIT_08);
var g:Number = Math.floor(n / BIT_08) - (a * BIT_16 + r * BIT_08);
var b:Number = Math.floor(n         ) - (a * BIT_24 + r * BIT_16 + g * BIT_08);

trace(dst.a, dst.r, dst.g, dst.b); // 出力 =&gt; 1 0.9921568627450981 0 0
trace(aa / BYTE, rr / BYTE, gg / BYTE, bb / BYTE); // 出力 =&gt; 1 0.9921568627450981 0 0

色々とデバッグ(Pixel Bender はデバック面倒過ぎ!)して分かったことは、除算を行うと何故か誤差が生じてしまい、うまく分解できていないということ。内部の計算に使用できる bit 数が異なるために起こる誤差なのか、何なのか・・・。誰か助けていただけませんか。