Cube to Plane (Away3D)
Click to start.
/**
* 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();
}
}
}