package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;
[SWF(width=640, height=480, backgroundColor=0xe0e0d0, frameRate=30)]
public class BoundCube3D extends Sprite
{
static public const SCREEN_C:uint = 0xe0e0d0,
SCREEN_W:int = 640,
SCREEN_H:int = 480,
CUBE_SIZE:int = 100,
CUBE_XNUM:int = 5,
CUBE_ZNUM:int = 5,
JUMP_V:int = 200,
JUMP_ROT:int = 20,
JUMP_G:Number = 9.8,
JUMP_T:Number = 0.15,
JUMP_E:Number = 0.4;
private var base:Sprite;
private var scene:Scene3D;
private var viewport:Viewport3D;
private var camera:Camera3D;
private var render:BasicRenderEngine;
public function BoundCube3D()
{
init3D();
}
/**
* @brief 初期化
*/
private function init3D():void
{
// ベース画面を設定
this.base = new Sprite();
this.base.graphics.beginFill( SCREEN_C );
this.base.graphics.drawRect( 0, 0, SCREEN_W, SCREEN_H );
this.base.graphics.endFill();
this.addChild( this.base );
// シーン設定
this.scene = new Scene3D();
// ビューポート設定
this.viewport = new Viewport3D( SCREEN_W, SCREEN_H );
this.base.addChild( this.viewport );
// レンダー設定
this.render = new BasicRenderEngine();
// キューブ作成
var materialList:MaterialsList = new MaterialsList( { all: new ColorMaterial( 0xffffff ),
front: new ColorMaterial( 0xe0e050 ),
back: new ColorMaterial( 0xe0e050 ),
top: new ColorMaterial( 0x5050e0 ),
bottom: new ColorMaterial( 0x5050e0 ),
left: new ColorMaterial( 0x50e050 ),
right: new ColorMaterial( 0x50e050 ) } );
var resizeLeft:int = ((CUBE_SIZE * 2) * (CUBE_XNUM-1)) / 2; // (0,0,0)を中心に位置調整
var resizeBack:int = ((CUBE_SIZE * 2) * (CUBE_ZNUM-1)) / 2; // (0,0,0)を中心に位置調整
for( var i:int = 0; i < CUBE_XNUM; ++i )
{
for( var j:int = 0; j < CUBE_ZNUM; ++j )
{
var cube:DisplayObject3D = new Cube( materialList, CUBE_SIZE, CUBE_SIZE, CUBE_SIZE );
cube.x = CUBE_SIZE * j * 2 - resizeLeft;
cube.z = CUBE_SIZE * i * 2 - resizeBack;
cube.rotationY = Math.random() * 360;
cube.extra = new Object;
cube.extra.isjump = false;
this.scene.addChild( cube, 'cube_' + i.toString() + '_' + j.toString() );
}
}
// カメラ設定
this.camera = new Camera3D();
this.camera.y = 500;
this.camera.z = -1000;
// なるべく真ん中にいるキューブを見るように設定
this.camera.lookAt( this.scene.getChildByName( 'cube_' + Math.floor( CUBE_XNUM / 2 ).toString() + '_' + Math.floor( CUBE_ZNUM / 2 ).toString() ) );
// イベント設定
this.base.addEventListener( MouseEvent.CLICK, clickBound3D );
this.base.addEventListener( Event.ENTER_FRAME, render3D );
}
/**
* @brief バウンドパラメータ設定
*/
private function clickBound3D( ev:MouseEvent ):void
{
for( var i:int = 0; i < CUBE_XNUM; ++i )
{
for( var j:int = 0; j < CUBE_ZNUM; ++j )
{
var cube:DisplayObject3D = this.scene.getChildByName( 'cube_' + i.toString() + '_' + j.toString() );
if( cube.extra.isjump == false )
{
cube.extra.v = Math.random() * JUMP_V;
cube.extra.rot = Math.random() * JUMP_ROT;
cube.extra.t = 1.0;
cube.extra.isjump = true;
}
}
}
}
/**
* @brief 更新と描画
*/
private function render3D( ev:Event ):void
{
for( var i:int = 0; i < CUBE_XNUM; ++i )
{
for( var j:int = 0; j < CUBE_ZNUM; ++j )
{
var cube:DisplayObject3D = this.scene.getChildByName( 'cube_' + i.toString() + '_' + j.toString() );
if( cube.extra.isjump == true )
{
// 回転
cube.rotationY += cube.extra.rot;
if( cube.rotationY >= 360 ) cube.rotationY = 0;
// 投げ上げ
cube.y = cube.extra.v * cube.extra.t - 0.5 * JUMP_G * Math.pow( cube.extra.t, cube.extra.t );
cube.extra.t += JUMP_T;
if( cube.y <= 0 )
{
cube.y = 0;
cube.extra.v *= JUMP_E;
cube.extra.t = 1.0;
if( cube.extra.v <= 1 )
{
cube.extra.isjump = false;
}
}
}
}
}
this.render.renderScene( this.scene, this.camera, this.viewport );
}
}
}