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

Cube to Plane (Away3D)

Click to start.
Get Adobe Flash player
by takumi0125 18 Jan 2013

    Talk

    PESakaTFM at 16 Jan 2013 00:42
    This reminds me of Dragon Ball Z when Cell is setting up the fighting ring for the Cell Games.
    takumi0125 at 16 Jan 2013 05:36
    That's right! I wanted this to reproduce that scene.

    Tags

    Embed
/**
 * Copyright takumi0125 ( http://wonderfl.net/user/takumi0125 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/2JwC
 */

    package {
        import flash.display.Sprite;
        import flash.display.Stage;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.geom.Vector3D;
        
        import away3d.cameras.Camera3D;
        import away3d.containers.Scene3D;
        import away3d.containers.View3D;
        import away3d.containers.ObjectContainer3D;
        import away3d.entities.Mesh;
        import away3d.lights.PointLight;
        import away3d.materials.ColorMaterial;
        import away3d.materials.lightpickers.StaticLightPicker;
        import away3d.primitives.CubeGeometry;
            
        import org.libspark.betweenas3.BetweenAS3;
        import org.libspark.betweenas3.easing.*;
        import org.libspark.betweenas3.events.*;
        import org.libspark.betweenas3.tweens.*;
            
        [SWF(backgroundColor = "0xffffff", frameRate = "60")]
        
        public class Main extends Sprite {
            private var _view:View3D;
            private var _scene:Scene3D;
            private var _camera:Camera3D;
            private var _light:PointLight;
                    
            private var _container:ObjectContainer3D;  //小さなキューブ郡のコンテナ
            
            private var _smallCubes:Vector.<Mesh>;  //小さいキューブを格納するVector
            private var _numSmallCubes:uint;        //小さいキューブの数  
            
            private var _largeCubeWidth:uint;   //大きいキューブの幅
            private var _largeCubeHeight:uint;  //大きいキューブの高さ
            private var _largeCubeDepth:uint;   //大きいキューブの奥行き
            
            private var _numCubesFlatPanelOneSide:uint;  //フラット状態の一辺のキューブ数
            
            private var _flatPanelWidth:Number;  //分割時の大きいキューブの幅
            private var _flatPanelDepth:Number;  //分割時の大きいキューブの奥行き
            
            private const _SMALL_CUBE_WIDTH:uint  = 20;  //小さいキューブの幅
            private const _SMALL_CUBE_HEIGHT:uint =  4;  //小さいキューブの高さ
            private const _SMALL_CUBE_DEPTH:uint  = 20;  //小さいキューブの奥行き
            
            private const _NUM_CUBES_WIDTH_DIR:uint  =  5;  //大きなキューブの幅方向の分割数
            private const _NUM_CUBES_HEIGHT_DIR:uint = 25;  //大きなキューブの高さ方向の分割数
            private const _NUM_CUBES_DEPTH_DIR:uint  =  5;  //大きなキューブの奥行き方向の分割数
            
            private const _SMALL_CUBE_DEVIDE_DURATION:Number =   1;  //分割時のアニメーション時間
            private const _SMALL_CUBE_SHIFT_DURATION:Number  = 0.5;  //フラット状態への移行時のアニメーション時間
            private const _SMALL_CUBE_SHIFT_INTERVAL:Number  = 0.1;  //フラット状態への移行時のキューブのインターバル時間
            
            private const _SLIT_WIDTH:uint  = 10;  //切れ目の幅
            private const _SLIT_HEIGHT:uint =  3;  //切れ目の高さ
            private const _SLIT_DEPTH:uint  = 10;  //切れ目の奥行き
            
            private const _DEVIDE_RISING_HEIGHT:int =  100;  //分割時に上昇する高さ
            private const _FLAT_PANEL_POS_Y:int     = -100;  //フラット状態のY位置
            
            private const _CAMERA_DEFAULT_POS_X:Number =    0;  //カメラのデフォルトx座標
            private const _CAMERA_DEFAULT_POS_Y:Number =  300;  //カメラのデフォルトy座標
            private const _CAMERA_DEFAULT_POS_Z:Number = -500;  //カメラのデフォルトz座標
            
            private const _LIGHT_DEFAULT_POS_X:Number =    0;  //ライトのデフォルトx座標
            private const _LIGHT_DEFAULT_POS_Y:Number =  400;  //ライトのデフォルトy座標
            private const _LIGHT_DEFAULT_POS_Z:Number = -400;  //ライトのデフォルトz座標
            
            //コンストラクタ
            public function Main() {
                _init();
            }
            
            //イニシャライズ
            private function _init():void {
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
                
                //AWAY3Dセッティング
                _view = new View3D();
                _view.antiAlias = 4;
                _view.backgroundColor = 0xaacf53;
                _scene = _view.scene;
                _camera = _view.camera;
                addChild(_view);
                
                //各値を算出
                _numSmallCubes = _NUM_CUBES_WIDTH_DIR * _NUM_CUBES_HEIGHT_DIR * _NUM_CUBES_DEPTH_DIR;
                _largeCubeWidth = _SMALL_CUBE_WIDTH * _NUM_CUBES_WIDTH_DIR;
                _largeCubeHeight = _SMALL_CUBE_HEIGHT * _NUM_CUBES_HEIGHT_DIR;
                _largeCubeDepth = _SMALL_CUBE_DEPTH * _NUM_CUBES_DEPTH_DIR;
                
                _numCubesFlatPanelOneSide = Math.sqrt(_numSmallCubes);  //ここは整数値になるよう各定数を調整
                
                _flatPanelWidth = _numCubesFlatPanelOneSide * _SMALL_CUBE_WIDTH;
                _flatPanelDepth = _numCubesFlatPanelOneSide * _SMALL_CUBE_DEPTH;
                
                //コンテナ生成
                _container = new ObjectContainer3D();
                _scene.addChild(_container);
                
                //カメラ設定
                _camera.x = _CAMERA_DEFAULT_POS_X
                _camera.y = _CAMERA_DEFAULT_POS_Y;
                _camera.z = _CAMERA_DEFAULT_POS_Z;
                _camera.lookAt(_container.position);
                
                //ライト設定
                _light = new PointLight();
                _light.x = _LIGHT_DEFAULT_POS_X
                _light.y = _LIGHT_DEFAULT_POS_Y;
                _light.z = _LIGHT_DEFAULT_POS_Z;
                _light.lookAt(_container.position);
                _scene.addChild(_light);
                
                //小さなキューブを生成・配置
                _smallCubes = new Vector.<Mesh>();
                var smallCube:*;
                var smallCubePosIndex:Vector3D;
                var colorMaterial:ColorMaterial = new ColorMaterial(0xaacf53, 1);
                colorMaterial.lightPicker = new StaticLightPicker([_light]);
                var cubeGeometry:CubeGeometry = new CubeGeometry(_SMALL_CUBE_WIDTH, _SMALL_CUBE_HEIGHT, _SMALL_CUBE_DEPTH, 1, 1, 1);
                for(var i:uint = 0; i < _numSmallCubes; i++) {
                    smallCubePosIndex = _getPosIndexInLargeCube(i);
                    smallCube = new Mesh(cubeGeometry, colorMaterial);
                    smallCube.x = smallCubePosIndex.x * _SMALL_CUBE_WIDTH - _largeCubeWidth / 2;
                    smallCube.y = smallCubePosIndex.y * _SMALL_CUBE_HEIGHT - _largeCubeHeight / 2;
                    smallCube.z = smallCubePosIndex.z * _SMALL_CUBE_DEPTH - _largeCubeDepth / 2;
                    _container.addChild(smallCube);
                    _smallCubes.push(smallCube);
                }
                
                //フレームごとの処理
                addEventListener(Event.ENTER_FRAME, _enterFrameHandler);
                
                //ステージをクリックで分割
                stage.addEventListener(MouseEvent.MOUSE_UP, _devideLargeCube);
                
                //リサイズ処理
                stage.addEventListener(Event.RESIZE, _resizeHandler);
            }
        
            //分割
            private function _devideLargeCube(e:MouseEvent):void {
                removeEventListener(MouseEvent.MOUSE_UP, arguments.callee);
                
                var smallCube:*;
                var smallCubePosIndex:Vector3D;
                var largeCubeWidthDevided:Number  = _largeCubeWidth + (_NUM_CUBES_WIDTH_DIR - 1) * _SLIT_WIDTH;     //分割時の大きいキューブの幅
                var largeCubeHeightDevided:Number = _largeCubeHeight + (_NUM_CUBES_HEIGHT_DIR - 1) * _SLIT_HEIGHT;  //分割時の大きいキューブの高さ
                var largeCubeDepthDevided:Number  = _largeCubeDepth + (_NUM_CUBES_DEPTH_DIR - 1) * _SLIT_DEPTH;     //分割時の大きいキューブの奥行き
                
                var tweens:Array = [];
                for(var i:uint = 0; i < _numSmallCubes; i++) {
                    //分割時の位置へTweenアニメーション
                    smallCube = _smallCubes[i];
                    smallCubePosIndex = _getPosIndexInLargeCube(i);
                    tweens.push(
                        BetweenAS3.tween(
                            smallCube,
                            {
                                x: smallCubePosIndex.x * (_SMALL_CUBE_WIDTH  + _SLIT_WIDTH) - largeCubeWidthDevided  / 2,
                                y: smallCubePosIndex.y * (_SMALL_CUBE_HEIGHT + _SLIT_HEIGHT) - largeCubeHeightDevided / 2 + _DEVIDE_RISING_HEIGHT,
                                z: smallCubePosIndex.z * (_SMALL_CUBE_DEPTH  + _SLIT_DEPTH) - largeCubeDepthDevided  / 2
                            },
                            null,
                            _SMALL_CUBE_DEVIDE_DURATION,
                            Expo.easeOut
                        )
                    );
                }
                
                var itween:ITween = BetweenAS3.parallelTweens(tweens);
                itween.addEventListener(TweenEvent.COMPLETE, function(e:TweenEvent):void {
                    //完了後にフラットな状態へ
                    _shiftToFlatPanel();
                });
                itween.play();
            }
            
            //フラットな状態にシフト (螺旋)
            private function _shiftToFlatPanel():void {
                removeEventListener(MouseEvent.MOUSE_UP, arguments.callee);
                
                var smallCube:*;
                var smallCubePosIndex:Vector3D;
                var spiralCnt:uint = 0;                                    //周回数
                var spiralIndex:uint = 0;                                  //周回内でのインデックス
                var numCubesOneSide:uint = _numCubesFlatPanelOneSide - 1;  //一辺に並べる個数
            
                for(var i:uint = 0; i < _numSmallCubes; i++) {
                    //フラット時の位置へTweenアニメーション
                    if(spiralIndex == numCubesOneSide * 4) {
                        spiralIndex = 0;
                        spiralCnt++;
                        numCubesOneSide -= 2;
                    }
                    
                    smallCube = _smallCubes[i];
                    smallCubePosIndex = _getPosIndexInFlatPanel(spiralIndex, spiralCnt, numCubesOneSide);
                    var tween:ITween = BetweenAS3.delay(BetweenAS3.tween(
                        smallCube,
                        {
                            x: smallCubePosIndex.x * _SMALL_CUBE_WIDTH - _flatPanelWidth / 2,
                            y: _FLAT_PANEL_POS_Y,
                            z: smallCubePosIndex.z * _SMALL_CUBE_DEPTH - _flatPanelDepth / 2
                        },
                        null,
                        _SMALL_CUBE_SHIFT_DURATION,
                        Bounce.easeOut
                    ), i * _SMALL_CUBE_SHIFT_INTERVAL);
                    
                    tween.play();
                    
                    spiralIndex++;
                }
            }
            
            //大きいキューブ状態の小さいキューブの位置を取得
            private function _getPosIndexInLargeCube(index:uint):Vector3D {
                return new Vector3D(
                    index % _NUM_CUBES_WIDTH_DIR,                                       //x
                    Math.floor(index / (_NUM_CUBES_WIDTH_DIR * _NUM_CUBES_DEPTH_DIR)),  //y
                    Math.floor(index / _NUM_CUBES_WIDTH_DIR) % _NUM_CUBES_DEPTH_DIR     //z
                );
            }
            
            //フラット状態の小さいキューブの位置を取得
            private function _getPosIndexInFlatPanel(spiralIndex:uint, spiralCnt:uint, numCubesOneSide:uint):Vector3D {
                var posIndexX:uint;  //x位置
                var posIndexZ:uint;  //z位置
                var spiralDir:Number = Math.floor(spiralIndex / numCubesOneSide);  //配置の方向
                            
                //配置方向によって位置を算出
                if(spiralDir == 0) {
                    //上辺
                    posIndexX = spiralIndex + spiralCnt;
                    posIndexZ = spiralCnt;
                } else if(spiralDir == 1) {
                    //右辺
                    posIndexX = numCubesOneSide + spiralCnt;
                    posIndexZ = spiralIndex - numCubesOneSide + spiralCnt;
                } else if(spiralDir == 2) {
                    //下辺
                    posIndexX = numCubesOneSide - (spiralIndex - numCubesOneSide * 2) + spiralCnt;
                    posIndexZ = numCubesOneSide + spiralCnt;
                } else {
                    //左辺
                    posIndexX = spiralCnt;
                    posIndexZ = numCubesOneSide - (spiralIndex - numCubesOneSide * 3) + spiralCnt;
                }
                            
                return new Vector3D(posIndexX, 0, posIndexZ);
            }
            
            //フレームごとの処理
            private function _enterFrameHandler(e:Event):void {
                //Y軸回転
                _container.rotationY -= 1;
                _view.render();
            }
            
            //リサイズ処理
            private function _resizeHandler(e:Event):void {
                _view.width = stage.stageWidth;
                _view.height = stage.stageHeight;
                _view.render();
            }
        }
    }