Home > ActionScript3.0

ActionScript3.0 Archive

[as3]メモリリークをデバッグ(2)

メモリリークをデバッグ(1)の続き。

実際にInstanceWatcherクラスを使ってみます。
ソースのオリジナルは、l4lさんの記事から。

Continue reading

[as3]メモリリークをデバッグ(1)

あー、ずいぶん期間を空けてしまった。一度書くのをサボると、そのうち忘れていくんだよな~・・・。

l4lさんの記事などでも取り上げられてるんですが、
メモリやガベージコレクションの動きを監視したい!というような話です。

実行中のある瞬間に、いったいいくつのインスタンスが存在しているのかを確認しながら、
メモリリークを防ぎたい。と、多くの人が思っているはずです。多分。

で、上のl4lさんの記事やその大元のfladdictさんの記事の考えを元に、
こんなクラスを作って見ました。

Continue reading

[as3][言語解析]ActionScript3.0で形態素解析もどき(1)

最近は3dとか物理エンジンとか、グラフィックっぽいことばかりだったので、
少し違うことを。

JavaScript で形態素解析もどき
このあたりを参考に形態素解析もどきで遊んでみます。

Continue reading

[as3][FOAM]初めてのFOAM(2) 多角形の表示

前回記事 初めてのFOAMの続きです。

今回は多角形の表示をします。
FOAMの基本的な使い方は前回の記事を参考にしてください。

var rigid:RigidBody = new RigidBody([X位置], [Y位置], [サイズ], [頂点の座標配列]);
foam.addElement(rigid);

これが多角形を表示するコードです。
メソッドの引数はほかにもあるのでいろいろ調節はできるようですが、
まだ調査不足のためそのあたりはいずれ・・・。

今回のサンプルでのコードとしてはこのように書いています。

// 座標をランダムに決定。0-300で。(今回はswfのサイズが300×300なので)
var rnd_x:Number = Math.random() * 300;
var rnd_y:Number = Math.random() * 300;
// 多角形のサイズをランダムに決定。20-60。この数値は適当。
var rnd_size:Number = 20 + Math.random() * 40;
// 頂点数をランダムに決定。2-9。頂点数2なら直線、3なら三角形に。
var rnd_num_vertices:Number = 1 + Math.ceil(Math.random() * 8);
// createSymmetricPolygonメソッドで頂点座標の配列を返す。
var rigid_arr:Array = ShapeUtil.createSymmetricPolygon(rnd_num_vertices, rnd_size);

// RigidBodyインスタンスを生成し、foamエンジンへ追加。
var rigid:RigidBody = new RigidBody(rnd_x, rnd_y, rnd_size, rigid_arr);
foam.addElement(rigid);

簡単ですね。
ただ、ちょっと重いかな・・・。まだバージョン0.1.01だもんなぁ・・・。

デモはこちら
screenshot

ソースコード全体は以下。

Continue reading

[as3][FOAM]初めてのFOAM

最近はBox2DFlashAS3と言うのがはやっているようですね。今更いろいろやろうにも出遅れた感が否めないので、ここはあえて違う物理エンジンをいじってみようと思います。

今回触ってみたのは、FOAMという物理エンジンです。
バージョンは0.1.01。まだまだ開発版ということですかね。

ではでは、初めてなので、まずは使い方から。

必要なものは、Foamクラスのインスタンスです。

private var foam:Foam = new Foam();
addChild(foam);

しかも、FoamクラスはSpriteクラスを継承しているため、描画もしてくれます。
なので、addChildしておきます。

foam.addGlobalForceGenerator(new Gravity(new Vector(0, 0.3)));

Gravityクラスが重力になるようです。(まだ調査しきれてません・・・)
これを、先ほどのfoamインスタンスのメソッド、addGlobalForceGeneratorに渡します。
これで、重力発生です。

続いて、オブジェクトを配置します。
FormインスタンスのメソッドaddElementに、ISimulatableインターフェースなインスタンスを渡してやります。
円形や多角形、ベジェ曲線などがISimulatableインターフェースをimplementsしたクラスとして提供されています。
今回は円形と四角を使ったサンプルを作ってみました。

デモはこちら。screenshot

ソースは以下。

/**
* FOAM sample1
* @author jinten.net
*/
package  {
	import flash.display.*;
	import org.generalrelativity.foam.dynamics.element.body.*;
	import org.generalrelativity.foam.dynamics.enum.Simplification;
	import org.generalrelativity.foam.dynamics.force.Gravity;
	import org.generalrelativity.foam.Foam;
	import org.generalrelativity.foam.math.Vector;
	import org.generalrelativity.foam.util.ShapeUtil;

	[SWF(width="300", height="300")]
	public class FoamSample1 extends Sprite {

		private const W:Number = 300;
		private const H:Number = 300;

		private var foam:Foam;

		public function FoamSample1() {
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.BOTTOM;

			//FOAMインスタンスの生成
			foam = new Foam();
			addChild(foam);

			//オブジェクトのドラッグ有効化
			foam.useMouseDragger(true);

			foam.addGlobalForceGenerator(new Gravity(new Vector(0, 0.3)));

			//circle
			foam.addElement(new Circle(100, 100, 30));
			foam.addElement(new Circle(200, 100, 30));

			var wall_arr:Array;
			//ground
			wall_arr = ShapeUtil.createRectangle(W, 20);
			foam.addElement(new RigidBody(W/2, 0, Simplification.INFINITE_MASS, wall_arr));
			foam.addElement(new RigidBody(W/2, H, Simplification.INFINITE_MASS, wall_arr));
			//wall
			wall_arr = ShapeUtil.createRectangle(20, H);
			foam.addElement(new RigidBody(0, H/2, Simplification.INFINITE_MASS, wall_arr));
			foam.addElement(new RigidBody(W, H/2, Simplification.INFINITE_MASS, wall_arr));

			foam.simulate();
		}
	}
}

[AS3]値渡しと参照渡し

flashrodさんの記事から、メソッドへの引数の渡し方について。

public function swap(a:Object, b:Object):void {
    var tmp:Object = a;
    a = b;
    b = tmp;
}

こんなメソッドを定義して、

var a:Object = {
    value: "abc",
    toString: function():String { return this.value; }
};
var b:Object = {
    value: "xyz",
    toString: function():String { return this.value; }
};
swap(a, b);
trace("a=", a);
trace("b=", b);

こんな感じで実行しても、

a= xyz
b= abc

こうならない。というお話。

ならないだろうとわかってはいるんですが、
言われてみれば参照渡しと言うならできるはず。
こういうところで説明ができない時点で、
なんとなく感覚でやってしまってるんだろうなぁ、と反省しなくては・・・。

結論としては、俗に言う「参照の値渡し」というやつなんですね。

C/C++で書くなら、

#include <stdio .h>

void swap(int* a, int* b){
	int* tmp = a;
	a = b;
	b = a;
}

int main(){
	int a = 1;
	int b = 2;

	printf("a=%d b=%dn", a, b);
	swap(&a, &b);
	printf("a=%d b=%dn", a, b);

  return 0;
}

と、まぁ参照というより、ポインタ使ってるっぽい感じのイメージでいいんですかね。多分。
とりあえず、自分的には理解できてすっきり。

細かい言葉のあやみたいなところではあるんですが、
いつかこういったささいな部分ではまって、時間を無駄にするかもしれないし。
勉強になりました。

[AS3]3d物理エンジン

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

AS3 3D Physics Engine : WOW-Engine

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

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

スクリーンショットデモ

[pv3d]初めてのPaperVision3D(2)

今回も引き続き
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って・・・忍者?忍者ってこんな自然に文章に混ざっても、英語圏で通じるレベルなのかぁ。ちょっと感動です。

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

/**
* 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;
		}
	}
}

[Flex]コンポーネントのサイズがゼロになる?

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イベントをハンドルしても良いかもしれませんね。

[pv3d]初めてのPaperVision3D(1)

少し時間もあったので、最近流行の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オブジェクトを何も置いていないので、何も表示されませんが、
とりあえず今回はテンプレート的にソースコードを出しつつ今日はココまで。

コード全体は以下。

/**
* 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);
		}
	}
}

Home > ActionScript3.0

Search
Google
Feeds
Meta
Advertisement

Return to page top