AIR

ムービークリップの制御と最適化

頭に思いついた表現をつくることは、なかなかにしんどい。Adobe MAX 2009 の講演で城戸さんが、ムービークリップの制御と最適化についてお話しています。

Adobe MAX 2009 アイディアの実装:コントロールと最適化 城戸雅行 氏
http://jp.max.adobe.com/player.html?2-10


モーション、レンダリング

ポイントを配列に入れて、それを変化させるモーション。
配列の中身を MC にあてるレンダリング。

var 視点 = [x:0, y:0];
var ポイント = {x:100, y:300};
var ボックス = new BoxMC();
addChild(ボックス);
function モーション(evt:Event) {
	ポイント.x += 2;
}
function レンダリング(evt:Event) {
	ボックス.x = ポイント.x;
	ボックス.y = ポイント.y;
}
addEventListener(Event.ENTER_FRAME, モーション);
addEventListener(Event.ENTER_FRAME, レンダリング);


モーション、レンダリング、視点

視点を加える。ポイントを変化させるのではなく、視点を動かして、ポイントとの差を MC にあてる。

var 視点 = {x:0, y:0};
var ポイント = {x:100, y:300};
var ボックス = new BoxMC();
addChild(ボックス);
function モーション(evt:Event) {
	//ポイント.x += 2;
	視点.x += 2;
}
function レンダリング(evt:Event) {
	ボックス.x = ポイント.x - 視点.x;
	ボックス.y = ポイント.y - 視点.y;
}
addEventListener(Event.ENTER_FRAME, モーション);
addEventListener(Event.ENTER_FRAME, レンダリング);


ポイントとボックスを増やす

MC ひとつひとつを動かすのではなく、視点だけを動かす。
最終的にレンダリングで、その結果をあてる。

var 視点 = {x:0, y:0};
var ポイントたち:Array = new Array();
var ボックスたち:Array = new Array();
ボックス追加();
function ボックス追加():void {
	for (var i:int = 0; i<20; ++i) {
		var ポイント = {x:Math.random() * stage.stageWidth, y:Math.random() * stage.stageHeight};
		ポイントたち[i] = ポイント;
		var ボックス = new BoxMC();
		ボックスたち[i] = ボックス;
		addChild(ボックスたち[i]);
	}
}
function モーション(evt:Event) {
	視点.x += 2;
}
function レンダリング(evt:Event) {
	for (var i:int = 0; i<ポイントたち.length; ++i) {
		var ポイント = ポイントたち[i];
		var ボックス = ボックスたち[i];
		ボックス.x = ポイント.x - 視点.x;
		ボックス.y = ポイント.y - 視点.y;
	}
}
addEventListener(Event.ENTER_FRAME, モーション);
addEventListener(Event.ENTER_FRAME, レンダリング);


視点に回転を加える

var 視点 = {x:0, y:0, angle:0};
var ポイントたち:Array = new Array();
var ボックスたち:Array = new Array();
ボックス追加();
function ボックス追加():void {
	for (var i:int = 0; i<20; ++i) {
		var ポイント = {x:Math.random() * stage.stageWidth, y:Math.random() * stage.stageHeight};
		ポイントたち[i] = ポイント;
		var ボックス = new BoxMC();
		ボックスたち[i] = ボックス;
		addChild(ボックスたち[i]);
	}
}
function モーション(evt:Event) {
	視点.angle += 0.01;
}
function レンダリング(evt:Event) {
	var cos = Math.cos(-視点.angle);
	var sin = Math.sin(-視点.angle);
	for (var i:int = 0; i<ポイントたち.length; ++i) {
		var ポイント = ポイントたち[i];
		var ボックス = ボックスたち[i];
		var 視点からの差X = ポイント.x - 視点.x;
		var 視点からの差Y = ポイント.y - 視点.y;
		ボックス.x = 視点からの差X * cos - 視点からの差Y * sin;
		ボックス.y = 視点からの差X * sin + 視点からの差Y * cos;
	}
}
addEventListener(Event.ENTER_FRAME, モーション);
addEventListener(Event.ENTER_FRAME, レンダリング);

視点に angle のパラメータを加える。

var 視点 = {x:0, y:0, angle:0};

回転の法則

x' = x * cos - y * sin;
y' = x * sin + y * cos;

首を右に傾けるということは、風景は左に傾くということなので、視点.angle は、マイナス(-)。


ステージ中央を基点にする

var 視点 = {x:0, y:0, angle:0};
var ポイントたち:Array = new Array();
var ボックスたち:Array = new Array();
ボックス追加();
function ボックス追加():void {
	for (var i:int = 0; i<20; ++i) {
		var ポイント = {x:Math.random() * stage.stageWidth - stage.stageWidth / 2, y:Math.random() * stage.stageHeight -  + stage.stageHeight / 2};
		ポイントたち[i] = ポイント;
		var ボックス = new BoxMC();
		ボックスたち[i] = ボックス;
		addChild(ボックスたち[i]);
	}
}
function モーション(evt:Event) {
	視点.angle += 0.01;
}
function レンダリング(evt:Event) {
	var cos = Math.cos(-視点.angle);
	var sin = Math.sin(-視点.angle);
	for (var i:int = 0; i<ポイントたち.length; ++i) {
		var ポイント = ポイントたち[i];
		var ボックス = ボックスたち[i];
		var 視点からの差X = ポイント.x - 視点.x;
		var 視点からの差Y = ポイント.y - 視点.y;
		ボックス.x = 視点からの差X * cos - 視点からの差Y * sin + stage.stageWidth / 2;
		ボックス.y = 視点からの差X * sin + 視点からの差Y * cos + stage.stageHeight / 2;
	}
}
addEventListener(Event.ENTER_FRAME, モーション);
addEventListener(Event.ENTER_FRAME, レンダリング);

ポイントの初期値はマイナスにも範囲をひろげて、レンダリング時にはステージ中央の座標を調べてシフトする。


ズームする

var 視点 = {x:0, y:0, angle:0, zoom:1};
var ポイントたち:Array = new Array();
var ボックスたち:Array = new Array();
ボックス追加();
function ボックス追加():void {
	for (var i:int = 0; i<20; ++i) {
		var ポイント = {x:Math.random() * stage.stageWidth, y:Math.random() * stage.stageHeight};
		ポイントたち[i] = ポイント;
		var ボックス = new BoxMC();
		ボックスたち[i] = ボックス;
		addChild(ボックスたち[i]);
	}
}
function モーション(evt:Event) {
	視点.zoom += 0.01;
}
function レンダリング(evt:Event) {
	var cos = Math.cos(-視点.angle);
	var sin = Math.sin(-視点.angle);
	for (var i:int = 0; i<ポイントたち.length; ++i) {
		var ポイント = ポイントたち[i];
		var ボックス = ボックスたち[i];
		var 視点からの差X = (ポイント.x - 視点.x ) * 視点.zoom;
		var 視点からの差Y = (ポイント.y - 視点.y ) * 視点.zoom;
		ボックス.scaleX = ボックス.scaleY = 視点.zoom;
		ボックス.x = 視点からの差X * cos - 視点からの差Y * sin + stage.stageWidth / 2;
		ボックス.y = 視点からの差X * sin + 視点からの差Y * cos + stage.stageHeight / 2;
	}
}
addEventListener(Event.ENTER_FRAME, モーション);
addEventListener(Event.ENTER_FRAME, レンダリング);

視点に zoom のパラメータを加える。

var 視点 = {x:0, y:0, angle:0, zoom:1};

視点からの差に zoom をかける。

var 視点からの差X = (ポイント.x - 視点.x ) * 視点.zoom;
var 視点からの差Y = (ポイント.y - 視点.y ) * 視点.zoom;

MC の大きさも変える。

ボックス.scaleX = ボックス.scaleY = 視点.zoom;


回転とズーム

var 視点 = {x:0, y:0, angle:0, zoom:1};
var ポイントたち:Array = new Array();
var ボックスたち:Array = new Array();
ボックス追加();
function ボックス追加():void {
	for (var i:int = 0; i<20; ++i) {
		var ポイント = {x:Math.random() * stage.stageWidth - stage.stageWidth / 2, y:Math.random() * stage.stageHeight -  + stage.stageHeight / 2};
		ポイントたち[i] = ポイント;
		var ボックス = new BoxMC();
		ボックスたち[i] = ボックス;
		addChild(ボックスたち[i]);
	}
}
function モーション(evt:Event) {
	視点.angle += 0.01;
	視点.zoom += 0.01;
}
function レンダリング(evt:Event) {
	var cos = Math.cos(-視点.angle);
	var sin = Math.sin(-視点.angle);
	for (var i:int = 0; i<ポイントたち.length; ++i) {
		var ポイント = ポイントたち[i];
		var ボックス = ボックスたち[i];
		var 視点からの差X = (ポイント.x - 視点.x ) * 視点.zoom;
		var 視点からの差Y = (ポイント.y - 視点.y ) * 視点.zoom;
		ボックス.scaleX = ボックス.scaleY = 視点.zoom;
		ボックス.x = 視点からの差X * cos - 視点からの差Y * sin + stage.stageWidth / 2;
		ボックス.y = 視点からの差X * sin + 視点からの差Y * cos + stage.stageHeight / 2;
	}
}
addEventListener(Event.ENTER_FRAME, モーション);
addEventListener(Event.ENTER_FRAME, レンダリング);
視点.angle += 0.01;
視点.zoom += 0.01;


ムービークリップの制御のコツ

モーションとレンダリングの部分をわける。

・モーションは、 MC を動かすのではなく、頂点データや視点データのみを動かす。
・レンダリングのところに回転やズームの処理を組み込む。最終的に MC を表示する。

レンダリングの部分はいわゆる3Dエンジンとなり、他への流用ができる。


頂点に何を表示するか

・MC をわりあてる。
・ラインを張る。
・画像を描画してテクスチャのように表示する。

モーション制御に頂点を扱う。


最適化

・見えない部分は計算しない。
・ビットマップ化する。
・補間を使う。


見えない部分は計算しない

レンダリングの処理で、表示する部分を判別して、画面から見えないところは計算をしないようにする。


ビットマップ化する


BitmapData を配列にいれておく。

array = [bitmapdata_0, bitmapdata_1, bitmapdata_2, bitmapdata_3, bitmapdata_4];

MC を回転させるのではなく、回転の画像を配列にいれておいてそれを参照して表示する。


補間を使う

左右対称のオブジェクトは、半分だけをつくって、残りは反転させる。2Dで相対で求める。


城戸さんもおっしゃっていた、『できるだけたくさんのひとに快適に観てもらいたい。』という気持ち。
実際、わかっていても最後まで配慮してつくることは難しい。けど、やらなくちゃ。すこしずつ。

コメント投稿

Get Adobe Flash player

トラックバック

Get Adobe Flash player