Beautifl - Flash Gallery

Thumbnail : 3D Balls
3D Balls
nackpan 2010-07-05 MIT License

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

//3Dの練習
//画面をclickすると、描画方式が切り替わります

package {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Matrix;
    import flash.geom.Matrix3D;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.geom.Vector3D;
    import flash.text.TextField;
    import flash.text.TextFormat;
    
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    
    import flash.display.GradientType;
    
    import flash.display.SpreadMethod;
    
    [SWF(backgroundColor = 0xF0F0F0)]
    public class FlashTest extends Sprite {
        private var BALL_MAX:int = 600;
        
        /////copyPixels描画関連
        //copyPixelsの素材
        private var pngBmp:Bitmap;
        private var ballData:BitmapData;
        //カンバスになるbitmap
        private var canvasBmp:Bitmap;
        private var canvasData:BitmapData;
        private var baseData:BitmapData;
        
        ///copyPixelsを使用するために用意するもの
        private var pngCopyData:BitmapData;
        private var sourceRect:Rectangle;
        private var destPoint:Point;
        
        
        private var txt:TextField;
        
        private var objs:Vector.<Ball3D>;
        
        private var centerZ:Number = 200;
        private var focalLength:Number = 400;// 250;
        
        //
        private var view_offset_x:int;
        private var view_offset_y:int;
        
        private var count:int = 0;
        
        private var vin:Vector.<Number>;
        private var vout:Vector.<Number>;
            
        
        private var ballCopySource:Vector.<BitmapData>;
        
        
        ////描画モード
        private var mode:int = 0;
        
        public function FlashTest() {
            // write as3 code here..
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            
                
            view_offset_x = stage.stageWidth / 2;
            view_offset_y = stage.stageHeight / 2;
            
            var i:int;
            var j:int;

            var s:int = 3200;
            var v_range:int = 0;// 100;
            
            vin = new Vector.<Number>(BALL_MAX * 3);
            vout = new Vector.<Number>(BALL_MAX * 3);
            
            objs = new Vector.<Ball3D>(BALL_MAX);
            for (i = 0; i < BALL_MAX; i++)
            {
                var obj:Ball3D = new Ball3D();
                obj.init(
                                        Math.round(Math.random() * s - s / 2) ,
                                        Math.round((Math.random() * s - s / 2) ),
                                        Math.round(Math.random() * s - s / 2) ,
                                        Math.round(Math.random() * v_range - v_range / 2) * 2,
                                        Math.round((Math.random() * v_range - v_range / 2) / 2),
                                        Math.round(Math.random() * v_range - v_range / 2),
                                        i);
                
                
                objs[i] = obj;
                
            }
            
                
            //ボール画像を用意
            ballData = makeShape();
            canvasData = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0x000000);
            baseData = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0xF0F0F0);
            
            //キャンバスを用意
            canvasBmp = new Bitmap(canvasData);
            this.addChild(canvasBmp);
            canvasBmp.visible = false;
            
            ////copyPixelsを用いて描画するための準備//////
            ///////あらかじめ、各スケールのボールのbitmapDataを作成しておく(0-0.4まで、0.01刻み)
            var m:Matrix = new Matrix();
            ballCopySource = new Vector.<BitmapData>();
            for (i = 0; i < 40; i++) {
                var scale:Number = i * .01;
                if (scale == 0) scale = .5;
                var bmpData:BitmapData = new BitmapData(200 * scale, 200 * scale, true, 0);
                m.a = i * .01;
                m.d = i * .01;
                bmpData.draw(ballData, m);
                ballCopySource[i] = bmpData;
            }
            sourceRect = new Rectangle(0,0,60,60);
            destPoint = new Point();
            
            
            txt = new TextField();
            txt.width = 160;
            txt.height = 20;
            txt.border = true;
            txt.background = true;
            txt.backgroundColor = 0xffffee;
            addChild(txt);
            txt.text = "graphic.drawCircle";
                
            
            
            stage.addEventListener(MouseEvent.MOUSE_DOWN, mousedown);
            
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }
        
        
        
        private function mousedown(event:MouseEvent):void
        {
            mode += 1;
            if (mode > 2) mode = 0;
            
            if (mode == 0) {
                txt.text = "graphic.drawCircle"; canvasBmp.visible = false;
            }
            if (mode == 1) {
                txt.text = "bitmapData.draw"; canvasBmp.visible = true;
            }
            if (mode == 2) {
                txt.text = "bitmapData.copyPixels"; canvasBmp.visible = true;
            }
            
        }
        
        private function makeShape():BitmapData
        {
            var shape:Shape = new Shape();
            //gradient
            var fillType:String = GradientType.RADIAL;
            var colors:Array = [0xFFFFFF, 0xFFFEFD,  0xFF4444, 0xFE4444, 0xFD4444];
            //var colors:Array = [0xFFFFFF, 0xFFFEFD,  0xBAAAAA, 0xB99999, 0xB88888];
            var alphas:Array = [1, 1, 1, 1, 1];
            var ratios:Array = [0x00, 0x02, 0xE0, 0xFA, 0xFF];
            var matr:Matrix = new Matrix();
            matr.createGradientBox(200, 200, 0, 0, -70);
            var spreadMethod:String = SpreadMethod.REFLECT;
  
            shape.graphics.beginGradientFill(fillType, colors, alphas, ratios, matr, spreadMethod, "rgb", 0);// .5);
            shape.graphics.drawCircle(100, 100, 100 );
            
            var bmpData:BitmapData = new BitmapData(200, 200, true, 0);
            bmpData.draw(shape, new Matrix(), null, null, null, true);
            return bmpData;
        }
        
        private function sortShapes():void
        {
            objs.sort(depthSort);
        }
        
        
        private function depthSort(objA:Ball3D, objB:Ball3D):int
        {
            var posA:Vector3D = objA.viewPos;
            var posB:Vector3D = objB.viewPos;
            return posB.z - posA.z;
        }
        
        
        private function onEnterFrame(event:Event):void
        {
            if (mode == 0) {
                draw1();
            }
            if (mode == 1) {
                draw2();
            }
            if (mode == 2) {
                draw3();
            }
            
            
        }
        
        //drawCircleで描いてみる
        private function draw1():void
        {
            
            count++;
            //ビュー変換用のMatrix3D
            var m3D:Matrix3D = new Matrix3D();
            //カメラの回転を戻す
            m3D.appendRotation(-count * 2 , Vector3D.Y_AXIS);
            m3D.prependRotation( -60, Vector3D.X_AXIS);
            //カメラの移動を戻す
            m3D.appendTranslation(0, 0, 3000 );
            
                
            
            var m:Matrix = new Matrix();
            
            var i:int;
            
            
            var s:int = 0;
            for (i = 0; i < BALL_MAX; i++) {
                
                //ワールド座標
                vin[s++] = objs[i].pos.x;
                vin[s++] = objs[i].pos.y;
                vin[s++] = objs[i].pos.z;
                
            }
            
            //ビュー変換
            /////////transformVectors使用
            m3D.transformVectors(vin, vout);
            s = 0;
            for (i = 0; i < BALL_MAX; i++) {
                objs[i].viewPos.x = vout[s++];
                objs[i].viewPos.y = vout[s++];
                objs[i].viewPos.z = vout[s++];
            }
            
                
            //zソート
            sortShapes();
            
            //描画
            graphics.clear();
            graphics.lineStyle(0);
            
            for (i = 0; i < BALL_MAX; i++){
                
                var scale:Number = focalLength / (focalLength + objs[i].viewPos.z + centerZ);
                
                graphics.beginFill(0xffffff);
                graphics.drawCircle(( objs[i].viewPos.x + 100) * scale + view_offset_x,
                                    ( objs[i].viewPos.y + 100) * scale + view_offset_y,
                                    100 * scale);
                graphics.endFill();
            
                
            }
            
            
        }
        
        //bitmapData.drawで描いてみる
        private function draw2():void
        {
            
            count++;
            //ビュー変換用のMatrix3D
            var m3D:Matrix3D = new Matrix3D();
            //カメラの回転を戻す
            m3D.appendRotation(-count * 2 , Vector3D.Y_AXIS);
            m3D.prependRotation( -60, Vector3D.X_AXIS);
            //カメラの移動を戻す
            m3D.appendTranslation(0, 0, 3000 );
            
            
            var m:Matrix = new Matrix();
                
            var i:int;
            
            canvasData.lock();
            
            canvasData.draw(baseData);
            
            
            var s:int = 0;
            for (i = 0; i < BALL_MAX; i++) {
                
                //ワールド座標
                vin[s++] = objs[i].pos.x;
                vin[s++] = objs[i].pos.y;
                vin[s++] = objs[i].pos.z;
                
            }
            
            //ビュー変換
            /////////transformVectors使用
            m3D.transformVectors(vin, vout);
            s = 0;
            for (i = 0; i < BALL_MAX; i++) {
                objs[i].viewPos.x = vout[s++];
                objs[i].viewPos.y = vout[s++];
                objs[i].viewPos.z = vout[s++];
            }
            
                
            //zソート
            sortShapes();
            
            //描画
            for (i = 0; i < BALL_MAX; i++){
                
                var scale:Number = focalLength / (focalLength + objs[i].viewPos.z + centerZ);
                
                //カメラ座標
                
                m.tx = objs[i].viewPos.x * scale + view_offset_x;
                m.ty = objs[i].viewPos.y * scale + view_offset_y;
                
                m.a = scale;
                m.d = scale;
                
                canvasData.draw(ballData, m);
            }
            
            canvasData.unlock();
            
        }
        
        
        //bitmapData.copyPixelsで描いてみる
        private function draw3():void
        {
            
            count++;
            //ビュー変換用のMatrix3D
            var m3D:Matrix3D = new Matrix3D();
            //カメラの回転を戻す
            m3D.appendRotation(-count * 2, Vector3D.Y_AXIS);
            m3D.prependRotation( -60, Vector3D.X_AXIS);
            //カメラの移動を戻す
            m3D.appendTranslation(0, 0, 3000 );
                
            var i:int;
            
            canvasData.lock();
            
            canvasData.draw(baseData);
            
            
            var s:int = 0;
            for (i = 0; i < BALL_MAX; i++) {
                
                //ワールド座標
                vin[s++] = objs[i].pos.x;
                vin[s++] = objs[i].pos.y;
                vin[s++] = objs[i].pos.z;
                
            }
            
            //ビュー変換
            /////////transformVectors使用
            m3D.transformVectors(vin, vout);
            s = 0;
            for (i = 0; i < BALL_MAX; i++) {
                objs[i].viewPos.x = vout[s++];
                objs[i].viewPos.y = vout[s++];
                objs[i].viewPos.z = vout[s++];
            }
                
            //zソート
            sortShapes();
            
            //描画
            for (i = 0; i < BALL_MAX; i++){
                
                var scale:Number = focalLength / (focalLength + objs[i].viewPos.z + centerZ);
                
                destPoint.x = objs[i].viewPos.x * scale + view_offset_x;
                destPoint.y = objs[i].viewPos.y * scale + view_offset_y;
                
                
                var n:int = int(scale * 100);
                if (n >= 40) n = 39;
                
                sourceRect.width = ballCopySource[n].width;
                sourceRect.height = ballCopySource[n].height;
                
                canvasData.copyPixels(ballCopySource[n], sourceRect, destPoint);
                
            }
            
            canvasData.unlock();
            
        }
    }
}

import flash.geom.Vector3D;
class Ball3D
{
    public var pos:Vector3D;
    public var viewPos:Vector3D;
    
    public var v:Vector3D;
    public var n:int;
    
    public function Ball3D():void
    {
        
    }
    
    public function init(x:Number, y:Number, z:Number, 
                        vx:Number, vy:Number, vz:Number,
                        n:int):void
    {
        pos = new Vector3D(x, y, z, 0);
        v = new Vector3D(vx, vy, vz, 0);
        //this.sp = sp;
        this.n = n;
        
        viewPos = new Vector3D();
    }
    
}