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

flash on 2010-10-29

-------------------------------------------------

ビルボードで3D

 300 体 + 20本 配置
上下左右キーでカメラの移動ができます。
1、2キーで視野角を変更できます。

contentLoaderInfo.bytes からのインスタンス化を試してみました。

-------------------------------------------------
Get Adobe Flash player
by mikoto 29 Oct 2010

    Tags

    3D
    Embed
/**
 * Copyright mikoto ( http://wonderfl.net/user/mikoto )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/1Bjp
 */

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",
    "http://sugar310.dip.jp/cgi/upload/source/up26488.png",
    "http://sugar310.dip.jp/cgi/upload2/source/sugar3190.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;
        }

    }
    
    function ObjectCreate2():void{
        
        var src:BitmapData = bitmap_container[2];
        
        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<150;i++){
        ObjectCreate();
        ObjectCreate2();
    }
    
    // 木を生成する関数
    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 CurCreate():void{
        var src:BitmapData = bitmap_container[3];
        var pos : Vector3D = new Vector3D(0,0,0);    // 座標
        // 描画オフセット
        var ofs : Point = new Point(-src.width / 2,-src.height);
        // 初期配置
        pos.x = 0;
        pos.z = 0;
        // 実行
        addEventListener(Event.ENTER_FRAME,function(e:Event):void{
            //pos.x = this._xmouse;
            //pos.z = this._ymouse;
            //pos.y = camera_pos.z - 10;
            // 描画要求
            RenderSetRequest(src,pos,ofs);
        });
    }
    //CurCreate();
    
    // ビュー行列作成
    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 = 4000;    // 遠方の 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));
        }
    }

}

        }
    }
}