ff: Cube to Plane (Away3D)

by bradsedito forked from Cube to Plane (Away3D) (diff: 51)
Import Flash Core Classes:
Import Flash Core Classes:
Import Tweening Engine(s):
import com.greensock.*; import com.greensock.easing.*;
Debug:
♥0 | Line 208 | Modified 2013-01-16 03:03:26 | MIT License
play

ActionScript3 source code

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






package 
{
    // Import Flash Core Classes:
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.text.*;
    // Import Flash Core Classes:
    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 Tweening Engine(s):
    import org.libspark.betweenas3.BetweenAS3;
    import org.libspark.betweenas3.easing.*;
    import org.libspark.betweenas3.events.*;
    import org.libspark.betweenas3.tweens.*;        //import com.greensock.*; import com.greensock.easing.*;
    // Debug:
    import net.hires.debug.Stats;

    [SWF(backgroundColor="0x000000", 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 _largeCubeArea:Number = (_largeCubeWidth * _largeCubeHeight * _largeCubeDepth);

        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 var   _SMALL_CUBE_AREA:Number = (_SMALL_CUBE_WIDTH * _SMALL_CUBE_HEIGHT * _SMALL_CUBE_DEPTH);
        
        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;
            _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(0x666666, 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);
            // FUNCTION INIT:
            
            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();
        }
    }
}