tips  >> 02.プログラミングなど  >> Flex  >> ActionScriptメモ.txt [blog]   [フレームで表示]
 

ActionScriptメモ


TODO係
〜 ユーザ登録はメール1本
携帯電話とメールで始める、ゆるめの家計簿、TODO管理、スケジュール管理。
※「ありもので作れる料理」機能も評判です。


基本的な文法

    変数
        var 変数名:型名;
        var num1:int;
        var textField1:TextField = new TextField();
    
    クラスの定義
        package 所属するパッケージ名 { // パッケージ名省略可
            import xxx;
            import xxx;
            
            // 変数宣言
            アクセス修飾子 var プロパティ名:プロパティの型;
            
            // コンストラクタ
            アクセス修飾子 function コンストラクタ名() {
                this.aaa = dddd;
            }
            
            // メソッド1
            アクセス修飾子 function メソッド名1(引数1:型 = デフォルト値):戻り値の型 {
                return this.mmmm;
            }
        }
    
    Flashを描画するクラスは Sprite クラスを継承する
    
        package {
            public class TestClass extends Sprite {
                // ...
            }
        }
    
    子オブジェクトを追加
        addChild(子オブジェクト);
    
    SWFファイルの埋め込み
        [Embed(source='ファイル名')]
        private var クラス名:Class;
    
    定数 (final ではない)
        public const MAX_LINE:int = 10000;



Hello World

    package {
        import flash.display.Sprite;
        import flash.text.TextField;
        
        public class Test01 extends Sprite {
            public function Test01() {
                var textField:TextField = new TextField();
                textField.text = "hello world";
                addChild(textField);
            }
        }
    }


クラス階層

Object
    Array
    String
     :
    
    EventDispatcher
        DisplayObject
            Bitmap
            InteractiveObject
                DisplayObjectContainer
                    Loader                  <---- 画像やSWFを読み込み可能なコンテナ
                    Sprite                  <---- 空のコンテナ
                        MovieClip           <---- タイムラインを持つコンテナ(?)
                        FlexSprite          <---- Flex 関連のクラスはこの辺
                            UIComponent
                                Container
                                    Canvas
                                    Box
                                        HBox
                                        VBox
                                    Tile
                                SWFLoader
                                    Image
                                Button
                                Label
                    Stage                  <---- 全てのDisplayObjectを保持するコンテナ7
                SimpleButton
                Video
                TextField
            MorphShape <--- オーサリングツールが生成するが、ActionScriptでは生成できない
            Shape
            StaticText <--- オーサリングツールが生成するが、ActionScriptでは生成できない
        
        Socket
        Timer
         :


モーフィングはオーサリングツール(Flash CS3)の「トゥイーン」という機能で作る
    
    マニュアルを引用:
        http://livedocs.adobe.com/flash/9.0_jp/ActionScriptLangRefV3/flash/display/MorphShape.html
        MorphShape クラスは、表示リスト上の MorphShape オブジェクトを表します。
        ActionScript で直接 MorphShape オブジェクトを作成することはできません。
        このオブジェクトは、Flash オーサリングツールでシェイプトゥイーンを
        作成したときに作成されます。 
        
        ⇒ と書いてあるがダンプを見るとそんなクラスは使われていないような・・・



DisplayObject(の子クラスたち)のプロパティ/メソッド

プロパティ
    height
    width
    
    rotation
    
    scaleX
    scaleY
    
    mouseX : マウス座標
    mouseY
    
    x      : 位置の座標
    y
    
    parent : 一個上
    root   : 一番上
    
    localToGlobal




ActionScriptで(MXMLを使わないで) UI周りの記述をする
    
    ※ でもこういう場合は MXML使ったほうが楽だ

    
    プレーンテキスト形式のラベル

        TextFormat : 文字のフォーマットを指定
            var format:TextFormat = new TextFormat();
            format.font = "Courier";
        
        TextField : テキスト表示
            // 作成
            var textField:TextField = new TextField();
            textField.text = "Hello";
            
            // フォーマットを指定
            textField.setTextFormat(format); // 第2引数で開始位置?を指定できる
            
            addChild(textField);

    
    HTML形式のラベル

        StyleSheet : スタイルを設定
            var style:StyleSheet = new StyleSheet
            styleObj.fontSize = "bold";
            styleObj.color    = "#FF0000";
            style.setStyle(".darkRed", styleObj);
            delete styleObj;
            
        TextField : テキスト表示 (使うオブジェクトはプレーンテキストと同じ)
            // 作成
            var textField:TextField = new TextField();
            textField.htmlText = "<span class='darkRed'>Red</span> apple";
            
            // フォーマットを指定
            textField.styleSheet = style;
            
            addChild(textField);
    
    
    ボタン
    
        SimpleButton
            upState   = new TextButtonState(0xFFFFFF, "おされてない");
            downState = new TextButtonState(0xCCCCCC, "おされてる");
            overState = 
        
            addEventListener(MouseEvent.CLICK, clickHandler)
        
        
        

スコープ

    MXMLコンポーネントを定義しているファイルでは、
        thisは、そのコンポーネントの現在のインスタンスへの参照
    
    コンポーネントのイベントリスナーで ActionScript を記述する場合、
    スコープはコンポーネントではなくアプリケーションになります
        thisは、Applicationオブジェクトを指す
    
    
    注意:なので、例えば下のコードで、myButton1,2のラベル名は切り替わらない
    
        <?xml version="1.0"?>
        <!-- usingas/AppScope.mxml -->
        <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

            <!-- The following does nothing because the app level scope does
                 not have a label to set -->
            <mx:Button id="myButton1" label="Click Me" click="label='Clicked'"/>
            <mx:Button id="myButton2" label="Click Me" click="this.label='Clicked'"/>

        </mx:Application>
    
    
    for文とかで定義した変数のスコープは、ブロック内だけではないらしい
    
        for(var i:int = 0; i < 10; i++) {
            trace(i); // 0〜9が出る
        }
        trace(i); // 10 と出る (ブロックの外でも見れてる)
        for(var i:int = 0; i < 10; i++) {
                               // ここで「変数定義が重複してるよ」と警告される
                               // (コンパイルエラーにはならない)
            trace(i); // 0〜9が出る
        }
        
        ※ JavaScriptは同じようにブロックの外で見れる。Javaは見れない



階層構造を遡りたい

    Application.application : 一番上
    parentDocument          : いっこ上 (UIComponentを継承したクラスで使用可能)
    
    stage                   : 一番上
    
    root                    : 一番上
    parent                  : いっこ上 (DisplayObjectContainer を継承したクラスで使用可能)
    
    
    ※ それぞれの関係が良く分からない
    


ExternalInterface

こういう風にすると、JavaScriptからActionScriptの関数が呼べたりするらしい

private function setupCallbacks():void
{
    // SWF クライアント関数をコンテナに登録する
    ExternalInterface.addCallback("newMessage", newMessage);
    ExternalInterface.addCallback("getStatus", getStatus);
    // SWF の呼び出し準備ができたことをコンテナに通知する
    ExternalInterface.call("setSWFIsReady");
}



画像を埋め込みたい (MXMLを使わない場合)


(1) Embed を使う

    package {
        import flash.display.Sprite;
        import flash.display.DisplayObject;

        public class TestProjectAS extends Sprite {
            [Embed(source='test01.jpg')]
            private var Test1:Class;
            
            public function TestProjectAS() {
                var test1:DisplayObject = new Test1();
                addChild(test1);
            }
        }
    }

    ※ Embed は、Class, Stringでしか使えない。
        addChild(String) は不可なので、Class を使っている

    ※ LoaderContent の checkPolicyFile を
        true にしておくとクロスドメインポリシーファイルの有無がチェックされる
    
    ※ test1:DisplayObject のところを test1:Sprite のように書くと実行時に次のようなエラーが・・
        TypeError: Error #1034: 強制型変換に失敗しました。
        TestProjectAS_test1@1898ec9 を flash.display.Sprite に変換できません。
            at TestProjectAS()


(2) Loader.load(URLRequest) を使う

    package {
        import flash.display.Sprite;
        import flash.display.Loader;
        import flash.net.URLRequest;

        public class TestProjectAS extends Sprite {
            public function TestProjectAS() {
                var loader:Loader = new Loader();
                loader.load(new URLRequest('cellconsul.jpg'));
                addChild(loader);
            }
        }
    }
    

    ※ swfファイルに埋め込まれないので、画像ファイルも
        swfファイルから見える場所に配置しておく必要あり
    
    ※ 無いとこんなエラーが
        →「Error #2044: ハンドルされていない IOErrorEvent : text=Error #2035: URL が見つかりません。」


(3) MXML の場合 : Image を使う
    
    <mx:Image id="img" source="@Embed(source='img/a.png')"/>
    
    sourceのところは、
        @Embed タグを入れる : コンパイル時にSWFファイルに埋め込まれる。
        URLを入れる         : SWFファイルには埋め込まれない。
                               画像はローカルのキャッシュに残る。
                               相対パスでも http で始まるパスでもOK。




Q. Loaderで、loadしようとしたら次のエラーが
    TypeError: Error #1034: 強制型変換に失敗しました。flash.display::Loader@5fcda61 を mx.core.IUIComponent に変換できません。

A. 
    Containerオブジェクト --> Spriteオブジェクト という感じでaddChildしているのなら、
    Container --> UIComponent --> Sprite という感じに、間にUIComponentを入れてあげればいい

    ヘルプから引用
    
    addChild() メソッドに渡せるコンポーネントは、UIComponent だけです。
    つまり、新しく作成したオブジェクトが mx.core.UIComponent の
    サブクラスでない場合は、そのオブジェクトをコンテナに関連付ける前に
    UIComponent でラップする必要があります。
    次の例では、UIComponent のサブクラスではない新しい Sprite オブジェクトを作成し、
    それを Panel コンテナに追加する前に UIComponent コンテナの子として追加します。

    <?xml version="1.0"?>
    <!-- usingas/AddingChildrenAsUIComponents.mxml -->
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
        <mx:Script><![CDATA[
            import flash.display.Sprite;
            import mx.core.UIComponent;

            private function addChildToPanel():void {

                var circle:Sprite = new Sprite();
                circle.graphics.beginFill(0xFFCC00);
                circle.graphics.drawCircle(0, 0, 20);

                var c:UIComponent = new UIComponent();
                c.addChild(circle);
                panel1.addChild(c);
                
            }
        ]]></mx:Script>

        <mx:Panel id="panel1" height="100" width="100"/>

        <mx:Button id="myButton" label="Click Me" click="addChildToPanel();"/>
        
    </mx:Application>

    ※ ここで知った
        http://rx8.cocolog-nifty.com/blog/2007/04/flex2_22a6.html



Q. addChildしたのはImageなのに、FlexLoader という型になってるっぽい!

    ※こんなエラーが出る
        TypeError: Error #1034: 強制型変換に失敗しました。mx.core::FlexLoader@6055f71 を mx.controls.Image に変換できません。

A. 
    img1.addEventListener(MouseEvent.MOUSE_OVER, highlightImg);
    canvas1.addChild(img1);
    
    のようにリスナを追加した場合
    
    function highligntImg(event:Event) {
        trace(event.target);  // これは ImageXXX.FlexLoaderXXX というオブジェクトで
        trace(event.target.parent); // これが ImageXXX オブジェクト
        
        Image(event.target.parent).src = "xxx.jpg"// なのでこうアクセスするといい
    }
    
    のようになるので、event.target.parent に対して操作をするといい


※ SWFLoader の例

    var loader:SWFLoader = new SWFLoader();
    loader.load("swf/test.swf");

    Application.application.addChild(loader);



キャスト

    a = int(aaa);           // a = (int) aaa; とは出来ない
    b = UIComponent(bbb);   // プリミティブ型じゃなくても同じようにできる
    b = bbb as UIComponent; // as を使って書いた場合は、変換に失敗したら null
    


配列の操作

    追加
        ary1.push(xx)    : 末尾に追加
        ary1.unshift(xx) : 先頭に追加
    
    削除
        ary1.pop()                  : 末尾を取り出して削除
        ary1.shift()                : 先頭を取り出して削除
        ary1.splice(a, b)           : a 番目から b 個取り出して削除
        ary1.splice(a, b, ary2)     :  * 代わりにary2を挿入
                                         (カンマ区切りで続けてもいい)
        ary1.splice(indexOf(xx), 1) : 要素 xx を削除 ※最初のひとつしか削除されない
        
        ※ delete[2] とかやっても、3つ目の要素が undefined になるだけらしい
        
    ソート
        ary1.sort(Array.CASEINSENSITIVE);
            ※ ソートの種類
                Array.CASEINSENSITIVE
                Array.DESCENDING
                Array.UNIQUESORT
                Array.NUMERIC
                (複数あるときは「 | 」でつなぐ)
    
    
    every() : コールバック関数が false になるまで順に実行
        ※ この例ではコールバック関数に無名関数を使用
        ※ elem の型を 引数で指定したくない場合は elem:* と書いておく
        
        var ary1:Array = [1, 5, 7, 10, 11, 15];
        ary1.every(function(elem:int, index:int, arr:Array):Boolean {
            str += " " + elem;
            return (elem < 10);
        });
            → str には 1, 5, 7, 10 が入る
    
    forEach() : 全ての要素について順に実行
        ary1.forEach(function(elem:int, index:int, arr:Array):void {
            str += " " + elem;
        });
            → str には 1 5 7 10 11 15 が入る
        
    some() : true になるまで順に実行
        ary1.some(function(elem:int, index:int, arr:Array):Boolean {
            str += " " + elem;
            return (elem == 7);
        });
            → str には 1 5 7 が入る



連想配列(Hash)  ※ Hashという型名はない。Object型を使う

    宣言してから要素を追加
        var hash1:Object = new Object();
        hash1["city"] = 63;                  ※ キーに空白を含んではいけない
        hash1["day"]  = "today";
    
    代入
        hash1 = {city: "63", day: "today"}; 
    
    削除
        delete(hash1["takahashi"]);
    
    全ての要素について処理
        キーを取り出す
            for (var key:String in hash1) {
                Alert.show(key + " => " + hash1[key]);
            }
    
        値だけ取り出す
            for each (var val:String in hash1) {
                Alert.show(val);
            }
    
    でも要素数とか取れないのが不便なので、
    ハッシュの役割をするクラスを作ってみる。無理やり
    
        package  {
            /**
             * 連想配列用のクラス
             */

            public dynamic class Hash {
                /**
                 * コンストラクタ
                 */

                public function Hash(o:Object = null) {
                    if (o != null) {
                        for (var k:String in o) {
                            this[k] = o[k];
                        }
                    }
                }
                
                /**
                 * 最初の要素を削除
                 */

                public function size():int {
                    var i:int = 0;
                    for (var key:String in this) {
                        i++;
                    }
                    return i;
                }
                
                /**
                 * 要素を指定して要素を削除
                 *
                 *  ※ キーを指定して削除するのは delete hash1[key] でいい
                 *
                 */

                public function remove(removeElement:Object, removeAll:Boolean = false):void {
                    for (var key:Object in this) {
                        if (this[key] == removeElement) {
                            delete this[key];
                            if (removeAll) {
                                return;
                            }
                        }
                    }
                }
            }
        }   



※ ダイナミッククラス

    クラスの定義時に dynamic をつけておくと、
    JavaScriptのオブジェクトや連想配列のように オブジェクトの要素を追加できる
    
    http://livedocs.adobe.com/flex/2_jp/docs/00001825.html


※ 参考:Objectクラスのリファレンスより
    http://livedocs.adobe.com/flex/2_jp/langref/Array.html

    結合配列 (ハッシュとも呼ばれる) の作成には Array クラスを使用しないでください。
    結合配列は、数値エレメントではなく名前付きエレメントを含むデータ構造です。
    結合配列の作成には、Object クラスを使用してください。
    ActionScript では Array クラスを使用して結合配列を作成できますが、
    結合配列で Array クラスのメソッドやプロパティは使用できません。 



Hashの代わりにDictionaryを使うのもあり。
    ※ でも Object型ではなくてDictionaryを使う利点が良く分からない

    package {
        import flash.display.Sprite;
        import flash.utils.Dictionary;

        public class TestProjectAS extends Sprite {
            public function TestProjectAS() {
                var dict:Dictionary = new Dictionary();
                dict[3]       = "さん";
                dict["three"] = "すりー";
                
                for (var k:* in dict) {
                    trace(dict[k]);   // => さん  すりー
                }
                
                trace(dict[3]);       // => さん
                trace(dict["three"]); // => すりー
            }
        }
    }



JavaScript同様 for .. in が使える。
foreachはないけど、forEach() メソッド、for each (.. in ..) というのがある

    // 連想配列(Hash)の中を一覧
    for (var p:String in obj) {
        xxx.text += p + ":" + obj[p] + "\n";
    }
    
    ※ 中を一覧したいだけであれば
        mx.utils.ObjectUtil.toString(obj); でも同様の結果が・・
    
        → こういうのを「イントロスペクトする」とか
           「イントロスペクション」というらしい
    
    ※ イントロスペクションAPIでの書き方
        
        import flash.utils.*;
        var classInfo:XML = describeType(button1);

        ta1.text = "Class " + classInfo.@name.toString() + "\n";

        // List the object's variables, their values, and their types.
        for each (var v:XML in classInfo..variable) {
            ta1.text += "Variable " + v.@name + "=" + button1[v.@name] + 
                " (" + v.@type + ")\n";
        }

    ※ 「インストロペクション」、「インストロペクト」 は読み間違い


関連して

Q. PHPでいうところの var_dump() みたいな関数が欲しい

A. ある。
    mx.utils.ObjectUtil.toString(obj)




ソケット通信(クライアント)

    開始
        var socket:Socket = new Socket(SERVER_ADDR, SERVER_PORT);
        
    受信時等の動作はイベントリスナに追加する
        socket.addEventListener(Event.CONNECT, connectHandler);

        ※ 使用できるイベント
            Event.CONNECT                     : 接続時
            Event.CLOSE                       : 切断時
            IOErrorEvent.IO_ERROR             : IOエラー時
            ProgressEvent.SOCKET_DATA         : データ受信時
            SecurityErrorEvent.SECURITY_ERROR : セキュリティエラー
    
    受信 ※ProgressEvent.SOCKET_DATAで指定したハンドラ
        socket.readUTFBytes(socket.bytesAvailable)
    
    送信
        socket.writeUTFBytes("文字列\n");
        socket.flush(); // ためずにすぐ送りたい場合は fulsh() する
    
    ※ XMLSocketの場合は ProgressEvent.SOCKET_DATA ではなく DataEvent.DATA


Q. Flash側が "<policy-file-request/>" というのを投げているようで、通信が途切れてしまう

A. ソケット通信前に、明示的にポリシーファイルを読み出すように書くといい。

    Security.loadPolicyFile("http://xxx.xxx.asdffas.com/crossdomain.xml");
    socket = new Socket(Constants.SERVER_ADDR, Constants.SERVER_PORT);



例:

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" height="398" backgroundColor="#FFFFFF">
        <mx:Script>
        <![CDATA[
            import mx.logging.Log;
            import flash.net.Socket;
            import flash.events.Event;
            import flash.events.ProgressEvent;
            import flash.events.IOErrorEvent;
            import flash.events.SecurityErrorEvent;
            import flash.display.Sprite;
            import mx.controls.Button;
            import mx.controls.Text;
            import flash.text.TextField;
            import mx.logging.targets.*;
            import mx.logging.*;

            private var SERVER_ADDR:String = 'localhost';
            private var SERVER_PORT:int    = 10000;
            
            private var socket:Socket;
            
            /**
             * startClient
             *
             * クライアント起動
             */

            public function startClient():Boolean {
                btnStartClient.enabled = false;
                
                // Socketのオープン
                socket = new Socket(SERVER_ADDR, SERVER_PORT);
                
                // Socketのイベントリスナ追加
                socket.addEventListener(Event.CONNECT, connectHandler);
                socket.addEventListener(Event.CLOSE, closeHandler);
                socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
                socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
                socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
                
                return true;
            }
            
            /**
             * 接続時の処理
             */

            private function connectHandler(event:Event):void {
                txtClientStatus.text += "接続OK\n";
            }
            private function closeHandler(event:Event):void {
                txtClientStatus.text += "切断\n";
            }
            private function socketDataHandler(event:ProgressEvent):void {
                txtClientStatus.text += "データ来た(" + socket.readUTFBytes(socket.bytesAvailable) + ")\n";
            }
            private function securityErrorHandler(event:SecurityErrorEvent):void {
                txtClientStatus.text += "Security Error!\n";
            }
            private function ioErrorHandler(event:IOErrorEvent):void {
                txtClientStatus.text += "IO Error!\n";
            }
            
        ]]>
        </mx:Script>  
        <mx:Canvas x="0" y="0" width="416" height="398" backgroundColor="#FFFFFF" borderStyle="solid">
            <mx:Button id="btnStartClient" click="startClient();" x="10" y="10" label="接続!"/>
            <mx:Text id="txtClientStatus" x="10" y="40" text="ここにメッセージを書く" width="396" height="348"/>
        </mx:Canvas>
    </mx:Application>



イベント処理

(1) MXMLで指定する場合
    
    <mx:Canvas id="cvsTest1" mouseOver="highlightCanvas(cvsTest1);" mouseOut="leaveCanvas(cvsTest1);">
    以下のような属性に呼び出したい処理を記述すれば良い。
        mouseOver        (=HTMLでいうonmouseover)
        mouseOut         (=HTMLでいうonmouseout)
        creationComplete (=HTMLでいうonload)
    
    ※ 選択されたオブジェクトがなんであるかは、上の例のように自分自身を引数に渡してあげれば良い。
       → this ではダメ。
    ※ 引数に「event」と書いておくとイベントオブジェクトが渡される

(2) ActionScript(addEventListener)で指定する場合

    private function initTestEvent():void {
        canvas2.addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler); 
        // ここでは引数1つ(Eventオブジェクト)を持つメソッドへの参照を
        // 指定しないといけないので、引数に自分自身を渡せない
    }
    private function mouseOverHandler(event:Event):void {
        highlightCanvas(Canvas(event.target));
        // でも event.target で、イベントを受け取ったオブジェクトを指定できる
    }



マウスイベント

※ 他に
    MouseEvent.CLICK
    MouseEvent.MOUSE_OVER ← MOUSE_OVER, MOUSE_OUT は1回だけ呼ばれる
    MouseEvent.MOUSE_OUT
    MouseEvent.MOUSE_MOVE
    
※ rollOver, rollOut と、mouseOver, mouseOut の違いは?
    TODO: ここにある。あとで見る
        http://designdrill.heteml.jp/2007/07/as37.html

※ MouseEvent.DOUBLE_CLICK が出来ない件
    → doubleClickEnabled を true にしないとダブルクリックは検出されない

    this.doubleClickEnabled = true;
    this.addEventListener(MouseEvent.DOUBLE_CLICK, testFunc);

※ ドラッグしているときを判定する場合とか
    MOUSE_MOVE のイベントハンドラ内で、
        if (event.buttonDown) {
            // 何か処理
        }
    こんな感じで書けば良い?
    
    → なんか違う。以下はリファレンスに載ってた例
    
    private function mouseDownHandler(event:MouseEvent):void {
        trace("mouseDownHandler");
        draw(overSize, overSize, downColor);

        var sprite:Sprite = Sprite(event.target);
        sprite.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
        sprite.startDrag();
    }

    private function mouseMoveHandler(event:MouseEvent):void {
        trace("mouseMoveHandler");
        event.updateAfterEvent();
    }
    
    private function mouseUpHandler(event:MouseEvent):void {
        trace("mouseUpHandler");
        var sprite:Sprite = Sprite(event.target);
        sprite.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
        sprite.stopDrag();
        draw(overSize, overSize, overColor);
    }
    

※ 相対座標と絶対座標
    event.localX
    event.localY
    
    event.stageX
    event.stageY


キーボードイベント

    txtMessage.addEventListener(KeyboardEvent.KEY_DOWN, txtMessageKeyDown);
    
        :
    
    private function txtMessageKeyDown(event:KeyboardEvent):void {
        if (event.keyCode == Keyboard.ENTER) {
            sendMessage(txtMessage.text);
        }
        // たくさんある場合は switch .. case でやればいい
    }





スタイルの設定

    Q. 
        canvas1:Canvas = new Canvas();
        canvas1.borderColor = "#FF0000";
        とかって指定が出来ない。
    
    A.
        canvas1.setStyle("borderColor""#FF0000");
        とやればいい
        
        ※ borderStyle, borderThickness(borderWidthではない), backgroundColorとかも同じ要領で。
    


JSON使う

    // コンパイル時は corelib.swc が libpath に必要
    // ※ ここで入手 → http://code.google.com/p/as3corelib/downloads/list
    // ※ コンパイル時に埋め込まれるので実行時は不要
    import com.adobe.serialization.json.JSON;

    // JSON文字列をパース
    var arr:Array = (JSON.decode(strJsonData) as Array);

    // オブジェクト風にアクセス
    for(var i:int = 0; i < arr.length; i++) {
        strResult += "  " + arr[i].name + "(" + arr[i].age + ") said '"
                  + arr[i].greeting + "'!\n";
    }
    // 連想配列風にアクセス
    for(i = 0; i < arr.length; i++) {
        strResult += "  " + arr[i]["name"] + "(" + arr[i]["age"] + ") said '"
                  + arr[i]["greeting"] + "'!\n";
    }


型チェック

    instanceof でチェック
        var c:Child;
        if (c instanceof Parent) {        // true
        if (c instanceof Child) {         // true
        if (c instanceof SomeInterface) { // false
    
    is でチェック
        var c:Child;
        if (c is Parent) {        // true
        if (c is Child) {         // true
        if (c is SomeInterface) { // true
    
    as でチェック?
        obj = c as Parent;        // 正しかったら代入が正しく行なわれる
        obj = c as Child;         //
        obj = c as SomeInterface; // 
        obj = c as Array;         // 違ったら null が入る
    
    typeof
        基本型(int, String, ...) 以外は全部「Object」のようだ



try .. catch

    try {
        // 何か処理
    } catch (e:Error) { // Exception ではない
        Alert.show(mx.utils.ObjectUtil.toString(e));
    }


TODO:そのクラスの型が何であるか調べる方法
    trace(obj1) でクラス名は出てくるけども・・





よく使う 表示関連のパラメータ

    ※ 設定しかた
        スタイルは   container1.setStyle("borderStyle""solid"); という感じで設定
        プロパティは container1.clipContent = false; という感じで指定

    UIComponent
        スタイル
            # 親コンポーネントからの相対座標を指定 (基準点は中心)
            verticalCenter:   -50
            horizontalCenter: 30.5
            
            # 子要素の大きさに合わせてリサイズしたい (子要素の外枠を表示したいときとか)
            left:   2
            right:  2
            top:    2
            bottom: 2
        
    Container
        スタイル
            # 枠線関連
            borderStyle:      solid    ※ solid, none, inset, outset
            borderColor:      #00FF00
            borderThickness:  2
            
            # スクロール関連 (これは意図した動作をしない。どういうときに使うのだろう)
            horizontalScrollPolicy:  off       ※ on, off, auto (ScrollPolicy.ON, OFF, AUTO)
            verticalScrollPolicy:    off
            
        プロパティ
            # 代わりに scroll をOFFにする方法  ※ styleじゃないけど
            clipContent = false
            
            # 子要素の大きさに合わせて広げる
            #  (でもResizeとかのEventではついてこない → ついてこさせたい場合はtargetsに追加すればいい)
            autoLayout = true
        


tips


数値かどうか判定

    if (isNaN(parseInt(str))) {
        Alert.show("数値を指定して。");
        return;
    }
    Alert.show(-5 * parseInt(str) + 3 + "");







Q&A形式


Q. Image に枠線がつけられない

A. 
    Imageには枠線を設定するスタイルがないので、
    Containerクラス(とかCanvasとか)をかぶせる。
    ※ 外側の要素に枠線をつけても Imageの後ろに隠れてしまうので・・

    UIComponent
     ├ SWFLoader        ※ SWFLoaderには枠線を設定するスタイルがない
     | └ Image
     |
     ├ Container        ※ Containerには枠線を設定するスタイルがある
     | ├ Canvas
     | ├ Box
     | | ├ VBox
     | | ├ HBox
     | | :
     | :
     :
    
    例)こんな感じ?
        // 作成
        cvsChild:Canvas = new Canvas();
        cvsChild.width  = imgChild.width;
        cvsChild.height = imgChild.height;
        cvsChild.setStyle("borderStyle",     "solid");
        cvsChild.setStyle("borderColor",     "blue");
        cvsChild.setStyle("borderThickness", 1);
        
        boxParent:VBox = new VBox();     // boxParent は imgChildの背面に
        boxParent.addChild(imgChild);    // 
        boxParent.addChild(canvasChild); // imgChildの前面に出したいので、
                                         // 後からaddChildする
        
        // リサイズのイベント設定時 (imgChildにイベントを設定したとして)
        rszContractImage.targets = event.target.parent.parent.getChildren();z
        rszContractImage.targets.push(event.target.parent.parent);           // boxParent
        


Q. メソッドのオーバーライドのしかた

A.

    class Oya {
        protected function someMethod() {
            // ↑「virtual」とか「abstract」みたいなキーワードは ないっぽい
        }
    }
    class Ko extends Oya {
        protected override function someMethod() {
            // ↑ 子クラスで「override」と書く
            // ...
        }
    }


Q. MouseEvent.CLICK に登録したイベントハンドラが2回とか3回呼ばれる。なんで?

A. 親要素にもイベントが伝播するらしい。(バブリングという)

    1回だけ呼ばれれば良いのであれば、イベントハンドラに
    
        if (event.eventPhase == EventPhase.AT_TARGET) return;
    
    と書いてしまおう。
    
    ※ ・・と思ってたけど、event.stopPropagation()とか stopImmediatePropagation() とか
        preventDefault() とか、その辺のメソッドを使えば良いのかも。
    
    ※ でもバブリングされていることの利点って何なんだろう・・・・
        → ボタンにリスナを追加したけど、実際にイベントを拾うのは
            その前面にある子要素(Labelとか)なので、前が塞がれている状態。
            なのでバブリングしないとイベントを拾えないとか、そういう話?
    
    ※ rootから子要素(イベントを拾ったオブジェクト)まで伝播することは「キャプチャ」という



Q. TextArea をスクロールさせたい。(tail みたいにして一番下が表示されるようにしたい)

A. 

    <mx:TextArea id="txtLog" text="( ここにはログを )" x="114" y="104" width="162" height="65" verticalScrollPolicy="auto"/>

    NG例:
        こんな感じでかけるかと思いきや、そうならない。
        イベント送出するだけじゃダメみたい。
        
        txtLog.text += str + "\n";
        var scrollEvent:ScrollEvent = new ScrollEvent(ScrollEventDirection.VERTICAL, false, false, ScrollEventDetail.AT_BOTTOM, 50, ScrollEventDirection.VERTICAL, 100);
        txtLog.dispatchEvent(scrollEvent);

    OK例:
        もっと簡単だった。書き込んだ後に以下を記述
        
        txtLog.text += str + "\n";
        txtLog.validateNow(); // 書き込んだ内容を flush!
        txtLog.verticalScrollPosition = txtLog.maxVerticalScrollPosition;



Q. 次のようにやると、それぞれ座標が違うはずなのに、同じ座標が返ってくる
    (1) TileとかHBoxの子要素としていくつかのオブジェクトを addChildする
    (2) 座標を取得

A. 
    addChildするごと((1)のタイミング)に validateNow() してやればいい。


Q. mx:Application の直下にオブジェクトを配置するとどうしても上に余白が出来てしまう。

A. mx:Application に、layout="absolute" という設定をしておくと良いらしい



Q. Javaでいう Integer.parseInt(str) ある?

A. parseInt(str), parseFloat(str) というのがある Number.parseInt() という風には書かない



Q. Container(Canvasとか)の内側の要素のサイズが大きいとスクロールバーが出てしまう。
    これを出したくない。

A. 
    container1.horizontalScrollPolicy = ScrollPolicy.OFF; // 文字列の "off" でもOK
    container1.verticalScrollPolicy   = ScrollPolicy.OFF;


Q. URLへのアクセス中にセキュリティエラーが発生しました
    サーバに上げてみると「URLへのアクセス中にセキュリティエラーが発生しました」
    ってエラーが出る。ローカルでのテストは大丈夫だったのに。
    
A.
    マニュアルには次のように書いてあるので、接続先のサーバ(LivedoorのWebサービスだったらLivedoorのサーバ)に、接続を許可する crossdomain.xml を配置されてないといとこのエラーが出るみたい。
    
    > リモートサーバーはアプリケーションをホストしているサーバーと同じドメインに設定するか、またはリモートサーバーが "crossdomain.xml" ファイルを定義する必要があります
    
    ※ http://livedocs.adobe.com/flex/2_jp/docs/00000006.html#874524



Q. Flex Builderでデバッグ実行時に下記エラーが出る。

    C:\Windows\System32\Macromed\Flash\Flash9d.ocx

    Flex Builder は、Flash Player のデバッグバージョンを検出できません。Flash Player 9 のデバッグバージョンをインストールするか、Flex Builder を再インストールする必要があります。現在のバージョンでデバッグを試みますか?

A. Flex Builderのインストール後、
    通常版のプレイヤーをインストールしなおしたために上書きされたようだ(?)
    更にデバッグ版(デバッガ版?)プレイヤーをインストールし直したら解決

    説明
        http://www.adobe.com/jp/support/flex/ts/documents/758bf58b.htm

    通常版プレイヤーのインストール
        http://www.adobe.com/jp/products/flash/about/

    デバッグ版プレイヤーのインストール
        http://www.adobe.com/support/flashplayer/downloads.html



Q. デバッグ版FlashPlayerで、Linux版だと標準出力にログが出るけど、Windows版はどこに出るの。
    * debug, debugger, trace()

A. 
    (1) mm.cfg というテキストファイルを以下の場所に作る。
    
        C:\Documents and Settings\username\mm.cfg    (2000/XPの場合)
        C:\Users\username\mm.cfg                     (Vistaの場合)
    
    (2) mm.cfg に以下の内容を書く
        TraceOutputFileEnable=1
        ErrorReportingEnable=1
        
        ※ 更にディレクトリ名を指定したいときは 次のように書いて、
            TraceOutputFileName=c:\flexLog.log
            
            ※ さらにHOMEPATH, HOMEDRIVEという名前の環境変数を定義しないといけないというウワサ
    
    (3) 普通に実行する
        → 以下のディレクトリに flashlog.txt というファイル名で書き出される
        
            C:\Documents and Settings\username\Application Data\Macromedia\Flash Player\Logs   (2000/XP)
            C:\Users\username\AppData\Roaming\Macromedia\Flash Player\Logs                     (Vista)



Q. Flash にも Cookieみたいなものある?

A. LSO (Local Shared Object)というのがあるみたい

    var xxx:SharedObject = SharedObject.getLocal('xxx');
    
    http://livedocs.adobe.com/flashlite/2_jp/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts_wEcute&file=00000754.html



Q. Fadeを使ってフェードアウトさせたあと、もう一度表示させたいのだけど、
    visibleにしても表示されない。

A.
    透明度の設定(alpha)を戻せば元に戻る?
    img01.alpha = 1;
    
    ※ alpha値は、0が不可視、0.5で半透明、1で可視、な状態らしい





雑多な知識


埋め込む

    [Embed(source="sound1.mp3")]
    「アセットクラス」と呼ぶらしい



タイマー

定義
    var timer:Timer = new Timer(1000, 5);
                                 ↑   ↑
                                 |   繰り返し回数。デフォルトが 0 なので注意
                                 単位はミリ秒

時間の間隔ごと(この場合1秒ごと)のイベント
    timer.addEventListener(TimerEvent.TIMER, onTick);

完了時のイベント
    timer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);

タイマー開始
    timer.start();




sleep(), wait() みたいな名前の関数は無いけども、Pauseというクラスがある。
    →TODO:使ってみる



配列のコピーで「深いコピー(Marshall Copy)」をしたいとき

    import flash.utils.ByteArray;

    function clone(source:Object):*
    {
        var myBA:ByteArray = new ByteArray();
        myBA.writeObject(source);
        myBA.position = 0;
        return(myBA.readObject());
    }

※浅いコピー
    ary2 = ary1.slice()  ?



ファイルのアップロード/ダウンロード

    import flash.net.FileReference;


アップロード
    fileRef.addEventListener(Event.SELECT, selectHandler);
    fileRef.addEventListener(Event.COMPLETE, completeHandler);

    1つだけ: FileReference.browse()
    複数   : FileReferenceList.browse()

ダウンロード

    fileRef.addEventListener(Event.OPEN, openHandler);
    fileRef.addEventListener(ProgressEvent.PROGRESS, progressHandler);
    fileRef.addEventListener(Event.COMPLETE, completeHandler);
    
    FileReference.download() 


クリップボード

    System.setClipboard(errorString);
    
    ※ IEではJavaScriptでクリップボードのクリアが出来るけどFireFoxでは出来ないから
        HTMLで、クリップボードをクリアするためのSWFファイルを呼ぶ
        とかいう使い方もするんだとか


Capabilities

    クライアント(Flash Player)の情報を取得する

    クライアント側で取得
        avHardwareDisable
        hasAccessibility
        hasAudio
        hasAudioEncoder
        hasEmbeddedVideo
        hasIME
        hasMP3
        hasPrinting
        hasScreenBroadcast
        hasScreenPlayback
        hasStreamingAudio
        hasStreamingVideo
        hasTLS
        hasVideoEncoder
        isDebugger
        language
        localFileReadDisable
        manufacturer
        os
        pixelAspectRatio
        playerType
        screenColor
        screenDPI
        screenResolutionX
        screenResolutionY
        version
    
    サーバ側で取得
        Capabilities.serverString で取得できる文字列を送信するといい
        
        ※こんな感じの文字列らしい
            A=t&SA=t&SV=t&EV=t&MP3=t&AE=t&VE=t&ACC=f&PR=t&SP=t&SB=f&DEB=t&V=WIN%209%2C0%2C0%2C0&M=Adobe%20Windows&R=1600x1200&DP=72&COL=color&AR=1.0&OS=Windows%20XP&L=en&PT=External&AVD=f&LFD=f&WD=f&IME=t



IME

    ユーザーのコンピュータに IME がインストールされているかどうか : Capabilities.hasIME
    ユーザーのコンピュータで IME が有効になっているかどうか       : IME.enabled
    現在の IME で使用されている変換モード                         : IME.conversionMode
    
    ※ TODO:調べる→「ボタンを押した時点で未変換のものは入力を確定させる」とか出来る?



setter/getter

    キーワード set, get を使う。

        使わない場合
            he.setAge(xxx);
            age = he.getAge();
        
            としていたところを
        
        使う場合
            he.age = xxx;
            age = he.age;
            
            と書ける。

    package {
        class User { 
            private var userAge:Number; 
            
            public function get age():Number {  // ← get
                return userAge;
            }
            
            public function set age(x:Number):void {  // ← set
                userAge = x;    
            }
        } 
    }
    
    ※ http://livedocs.adobe.com/flex/2_jp/langref/statements.html#set



深度の変更

    // 最背面へ
    container.setChildIndex(shapeToMove, 0);

    // 1つ前面へ
    container.swapChildren(shapeToMove, container.getChildAt(container.getChildIndex(shapeToMove) + 1));

    // 最前面へ
    container.setChildIndex(shapeToMove, container.numChildren - 1);





APEメモ
    
APE
    2Dの物理エンジンらしい
    http://www.cove.org/ape/index.htm


※ 取ってきてそのディレクトリをインクルードパスに指定する
    svn export http://ape.googlecode.com/svn/trunk/source/  APE


クラス階層

AbstractCollection.as
    Composite.as
    Group.as

AbstractItem.as
    AbstractParticle.as
        CircleParticle.as
            WheelParticle.as
        RectangleParticle.as
            SpringConstraintParticle.as
    AbstractConstraint.as
        SpringConstraint.as

RimParticle.as  (AbstractParticleの子クラスではない)

APEngine.as

Collision.as
CollisionDetector.as
CollisionResolver.as

Interval.as

MathUtil.as

Vector.as



APEngine
    (中に Groupを追加していく)

    APEngine.init(1/4)
        1秒を何分割するかを指定
    APEngine.container
        コンテナを指定。extends Sprite なクラスで thisを渡しているけど、
        Canvasとかでも大丈夫だろうか
    APEngine.addMasslessForce(new Vector(0, 3));
        重力を指定する
    
    APEngine.addGroup(group1);
        Groupの子クラスを追加していく
        ↑
        この要素で形を定義? ※Groupの中はParticleを集めているみたい



Group
    (中に Item(ParticleとConstraint)を追加していく)


    addParticle(particle1)
        Particleの子クラスを追加していく

    addConstraint(constraint1)
        


Particle

    particle1.mass = 0.001;
    particle1.setStyle(1, colE, 1, colE);
    particle1.visible = false;
    particle1.collidable = false;  // collide: 衝突



Constraint

    constraint1.restLength = 40;
    constraint1.visible = false;



channel3 メモ

channel3
    はてなが作っている3Dのライブラリ
    http://sourceforge.net/projects/channel3/


クラス図

<< effect >>

    [I] Effect
    ↑
    [C] Animation, [C] FaceCulling, [C] Light, [C] Material, [C] SectionEffect
                                                ↑           ↑
                                                |           [C] ZBuffer
                                                |           ↑
                                                |           [C] SortZBuffer, [C] SpriteZBuffer
                                                |
                                               [C] LineMaterial, [C] MixedMaterial, [C] TextureMaterial

<< event >>

    [C] (flash.events.Event)
    ↑
    [C] Ch3Event

<< fragment >>
    
    [C] IndexedObject (channel3.util)
    ↑
    [C] Fragment
    ↑
    [C] Face, [C] Polyline, [C] Sprite2D
    ↑
    [C] Quadrilateral, [C] Triangle

<< math >>

    [C] Matrix4, [C] Vector, [C] Vector2, [C] Vertex


<< scene >>

    [C] IndexedObject (channel3.util)
    ↑
    [C] Node
    ↑
    [C] Group, [C] Geometry,  [C] Camera3D (channel3.view)
               ↑
<< primitive >>|
               |
               [C] Cube, [C] Plane


<< util >>
    
    [C] (flash.events.EventDispatcher)
    ↑
    [C] SaParser
    
    [C] AnimationData, [C] Cache, [C] IndexedObject


<< view >>

    [C] (flash.events.EventDispatcher)
    ↑
    [C] Renderer
    
    [C] Camera3D



サンプルから
    
    // ------------------------------
    // 1. Hello World
    import channel3.primitive.Cube;
    import channel3.view.Renderer;

    private function creationCompleteHandler():void {
        // Create Cube object.
        var cube:Cube = new Cube(100);

        // Create renderer, and render.
        var renderer:Renderer = new Renderer(canvas, cube);
        renderer.render();
    }
    
    // ------------------------------
    // 2. transformation
    import channel3.primitive.Cube;
    import channel3.view.Renderer;
    import channel3.event.Ch3Event;
    import channel3.math.Matrix4;

    private var cube:Cube;

    private function creationCompleteHandler():void {
        // Create Cube object.
        cube = new Cube(100);

        // Move a cube along x, y, z axis. (Each axis is right, up, coming direction.)
        cube.translate(50, 20, -80);

        // Create renderer.
        var renderer:Renderer = new Renderer(canvas, cube);

        // Add event listener to renderer, and listener called each time after rendering.
        renderer.addEventListener(Ch3Event.AFTER_RENDER, rotateCube);

        // Start rendering. A cube is rendered for every frame.
        renderer.start();
    }


    // event handler called every time after rendering
    private function rotateCube(event:Ch3Event):void {
        // Rotate cube along Y axis. Angle is given by radian.
        cube.rotateY(Math.PI / 48);

        // Directly handle 4x4 transform matrix. Right matrix is applied first, and left is next.
        cube.transform = cube.transform.product(Matrix4.rotationX(Math.PI / 24));
    }




Papervision 3D メモ (pv3dと略すらしい)

SVNリポジトリ
    http://papervision3d.googlecode.com/svn/trunk/as3/

サンプル
    http://blog.papervision3d.org/2007/02/13/thank-you/

参考記事
    http://rect.blog49.fc2.com/blog-entry-57.html


package {
    import flash.display.*;
    import flash.events.*;

    import org.papervision3d.scenes.*;
    import org.papervision3d.objects.*;
    import org.papervision3d.cameras.*;
    import org.papervision3d.materials.*;

    [SWF(backgroundColor=0x000000)]
    public class PvSample01 extends Sprite {
        private var container : Sprite;
        private var scene     : Scene3D;
        private var camera    : Camera3D;
        private var rootNode  : DisplayObject3D;

        private var startX    : Number = 0;
        private var startY    : Number = 0;
        
        /**
         * コンストラクタ
         */

        public function PvSample01():void {
            stage.frameRate = 60;
            stage.quality   = "BEST";
            stage.scaleMode = "noScale";
            stage.align = StageAlign.TOP_LEFT;
            this.stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
            this.stage.addEventListener(MouseEvent.MOUSE_UP,   onMouseUp);
            this.stage.addEventListener(Event.RESIZE, onStageResize);
            // ※ this.addEventListener とやると、
            //    描かれた図形に触れたときのみイベントが発生する
            
            init3D();
        }
        
        /**
         * 初期化時に呼ぶ(このメソッド名で書くという決まりではない)
         */

        private function init3D():void {
            //コンテナ生成
            this.container = new Sprite();
            addChild(this.container);
            this.container.x = this.stage.stageWidth  / 2;
            this.container.y = this.stage.stageHeight / 2;
            
            //シーン生成
            scene = new Scene3D(container);
            
            //カメラ設定
            camera = new Camera3D();
            camera.x = 200;
            camera.y = 0;
            camera.z = 0;
            camera.focus = 500;
            camera.zoom = 1;
            
            //rootNode生成
            rootNode = scene.addChild(new DisplayObject3D("rootNode"));
            
            // x, y, z 軸を描く
            var xAxis:DisplayObject3D = drawAxis(0xFF0000);
            xAxis.yaw(90);
            var yAxis:DisplayObject3D = drawAxis(0x00FF00);
            yAxis.pitch(-90);
            var zAxis:DisplayObject3D = drawAxis(0x0000FF);
            
            // 何か図形を描く
            var color:uint = 0xFFFF00;
            var colorMaterial:ColorMaterial = new ColorMaterial(color, 1);
            var wireMaterial:WireframeMaterial = new WireframeMaterial(color);
            
            var compoMaterial:CompositeMaterial = new CompositeMaterial();
            // compoMaterial.addMaterial(colorMaterial);
            compoMaterial.addMaterial(wireMaterial);
            compoMaterial.doubleSided = true;
            
            var materialsList:MaterialsList = new MaterialsList();
            materialsList.addMaterial(compoMaterial, "all");
            
            var cube1:DisplayObject3D = new Cube(materialsList, 20, 20, 20);
            cube1.z = 50;
            
            // rootNodeに足す
            rootNode.addChild(xAxis);
            rootNode.addChild(yAxis);
            rootNode.addChild(zAxis);
            rootNode.addChild(cube1);
            
            // もっと描く
            var cubes:Array = new Array();
            for (var i:int = 0; i < 3; i++) {
                cubes[i] = new Array();
                for (var j:int = 0; j < 3; j++) {
                    cubes[i][j] = new Array();
                    for (var k:int = 0; k < 3; k++) {
                        cubes[i][j][k] = new Cube(materialsList, 10, 10, 10);
                        cubes[i][j][k].x = 40 * (i + 1);
                        cubes[i][j][k].y = 40 * (j + 1);
                        cubes[i][j][k].z = 40 * (k + 1);
                        rootNode.addChild(cubes[i][j][k]);
                    }
                }
            }
            
            //レンダリング
            this.scene.renderCamera(camera);
        }
        
        private function onStageResize(event:Event):void {
            this.container.x = this.stage.stageWidth  / 2;
            this.container.y = this.stage.stageHeight / 2;
        }
        /**
         * ドラッグ開始時(マウスボタンを押したとき)の処理
         */

        private function onMouseDown(event:MouseEvent):void {
            startX = event.stageX;
            startY = event.stageY;
            this.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
        }
        
        /**
         * ドラッグ中の処理
         *   オブジェクトを回転させる
         */

        private function onMouseMove(event:MouseEvent):void {
            // 順番気にせず回転させる場合
            // rootNode.yaw(- (event.stageX - startX));
            // rootNode.pitch(event.stageY - startY);
            
            // 順番に回転させる場合
            rootNode.rotationZ -= (event.stageY - startY);
            rootNode.rotationY -= (event.stageX - startX);
            
            // 直感的に(画面上のx軸、y軸に沿って)回転させる方法はどうやるんだろう
            
            startX = event.stageX;
            startY = event.stageY;
            
            // レンダリングしなおす
            this.scene.renderCamera(camera);
        }
        
        /**
         * ドラッグ終了時(マウスボタンを離したとき)の処理
         */

        private function onMouseUp(event:MouseEvent):void {
            this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
        }
        
        /**
         * x, y, z 軸を表す矢印を描く
         */

        private function drawAxis(color:uint):DisplayObject3D {
            // 色設定
            var colorMaterial:ColorMaterial = new ColorMaterial(color, 1);
            var wireMaterial:WireframeMaterial = new WireframeMaterial(color);
            
            var compoMaterial:CompositeMaterial = new CompositeMaterial();
            compoMaterial.addMaterial(colorMaterial);
            // compoMaterial.addMaterial(wireMaterial);
            compoMaterial.doubleSided = true;
            
            var materialsList:MaterialsList = new MaterialsList();
            materialsList.addMaterial(compoMaterial, "all");
            
            // 線を引く (円柱だけど)
            var axis:DisplayObject3D = new Cylinder(compoMaterial, 2, 150);
            axis.z = 75;
            axis.rotationX = 90;
            
            // 矢印の先を描く (球だけど)
            var sphere:DisplayObject3D = new Sphere(compoMaterial, 10);
            sphere.z = 150;
            
            var node:DisplayObject3D = new DisplayObject3D();
            node.addChild(axis);
            node.addChild(sphere);
            
            return node;
        }
    }
}





未整理


ActionScriptからFlexコンポーネントの作成

<?xml version="1.0"?>
<!-- usingas/ASVisualComponent.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Script><![CDATA[
     import mx.controls.Button;
     public var button2:Button;

     public function createObject():void {
        button2 = new Button();
        button2.label = "Click Me";
        hb1.addChild(button2);
     }
  ]]></mx:Script>
  <mx:HBox id="hb1">
     <mx:Button label="Create Object" click="createObject()"/>
  </mx:HBox>
</mx:Application>



ログ機能

    trace(event.currentTarget + ":" + event.type);

    
    // ? TODO:試してみる
    import mx.logging.*;
    import mx.logging.targets.*;

    private var myLogger:ILogger;
    addEventListener("click", logUIEvent);      



ASDoc
    
    Javaでいうjavadocと同じようなもの



テストのオートメーション用ライブラリも標準でついているらしい?
TODO:


crossdomain.xml が対象のサーバのルートパス?にないときに明示的に指定する

    Security.loadPolicyFile("http://www.lingr.com/api/crossdomain.xml")



相対座標(ローカル)から絶対座標(グローバル)に

→ localToGlobal を使う

    var point:Point = container1.parent.localToGlobal(new Point(container1.x, container1.y));

    trace(point.x + " / " + point.y);

    → 「container1.parent からみた container1 の座標を、グローバルにする」なので「parent」が必要



絶対座標で描画したオブジェクトを一番上の(親の)オブジェクトに追加する

(1) メインのSpriteクラス内で書く場合

    stage.addChild(shape01);   // Shape を足す場合
    this.addChild(uic01);      // UIComponent を足す場合

(2) 他のクラスから書く場合

    Application.application.stage.addChild(shape01); // Shape を足す場合
    Application.application.addChild(uic01);         // UIComponent を足す場合


※ メインのクラスをMXMLで書いてるときの話




event.updateAfterEvent() って?

    フレームレートの設定にかかわらず、画面の描画を更新します。





ローカルのキャッシュについて (TODO:

    保存される場所 (Vistaの場合)
        C:\Users\ユーザ名\AppData\Local\Temp
    
    参考:クライアントサイドのキャッシュの禁止
        http://livedocs.adobe.com/flex/2_jp/docs/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001388.html

        → よく分からない。



blurFilter とかのEffectが終了したときのイベント

    effectEnd



※ コロン(:) の前後は空白入れて問題ないから、
    次のように : の部分で揃うようにスペースを入れると見やすいかも

    public class Class1 {
        private var id    :String  = 'xzad';
        private var name  :String  = 'xmksd';
        private var vaild :Boolean = false;
        
        ・・・
    }




拡大縮小のエフェクト

MXML使う場合

    (1) Zoom を定義しておいて

        <mx:Zoom id="zoomAll" zoomWidthTo="5" zoomHeightTo="5" zoomWidthFrom="1" zoomHeightFrom="1"  />
        
        ※ この場合 1倍→5倍へ拡大

    (2) 拡大したいタイミングで(イベントハンドラ内で)次のように書く
        zoomAll.play([event.target], false);  // 拡大 (再生) * デフォルト
        zoomAll.play([event.target], true);   // 縮小 (逆再生)
        
        ※ この四角カッコは何だろう → 配列だった

ActionScriptのみでいく場合

    private function testZoom():void {
        var zoom1:Zoom = new Zoom();
        zoom1.target = label1;
        zoom1.zoomWidthFrom = 1;
        zoom1.zoomHeightFrom = 1;
        zoom1.zoomWidthTo  = 3;
        zoom1.zoomHeightTo = 3;
        
        zoom1.addEventListener(EffectEvent.EFFECT_END, testZoom2);
        zoom1.play();
    }



「拡大終わったら縮小して、縮小し終わったら消して・・」みたいにエフェクトを連鎖させたい。


(1) イベントハンドラをつなげていく方法

    → addEventListener(EfffectEvent.EFFECT_END, xxx) で足しておいて、
        次のイベントハンドラ内で removeEventListener で元に戻す。
    → イベントハンドラだらけでごちゃごちゃしそう。

    private function testZoom():void {
        var zoom1:Zoom = new Zoom();
        zoom1.target = label1;
        zoom1.zoomWidthFrom = 1;
        zoom1.zoomHeightFrom = 1;
        zoom1.zoomWidthTo  = 3;
        zoom1.zoomHeightTo = 3;
        
        zoom1.addEventListener(EffectEvent.EFFECT_END, testZoom2);
        zoom1.play();
    }
    
    private function testZoom2(event:EffectEvent):void {
        var zoom1:Zoom = Zoom(event.target);
        zoom1.removeEventListener(EffectEvent.EFFECT_END, testZoom2);
        zoom1.play([zoom1.target], true);
    }



※ 関数が増えるのが嫌なので、無名関数で書いていった場合の例

    move.addEventListener(EffectEvent.EFFECT_END, function (event:Event):void {
        event.target.removeEventListener(event.type, arguments.callee);
        var move:Move = Move(event.target);
        move.addEventListener(EffectEvent.EFFECT_END, function (event:Event):void {
            event.target.removeEventListener(event.type, arguments.callee);
            lblPoint.text = parseInt(lblPoint.text) + parseInt(lblDamage.text) + "";
            lblDamage.visible = false;  // (3)
        });
        move.play(move.targets, true); // (2)
    });
    move.play(); // (1)

    → (1) → (2) → (3) の順に実行されることになる

    ※ removeEventListener するときに、関数名を指定しなければいけないのだが
       無名関数でも arguments.callee というので呼び元の関数が指定できるところがポイント


(2) Sequence を使う方法   ※ こっちでやるほうが楽(変数とか共有できるし)

    ※ zoomUp, pause, zoomDown というエフェクトを用意しといたとして

    var seq:Sequence = new Sequence();
    seq.targets = [txtTalk, imgTalk];
    seq.addChild(zoomUp);
    seq.addChild(pause);
    seq.addChild(zoomDown);
    
    seq.play();



その他エフェクトについてメモ

Zoom : 拡大縮小

    // 拡大するエフェクト
    zoomUp = new Zoom();
    zoomUp.targets = [imgTalk, txtTalk]; // targets に配列を渡せば複数指定OK
    zoomUp.originX = 0; // どこを中心に拡大するかを指定
    zoomUp.originY = 0;
    zoomUp.zoomHeightFrom = 0.2;
    zoomUp.zoomWidthFrom  = 0.2;
    zoomUp.zoomHeightTo   = 1;
    zoomUp.zoomWidthTo    = 1;
    
    ※ originX, originY の座標は、対象のオブジェクトの(親ではない)の、左上


Fade : 透明にしてフェードアウトさせたり
    ※ 2つの画像を置き換える例

    var fade1:Fade = new Fade();
    var fade2:Fade = new Fade();
    
    fade1.alphaFrom = 0;
    fade2.alphaFrom = 0;
    fade1.alphaTo   = 1;
    fade2.alphaTo   = 1;
    fade1.duration  = 500;
    fade2.duration  = 500;
    
    fade1.play([imgDamage1], !(pointAfter > 0));
    fade2.play([imgDamage2],  (pointAfter > 0));

Dissolve : Fadeと似た動作。文字も扱える

    var dissolve:Dissolve = new Dissolve();
    dissolve.targets = [imgMessage, txtMessage];
    dissolve.alphaFrom = 1;
    dissolve.alphaTo   = 0.0;
    dissolve.play();


Move : 移動する

    var move:Move = new Move();
    move.target = txtTalk; // 1つだけ指定したい場合は target に渡すと良い
    move.xFrom = 10;
    move.yFrom = 80;
    move.xTo   = 500;
    move.yTo   = 30;
    move.duration = 1000; // 再生時間を設定 → ゆっくり動かしたい場合はこの数字を長く ※ ミリ秒単位
    move.play();

Pause : 停止する

    var pause:Pause = new Pause();
    pause.duration = 3000; // 3秒間停止
    pause.play();

Sequence : 複数のエフェクトを連続して実行

    var seq:Sequence = new Sequence();
    seq.targets = [txtTalk, imgTalk];
    seq.addChild(zoomUp);
    seq.addChild(pause);
    seq.addChild(zoomDown);
    
    seq.play();

WipeUp : ワイパーで掃くような動作 (WipeDown, WipeLeft, WipeRight は 向きが違うだけ

    var wipeUp:WipeUp = new WipeUp();
    wipeUp.play([img01]);



Q. Dissolve で表示を徐々に消した後、消したはずのものが再表示されてしまう。

A.
    再表示されてしまうのが何でなのかは分からないが、
    イベント終了時に非表示にしてしまえばいい。

    var dissolve:Dissolve = new Dissolve();
    dissolve.targets = [imgMessage, txtMessage];
    dissolve.alphaFrom = 1;
    dissolve.alphaTo   = 0.0;
    
    dissolve.addEventListener(EffectEvent.EFFECT_END, function (event:Event):void {
        for (var key:String in event.target.targets) {
            event.target.targets[key].visible = false; // または alpha = 0
        }
    });
    
    dissolve.play();



Dissolve と Fade の違い

    ・背景色が透明のオブジェクト(SWFLoader)のalpha値を下げて透過させるとき
        :) Fade だと背景が透過したまま
        :( Dissolveだと 再生中に背景が白くなる

    ・alpha値を下げて消すときに
        :) Fade だと 再生が終わると消えたまま
        :( Dissolve だと 再生が終わると、再度表示される(alpha=1になる)

    ・画像と一緒に文字が消したい
        :( Fade だと、フォントを埋め込まないと消えてくれない
        :) Dissolve だと、文字も一緒に消えてくれる



コンボボックス:<select>みたいなもの

MXML側

    <mx:ComboBox id="combo1" x="291" y="138" width="119" fontSize="12">
        <mx:dataProvider>
            <mx:Object label="あああ" data="aaa"/>
            <mx:Object label="いいい" data="bbb"/>
        </mx:dataProvider>
    </mx:ComboBox>

    ※ data="xxx" は何に使われるのだろう

ActionScript側

    combo1.selectedLabel => "あああ" とか "いいい" とかの文字列が取れる
    combo1.selectedIndex => 0, 1 .. のインデックスが取れる
    combo1.selectedItem  => ?
    




作るべきファイル

    MXML + CSS + ActionScript (+ jpg, gif, swf) → SWF
    
    ※ コンパイルするとSWFファイルが出来上がる

コンパイラ
    Flex 2 SDK
        mxmlc : MXML, AS, イメージファイルから、アプリケーション(SWF)を作成する
        compc : MXML, AS, イメージファイルから、コンポーネント(SWC)を作成する



SWFファイルをHTMLに埋め込むとき

    <embed src="xxx.swf" width="652" height="182">

※ 他のオプション、自動再生されてほしくないときとか

    <embed src="xxxx.swf"
           width="100"
           height="100"
           play="false"
           loop="false"
           type="application/x-shockwave-flash"
           pluginspage="http://www.macromedia.com/go/getflashplayer"
    />



MXMLファイルの話


CSSを書く場所

直接書く場合
    <mx:Style>
        TextArea {
            font-size: 36px;
            font-weight: bold;
        }
    </mx:Style>

別ファイルに出す場合
    <mx:Style source="styles.css" />



ActionScriptコードを書く場所

直接書く場合
    <mx:Script>
        <![CDATA[
            public function close() : void {
            myPanel.visible = false;
            }
        ]]>
    </mx:Script>

別ファイルに出す場合((1) 関数とか変数とかをインクルード)
    <mx:Script source="myFunctions.as" />


別ファイルに出す場合((2) クラスにする)
    <mx:Script>
        <![CDATA[
            import pkg1.class1;
        ]]>
    </mx:Script>




HTTPService、WebService タグ
    → リモートサーバーからデータを取得することができます。
    → RPCコンポーネントとも呼ばれます

    public function useHttpService(parameters:Object):void {
        service = new HTTPService();
        service.url = "http://xxxx.xxx.xx.xxxx/xxx.xml";
        service.method = "GET";
        service.addEventListener("result", httpResult);
        service.addEventListener("fault", httpFault);
        service.send(parameters);
    }

    public function httpResult(event:ResultEvent):void {
        var result:Object = event.result;
        // 返ってきたのがXMLなら、result["lwws"]["telop"] みたいな
        // 感じでデータを取ってこれる
    }

    public function httpFault(event:FaultEvent):void {
        var faultstring:String = event.fault.faultString;
        Alert.show(faultstring);
    }


※ 外部のサーバと通信するには、相手サーバ側に crossdomain.xmlファイルが無いといけない。

※ TODO: パスを明示的に指定する方法




Flash側でデータ受け取る話

    ラッパーの <object> および <embed> タグの flashVars プロパティを使用して、Flex アプリケーションに変数を渡すことができます。

    呼び出し元HTML 〜 (1) flashVarで指定する場合
        <object id='mySwf' classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0' height='100%' width='100%'>
            <param name='src' value='FlashVarTest.swf'/>
            <param name='flashVars' value='firstName=Nick&lastName=Danger'/>
            <embed name='mySwf' src='FlashVarTest.swf' pluginspage='http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash' height='100%' width='100%' flashVars='firstName=Nick&lastName=Danger'/>
        </object>
    
    呼び出し元HTML 〜 (2) GETで指定する場合
        <object ... >
            <param name='src' value='TitleTest.mxml.swf?myName=Danger'>
            ...
            <embed src='TitleTest.mxml.swf?myName=Danger' ... />
        </object>
    
    ※ アドレスバーに直打ちでも良い
        http://localhost:8100/flex/myApp.swf?myName=Nick&myHometown=San%20Francisco


    受け取る側(ActionScript側)
        MXML使用している場合
            myName = Application.application.parameters.myName;
        
        ActionScriptで書いてる場合
            myName = root.loaderInfo.parameters["myName"];
    
    




次の画面に遷移する話

navigateToURL() メソッドの機能を、URLLoader クラスの load() メソッドと混同しないでください。URLLoader クラスは、指定された URL を ActionScript による操作のためにオブジェクトにロードします。navigateToURL() メソッドは、指定された URL にブラウザで移動します。

※マニュアルより



ブラウザで画面遷移

    navigateToURL(new URLRequest("http://www.adobe.com/flex"),"_blank");



JavaScriptのメソッドを呼ぶ

    方法1: ExternalInterface APIを使用する
        <mx:Button id="b1" label="あああ" click="ExternalInterface.call('alert''hello')" />
    
    方法2: navigateToURLメソッドを使う
        var u:URLRequest = new URLRequest("javascript:catchClick('" + eName + "','" + eType + "')");
        navigateToURL(u,"_self");



ライブラリパス(libpath)を追加する方法

「ナビゲータ」ペインの libpath設定したいプロジェクトを
右クリック→プロパティ→Flexビルドパス

で、「ライブラリパス」タブで、swcファイルもしくはswcファイルの入っているディレクトリを指定する
Papervision3dやAPEみたいに swc形式じゃなくてソースが手に入っている場合は、
「ソースパス」タブで ソースの置いてあるディレクトリを指定する。




用語:
    イベント
    トリガ
    ビヘイビア
    エフェクト
    ビューステート
    トランジション




豆知識系

(1) MXMLはコンパイル時にいったんActionScriptに変換される

    生成されたコードを確認するには、keep-generated-actionscript コンパイラオプションの値を true に設定します。
    こうすると、コンパイル時に *.as ヘルパーファイルが "/generated" ディレクトリに保存されます。






背景色にグラデーションがかかってて嫌だ

    backgroundGradientColors を "[0xFFFFFF, 0xFFFFFF]" に設定すると真っ白に。



IE経由じゃなくてスタンドアロン版のFlashPlayerでデバッグしたい

    プロジェクトの「プロパティ」→「Flexコンパイラ」
        →「HTMLラッパーファイルの生成」のチェックを外す
    
    → そうすると swf ファイルのみ生成されるので、実行時にプレイヤーが開く(?)



携帯Flash
    ・2.1までしか対応してない (2007/08現在)
    ・コンテンツ開発キット(CDK)というのが必要




ActionScriptから、MXMLに記述したコンポーネントを参照したい場合は、idをつけて参照

MXML
    <mx:Button id="myButton" label="Click Me"/>

ActionScript
    myButton.label = "Clicked";





データモデル。

TODO: モデルに格納されたデータはどこで参照するの?
    →ActionScript側でオブジェクトとして見えてくれる?


<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <!-- データモデル "contact" に連絡先情報を格納する
        上記の各 TextInput コントロールの text プロパティが
        データモデルのフィールドに渡される -->
    <mx:Model id="contact">
        <info>
            <homePhone>{homePhoneInput.text}</homePhone>
            <cellPhone>{cellPhoneInput.text}</cellPhone>
            <email>{emailInput.text}</email>
        </info>
    </mx:Model>

    <!-- TextInput コントロールに入力されたデータをバリデータコンポーネントで検証する -->
    <mx:PhoneNumberValidator id="pnV"  source="{homePhoneInput}" property="text"/>
    <mx:PhoneNumberValidator id="pnV2" source="{cellPhoneInput}" property="text"/>
    <mx:EmailValidator       id="emV"  source="{emailInput}"     property="text"/>

    <mx:Panel title="My Application" paddingTop="10" paddingBottom="10"
        paddingLeft="10" paddingRight="10" >
        <!-- ユーザーが TextInput コントロールに連絡先情報を入力する -->
        <mx:TextInput id="homePhoneInput" text="This isn't a valid phone number."/>
        <mx:TextInput id="cellPhoneInput" text="(999)999-999"/>
        <mx:TextInput id="emailInput"     text="me@somewhere.net"/>
    </mx:Panel>

</mx:Application>



カスタムのValidatorも作ってみたい



データのフォーマッター


<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <!-- ZipCodeFormatter を宣言し、パラメータを定義する -->
    <mx:ZipCodeFormatter id="ZipCodeDisplay" formatString="#####-####" />

    <mx:Script>
        <![CDATA[
            private var storedZipCode:Number=123456789;
        ]]>
    </mx:Script>

    <mx:Panel title="My Application" paddingTop="10" paddingBottom="10"
        paddingLeft="10" paddingRight="10" >

        <!-- フォーマッタをトリガし、ストリングにデータを読み込む -->
        <mx:TextInput text="{ZipCodeDisplay.format(storedZipCode)}" /> 

    </mx:Panel>
</mx:Application> 



ハイパーリンク

<?xml version="1.0"?>
<!-- controls\button\LBSimple.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    
    <mx:LinkButton label="ADBE" 
        width="100"
        click="navigateToURL(new URLRequest('http://quote.yahoo.com/q?s=ADBE'), 'quote')"/>
</mx:Application>



カメラからのストリーミングビデオ
次の例のように、VideoDisplay.attachCamera() メソッドを使用してコントロールを設定すれば、カメラからのビデオストリームをコントロールに表示できます。

<?xml version="1.0"?>
<!-- controls\videodisplay\VideoDisplayCamera.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Script>
        <![CDATA[
    
            // Define a variable of type Camera.
            import flash.media.Camera;
            public var cam:Camera;

            public function initCamera():void {
                // Initialize the variable.
                cam = Camera.getCamera();
                myVid.attachCamera(cam)
            }
        ]]>
    </mx:Script>
  
    <mx:VideoDisplay id="myVid" 
        width="320" height="240" 
        creationComplete="initCamera();"/>
</mx:Application>


Flash Media Server 2 での VideoDisplay コントロールの使用
VideoDisplay コントロールを使用すれば、次の例のように、Adobe の Macromedia Flash Media Server 2 からメディアストリームを読み込むことができます。

<?xml version="1.0"?>
<!-- controls\videodisplay\VideoDisplayFMS.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:HBox>
        <mx:Label text="RTMP FMS 2.0"/>
        <mx:VideoDisplay 
            autoBandWidthDetection="false" 
            source="rtmp://localhost/videodisplay/bike.flv"/>
    </mx:HBox>
</mx:Application>


Alert出したい

    <mx:Script>
        <![CDATA[
            import mx.controls.Alert;
        ]]>
    </mx:Script>
    <mx:Button label="ADBE" click="Alert.show('メッセージ''タイトル', Alert.YES | Alert.NO);" />



デフォルトのボタンを設定する

    <mx:Form defaultButton="{mySubmitBtn}">
        ...
    </mx:Form>
    
    ※ タブ順序を指定する tabIndex というフィールドもあるようだ



カスタムバリデータ(Validator)

    例1
        http://livedocs.adobe.com/flex/2_jp/docs/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001772.html#115022
    
    例2
        http://livedocs.adobe.com/flex/2_jp/docs/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001773.html#115114





レイアウト用のコンポーネント
    HBox:「この中でコンポーネントを横に並べたい」という用途
    VBox:「この中でコンポーネントを縦に並べたい」という用途


スクロール
    horizontalScrollPolicy="on"
    verticalScrollPolicy="on"


座標
    マウスイベントを処理するときは、可能であれば MouseEvent オブジェクトの座標を使用するのが最適です。




ダウンロードプログレスバー
    デフォルトは有効
    
    無効にする場合はこうする
        <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" usePreloader="false">



Gridレイアウトコンテナ

    HTMLでいうtable
    → なので、rowspanとかcolspanとかの指定ができる
    


履歴管理
    
    Flex History Manager を使用すると、ユーザーは、Web ブラウザの [戻る] および [進む] ナビゲーション機能を使用して、Flex アプリケーション内を移動できます。
    

HTML/JavaScriptでいうとこの onload ってどう書くの?

    applicationComplete 属性を使う

    <mx:Application applicationComplete="initializeClient()" ...
    
    



HBox : 横に並べたいときに使う
VBox : 縦に並べたいときに使う
Tile : 横に並べるが、端まできたら折り返す




TextInput で、restrict というパラメータをセットすると入力できる文字を制限できる

    0-9   と設定したら 数字しか入力できない
    ^a-z  と設定したら、小文字アルファベットは入力できない(それ以外は可)
    
    ※ 正規表現ではないので、「行末に」とかの指定は出来ないようだ


Q. Subversionのリポジトリと同期したい

A.
    Subversion (SVN)のプラグイン subclipseのインストール
    Eclipse v3.3 (Europa) というバージョンを使ったときの話 ※ Flex Builder 3 (Standalone)(Eclipse v3.2) でも同様
    
    (1) まず本体のupdate ※ これ無くてもよかったかも
        上部メニューから [Help] - [Software Updates] - [Find and Install]
    
    (2) Subclipseのインストール
    
        上部メニューから [Help] - [Software Updates] - [Find and Install]
        →「Search for new features to install」を選択
        →「New Remote Site」を選択
            name : subclipse (何でもいい)
            URL  : http://subclipse.tigris.org/update_1.2.x   ※ Eclipse3.2/3.3のとき
                   http://subclipse.tigris.org/update_1.0.x   ※ Eclipse3.0/3.1のとき(Flex Builder
        → Finish
        → Subclipseが一覧に出てくるので、「+」で展開して
            「Subclipse( plugin)」を選択 (「Integration」は選択しない)
    
        ※「Integration」を選択すると次のエラーが出るので選択しなかった
            Buckminster - Subversion support (Incubation) (0.1.0.v20070626) requires plug-in "org.eclipse.buckminster.core".
    
        ※ メニューが日本語化されてる場合はこんな感じ
            ヘルプ → ソフトウェア更新 → 検索とインストール
            インストールする新規フィーチャーを検索
            新規リモート・サイト
           
        ※ 本体は英語でもプラグインは日本語になっているところがややうれしい
    
    (3) 使う
        ※ フォルダ名にスペースが入っているとうまくいかないみたいなので、
            [File] - [Switch Workspace] で、ワークスペースを、スペースを含まないパスにしておく。
            (Flex Builder 3のデフォルトは C:\Documents and Setting\... なのでNG)
    
        1. 右上の方の「+」マーク(Open Perspective) を押して「Other...」を選択
            →「SVNリポジトリ・エクスプローラ」を選択してOK
        2. 「SVNリポジトリ・エクスプローラ」のパースペクティブを選ぶボタンが右上に出るので選択
        3. 左側の「SVNリポジトリ」ビューで右クリック→「新規」→「リポジトリ・ロケーション」
        4. 「ロケーション」にSVNのパスを入力
            例:
                http://xxxxxxx/xxxxx
        5. チェックアウトしたいディレクトリ(プロジェクト)を1個選んで
            右クリック→「チェックアウト」
    

Q. Flex Builder 3 の プロファイリング機能が思うように動いてくれない

A. 

    (1) 「パースペクティブのカスタマイズ」辺りでボタンを表示する設定をする

    (2) [Window]-[Preference] で、
        [Flex]-[Profile]-[Player/Browser] の「Flash Player」に
        Flash Playerのパスを入力。
        
        C:\Program Files\Adobe\Flex Builder 3\Player\win\FlashPlayer.exe

    (3) プロファイルするボタンの右側にある「▼」→「Other...」
        ・「URL to path to launch」の「Use defaults」のチェックをOFF
        ・「Profile」の拡張子を html から swf に変更する
    
    (4) プロジェクトのプロパティで「Flexコンパイラ」の欄の
        「Use default SDK」にチェックを入れる。
        (Flex Builder 2と共存している環境(既存のプロジェクト?)だとFlex Builder 2のコンパイラを使用する設定になるので)

    ・・という風に、Flash Playerで実行されるようにしないとプロファイルが取れないみたい。

    
    ※ 表示された統計情報の保存方法が分からない・・・


--------------------+-------------------------------------------------------
Q. HTML に FLASH を埋め込むと、最前面に表示されてしまう

A. 
    下記の param 要素を object 要素内に追加しておいて
        <param name="wmode" value="transparent">
    
    embed 要素に wmode 属性を追加する。
        wmode="transparent"





再生をループさせないようにする。※ オーサリングツール(Flash CS3)での話

2つあって、

    (1) 「パブリッシュ」の際のHTMLの設定で「ループしない」オプションがある
        → でもこれだとSWFファイルはそのまま
    
    (2) SWFファイルの最後のフレームで stop() メソッドを呼ぶ
        ・ レイヤーを追加
        → 最後のフレームにキーフレームを挿入
        → [ウィンドウ]-[アクションスクリプト]
        → さっき追加したキーフレームを選択して「this.stop();」を記入する


モーフィング画像を作る ※ オーサリングツール(Flash CS3)での話

    フレームを右クリック→シェイプトゥイーンの追加
    → 右のほうにキーフレームを追加
    → 背景が薄い緑色になってつながった状態でトゥイーンが作成できた状態
    → 開始時点のフレームに絵を描く
    → 終了時点のキーフレームに絵を描く
    
    Q. モーフィングの変化の度合いは変えられるか
    A.「イージング」というパラメータを調整することで可能
        http://www.adobe.com/jp/devnet/flash/articles/animation_guide_06.html


ファイルサイズを減らす工夫  ※ オーサリングツール(Flash CS3)での話

(1) 要らなければ「コンポーネント」とか「サウンド」を削除する
    Flash CS3で右下の方で、サウンド(mp3, wav)と、
    コンポーネント(ComponentAssetsフォルダとボタン等)を削除する。
    ※ 「タイプ」でソートする

(2) パブリッシュ設定で「非表示レイヤーの書き出し」のチェック外す(結構減る)
(3) パブリッシュ設定で「Traceアクションを省略」にチェック入れる(変わらない)
(4) パブリッシュ設定で「ムービーの圧縮」のチェック外す(サイズは増えるけど読み込み時の負荷減ってくれたりしないかなあ)



crossdomain.xml の設定例

    <cross-domain-policy>
        <allow-access-from domain="*" to-ports="*" />
    </cross-domain-policy>



関数クロージャ、withステートメントとかの話題

    関数クロージャ:関数の中に関数が定義できる
        http://livedocs.adobe.com/flash/9.0_jp/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000057.html
        
    withステートメント
        http://livedocs.adobe.com/flashlite/2_jp/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts_wEcute&file=00000327.html
    
    → どっちも「変わってる」という点は分かるけど、どいう使われ方するのか良く分からない



コマンドラインでのコンパイル

コマンド
    mxmlc xxxx.as
        → xxxx.swf が出来る


Q. mxmlc を実行すると次のエラーが出る
    Failed to load Main-Class manifest attribute from /opt/bin/../lib/mxmlc.jar

A.
    例えばインストールした実行ファイルが /opt/flex_sdk_2/bin/mxmlc で、
    リンクを /opt/bin/mxmlc に貼っているとかなら

    export FLEX_HOME=/opt/flex_sdk_2/

    と環境変数を指定すれば解決
    
    ※ /opt/flex_sdk_2/bin/mxmlc を直接呼べば良いじゃんという話もある


Q. mxmlc でコンパイルしようとしたら次のエラーが出る

    SSHでつないでるとき   : Error: exception during transcoding: Failed to grab pixels for image 
    X-Windowでの操作のとき: (.:786): Gtk-WARNING **: cannot open display: 

A.
    GNUのJava (Fedoraのデフォルト) だと、画像(*.png)をEmbedするときにこうなるみたい。
    SunのJava を使うようにする。


Q. mxmlc でコンパイルしようとすると次のエラーが出る
    Error: A file found in a source-path must have an externally visible definition.
    If a definition in the file is meant to be externally visible, please put the definition in a package.

A.
    package とか public とかのつけ忘れです

※ちなみに public のつけ忘れだと
コンパイル ⇒ Warning: class 'TestHello' がデフォルトの名前空間にスコープされます :内部 。このパッケージの外部には表示されません。 
実行 ⇒ ReferenceError: Error #1065: 変数 TestHello は定義されていません。 

※ ちなみにファイル名と public にしたクラス名が違う場合
    Error: A file found in a source-path 'XxxXxx' must have the same name as
    the class definitioninside the file 'YyyYyy'.

※ クラス名とコンストラクタ名が違う場合
    Warning: return value for function 'TestEvaluate007' に型宣言がありません。
    → コンパイルは通るけど実行すると何もでない



Q. 外部のライブラリ(Papervision3DとかAPEとか)をソースパスに含めたい

A.
    mxmlc -compiler.source-path=/path/to/PV3D_1_5/src Sample01.as
    
    ※ このときにソースパスがカレントディレクトリのサブディレクトリ以下にあったりすると
        Warning: Source path entry, 'PV3D_1_5/src', is a subdirectory of source path entry,
        とかって出るが、気にしない


Q. Embedの構文を使用したファイルをmxmlcでコンパイルしようとしたら次のようなエラーが出た
    Error: An error occurred because there is no graphics environment available. 
    Please set the headless-server setting in the Flex configuration file to true.

    java.lang.InternalError: An error occurred because there is no graphics environment available.
    Please set the headless-server setting in the Flex configuration file to true.

A.
    X-Windowの使える環境 (リモートでもDISPLAY環境変数をセットしてればOK) でコンパイルすればOKだったらしい。
    
    ※X-Windowの使用できない環境だった場合、
        「この場合は、flex_sdk_2/frameworks/flex-config.xml の <compile> タグ直下に
            <headless>タグを挿入することで解決できます。」
        らしい。
        http://blog.livedoor.jp/agnode/archives/50969660.html




Q. Excelでいうとこの「最前面に表示」とか「最背面に表示」とか

A. DisplayObjectContainerにある、次のメソッドはそういう用途のもの?
    addChildAt(child, index)
    setChildIndex(child, index)
    swapChildren(child1, child2)
    swapChildrenAt(index1, index2)



SimpleButton

ステータス毎に表示するオブジェクトを登録するらしい。へーと思った。
    → 下記プロパティにDisplayObjectを配置する
    
    downState
    hitTestState
    overState
    upState

※ useHandCursor
    マウスがボタン上に移動したときに、ハンドカーソルを表示するかどうかを示す


可変長引数を扱う

    定義のところで  ... xxx と書いたら、
    関数内では xxx の部分が配列として読めるようだ

    function average(... args) : Number{
        var sum:Number = 0;
        for (var i:uint = 0; i < args.length; i++) {
            sum += args[i];
        }
        return (sum / args.length);
    }



sort

オブジェクトをソートしたいときに、Array.sortOn() を使うと
フィールド名を指定してソートできる

→ 「Array.sort(compareFunction, sortOptions) を使って自前で書く」といったことをしなくて済んでうれしい


    // クラスがこんなだとして
    package {
        public class Man {
            public var height :int;
            public var age    :int;
            public var name   :String;
            
            public function Man(name:String, age:int, height:int):void {
                this.name   = name;
                this.age    = age;
                this.height = height;
            }
        }
    }
    // ソートする方のコード
    var men:Array = new Array();
    men.push(new Man("Tom",  18, 160));
    men.push(new Man("John", 18, 170));
    men.push(new Man("Bob",  23, 180));
    men.push(new Man("Taro", 21, 170));
    
    var sortedMen:Array = men.sortOn(["age""height"], [Array.NUMERIC | Array.DESCENDING, Array.NUMERIC | Array.DESCENDING]);
        // 第1引数にフィールド名、第2引数に並べ方オプションを指定する。
        //
        // 並べ方のオプションは次のが使える
        //  ・ Array.CASEINSENSITIVE
        //  ・ Array.DESCENDING
        //  ・ Array.UNIQUESORT
        //  ・ Array.RETURNINDEXEDARRAY
        //  ・ Array.NUMERIC
        //
        // どっちの引数も、複数ある場合は配列で渡せば良い
        //
        
    for (var i:int = 0; i < sortedMen.length; i++) {
        trace(sortedMen[i].name + "\t" + sortedMen[i].age + "\t" + sortedMen[i].height);
    }
    
    // 出力
    // Bob     23      180
    // Taro    21      170
    // John    18      170
    // Tom     18      160


プロトタイプ継承って

    B.prototype = new A(); とやったら Aが親、Bが子。
    
    http://livedocs.adobe.com/flex/201_jp/html/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Book_Parts&file=04_OO_Programming_161_11.html



Q. 自クラス名を取得したい

A. 
    flash.utils.describeType(obj) と、XMLクラスを使ってなんか色々取れるっぽい

    var xml:XML = new XML(flash.utils.describeType(this));
    trace(xml.@name); // => クラス名   Sample01
    trace(xml.@base); // => 親クラス名 flash.display::Sprite
    
    for (var i:int = 0; i < xml..extendsClass.length(); i++) {
        trace(xml..extendsClass[i].@type); // => 親クラスを辿る
    }
    
    
    ※ なんかこのxpathみたいな記法は、E4X(ECMAScript for XML)というらしい
        → ドキュメントに例が出てる
            http://livedocs.adobe.com/flex/201_jp/langref/XML.html#includeExamplesSummary


Q. キーボードイベントが発生したときにイベントを受け付けるのは誰。

A.
    stage.focus = xxx; // xxx は Spriteとか。
    
    で指定したオブジェクト。とその親要素たち。


DisplayObjectクラスの hitTestPoint(x, y)
    
    var s1:Sprite = new Sprite();
      ...
    
    s1.hitTestPoint(mouseX, mouseY);
    
    第3引数を指定しないでおくと、
    マウスの位置が s1 の周りの矩形領域内のときにtrue。
    中に書いてある図形の形には関係なく四角。
    
    第3引数を true にしておくと、
    例えば丸を描いたときに、塗っていれば中も、線で描いていたなら線の上だけ true。
    これは MouseEventが発生するのと同じ基準っぽい。


    hitTestObject(obj) は、s1.hitTestObject(s2) のようにして、s1 と s2 が重なっているか判定。
    重なっているかどうかは矩形領域?graphicsオブジェクト? TODO:後で確認する



tips: オーサリングツール(Flash CS3)での話

    fl.* パッケージのソースは
    
    C:\Program Files\Adobe\Adobe Flash CS3\ja\Configuration
    
    に置いてある。native関数は無さそうだ

    ActionScript 3.0
    とか
    Component Source\ActionScript 3.0\User Interface
    とかの
    それぞれのフォルダに fl/xxxx/XxxXxx.as がある。


※ fl.* パッケージのソースを編集して、反映させたい場合

    上記のファイルをそのまま編集すると、次回以降も編集した結果が反映されてしまって困るので、
    (1) 上記ディレクトリをどこかにコピーする
    (2) [ファイル]-[パブリッシュ設定]で、「ActionScript 3.0」の横にある [設定]ボタン押して
        クラスパスの設定で、(1)でコピーした先のディレクトリを指定する。
        ※ fl ディレクトリのあるディレクトリを指定する
    (3) 編集
    (4) パブリッシュ



BlurFilterの qualityパラメータ

    http://livedocs.adobe.com/flex/2_jp/langref/flash/filters/BlurFilter.html#blurX
    
    > blurX
    > 水平方向のぼかし量です。指定できる値は 0 〜 255 (浮動小数) です。
    > デフォルト値は 4 です。2 のべき乗 (2、4、8、16、32 など) は、
    > 他の値と比べて速くレンダリングできるよう最適化されます。 
    
    と書いてある。
    
    ⇒ 試してみた(quality = 1〜3、blurX = blurY = 1〜50 でそれぞれ計測)
    ⇒ 確かにそうなってる quality = 2, 3 のとき特に差がハッキリ
    
    ついでに下の記述についても確認してみた。
    
    > quality
    > ぼかしの実行回数です。デフォルト値は、フィルタを 1 回適用することに
    > 相当するBitmapFilterQuality.LOW です。
    > 値 BitmapFilterQuality.MEDIUM はフィルタを 2 回適用します。
    > 値 BitmapFilterQuality.HIGH はフィルタを 3 回適用し、
    > ガウスぼかしに近似したものになります。
    > フィルタに設定された値が小さいほど、速くレンダリングできます。 
    
    ⇒ 2倍、3倍という風になっていないように見えるのは、
        quality = 1 のときだけ別のアルゴリズムでフィルタをかけているのかしら。



Flash 10 について

    Flash 10の新機能
       http://www.adobe.com/jp/products/flashplayer/features/

        新機能
            1. 3Dエフェクト
            2. カスタムのフィルタおよびエフェクト
            3. 高度なテキストサポート
            4. ダイナミックなサウンド生成
            5. ドローイングAPI
            6. Vectorデータタイプ
            7. ダイナミックストリーミング
            8. Speexオーディオコーデック

        強化機能
            9. ハードウェアアクセラレーション
            10. ファイルアップロード・ダウンロードAPI 強化機能

    ⇒ 1, 2, 5, 10 は具体的にActionScriptでいうと どの辺のクラスが?
        というのは下のリンクのPDFに分かりやすく載ってます
        
        「FlashPlayer 10のじかん」
            http://www.be-interactive.org/index.php?itemid=417
        
            3Dのところに関しては
            ・flash.geom, flash.display 辺りに Xxx3Dみたいな
                クラスがあってそれを使う
            ・プリミティブな処理(行列演算とか)がNative化されてる
                (playerglobal見て確認したわけじゃないけど)
            という感じみたい
            
            ※ Flex2のplayerglobal調べたときは flash.geom.Matrixは
                nativeになってなくてActionScriptで書かれてたような・・


    ⇒ 9. の辺りは どういう条件で有効になる?
            ブラウザだと wmode=gpu とかって設定するみたいだけど
            ActionScriptの場合はコードから変える?
            画面サイズを大きくしたりして速度が落ちると自動的に切り替わるとか?
            ⇒ NVPerfKit等で切り替わるタイミングを調べてみればいいのかも

    「Flash Player 10 の GPU サポート機能について」
        http://weblogs.macromedia.com/akamijo/archives/2008/05/flash_player_10_1.html
        
        ・ 60FPS(ディスプレイのリフレッシュレート)以上ださないようにしてるんだとか
    
    ※ 関連リンク
            Flash 10 新機能
                http://www.adobe.com/jp/products/flashplayer/features/
            Flash 10 Beta紹介記事
                http://journal.mycom.co.jp/news/2008/05/15/026/index.html
            Flash Player 10について
                http://www.adobe.com/jp/devnet/logged_in/jchurch_flashplayer10.html
            フォント部分(Saffron 3.1)
                http://www.merl.com/people/perry/SaffronWebPage/index.html
                ※ Automatic Grid Fitting とか Application-Hinted Glyphs というアルゴリズム?で小さいフォントもきれい
                ※ フォントにもHWアクセラレーションが
            Flash CS4新機能 - 「ボーンツール」とか便利機能が・
                http://clockmaker.jp/blog/2008/09/creative-suite-4_flash-cs4/

    ※ 追記
        カスタムフィルタというかシェーダ的な機能が追加されたという話で、
        AIF Toolkit という名前のが、Pixel Blender Toolkit になった?
        と思ったら、Blenderではなくて Pixel Bender Toolkit? もともとそんな呼び名だったっけ?
        



Q. コンパイル時に次のようなエラーメッセージが出る
    A file found in a source-path can not have more than one externally visible definition.

A. 
    1ファイルに2つクラスを書いてはダメですよということ?

    ⇒ こういうコードでエラーが出る
    
        package {
            class A
            {
                xxx
            }
            
            class B
            {
                xxx
            }
        }




Q. 背景色とかサイズの設定がしたい

A.
    package {
        import ....;
        
        [SWF(width="320", height="320", backgroundColor="#ffffff", frameRate="24")]
        public class XxxXxx extends Sprite
        {
            ...
        }
    }


Q. TextFieldの主な設定値が知りたい

A.

    var txtFooter:TextField = new TextField();
    txtFooter.text = "xxxxxxxxxxxxxxxxxx";
    txtFooter.background = true;
    txtFooter.backgroundColor = 0xFFFFDD;
    txtFooter.x          = 0;
    txtFooter.y          = 400;
    txtFooter.width      = 420;
    txtFooter.height     = 35;
    txtFooter.selectable = false;
    txtFooter.multiline  = true;
    txtFooter.border     = true;


Webカメラをつなぐ

    package {
        import flash.display.Sprite;
        import flash.media.Camera;
        import flash.media.Video;

        public class TestWebCam extends Sprite
        {
            public function TestWebCam()
            {
                var camera:Camera = Camera.getCamera();
                
                var video:Video = new Video(camera.width, camera.height);
                video.attachCamera(camera);
                
                addChild(video);
            }
        }
    }
    
    ⇒ ローカルのカメラの画像だすだけなら、これだけ。。拍子ぬけするぐらい簡単。
        ※ しかし画像が粗いな。。
        ※ camera.setQuality(0, 100); とやると「画質優先」だけど、これはFMS使うときのオプション

    package {
        import flash.display.Bitmap;
        import flash.display.BitmapData;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.media.Camera;
        import flash.media.Video;

        public class TestWebCam extends Sprite
        {
            public function TestWebCam()
            {
                var camera:Camera = Camera.getCamera();
                
                var video:Video = new Video(camera.width, camera.height);
                video.attachCamera(camera);
                
                var bitmapData:BitmapData = new BitmapData(camera.width, camera.height);
                
                
                addChild(new Bitmap(bitmapData));
                
                addEventListener(Event.ENTER_FRAME, function(e:Event):void {
                    bitmapData.draw(video);
                    for (var x:int = 0; x < bitmapData.width; x++) {
                        for (var y:int = 0; y < bitmapData.height; y++) {
                            var p:uint = bitmapData.getPixel(x, y);
                            
                            if (p == 0xFFFFFF) { // 真っ白なところを赤く塗りつぶす。
                                bitmapData.setPixel(x, y, 0xFF0000);
                            }
                        }
                    }
                });
            }
        }
    }
    
    ⇒ 画像認識とかピクセル単位で処理がしたい時は、こうやってBitmapDataクラスを間に挟む
    
    
    未整理メモ
        うーむ。
        
        カメラの入力をここまでラップしていてくれていると、
        画像処理やりたい人にとって敷居がだいぶ低くなっている気がする。
        
        欲を言うと OpenCV みたいなライブラリがあったら、、
        FLARToolkit というのがそういう用途に使える?
        ARToolkit のデモは、紙の上の四角の上に立体が乗るというものしか見たことがないのでよく分からず。。
        


未整理

    [SWF(width="320", height="320", backgroundColor="#ffffff", frameRate="60")]
    public class XxxXxx extends Sprite {
        ...
    }



Q.
    URLLoaderを使ってローカルファイルにアクセスするSWFを作ったら、Flex Builder上では動いたのに
    そのファイルをコピーして再生したら次のエラーが出て動かせない。

    SecurityError: Error #2148: SWF ファイル file:///C|/xxxx.swf はローカルリソース file:///C|/xxxx.conf にアクセスできません。ローカルファイルシステムの SWF および信頼されているローカル SWF ファイルのみがローカルリソースにアクセスできます。

A.
    次のようにすると解決。
    
    (1) C:\WINDOWS\system32\Macromed\Flash に FlashPlayerTrustディレクトリを(なければ)作成

    (2) securitl.cfg というファイルを作成して(ファイル名は何でも良いらしい)、
        SWFファイルの置いてあるディレクトリ名を書く
        
        C:\xxx\xxx\xxx

    ※ というのを、ここに書いてあった
        → http://kanamehackday.blog17.fc2.com/blog-entry-82.html
        
        これ見てなかったら、わざわざWebサーバをローカルに立てようとか考えてしまった。。



リンク

    配列操作の比較表、文字列操作の比較表、真偽値の比較表
        http://blog.livedoor.jp/takaaki_bb/archives/51242763.html
    
    ブログのActionScriptカテゴリ
        http://blog.livedoor.jp/takaaki_bb/archives/cat_10023888.html




読んだ本/使っていた本
ActionScript 3.0ゲームプログラミングブック」(布留川 英一)

いろんな機能をざっとさらえる。ActionScriptの記述がメインで、MXMLに関する記述はほとんどなし
The Essential Guide to Flex 2 with ActionScript 3.0」(Charles E. Brown)

(英語) 画面イメージとかチュートリアルみたいのがあって分かりやすい。MXMLでWebアプリな人向け?
Actionscript 3.0 Cookbook」(Joey Lott, Darron Schall, Keith Peters)

(英語) サンプルコードが落とせたりキャプチャが載ってるといいんだけど・・
記憶に残るウェブサイト」(川上 俊)

とても良い。技術本ではなくてインタビュー集。

読みたい本
Essential ActionScript 3.0」(Colin Moock)

(英語)「Essential」なので読んでみたい。
Foundation ActionScript 3 Animation:Making Things Move!」(Keith Peters)

(英語) アニメーションとか3Dとか。パラパラみてると楽しげだ。
Adobe Flash CS3 詳細 ActionScript 3.0 入門ノート」(大重美幸)

分かりやすそう
New Masters of Flash」(中村 勇吾)

yugopさんが気になったので読んでみたい
Flash Math&Physics Design」(古堅 真彦)

動きのあるサイトを作ってみたい
Flash Math Creativity」(David Hirmes)

覚え書き
ActionScript 3.0 アニメーション」(Keith Peters)

覚え書き

「ここは違う」、「ここはこうするといいよ」等あったら下記フォームから連絡ください。
※ 何も来なさすぎて寂しいので、雑談とかグチのメールでも歓迎です。

お名前
e-mail
本文