flash on 2009-5-6
Just for my Practice.
Original code: Plz Cross apply
http://lab.takumi-hasegawa.jp/
thanks a lot hasegawa-san! :)
//Just for my Practice.
//Original code: Plz Cross apply
//http://lab.takumi-hasegawa.jp/
//thanks a lot hasegawa-san! :)
package {
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.*;
import flash.utils.Timer;
//tweener
import caurina.transitions.*;
//pv3d
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.render.*;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.*;
import org.papervision3d.materials.*;
import org.papervision3d.materials.shadematerials.*;
import org.papervision3d.materials.utils.*;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.core.math.*;
import org.papervision3d.events.InteractiveScene3DEvent;
public class Main extends Sprite {
//pov3d
private var scene:Scene3D;
private var viewport:Viewport3D;
private var camera:Camera3D;
private var renderer:BasicRenderEngine;
private var rootNode:DisplayObject3D;
private var light:PointLight3D;
private var material:*;
private var num:uint; //タイルの数
private var bigCube:DisplayObject3D; //タイルのかたまり
private var bigCubeWidth:uint; //bigCubeの一辺
private var bigCubeYPos:uint; //クリック時にy方向に移動する距離
private var x_segment:uint; //x軸方向の分割数
private var y_segment:uint; //y軸方向の分割数
private var z_segment:uint; //z軸方向の分割数
private var tiles:Array; //タイルのオブジェクトを格納する配列
private var tile_width:uint; //タイルの幅 (x軸方向)
private var tile_depth:uint; //タイルの奥行き (z軸方向)
private var tile_height:uint; //タイルの高さ (y軸方向)
private var tile_distance:uint; //タイルを切り離したときの間隔
public function Main() {
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.frameRate = 36;
//任意の数
x_segment = 3; //4が限界w
tile_width = 80; //x_segmentの倍数
tile_distance = 10;
bigCubeYPos = 200;
//bigCubeを直方体にするために値を決定
bigCubeWidth = x_segment * tile_width;
tile_depth = tile_width;
tile_height = tile_width / x_segment;
y_segment = x_segment * x_segment;
z_segment = x_segment;
num = x_segment * y_segment * z_segment;
displayInit(num);
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
private function displayInit(n:uint):void {
//viewport
viewport = new Viewport3D(0,0,true, true);
addChild(viewport);
//renderer
renderer = new BasicRenderEngine();
//renderer = new QuadrantRenderEngine(QuadrantRenderEngine.CORRECT_Z_FILTER);
//camera
camera = new Camera3D();
camera.x = 0;
camera.y = 500;
camera.z = -1500;
camera.focus = 500;
camera.zoom = 1;
camera.target = DisplayObject3D.ZERO;
//scene
scene = new Scene3D();
//light
light = new PointLight3D();
light.x = 600;
light.y = 600;
light.z = -600;
//rootNode
rootNode = new DisplayObject3D();
scene.addChild(rootNode);
//bigCube
bigCube = new DisplayObject3D();
rootNode.addChild(bigCube);
//material
material = new FlatShadeMaterial(light, 0xFFFFFF, 0x000000, 0);
//material = new ColorMaterial(0xCCCCCC, 1, false);
material.interactive = true;
//tiles
tiles = new Array();
for(var i:uint = 0; i < n; i++) {
tiles[i] = new Cube(new MaterialsList({all:material}), tile_width, tile_depth, tile_height, 1, 1, 1);
tiles[i].position = culcuratePosition(i);
tiles[i].addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, toPlane);
bigCube.addChild(tiles[i]);
}
bigCube.rotationY = 45; //45度回転
}
private function enterFrameHandler(event:Event):void {
//3Dレンダリング
renderer.renderScene(scene, camera, viewport);
}
//タイルをキューブ状に位置を計算
private function culcuratePosition(i:uint, distance:uint = 0):Number3D {
var px:Number = (i % x_segment) * (tile_width + distance) - (bigCubeWidth + (x_segment - 1) * distance - tile_width) / 2;
var py:Number = Math.floor(i / (x_segment * z_segment)) * (tile_height + distance) - (bigCubeWidth + (y_segment - 1) * distance - tile_width) / 2;
var pz:Number = Math.floor(i / x_segment) % z_segment * (tile_depth + distance) - (bigCubeWidth + (z_segment - 1) * distance - tile_width) / 2;
return new Number3D(px, py, pz);
}
//タイルを平面状に並べる際の位置を計算
private function culcuratePosition2(i:uint):Number3D {
var a:uint = Math.ceil(Math.sqrt(num));
var px:Number = (i % a) * tile_width - (tile_width * a - tile_width) / 2;
var py:Number = -bigCubeYPos;
var pz:Number = Math.floor(i / a) % a * tile_depth - (tile_depth * a - tile_width) / 2;
return new Number3D(px, py, pz);
}
//タイルを平面状にならべる処理スタート
private function toPlane(e:Event):void {
for(var i:uint = 0; i < num; i++) {
tiles[i].removeEventListener(InteractiveScene3DEvent.OBJECT_CLICK, toPlane);
}
Tweener.addTween(bigCube, {y:bigCube.y + bigCubeYPos, time:3, transition:"easeInOutQuint", onComplete:separateTiles});
}
//タイルを切り離し
private function separateTiles():void {
for(var i:uint = 0; i < num; i++) {
var pos:Number3D = culcuratePosition(i, tile_distance);
Tweener.addTween(tiles[i], {x:pos.x, y:pos.y, z:pos.z, time:3, transition:"easeInOutQuint", onComplete:placeTiles});
}
}
//タイルを平面状に並べる
public function placeTiles():void {
var timer:Timer = new Timer(100, num)
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, timerCompleteHandler);
timer.start();
}
//タイルを平面状に並べる際のタイマーハンドラ
public function timerHandler(e:TimerEvent) {
var i:uint = e.target.currentCount - 1;
var pos:Number3D = culcuratePosition2(i);
Tweener.addTween(tiles[i], {x:pos.x, y:pos.y, z:pos.z, time:0.5, transition:"easeOutBounce"});
tiles[i].removeEventListener(InteractiveScene3DEvent.OBJECT_CLICK, placeTiles);
}
//タイルを平面状に並べ終わった後に実行
private function timerCompleteHandler(e:TimerEvent) {
for(var i:uint = 0; i < num; i++) {
tiles[i].addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, placeTiles2);
}
}
//タイルをキューブ状に並べる
public function placeTiles2(e:Event):void {
var timer:Timer = new Timer(100, num)
timer.addEventListener(TimerEvent.TIMER, timerHandler2);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, timerCompleteHandler2);
timer.start();
}
//タイルをキューブ状に並べる際のタイマーハンドラ
public function timerHandler2(e:TimerEvent) {
var i:uint = num - (e.target.currentCount - 1) - 1;
var pos:Number3D = culcuratePosition(i);
Tweener.addTween(tiles[i], {x:pos.x, y:pos.y, z:pos.z, time:0.5, transition:"easeOutBounce"});
tiles[i].removeEventListener(InteractiveScene3DEvent.OBJECT_CLICK, placeTiles2);
}
//タイルをキューブ状に並べ終わった後に実行
private function timerCompleteHandler2(e:TimerEvent) {
Tweener.addTween(bigCube, {y:bigCube.y - bigCubeYPos, time:3, transition:"easeInOutQuint", onComplete:initClickEvent});
}
//各タイルにクリックイベントを付加
private function initClickEvent():void {
for(var i:uint = 0; i < num; i++) {
tiles[i].addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, toPlane);
}
}
}
}