In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

ビルボードで3D

-------------------------------------------------
ビルボードで3D
 300 体 + 20本 配置
上下左右キーでカメラの移動ができます。
1、2キーで視野角を変更できます。
contentLoaderInfo.bytes からのインスタンス化を試してみました。
-------------------------------------------------
Get Adobe Flash player
by Hakuhin 23 Dec 2009
/**
 * Copyright Hakuhin ( http://wonderfl.net/user/Hakuhin )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/k7Ru
 */

// -------------------------------------------------
//
// ビルボードで3D
// 
// 300 体 + 20本 配置
// 上下左右キーでカメラの移動ができます。
// 1、2キーで視野角を変更できます。
//
// contentLoaderInfo.bytes からのインスタンス化を試してみました。
//
// -------------------------------------------------
package {
	import flash.events.*;
	import flash.display.*;
	import flash.net.*;
	import flash.text.*;
	import flash.utils.*;
	import flash.system.*;
	import flash.geom.*;
	import flash.filters.*;
	import flash.ui.*;

    public class Main extends Sprite {
        public function Main() {



// -------------------------------------------------
// コンストラクタ
// -------------------------------------------------

// フレームレート
stage.frameRate = 60;

// 100%表示
stage.scaleMode = StageScaleMode.NO_SCALE;

// 左上
stage.align = StageAlign.TOP_LEFT;
stage.align = "TL";

// スプライトを作成
var board:Sprite = new Sprite();
addChild(board);

// 画像のURL
var graphic_url:Array = [
	"http://actionscript.web.officelive.com/wonderfl/meme.png",
	"http://actionscript.web.officelive.com/wonderfl/tree.png",
];

// リソース読み込み開始
load(load_complete_func,graphic_url);

// 読み込み終了
function load_complete_func():void{
	// 初期化へ
	init();
}

// リソースを格納する入れ物
var bitmap_container : Array = new Array();


// -------------------------------------------------
// 読み込み
// -------------------------------------------------
function load(complete_func:Function,url_array:Array):void{

	// URLを取り出す
	var url : String = url_array.shift();

	// URLが無くなればコールバック関数を呼び出して終了
	if(!url){
		// 読み込み終了
		complete_func();
		return;
	}

	// ローダー
	var loader_obj : Loader = new Loader();

	// 読み込み開始
	loader_obj.load(new URLRequest(url));

	// 読み込み終了
	var info : LoaderInfo = loader_obj.contentLoaderInfo;
	info.addEventListener (Event.INIT,LoaderInfoInitFunc);
	function LoaderInfoInitFunc (event : Event):void {

		// メモリからインスタンス化
		var loader_memory : Loader = new Loader();
		loader_memory.contentLoaderInfo.addEventListener (Event.COMPLETE,LoaderInfoCompleteFunc);
		function LoaderInfoCompleteFunc (event : Event):void {

			// キャプチャ
			var bmp : BitmapData = new BitmapData(loader_memory.width,loader_memory.height,true,0);
			stage.addChild(loader_memory);
			bmp.draw(stage);
			stage.removeChild(loader_memory);
	
			// コンテナに格納
			bitmap_container.push(bmp);
  
			// 再帰読み込み
			load(complete_func,url_array);
		}
		
		// 読み込み開始
		loader_memory.loadBytes(loader_obj.contentLoaderInfo.bytes);
	}
}


// -------------------------------------------------
// 初期化
// -------------------------------------------------
function init():void{

	// ステージサイズ
	var w:uint;
	var h:uint;
	var w_half:uint;
	var h_half:uint;
	
	// リサイズ時にフィット
	stage.addEventListener(Event.RESIZE,ResizeFunc);
	function ResizeFunc(e:Event):void{
		w = stage.stageWidth;
		h = stage.stageHeight;
		w_half = w / 2;
		h_half = h / 2;
	}
	ResizeFunc(null);

	// テキスト設定
	var tf : TextField = new TextField();
	tf.x = 5;
	tf.y = 5;
	tf.width = 200;
	tf.height = 40;
	tf.border = true;
	tf.background = true;
	tf.alpha = 0.9;
	
	// テキスト書式
	var format : TextFormat = new TextFormat();
	format.font = "MS ゴシック";
	tf.defaultTextFormat = format;

	// テキスト表示
	addChild(tf);
	addEventListener(Event.ENTER_FRAME,function(e:Event):void{
		var str:String = "";
		str += "上下左右キーで移動\n";
		str += "視野角:" + (Math.floor(camera_angle * 100) / 100) + " (1,2キーで変更)\n";

		tf.text = str;
	});

	// オブジェクトを生成する関数
	var WORLD_SIZE : Number = 1200;
	function ObjectCreate():void{
		
		var src:BitmapData = bitmap_container[0];
		
		var pos : Vector3D = new Vector3D(0,0,0);	// 座標
		var spd : Vector3D = new Vector3D(0,0,0);	// 速度	
		var exec:Function = wait_init;				// 実行
		var frame:int = 0;							// フレーム

		// 描画オフセット
		var ofs : Point = new Point(-src.width / 2,-src.height);

		// 初期配置
		pos.x = (Math.random() * 2 -1) * 1000;
		pos.z = (Math.random() * 2 -1) * 1000;
		spd.x = (Math.random() * 2 -1) * 0.5;
		spd.z = (Math.random() * 2 -1) * 0.5;
		
		// 実行
		addEventListener(Event.ENTER_FRAME,function(e:Event):void{

			// 重力
			spd.y -= 0.35;
			
			// 座標に速度を加算
			pos = pos.add(spd);
			
			// 地面
			if(pos.y < 0){
				pos.y = 0;
				spd.y *= -0.5;
			}
			
			// 外に出たら戻す
			if(pos.x < -WORLD_SIZE)		spd.x *= -1;
			if(pos.x >  WORLD_SIZE)		spd.x *= -1;
			if(pos.z < -WORLD_SIZE)		spd.z *= -1;
			if(pos.z >  WORLD_SIZE)		spd.z *= -1;
			
			exec();

			// 描画要求
			RenderSetRequest(src,pos,ofs);
		});
		
		function wait_init():void{
			frame = Math.floor(Math.random() * 300) + 60;
			exec = wait_exec;	
			exec();
		}
		function wait_exec():void{
			frame -= 1
			if(frame < 0){
				exec = jump_init;
			}
		}
		function jump_init():void{
			spd.y = Math.random() * 5 + 3;
			exec = jump_exec;	
			exec();
		}
		function jump_exec():void{
			exec = wait_init;
		}

	}
	
	// オブジェクトを生成
	var i:Number;
	for(i=0;i<300;i++){
		ObjectCreate();
	}
	
	// 木を生成する関数
	function TreeCreate():void{
		
		var src:BitmapData = bitmap_container[1];
		
		var pos : Vector3D = new Vector3D(0,0,0);	// 座標
		
		// 描画オフセット
		var ofs : Point = new Point(-src.width / 2,-src.height);
		
		// 初期配置
		pos.x = (Math.random() * 2 -1) * WORLD_SIZE;
		pos.z = (Math.random() * 2 -1) * WORLD_SIZE;
		
		// 実行
		addEventListener(Event.ENTER_FRAME,function(e:Event):void{

			// 描画要求
			RenderSetRequest(src,pos,ofs);
		});
	}
	
	
	
	// 木を生成
	for(i=0;i<20;i++){
		TreeCreate();
	}

	// カメラ
	var camera_pos : Vector3D = new Vector3D(0,100,-1000);	// 座標
	var camera_spd : Vector3D = new Vector3D(0,0,0);		// 速度
	var camera_rot : Number = 0;		// 角度
	var camera_rot_spd : Number = 0;	// 角速度
	
	// キー操作
	var key:Array = new Array;
	stage.addEventListener(KeyboardEvent.KEY_DOWN, function(e:KeyboardEvent):void{
		key[e.keyCode] = true;
	});
	stage.addEventListener(KeyboardEvent.KEY_UP, function(e:KeyboardEvent):void{
		key[e.keyCode] = false;
	});
	addEventListener(Event.ENTER_FRAME, function(e:Event):void{
		
		// 視野角を変更
		if(key[49])	camera_angle -= 1;
		if(key[50])	camera_angle += 1;
		if(camera_angle <   1)	camera_angle = 1;
		if(camera_angle > 180)	camera_angle = 180;
		
		var dx:Number = 0;
		if(key[Keyboard.LEFT])		dx -= 1;
		if(key[Keyboard.RIGHT])		dx += 1;

		var dy:Number = 0;
		if(key[Keyboard.UP])		dy -= 1;
		if(key[Keyboard.DOWN])		dy += 1;
		
		// キー入力を角速度に加算
		camera_rot_spd += dx * 0.1;
		
		// カメラ角度に角速度を加算
		camera_rot += camera_rot_spd;
		
		// 角速度の摩擦
		camera_rot_spd *= 0.9;
		
		// 進行方向に移動
		var rad:Number = (-camera_rot - 90) * Math.PI / 180;
		camera_spd.x += Math.cos(rad) * dy;
		camera_spd.z += Math.sin(rad) * dy;
		
		// カメラ座標に速度を加算
		camera_pos = camera_pos.add(camera_spd);
		
		// 速度の摩擦
		camera_spd.scaleBy(0.9);
		
	});

	// ビュー行列作成
	function ViewMatrixCreate():Matrix3D{
		var mtx : Matrix3D = new Matrix3D();
		mtx.identity();													// 単位行列
		mtx.appendRotation(10,Vector3D.X_AXIS);					// x軸回転
		mtx.appendRotation(camera_rot,Vector3D.Y_AXIS);					// y軸回転
		mtx.appendTranslation(camera_pos.x,camera_pos.y,camera_pos.z);	// 座標
		mtx.invert();													// 逆行列
		return mtx;
	}
	
	
	// 描画要求
	var draw_container : Array = new Array();
	var pos_vector : Vector.<Number> = new Vector.<Number>();

	// 描画要求クリア
	function RenderRequestClear():void{
		draw_container = new Array();
		pos_vector = new Vector.<Number>();
	}
	// 描画要求
	function RenderSetRequest(bmp:BitmapData,pos:Vector3D,ofs:Point):void{
		var id:uint = pos_vector.length;
		pos_vector[id+0] = pos.x;
		pos_vector[id+1] = pos.y;
		pos_vector[id+2] = pos.z;
		draw_container.push({bmp:bmp,id:id,ofs:ofs});
	}
	
	// 描画処理
	var camera_angle : Number = 60;		// 視野角
	addEventListener(Event.ENTER_FRAME,function(e:Event):void{
		
		// 表示リストから外す
		ContainerRemoveChildAll(board);

		// 視点からの距離
		var camera_fov : Number = 1 / Math.tan( camera_angle * 0.5 * Math.PI / 180);

		var i:int;
		var num:int = draw_container.length;
		var view_mtx:Matrix3D = ViewMatrixCreate();
		
		// ビュー行列変換を一括で行う
		view_mtx.transformVectors(pos_vector,pos_vector);
		
		// z コンテナ(zソート用の双方向リストを複数作成する)
		var z_container : Array = new Array();
		var z_list:Object;
		var Z_DIVISION:uint = 20;	// 分割数
		var Z_LENGTH:Number = 2000;	// 遠方の z 値

		// 双方向リストを作成
		for(i=0;i<Z_DIVISION;i++){
			z_list = new Object();
			z_list.pref = z_list;
			z_list.post = z_list;
			z_list.z = i * Z_LENGTH / Z_DIVISION;
			
			z_container[i]= z_list;
		}
	
		for(i=0;i<num;i++){
			var obj : Object = draw_container[i];
			
			// 座標取り出し
			var pos : Vector3D = new Vector3D(pos_vector[obj.id+0],pos_vector[obj.id+1],pos_vector[obj.id+2]);
			
			// カメラの裏側なので処理をしない
			if(pos.z < 1)	continue;

			// パスペクティブプロジェクション変換
			pos.x = pos.x / pos.z * camera_fov;
			pos.y = pos.y / pos.z * camera_fov;
			
			// ビューポート変換
			pos.x = pos.x * w + w_half;
			pos.y =-pos.y * w + h_half;
			
			obj.pos = pos;
			obj.z = pos.z;
			
			// z 値を分割してリスト格納位置を決める
			var div:uint = Math.floor(obj.z / Z_LENGTH * Z_DIVISION);
			if(div > Z_DIVISION - 1)	div = Z_DIVISION - 1;

			// z値でソート
			z_list = z_container[div];
			var pref : Object;
			var post : Object = z_list.post;
			while(true){
				if(z_list == post)		break;
				if(post.z > obj.z)		break;
				post = post.post;
			}
			
			// zコンテナに登録
			pref = post.pref;
			obj.pref = pref;
			obj.post = post;
			pref.post = obj;
			post.pref = obj;
		}
		
		// 描画をクリア
		var g : Graphics = board.graphics;
		g.clear();

		// ビットマップ行列
		var bmp_mtx:Matrix = new Matrix();
		bmp_mtx.identity();
		
		// 奥から順番に描画
		for(i=Z_DIVISION-1;i>=0;i--){
			z_list = z_container[i];
				
			var list : Object = z_list.pref;
			while(true){
				if(z_list == list)	break;
				
				var s:Number = 1.0 / list.z * camera_fov * w;
				var x:Number = list.pos.x + list.ofs.x * s;
				var y:Number = list.pos.y + list.ofs.y * s;

				// 矩形描画
				bmp_mtx.a = bmp_mtx.d = s;
				bmp_mtx.tx = x;
				bmp_mtx.ty = y;
				g.beginBitmapFill ( list.bmp , bmp_mtx , false , true );
				g.drawRect ( x , y , list.bmp.width * s , list.bmp.height * s );
				
				list = list.pref;
			}
		}
		
		// 描画要求をクリア
		RenderRequestClear();
	});

	// -------------------------------------------------
	// 表示リストをすべて外す
	// -------------------------------------------------
	function ContainerRemoveChildAll(container:DisplayObjectContainer):void{
		while(true){
			if(!container.numChildren)	return;
			container.removeChild(container.getChildAt(0));
		}
	}

}

		}
    }
}