ActionScript

Archives

Shapetween

2009.5.7 木曜日

何か書かないと永遠に放置しそうになるので久しぶりに投稿。
今回はActionScriptじゃなくてProcessingについて。

ActionScriptだと「Tweener」というアニメーションライブラリが有名でとても便利なんだけど、Processingだと「Shapetween」が同じようなライブラリにあたるみたい。このライブラリについて、日本語であまり解説されていないみたいなので、Tweenerとちょっと比べてみました。

まず、考え方で大きく違うのはTweenerはオブジェクト(DisplayObejct?)にアニメーションを指定するのに対して、Shapetweenではそれ自体がオブジェクトだということ。だからShapetweenでは、time()とposition()という2つのメソッドで0〜1までのfloat(ActionScriptだとNumber)を取得し、それを任意のオブジェクトのプロパティなどに代入するといった具合で使います。

描画の概念が違うのでActionScriptと比べること自体ナンセンスな感じがするけど、下のプログラムは、マウスを押すたびに赤い円のサイズが大きくなる両プログラムのサンプル。ActionScriptの方はWonderflに追加してみました。

import megamu.shapetween.*;

Tween tweener;

//設定
void setup() {

	//アニメーション設定
	tweener = new Tween(this, 1, Tween.SECONDS, Shaper.LINEAR);

	//一度だけ実行(リピートしない)
	tweener.setPlayMode(Tween.ONCE);

	//描画設定(線なし、塗り赤)
	noStroke();
	fill(255, 0, 0);
}

//描画
void draw() {

	//初期化
	background(255);

	//円を描画
	ellipse(width / 2, height / 2, tweener.position() * 100, tweener.position() * 100);
}

//マウスが押された場合
void mousePressed() {

	//アニメーション再開
	tweener.start();
}
package {
	import caurina.transitions.Tweener;
	import flash.events.MouseEvent;
	import flash.display.Sprite;

	public class Main extends Sprite {

		private var Circle_mc:Sprite;

		public function Main():void {

			//赤い円を描画
			Circle_mc = new Sprite();
			addChild(Circle_mc);
			Circle_mc.graphics.beginFill(0xFF0000, 1.0);
			Circle_mc.graphics.drawEllipse(0, 0, 1, 1);
			Circle_mc.graphics.endFill();

			//リスナー
			stage.addEventListener(MouseEvent.MOUSE_DOWN, MouseDown);
		}

		//マウスが押された場合
		private function MouseDown(e:MouseEvent):void {

			//アニメーション解除
			Tweener.removeTweens(Circle_mc);

			//サイズを初期化
                        Circle_mc.x = Circle_mc.y = 50;
			Circle_mc.width = Circle_mc.height = 1;

			//アニメーション開始
			Tweener.addTween(Circle_mc, {
				x			:0,
				y			:0,
				width		:100,
				height		:100,
				time		:2.0,
				transition	:"liner"
			});
		}
	}
}

Posted by tmdf| |comments (0)

Animeクラスを作ってみた

2009.3.16 月曜日

よくお世話になる Spark project に何かコミットしてみようと思い、自分の欲しかった Animeクラス をアップしてみた。

ソースコードとサンプルはむこうに置いてあるのでよかったら試してみて下さい。要望・質問などがある方は、このブログ、Spark Projectどちら経由でもお気軽にどうぞ。

Posted by tmdf||comments (0)

Flashで複数マイク

2009.3.12 木曜日

マイク入力を複数取得できたら相対関係である程度位置を特定できないかな?と思い、試してみたけどうまくいかない。

2台のマイクは、PCのマイク入力ポートと、USB接続のWebカメラのマイク。「設定」メニューでは2つのマイクを認識しているし、この画面だとマイクを切り替えると2つ同時に動いてる。スクリプトで交互に切り替えるとそれぞれちゃんと動く。でも2台同時に入力させると片一方からの入力を無視する。Event.ENTER_FRAMEする度に取得するマイクIDを切り替えて擬似的に処理しようとしたらCPUスペックが足らないみたい。これでは駄目だ。

追記 2009.7.2
USBとかIEEE1394の複数ライン入力があるオーディオインターフェイス使えばできる?

実用性は無いけど実験用スクリプトは下記。

package {
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.media.Microphone;
	import flash.text.TextField;

	public class Main extends Sprite {

		//Mic0
		private var mic0:Microphone;
		private var Mic0_Bar_mc:MovieClip;
		private var Mic0_Level_tf:TextField;

		//Mic1
		private var mic1:Microphone;
		private var Mic1_Bar_mc:MovieClip;
		private var Mic1_Level_tf:TextField;

		public function Main():void {

			//マイクの台数取得
			var l:int = Microphone.names.length;

			//1台以上
			if (l >= 1) {

				//マイクの設定
				mic0 = Microphone.getMicrophone(0);
				mic0.setLoopBack(false);
				mic0.setUseEchoSuppression(true);

				//音量バーを作成
				Mic0_Bar_mc = new MovieClip();
				addChild(Mic0_Bar_mc);
				Mic0_Bar_mc.graphics.beginFill(0xFF0000, 1);
				Mic0_Bar_mc.graphics.drawRect(0, 0, 200, 20);
				Mic0_Bar_mc.graphics.endFill();

				//テキストフィールドを作成
				Mic0_Level_tf = new TextField();
				addChild(Mic0_Level_tf);
				Mic0_Level_tf.autoSize = "left";
				Mic0_Level_tf.textColor = 0x000000;
				addEventListener(Event.ENTER_FRAME, GetMic0);
			}

			//マイクが2台以上ある場合
			if (l >= 2) {

				//マイクの設定
				mic1 = Microphone.getMicrophone(1);
				mic1.setLoopBack(false);
				mic1.setUseEchoSuppression(true);

				//音量バーを作成
				Mic1_Bar_mc = new MovieClip();
				addChild(Mic1_Bar_mc);
				Mic1_Bar_mc.graphics.beginFill(0xFF0000, 1);
				Mic1_Bar_mc.graphics.drawRect(0, 0, 200, 20);
				Mic1_Bar_mc.graphics.endFill();
				Mic1_Bar_mc.y = 40;

				//テキストフィールドを作成
				Mic1_Level_tf = new TextField();
				addChild(Mic1_Level_tf);
				Mic1_Level_tf.autoSize = "left";
				Mic1_Level_tf.textColor = 0x000000;
				Mic1_Level_tf.y = 40;
				addEventListener(Event.ENTER_FRAME, GetMic1);
			}
		}

		private function GetMic0(e:Event):void {

			//更新
			var level:int = mic0.activityLevel;
			Mic0_Bar_mc.width = level * 2;
			Mic0_Level_tf.text = String(level);
		}

		private function GetMic1(e:Event):void {

			//更新
			var level:int = mic1.activityLevel;
			Mic1_Bar_mc.width = level * 2;
			Mic1_Level_tf.text = String(level);
		}
	}
}

Posted by tmdf||comments (0)

Flashの実行速度

2009.3.3 火曜日

デモを作ってると、Flashの実行速度を重視(見た目の綺麗さよりも反応速度)することがよくあと思います。swf、exe、airなど書き出す形式によって、実行速度が違うのでまとめました。スタンドアロンのFlash Player 10は2009.02.24時点での最新verをAdobe Flash Player – Downloadsから、Flash Player 9 は自分のPCにインストールされていたverを使用。

検証で使用したPCのスペックは、
・WindowsXP SP3 CPU : Pentium4 3.8GHz RAM : 1.0GB
・MacOSX 10.5.6 CPU : Core 2 Duo 2.0GHz RAM : 2.0GB
※AIR形式のウィンドウスタイルはシステムクローム。

FPS グラフ

結果、ActionScript3を実行して描画するにはWindowsで、CS3のexe形式が速い。
swf形式だと再生するFlash Playerに依存するみたいだからちょっと微妙。

理由は分からないけど、Windowsの場合、描画領域にマウスカーソルが重なっていない方が実行速度が上がる(Macは変わらない)。AIR独自の機能を使う、Macでデモしなければいけない、右クリックのイベント取得を行いたい場合がAIR形式で書き出すシチュエーションかな。

テストしたスクリプトは手っ取り早く負荷がかかりそうな雰囲気のあるPapervision3D (Public Beta 2.0 – Great White)を使って、パーティクルの周りをグルグルさせました。

package {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.text.TextField;
	import flash.utils.getTimer;
	import org.papervision3d.cameras.Camera3D;
	import org.papervision3d.core.geom.Particles;
	import org.papervision3d.core.geom.renderables.Particle;
	import org.papervision3d.core.math.Number3D;
	import org.papervision3d.materials.special.ParticleMaterial;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.render.BasicRenderEngine;
	import org.papervision3d.scenes.Scene3D;
	import org.papervision3d.view.Viewport3D;

	public class Main extends Sprite {

		//PV3D
		private var viewport:Viewport3D;
		private var camera:Camera3D;
		private var scene:Scene3D;
		private var renderer:BasicRenderEngine;
		private var input:Number = 0;

		//FPS計測
		private var fps:TextField;
		private var memory:int = 0;
		private var frame:int = 0;

		public function Main():void {

			//フレームレートとクオリティの設定
			stage.frameRate = 1000;
			stage.quality = "low";

			//PV3D
			viewport = new Viewport3D(stage.width, stage.height, true, false);
			addChild(viewport);
			camera = new Camera3D();
			camera.focus = 100;
			camera.zoom = 1;
			var target:DisplayObject3D = new DisplayObject3D();
			camera.target = target;
			scene = new Scene3D();
			renderer = new BasicRenderEngine();
			var particles:Particles = new Particles();
			var pm:ParticleMaterial = new ParticleMaterial(0xFFFFFF, 0.5, 0);
			for (var i:int = 0; i < 1000; i ++) {
				var pt:Number3D = new Number3D();
				pt.x = Math.random() * 1000 - 500;
				pt.y = Math.random() * 1000 - 500;
				pt.z = Math.random() * 1000 - 500;
				var chip:Particle = new Particle(pm, 10, pt.x, pt.y, pt.z);
				particles.addParticle(chip);
			}
			scene.addChild(particles);

			//テキストフィールドを作成
			fps = new TextField();
			addChild(fps);
			fps.autoSize = "left";
			fps.textColor = 0xFFFFFF;

			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}

		//毎フレーム実行
		private function onEnterFrame(e:Event):void {

			//PV3D
			input ++;
			var r:int = 500;
			var radian:Number = Math.PI / 180 * input;
			camera.x = r * Math.cos(radian);
			camera.z = r * Math.sin(radian);
			renderer.renderScene(scene, camera, viewport);

			//FPS
			frame ++;
			if (getTimer() - memory >= 1000) {
				fps.text = String(frame) + "fps";
				frame = 0;
				memory = getTimer();
			}
		}
	}
}

Posted by tmdf||comments (0)

as3flickrlibでExif

2009.2.28 土曜日

ActionScript3でExif」の記事で取り上げたas3flickrlibについて。このライブラリはFlickrにアップロードした写真を外部サイトから使用するためのもので、いろいろ便利そうなので紹介。とりあえず、ActionScriptからFlickrの写真を使用する流れをざっと説明すると

  • Yahoo! US のアカウントを作る(Japanじゃダメ)
  • Flickr にアカウントを作る(上のアカウントでサインイン)
  • 写真をアップロードする
  • Flickr Service から API Key を作成する
  • as3corelib をダウンロードしてパスを通す
  • as3flickrlib をダウンロードしてパスを通す

これで準備は完了。無料アカウントの場合の制限は、アップロードできるデータが100MB/月、Setsは3つ、大きいサイズ(たぶん1024×768以上)のデータはリサイズされるなど。詳しくはFlickr: Helpに書いてあるから読んでみて下さい。

写真を読み込む方法については 「FlickrViewer:as3flickrlibを使ってFlickrから画像を読み込む方法 – プログラミングとかそんなの」や、「AS3でFlickrAPI を使ってみる(with as3flickrlib) その1」「その2」「その3」などにも詳しく書かれています。

この前と同じようにサムネイルと撮影日時を取得するスクリプトは以下。

//Main.as
package {
	import com.adobe.webapis.flickr.FlickrService;
	import com.adobe.webapis.flickr.events.FlickrResultEvent;
	import com.adobe.webapis.flickr.methodgroups.Photos;
	import com.adobe.webapis.flickr.Photo;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	import flash.text.TextField;

	public class Main extends Sprite {

		private var flickr:FlickrService;
		private var loader:Loader;
		private var debug:TextField;
		private var taken:Date;

		public function Main():void {

			//Flickr API 初期設定
			var api:String = "?????"; //あなたのAPI
			flickr = new FlickrService(api);
			var photos:Photos = new Photos(flickr);
			photos.getInfo("3255185405"); //読み込みたい写真のID
			flickr.addEventListener(FlickrResultEvent.PHOTOS_GET_INFO, GetInfo);
		}

		//データ取得
		private function GetInfo(e:FlickrResultEvent):void {

			//URLを作成
			var photo:Photo = e.data.photo;
			var farm:String = photo.farm;
			var server:String = String(photo.server);
			var id:String = photo.id;
			var secret:String = photo.secret;
			var size:String = "t";
			var url:String = "http://farm" + farm + ".static.flickr.com/" + server + "/" + id + "_" + secret + "_" + size + ".jpg";

			//日付を取得
			taken = photo.dateTaken;

			//読み込み
			loader = new Loader();
			var request:URLRequest = new URLRequest(url);
			var context:LoaderContext = new LoaderContext(true);
			loader.load(request, context);
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
		}

		//読み込み完了
		private function onComplete(e:Event):void {

			//サムネイルを表示
			addChild(loader);

			//テキストフィールドを作成
			debug = new TextField();
			addChild(debug);
			debug.autoSize = "left";
			debug.y = 100;

			//撮影日時を表示
			debug.text = String(taken);
		}
	}
}

他のblogでも書かれているけど、Fickrは実行されるswfからすると他のドメインのサービスになるので、クロスドメインの設定をしないといけない。上のスクリプトでいうところの49行目 contextがそれ。ローカルでテストしている時は書かなくても動いちゃうから気づきにくい。あと、40行目の変数 sizeはそのまま画像のサイズ指定だけど、”t”とか”b”とか指定できる。オリジナルサイズの”o”を指定ってできないのかな?”o”の場合だと吐き出されるsecretの部分が違うのでそんなURLないよって返されちゃいます。1024×768の画像でいいなら、解像度1600×1200ぐらいのをアップして”b”を指定すればいいと思う。

他にも「Flash で Flickr に写真をアップロードするサンプル」なんかもこのライブラリを使う時に参考になるかも。

Posted by tmdf||comments (0)

Flash Player 10 バグ?

2009.2.27 金曜日

仕事で作ったexe形式のFlashで変なバグ?があったので報告。動作環境はWindowsXP Professional SP3 で、コンパイルはFlash CS4 Professional、形式はFlash Player 10.0 r2。

症状は長時間(だいたい5時間とか)フルスクリーンで実行中に、いつのまにか表示の更新がされなくなる。他のウィンドウを操作したり、何らかのアクションを起こすと表示が更新されるし、更新されていない間の処理も実行されているので、プログラム自体が止まっているわけじゃないみたい。

スクリプト内のVectorをArrayにしてCS3からFlash Player 9で書き出したら12時間以上問題なく動作したからいいんだけど、何が原因かよくわからない。

Posted by tmdf||comments (0)

ActionScript3でExif

2009.2.27 金曜日

ActionScript3からExifを参照するには、読み込んだJPEGをバイナリで解析しないといけない。でも自分でバイナリを読むスクリプトを書くのは面倒なので、誰かがすでに作ってくれたライブラリを利用させてもらいましょう。ざっと調べたところ、下記のライブラリがあるみたい。

Exiflibray for AS3

これはLoaderクラスを拡張したExifLoaderクラスを使ってJPEGファイルを読み込んで、プロパティのExifデータを取得す使いやすいライブラリ。FLASH IDEだと#1110 コンパイルエラーが起きてうまくいかないので、FlexSDKでコンパイルしました。xmlのembedがうまく動かいていないみたい。以下はサムネイルと撮影日時を表示するスクリプト。

//Main.as
package {
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.net.URLRequest;
	import flash.text.TextField;
	import jp.shichiseki.exif.ExifLoader;
	import jp.shichiseki.exif.IFD;

	public class Main extends Sprite {

		private var loader:ExifLoader;
		private var debug:TextField;

		public function Main():void {

			//読み込み
			loader = new ExifLoader();
			var request:URLRequest = new URLRequest("test.jpg");
			loader.load(request);
			loader.addEventListener(Event.COMPLETE, onComplete);
		}

		//読み込み完了
		private function onComplete(e:Event):void {

			//サムネイルを表示
			var thumnail:Loader = new Loader();
			thumnail.loadBytes(loader.exif.thumbnailData);
			addChild(thumnail);

			//テキストフィールドを作成
			debug = new TextField();
			addChild(debug);
			debug.autoSize = "left";
			debug.y = 150;

			//Exifデータを配列に
			var ifd:IFD = loader.exif.ifds.primary;

			//撮影日時を表示
			debug.text = "DateTime" + ":" + ifd["DateTime"];
		}
	}
}

exif-as3

こっちは標準のURLLoaderクラスを使ってバイナリ形式で読み込んで、関数に投げるとExifが帰ってくるライブラリ。型指定をかなり省略して書いているので、コンパイル時にWarningが大量に出るけどとりあえず無視すれば大丈夫。Exifのタイトルが中国語でちょっと新鮮!! 以下は上と同じくサムネイルと撮影日時を表示するスクリプト。

//Main.as
package {
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.text.TextField;
	import nt.imagine.exif.ExifExtractor;

	public class Main extends Sprite {

		private var loader:URLLoader;
		private var exif:ExifExtractor;
		private var debug:TextField;

		public function Main():void {

			//読み込み
			loader = new URLLoader();
			loader.dataFormat = "binary";
			var request:URLRequest = new URLRequest("test.jpg");
			loader.load(request);
			loader.addEventListener(Event.COMPLETE, onComplete);
		}

		//読み込み完了
		private function onComplete(e:Event):void {

			//ライブラリにバイナリデータを投げる
			exif = new ExifExtractor(loader);

			//サムネイルを表示
			var thumnail:Loader = new Loader();
			thumnail.loadBytes(exif.getThumb());
			addChild(thumnail);

			//テキストフィールドを作成
			debug = new TextField();
			addChild(debug);
			debug.autoSize = "left";
			debug.y = 150;

			//Exifデータを配列に
			var tag:Array = exif.getAllTag();

			//撮影日時っぽいのを表示
			debug.text = tag[22].CN + ":" + tag[22].values;
		}
	}
}

as3-exif

ActionScript3がまだベータ版だった頃に発表されたようで、ActionScript2では扱えなったバイナリデータを扱えるってことで公開されたみたい。試していません。

as3flickrlib

このライブラリは名前のとおり、Flickr APIをActionScriptで操作しようというもの。扱いたい写真をFlickr にアップロードしなければいけないし、Exifを読みたいだけならちょっと面倒。でも使い方しだいでは非常に便利なので、このライブラリについては別途書きたいと思います。

Exif

ちょうど自分が作っていた時と入れ違いでSparkProjectにコミットされたようです。これもまだ試していません。

Posted by tmdf||comments (2)

Photo

PROFILE

森田 考陽 [Takaaki Morita]
Twitter: @tmdf
Other: mtdf.net

Designer / Programmer

RECENT POSTS

MONTHLY ARCHIVES