/**
* Copyright tak0294 ( http://wonderfl.net/user/tak0294 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/glKg
*/
package {
import Box2D.Collision.b2AABB;
import Box2D.Collision.Shapes.b2PolygonDef;
import Box2D.Common.Math.b2Vec2;
import Box2D.Dynamics.b2Body;
import Box2D.Dynamics.b2BodyDef;
import Box2D.Dynamics.b2DebugDraw;
import Box2D.Dynamics.b2World;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.materials.*;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;
import org.papervision3d.lights.*;
import org.papervision3d.materials.shadematerials.*;
/**
* 床の上に箱を落とすFlash
*/
public class Main extends Sprite {
private var world:b2World;
private var old_body:b2Body;
private var body_arr:Array = new Array();
private var body_arr3d:Array = new Array();
private var body_count:Number = 0;
// PV3D用基本変数
private var viewport:Viewport3D;
private var scene:Scene3D;
private var camera:Camera3D;
private var renderer:BasicRenderEngine;
private var rootNode:DisplayObject3D;
private var light:PointLight3D;
// 床用変数
private var floorBody1:b2Body;
private var floor3d:Cube;
public function Main():void {
////////////////////////////////////////
// 物理エンジンのセットアップ
// 外枠を定義する
var worldAABB:b2AABB = new b2AABB();
worldAABB.lowerBound.Set(-100, -100);
worldAABB.upperBound.Set(100, 100);
// 重力を下方向に10m/s^2とする
var gravity:b2Vec2 = new b2Vec2(0, 10);
// 外枠と重力を指定して、物理エンジン全体をセットアップする
world = new b2World(worldAABB, gravity, true);
////////////////////////////////////////
// 床の設置
// 床は画面の下のほうに設置します
// 床の位置を左から2.5m、上から3mとする
var floorBodyDef:b2BodyDef = new b2BodyDef();
floorBodyDef.position.Set(2.5, 3);
// 床の形を、幅4m、厚さ20cmとする
// 指定するのはその半分の値
var floorShapeDef:b2PolygonDef = new b2PolygonDef();
floorShapeDef.SetAsBox(2, 0.1);
// 床を動かない物体として作る
var floor:b2Body = world.CreateBody(floorBodyDef);
floor.CreateShape(floorShapeDef);
////////////////////////////////////////
// 描画設定
var debugDraw:b2DebugDraw = new b2DebugDraw();
debugDraw.m_sprite = this;
debugDraw.m_drawScale = 100; // 1mを100ピクセルにする
debugDraw.m_fillAlpha = 1; // 不透明度
debugDraw.m_lineThickness = 1; // 線の太さ
//debugDraw.m_drawFlags = 0xFFFFFFFF;
debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit;
world.SetDebugDraw(debugDraw);
// PV3Dの初期設定
viewport=new Viewport3D(0, 0, true, true);
scene=new Scene3D();
camera=new Camera3D();
renderer=new BasicRenderEngine();
rootNode=scene.addChild(new DisplayObject3D("rootNode"));
camera.zoom=30;
camera.focus=60;
camera.x=-400;
camera.y=400;
camera.target=DisplayObject3D.ZERO;
// light = new PointLight3D(false);
// light.z = 0;
// light.x = -400;
// light.y = 800;
addChild(viewport);
// PV3Dの床の設定
var boxcolor:Array=new Array();
for(var i:int=0; i < 6; i++)
{
boxcolor[i]=new ColorMaterial(Math.floor(Math.random() * 0xFFFFFF), 0.6);
}
var materials:MaterialsList=new MaterialsList({front:boxcolor[0], back:boxcolor[1], right:boxcolor[2], left:boxcolor[3], top:boxcolor[4], bottom:boxcolor[5]});
floor3d=new Cube(materials, 1000, 100, 10, 4, 4);
rootNode.addChild(floor3d);
// イベントハンドラを登録する
stage.addEventListener(MouseEvent.CLICK, clickHandler);
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
private function clickHandler(event:MouseEvent):void {
////////////////////////////////////////
// 箱の設置
// 箱は床の上から落として、少しはねるようにします
// 箱の位置を左から2.5m、上から1mとする
var boxBodyDef:b2BodyDef = new b2BodyDef();
boxBodyDef.position.Set(event.stageX / 100, event.stageY / 100);
// 箱の形を、幅40cm、高さ40cmとして45度ぐらい右に回す
var boxShapeDef:b2PolygonDef= new b2PolygonDef();
boxShapeDef.SetAsOrientedBox(0.2, 0.2, new b2Vec2(0, 0), 0);
boxShapeDef.density = 1; // 密度 [kg/m^2]
boxShapeDef.restitution = 0.5; // 反発係数、通常は0~1
// 箱を動く物体として作る
var boxBody:b2Body = world.CreateBody(boxBodyDef);
body_arr[body_count] = boxBody;
/*
//Jointの作成
if(old_body != null)
{
var distanceJD:b2DistanceJointDef = new b2DistanceJointDef();//まず jd.body1 = this.old_body;
//オブジェクトを2つ指定して、固定する位置を指定する。GetPosition()でオブジェクトの中心位置を取得できる。
distanceJD.Initialize(boxBody,old_body,boxBody.GetPosition(),old_body.GetPosition());
world.CreateJoint(distanceJD);
}
*/
this.old_body = boxBody;
boxBody.CreateShape(boxShapeDef);
boxBody.SetMassFromShapes();
var boxcolor:Array = new Array();
for(var j:int=0; j < 6; j++)
{
boxcolor[j]=new ColorMaterial(0x222222, 1);
}
//var materials=new MaterialsList({front:boxcolor[0], back:boxcolor[1], right:boxcolor[2], left:boxcolor[3], top:boxcolor[4], bottom:boxcolor[5]});
var materials:MaterialsList = new MaterialsList({all:new GouraudMaterial(light,0xFFFFFF,0x666666)});
var cube:Cube=new Cube(materials, 80, 40, 40, 4, 4);
//マテリアル設定
//var materials = new WireframeMaterial( 0x999999 );
//materials.doubleSided = true;
//var spe:Sphere = new Sphere(materials, 40, 8, 6);
rootNode.addChild(cube, "cube" + body_count.toString());
body_count++;
}
private function enterFrameHandler(event:Event):void {
if (world == null) {
return;
}
// Flashはデフォルトで秒間24フレームなので、
// 物理シミュレーションを1/24秒進める
world.Step(1 / 24, 10);
for(var i:int=0; i < body_count; i++)
{
var bb:b2Body=body_arr[i]as b2Body;
//if (bb == boxboy)
{
var cube:Cube=rootNode.getChildByName("cube" + i.toString())as Cube;
cube.x=(bb.GetPosition().x) * 100 - 200;
cube.y=-(bb.GetPosition().y) * 100 + 300;
cube.rotationZ=-bb.GetAngle() * (180 / Math.PI);
//break;
}
}
renderer.renderScene(scene, camera, viewport);
}
}
}