アクセシビリティ
デベロッパーリソース

目次

Firework.jp :「自分で花火を作って、打ち上げる」花火大会の仕組み

色情報から粒子データへ拡張する

花火玉から色情報の配列を受け取ったら、花火の打ち上がりを演出するための「粒子」データ(位置、移動距離、持続エネルギー)へと変換していきます。

色は、物理エンジンによって描画されるため、数値化して取得します。

位置は、火花のxとyの座標になりますが、初期設定として花火が拡散する時の中心の位置を指定します。花火の中心位置は打ち上がるときのタイミングによって変わってくるので、値を任意に変更できるようにメソッドの引数として設定できるようにしておきます。

移動距離は、配列の順番によってルール付けされています。その情報から粒子の速さ(半径の長さ)と方向(角度)を取得し、取得された半径と角度からx軸方向とy軸方向 の移動距離を計算していきます(図5)。

図5 配列の順番から、粒子の速さ(半径の長さ)と方向(角度)を導きだしています。更にそこから、vx(x軸の移動距離)とvy(y軸の移動距離)を計算しています

図5 配列の順番から、粒子の速さ(半径の長さ)と方向(角度)を導きだしています。更にそこから、vx(x軸の移動距離)とvy(y軸の移動距離)を計算しています

色情報から粒子データへ拡張する内容をまとめると、図7のようになります。

図7 火薬のデータは、color x y vx vy energyのパラメータに拡張されます。

図7 火薬のデータは、color x y vx vy energyのパラメータに拡張されます。

以下は、色情報を粒子データに変換するスクリプトです。

// color_arr : カラー情報の配列
// x : パーティクルのX座標
// y : パーティクルのY座標
// n : 星データからパーティクルに拡張する配列量の倍率
// radius : 拡散する距離の基準値
static public function encode( color_arr:Array = null , x:Number = 0 , y:Number = 0 , n:uint = 1 , radius:Number = 14 ):Array {
	
	if ( color_arr == null ) {
		return null;
	}
	
	var renge_length:uint = 5;
	var renge_margin:Number = radius / ( renge_length * 2 - 1 );
	var renge:Number;
	var angle_length:uint;
	var angle_margin:Number;
	var angle:Number;
	
	// カラー情報
	var star_obj:Object;
	var id:int = 0;
	
	// 火花データ
	var particle_arr:Array;
	var particle_obj:Object;
	var p_angle:Number;
	var p_renge:Number;
	var rad:Number;
	
	particle_arr = new Array();
	renge = 0;
	
	// 円周を増幅
	for ( var i:int = 0; i < renge_length; i++ ) {
		
		angle_length = ( i == 0 ) ? 1 : 6 * i;
		angle_margin = 360 / angle_length;
		angle = 90;
		
		// 円周の玉数を増幅
		for ( var k:int = 0; k < angle_length; k++ ) {
			
			// カラー情報の配列からオブジェクトを取得
			star_obj = color_arr[ id ];
			if ( star_obj.color != null ) {
				
				// 火花データを拡張
				particle_obj = new Object();
				p_angle = angle + Math.random() * ( angle_margin || 0 );
				p_renge = renge + Math.random() * ( renge_margin || 0 );
				rad = p_angle * PI;
				particle_obj.x = x;
				particle_obj.y = y;
				particle_obj.vx = Math.cos( rad ) * p_renge;
				particle_obj.vy = Math.sin( rad ) * p_renge;
				particle_obj.energy = 5 + 10 * Math.random();
				particle_obj.color = Number( "0x" + star_obj.color );
				if ( star_obj.bright ) particle_obj.bright = star_obj.bright || 3;
				if ( star_obj.graviton ) particle_obj.graviton = star_obj.graviton || 0.05;
				particle_arr.push( particle_obj );
				
			}
			
			id++;
			
			// 角度を足す
			angle += angle_margin;
			
		}
		
		// 半径を足す
		renge += renge_margin;
		
	}
	
	return particle_arr;
	
}