Flex ActionScript 関連覚書などなど

ずいぶん前からその存在は知っていたんですが、
最近やっと出たみたいですね。

AS3 3D Physics Engine : WOW-Engine

ということで、早速触ってみたんですが・・・。
情報が少ない!わからないことばかり。

とりあえず今日は習作ということで。

スクリーンショットデモ

今回も引き続き
pv3d 2.0 tutorial list[pv3d.org]から。

前回でPaperVision3Dで3D描画を行うための世界は整っているので、
今回はその世界に3Dオブジェクトを追加して表示してみます。
と、いってもチュートリアルの通りに進めたところ、すごく簡単でした。

var material:ColorMaterial = new ColorMaterial(col, 0.9);
material.doubleSided = true;
 
var plane:Plane = new Plane(material);
scene.addChild(plane);

こんな感じで、
ColorMaterialのインスタンスを生成します。
これが、「面」になるようで、ColorMaterialは、色の付いた面になるようです。

material.doubleSided = true;

この部分では、面の裏側も色を塗ることを指定しています。
この指定をしないと片面しか色を塗ってくれないようです。

Planeクラスは「平面」です。
Planeクラスに先ほどの「面」を引数にして生成した後、シーンにaddChildします。

これで、3D空間へ平面を置くことができました。

Planeクラスのyawメソッドなどを呼ぶと平面を回転してくれます。
どのメソッドでどのように回転するかなどは、チュートリアルのサイトの、
3d Object Movement Explorerのページが参考になります。

平面の回転や移動等をしつつ、
前回のソースコードサンプルのようにEnterFrameイベントのリスナーで、
renderer.renderSceneメソッドを呼べば、
3Dの表示&ちょっとしたアニメーションまで完成です。


スクリーンショット

デモ

ちなみに、全然関係ないんですが、今回参考にしたサイトの、
7. Basic Interactivityで、

When starting out with pv3d, many as3 ninjas don’t realize you need to enable interactivity in the viewport and the material before being able to listen to the various click events.

ninjasって・・・忍者?忍者ってこんな自然に文章に混ざっても、英語圏で通じるレベルなのかぁ。ちょっと感動です。

とりあえず、チュートリアルそのままではアレなので少しだけ変えて、
今回のソースコードも公開。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
* PaperVision3D sample
* @author jinten.net
*/
package {
	import flash.display.Sprite;
	import flash.events.Event;
	import org.papervision3d.cameras.Camera3D;
	import org.papervision3d.cameras.FreeCamera3D;
	import org.papervision3d.materials.ColorMaterial;
	import org.papervision3d.objects.primitives.Plane;
	import org.papervision3d.render.BasicRenderEngine;
	import org.papervision3d.scenes.Scene3D;
	import org.papervision3d.view.Viewport3D;
 
	[SWF(backgroundColor = "#FFFFFF", width="400", height="300")]
 
	public class pv3d_sample1 extends Sprite {
 
		private var scene:Scene3D;
 
		private var viewport:Viewport3D;
		private var camera:Camera3D;
 
		private var renderer:BasicRenderEngine;
 
		private var planes:Array = new Array();
 
		public function pv3d_sample1() {
			init();
		}
 
		private function init():void {
			scene = new Scene3D();
 
			initObjects();
 
			viewport = new Viewport3D(400, 300);
 
			camera = new Camera3D(planes[0]);
 
			renderer = new BasicRenderEngine();
 
			addChild(viewport);
 
			addEventListener(Event.ENTER_FRAME, enterFrameHandler);
		}
 
		private function enterFrameHandler(e:Event):void {
			for (var i:int = 0; i < planes.length; i++) {
				planes[i].yaw((i%2==0?2:-2));
			}
			camera.x = mouseX;
			camera.y = mouseY;
 
			renderer.renderScene(scene, camera, viewport);
		}
 
		private function initObjects():void {
			planes.push(makePlane(0xFF6666, 0, 0, 0));
			planes.push(makePlane(0x66FF66, 400, 0, 0));
			planes.push(makePlane(0x6666FF, -400, 0, 0));
			planes.push(makePlane(0xFFFF66, 0, 400, 0));
			planes.push(makePlane(0x66FFFF, 0, -400, 0));
			planes.push(makePlane(0xFF66FF, 0, 0, 400));
			planes.push(makePlane(0x666666, 0, 0, -400));
		}
 
		private function makePlane(col:uint, x:Number, y:Number, z:Number):Plane {
			var material:ColorMaterial = new ColorMaterial(col, 0.9);
			material.doubleSided = true;
 
			var plane:Plane = new Plane(material, 300, 300);
			plane.x = x;
			plane.y = y;
			plane.z = z;
			scene.addChild(plane);
			return plane;
		}
	}
}

Frog on AIRさんのサイトで、こんな記事がありました。

オブジェクトのサイズを取得できない(AIR β2/β3)

記事の内容は、mx.controls.Butttonのインスタンスを生成した直後に、widthとheightの値を確認すると0になってしまう。というようなものです。

実際僕も何か作っているとき、同じような状況を何度も経験しました。
ホント大ハマリして、何時間も費やしたり・・・。
自分の備忘録も兼ねて、少しこのあたりを書き残しておきます。

クラスの種類
Flex2のリファレンスで説明されているクラスの中には、
純粋なActionScript3.0のクラスとFlex2のクラスの2種類があります。

純粋なActionScript3.0のクラスとは、
Array、Number、SpriteやTextFieldなどのクラスで、
importするときのクラスパスが、flash.~のものです。

対して、Flex2のクラスとは、
UIComponent、Button、Alert、PopUpManagerなどなど、
importするときのクラスパスが、mx.~のものです。

純粋なActionScript3.0のクラスというのは、
ActionScript3.0という言語でプログラミングをする場合には基本的に使えるクラスで、
FlexBuilder2でもFlashCS3でも使えるはずです。
一方Flex2のクラスというのは、
上記純粋なActionScript3.0のクラスを拡張(継承)したクラスで、
Flex2SDKのコンパイラでは一緒に提供されているだけです。
Flex2のクラスというのは、つまり、ActionScript3.0でプログラムする場合に、
使用できるオプション的なクラス郡になります。

例えばButtonクラスならSpriteを継承したクラスFlexSprite、
をさらに継承したUIComponentクラス、
をさらに継承したものがButtonクラスです。

Flex2のクラス
Flex2のクラスはFlexフレームワーク上で動作することを前提に作成されています。
つまりいくつかのフレームワークのルールに従う必要があるということです。

このルールのひとつとしてFlex2フレームワークを用いる場合には、
多くの便利なビジュアルコンポーネントを利用できるようになる代わりに、
独自のDisplayObjectを表示させたい場合には、
UIComponentクラスを継承しなければならないというルールがあります。
(IUIComponentインターフェースでもいいのかな・・・?)

UIComponentクラスでは、
コンストラクタでは最低限のプロパティとイベントリスナの初期化しか行いません。
(このため、インスタンス生成直後にはwidthなどは0になります。)
コンポーネントがDisplayObjectのツリー上にaddChildされるたあと
initialize()メソッドが呼ばれ、描画に必要なプロパティの一部がセットされます。
その後、実際に描画されるタイミングでupdateDisplayListというメソッドで、
レイアウトやサイズ等の値が計算され(ここでwidth等の値が確定します)、描画されます。
もちろんaddChildメソッドもoverrideして、子DisplayObjectを自身に追加する際には、
子DisplayObjectのinitializeメソッドを呼び出すようにしてあります。

と、いうことで一番初めのButtonクラス生成直後にwidth、heightの値が0となる件にやっと繋がりました。Flex2のDisplayObject系のクラスでは、処理の無駄を省くため、プロパティ実際のビジュアル部分のレイアウトやサイズ等の計算は次の描画タイミング時まで保留されます。そのため、すぐにwidthやheightの値を取得することができません。

以下、対応策の案としては、

1.Flex2のクラスを使わない
元も子もないですが、使わないというのも一手ですよね。
全部flashパッケージ内から賄い、足りない部分は自分で作る、と。
ボタンくらいだったら、SimpleButtonクラスでも十分なことも多いです。

2.callLaterメソッド
UIComponentクラスで定義されているcallLaterメソッドを使います。
(参考:callLaterメソッドの使用)

callLater() メソッドは、現在の更新ではなく、次の画面更新で実行する処理をキューに格納します。

つまりcallLater(hogeMethod)を用いることで、
コンポーネントが描画される(描画用のレイアウト・サイズ計算処理などが終了した)ときに
hogeMethodが呼ばれるので、widthなどの値を取得することができます。

今回のように初期化時だけであれば、
creationCompleteイベントをハンドルしても良いかもしれませんね。

少し時間もあったので、最近流行のPaperVision3Dに手を出してみました。

で、3Dとかさっぱりわからないのですが、とにかく触ってれば、
必要に迫られて色々知識も増えていくだろうということでひとまず参考にしたサイトはこちら。
pv3d 2.0 tutorial list[pv3d.org]

まだ途中みたいですが、チュートリアルになってます。
順に進めていくと、PaperVision3Dでの基本部分のコードの書き方がわかります。

まずは、3Dな世界の構築部分です。
最低限必要なインスタンスは4種類。まずは、インスタンスを生成します。

viewport = new Viewport3D();
scene = new Scene3D();
camera = new FreeCamera3D();
renderer = new BasicRenderEngine();

ちなみにScene3DクラスはSceneObject3Dのサブクラス、
FreeCamera3DはCameraObject3Dのサブクラスです。
シーンやカメラには他にも種類があるようですが、
今回は参考にしたサイトで使っていたクラスをそのままです。

続いてViewport3DのインスタンスをaddChildに渡します。

addChild(viewport);

これで、描画ツリーに3D世界を追加完了。

最後にBasicRenderEngine.rendererメソッドを呼べば描画されます。

renderer.renderScene(scene, camera, viewport);

このとき、scene、camera、viewportの各インスタンスを渡してあげます。

これだけ。

簡単ですね。

まだ3Dオブジェクトを何も置いていないので、何も表示されませんが、
とりあえず今回はテンプレート的にソースコードを出しつつ今日はココまで。

コード全体は以下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
* PaperVision3D sample
* @author jinten.net
*/
package {
	import flash.display.Sprite;
	import flash.events.Event;
	import org.papervision3d.cameras.FreeCamera3D;
	import org.papervision3d.render.BasicRenderEngine;
	import org.papervision3d.scenes.Scene3D;
	import org.papervision3d.view.Viewport3D;
 
	[SWF(backgroundColor = "#FFFFFF")]
 
	public class pv3d_sample1 extends Sprite {
 
		private var viewport:Viewport3D;
		private var scene:Scene3D;
		private var camera:FreeCamera3D;
		private var renderer:BasicRenderEngine;
 
		public function pv3d_sample1() {
			init();
		}
 
		private function init():void {
			viewport = new Viewport3D();
			scene = new Scene3D();
			camera = new FreeCamera3D();
			renderer = new BasicRenderEngine();
 
			addChild(viewport);
			addEventListener(Event.ENTER_FRAME, enterFrameHandler);
		}
 
		private function enterFrameHandler(e:Event):void {
			renderer.renderScene(scene, camera, viewport);
		}
	}
}

Flexからアニメーションをガリガリ作る時の標準は今はTweenerライブラリなんでしょうかね?
新しく開発中っぽいアニメーション用のライブラリを見つけたのでメモ。

Go animation system
(現在 closed betaらしい)
* とても軽量(およそ4K)
* 柔軟な設計で、高い拡張性を持つ。
* Fuseのようになんでもできるというようなものではない。
* ただし。Goを使ってFuseのようなものを作ることはできる。
* Goは特殊な書き方を要求しない。
* Goのエンジンは10から20000ものアニメーションを動かすことができる。
* 物理エンジンや3Dエンジンと一緒に使えるよう設計されている。
* GoのアプローチはCairngormフレームワークにインスパイアされている。

だ、そうです。
「物理エンジンや3Dエンジンと一緒に使えるよう設計されている。」ってのが興味深いですね。

気が付けば出てました。
FlashDevelop Beta5。

FlashDevelopでAIRを開発すべく色々と設定を漁ってきましたが、
ついに正式にサポートされたようです。
新規プロジェクトのActionScript3の項目には、

  • Flex 3 Project
  • AIR Flex 3 Projector
  • AIR Projector
  • というFlex3用のプロジェクト項目がデフォルトで入るようになりました。

    これで、誰でも面倒な設定無しでAIRの開発ができますね。
    ・・・と、言いたいところですが、
    まだ設定を自動で全てやってくれるというところまでは言っていないようです。
    なので、手動で設定しましょう。以下2点を設定すれば普通に使えるはずです。

    まずはコンパイラです。
    「Flex3プロジェクト」や「AIRプロジェクト」といっても、
    コンパイラの切り替えを促すようにはなっていないようなので、
    FlashDevelopの通常のFlexSDKをFlex2SDKにしている場合には、
    Flex3のSDKに設定しなおします。
    これは、メニューの「Project」->「Properties」の設定ダイアログから、
    「Compiler Options」タブを選択し、
    「Custom Path to Flex SDK」の項にFlex3のSDKへのパスを設定しましょう。

    続いては、コード補完です。
    コード補完用のファイルはデフォルトで付いてくるようになったのですが、
    それがなぜかプロジェクトに反映されていません。
    これも、メニューの「Project」->「Properties」の設定ダイアログから、
    「Compiler Options」タブを選択し、
    「Intrinsic Libraries」の項に必要なパスを追加しましょう。
    コード補完用のファイルは、(インストールフォルダ)\FirstRun\Library 以下にあります。
    例えば、AIRのプロジェクトなら、

  • Library\AS3\frameworks\Flex3
  • Library\AS3\frameworks\AIR
  • の二つを追加すれば、
    Flex3のmx系のコード補完と、AIR用のコード補完がきくようになります。

    画像は、先日のミニAIRアプリ(13行アプリ)の設定ダイアログです。
    設定ダイアログ

    ミニAIRアプリ

    カテゴリー AIR

    英語のBlogとか読みますか?

    英語力がなさ過ぎて、いつもすごく時間がかかります。
    GoogleToolBarがマウスオーバーで英単語の意味をポップアップしてくれるのですが、
    残念ながらあまり的確ではありません・・・。

    新しいタブを開いて、英辞郎を開いて検索して・・・、
    が面倒で面倒で!

    なので、サクッとそれっぽいのを作りましょうー。
    で、コードは以下です。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    < ?xml version="1.0"?>
    < mx :Application xmlns:mx="http://www.adobe.com/2006/mxml">
      < mx :Script>
      < ![CDATA[
        private function translate(word:String):void {
          html.location = "http://eow.alc.co.jp/" + word;
          textinput.text = "";
        }
      ]]>
      < /mx:Script>
      < mx :HTML id="html" width="100%" height="100%" />
      < mx :TextInput id="textinput" width="100%" enter="{translate(textinput.text)}" />
    < /mx:Application>

    テキストボックスに文字を入れてエンターキーで、英辞郎のページを開きます。
    ま、マッシュアップ(小)。

    13行。よし!と思ってから数分。
    こういう感じでサクッと作れるのがいいですねー。

    Alt+TABでブラウザとAIRアプリを切り替えつつ、ダバダバ読み進めると。
    ん~、まぁ・・・、さすがに実用にはほど遠いですね。

    FlashDevelop3.0.0 Beta4が出ましたね。
    設定の仕方は、こちら
    [IDE]ActionScript3.0(Flex3・AIR)の開発環境構築(1)
    [IDE]ActionScript3.0(Flex3・AIR)の開発環境構築(2)
    に書きましたが、少し設定の方法も変わったようなので、
    FlashDevelop3.0.0 Beta4でFlex/AIR対応させるやり方を新しく書きます。
    (自分用の備忘録に近いですが・・・)

    まず、FlashDevelop3.0.0をインストールをしましょう。
    とりあえずFlashDevelopを起動できるところまでいったら、
    文字コードの設定をします。
    Tools -> Program Settings で、設定ダイアログを開きます。
    左側の項目からMain FlashDevelopを選択し、「その他」の項目の「Default CodePage」
    をUTF8にします。ドロップダウンで選択するだけなので簡単ですが、
    この設定をしないと日本語のコメントなどがかけません。

    続いてFlex3コンパイラの設定をします。
    設定ダイアログの左側の項目から、Plugins AS3Contextを選択し、
    「Flex 2 SDK Location」の項目にFlex3のパスを指定します。
    この指定をするときに結構間違うらしいのですが、mxmlcなどがあるbinフォルダ
    をしていると上手く動きません。その上のbinフォルダを含むフォルダを指定です。

    それから、コード補完用のファイルを設定します。その辺の設定は、
    [IDE]ActionScript3.0(Flex3・AIR)の開発環境構築(1)のままですね。

    そしてここがBeta4のキモです。なんとこのままではコンパイルが上手くいきません。
    Flex3 Beta3ではfcshが日本語対応したためにFlashDevelopで上手く動かなくなっているのだそうです。ちなみにfcshとは、コンパイルの状態をキャッシュして二度目以降のコンパイル速度を上げるものです。Flex3のsdkには同梱されています。
    [ActionScript3]FlashDevelopとFlex 3 SDK beta 2の相性が悪いのを何とかする
    こちらの記事を参考にコンパイラの設定を直します。
    sdkのbinフォルダ内に「jvm.config」というファイルがあるので、このファイルをエディタで開きます。

    # Arguments to VM
    java.args=-Xmx384m -Dsun.io.useCanonCaches=false

    この部分を、

    # Arguments to VM
    java.args=-Xmx384m -Dsun.io.useCanonCaches=false -Duser.language=en

    と追記して保存しておきます。これでfcshが英語で起動するようです。

    とりあえず、ここまででFlashDevelopでコンパイルができるはずです。チェックしてみましょう。

    AIRプロジェクトの設定についてはほとんど、[IDE]ActionScript3.0(Flex3・AIR)の開発環境構築(2)と同じですが、色々バージョンアップして違うところもあるので、また次回書きます。

    ではでは。

    こちらの記事[AS3S.ORGさん]でデバッグに便利な環境について書かれていたので。
    流れに乗って。

    1. Debug Player

    これは必須ですね。FlashPlayerのDebug用バージョン。普通のFlashPlayerだとランタイムエラーとか拾ってくれないので。エラーが出ているのに表示されないのでデバッグが余計大変になってしまいます。しかも、普通に動くけど実はエラーが起きているということもあるというのが曲者です。例えば画像の読み込み時のIOErrorとかですね。気がつかないままリリースすると、他の開発者の人に「あーIOErrorをちゃんとハンドルしてないんだー」みたいなことがばれてしまうのは恥ずかしいです。

    ちなみに、いろんなベータ版とか試してるうちにこっそりとFlashPlayerが新しく置き換わることが結構あって、気がつかないうちにDebugPlayerではなくなっている、ということもあります。DebugPlayerの場合はFlash/Flex上で右クリックしたときに「デバッグ」というコマンド(ただしグレーで実行できない)が入るようですよ。

    2. Flash Tracer

    FireFoxのアドオンでtraceの出力をFlreFoxのサイドバーで確認できるというものです。

    すごい趣味の問題なんですけど、サイドバーじゃなかったらなぁ、と。デバッグ用の出力ウインドウはなんか画面下に欲しいんですよね。
    (FireFoxに他のアドオン入れれば下にできるのかもしれないけど、ブックマークの時とかは横にあって欲しいし・・・)

    3. Flash Switcher

    FireFoxでFlashPlayerのバージョンを切り替えるアドオンです。
    便利なんだけど・・・、他のタブでFlashPlayerが起動してると動かないんですよね。僕は結構タブを多めに開いたままにする派なので、なかなか使いづらい・・・。
    FireFoxが常用のブラウザじゃない人には良いかも。

    あとは、最近いたるところで話しにのぼっている、
    ThunderBoltですね。
    FireBugに出力できるというライブラリです。ただの出力か、警告かエラーかなど色々な出力を簡単に実現できるのは良いところですが、ソースコードにデバッグ用のコードが色々残ってしまうのが若干面倒ですね。
    FireBugに出力するだけ、という意味では、
    ExternalInterface.call("console.log", "hogehoge");
    でだせます。自分でうまいことデバッグ用のクラスを書いたほうが後々便利かもしれませんね・・・。

    Shigeru-Nakagaki.comさんの記事にて、ActionScript3.0でのincludeについての解説がありました。

    importについては、普段つかっているものなので、理解はしていたんですが、
    「include」があることすら知りませんでした・・・。

    include

    コンパイル時にソースを丸ごとぶち込みます
    注意点としては複数のファイルで同じファイルをincludeすると
    無駄にSWFが肥大化しますので、個人的にはお勧めしません ^_^;
    オブジェクト指向なんていう形式的なことは
    毛頭言う気はありませんが、それでもFlexでは
    クラス化したほうが良いと思います

    なるほど。
    ってことは、staticな変数とかは、コンフリクトを起こしてしまうんでしょうかね?
    そもそもincludeの使いどころってどういう状況なんだろう?過去のバージョンとの互換とかのために使えるようになってるだけなら良いんですが、どこかに使いどころがあるんでしょうね、多分。そういえばFlexFrameworkのソースの中にincludeがあったような・・・。

    ちゃんとAdobeから出されているリファレンスとか読み込まないとだめだなぁと痛感しますね。

    いつもその場しのぎで検索していくだけでは・・・だめだっ!

    « 戻る他のキーワードで検索 »