/* * Copyright (c) 2007 michiyasu wada * http://www.seyself.com/ * * Distributed under The MIT License. * [http://www.opensource.org/licenses/mit-license.php] */ package { import flash.display.Sprite; import flash.events.Event; // Import Papervision3D import org.papervision3d.scenes.Scene3D; import org.papervision3d.cameras.Camera3D; import org.papervision3d.cameras.FreeCamera3D; import org.papervision3d.objects.*; import org.papervision3d.core.geom.Mesh3D; import org.papervision3d.materials.MaterialsList; import org.papervision3d.materials.MovieAssetMaterial; import org.papervision3d.materials.ColorMaterial; // Import Box2D import Box2D.Dynamics.*; import Box2D.Collision.*; import Box2D.Collision.Shapes.*; import Box2D.Common.Math.*; public class Document extends Sprite { // ___________________________________________________________________ PV3D Properties static public var SCREEN_WIDTH :int = 550; static public var SCREEN_HEIGHT :int = 400; private var container :Sprite; private var scene :Scene3D; private var camera :FreeCamera3D; private var ground :DisplayObject3D; private var ball :Sphere; // ___________________________________________________________________ Box2D Properties private var m_world:b2World; private var m_iterations:int = 10; // 繰り返し private var m_timeStep:Number = 1 / 30; // 処理時間(?) // ___________________________________________________________________ Maze private var maze :Maze; private var preX :Number; private var preY :Number; public function Document() { container = new Sprite(); init3D(); initBox2D(); /* Maze */ maze = new Maze(22,16); maze.create(); /* Papervision3D & Box2D */ var i:int, j:int, n:Number, k:Number; var front:Boolean, back:Boolean, top:Boolean, bottom:Boolean, left:Boolean, right:Boolean; var nx:Number, ny:Number, nz:Number; var cube:Cube; var x:int = maze.map.length; var y:int = maze.map[0].length; var size:Number = 100; var ix:Number, iy:Number; for(j=2;j<=y-3;j++){ for (i = 2; i <= x - 3; i++) { var outPos = ( i == 2 || i == x - 3 ) && !maze.map[i][j]; if ( maze.map[i][j] || outPos ) { //output += 'X'; else output += ' '; n = (i + x * j); front = true; back = false; top = !!maze.map[i][j+1] && j!=y-3; bottom = !!maze.map[i][j-1] && j!=2; left = !!maze.map[i-1][j] && i!=2; right = !!maze.map[i+1][j] && i!=x-3; if( !outPos ){ nx = i - x / 2 + 0.5; ny = j - y / 2 + 0.5; nz = 0; } else { k = (i == 2) ? -1 : 1; nx = (i+k) - x / 2 + 0.5; ny = j - y / 2 + 0.5; nz = 0; if (i==2) { ix = (nx+1)*size + size / 2; iy = ny * size + size / 2; } } cube = pvCcreateCube( "c"+n, size, nx, ny, nz, [front, back, top, bottom, left, right] , !outPos ); b2CreateBox( cube, size, nx, ny ); } } } var radius:Number = size * 0.4; ball = pvCreateSphere( "ball" , radius ); b2CreateBall( ball, radius, ix , iy ); //this.addEventListener( Event.ENTER_FRAME, loop ); this.addEventListener( Event.ENTER_FRAME, update ); } // ___________________________________________________________________ Loop public function update( event:Event ) { Box2DUpdate( event ); PV3DUpdate( event ); } private function PV3DUpdate( event:Event ):void { ground.rotationX = ( container.mouseY / 20 ); ground.rotationY = ( -container.mouseX / 20 ); scene.renderCamera( this.camera ); } public function Box2DUpdate( event:Event ):void{ m_world.m_gravity.x = container.mouseX * 3; m_world.m_gravity.y = -container.mouseY * 3; m_world.Step( m_timeStep, m_iterations ); // Go through body list and update sprite positions/rotations for (var bb:b2Body = m_world.m_bodyList; bb; bb = bb.m_next) { if ( bb.m_userData is Mesh3D && bb.m_userData==ball ) { bb.m_userData.x = bb.m_position.x; bb.m_userData.y = bb.m_position.y; //bb.m_userData.rotation = bb.m_rotation * (180 / Math.PI); } } } // ___________________________________________________________________ Papervision3D private function init3D():void { // Create container sprite and center it in the stage addChild( container ); container.x = SCREEN_WIDTH /2; container.y = SCREEN_HEIGHT /2; // Create scene scene = new Scene3D( container ); // Create camera camera = new FreeCamera3D(); camera.z += -2000; camera.zoom = 8; //trace("camera.zoom = "+camera.zoom); ground = new DisplayObject3D(); scene.addChild( ground ); } public function pvCcreateCube( name:String, size:Number, _x:Number=0, _y:Number=0, _z:Number=0, excludes:Array=null, sai:Boolean=true ) { // Attributes var quality :Number = 1; // Materials var materials:MaterialsList = getMaterial( sai ); // Cube face settings // You can add or sustract faces to your selection. For examples: Cube.FRONT+Cube.BACK or Cube.ALL-Cube.Top. // On single sided materials, all faces will be visible from the inside. var insideFaces :int = Cube.ALL; // Front and back cube faces will not be created. var excludeFaces :int = 0; if( excludes[0] ) excludeFaces += Cube.FRONT; if( excludes[1] ) excludeFaces += Cube.BACK; if( excludes[2] ) excludeFaces += Cube.TOP; if( excludes[3] ) excludeFaces += Cube.BOTTOM; if( excludes[4] ) excludeFaces += Cube.LEFT; if( excludes[5] ) excludeFaces += Cube.RIGHT; // Create the cube. var cube:Cube = new Cube( materials, size, size, size, quality, quality, quality, 0, excludeFaces, { x:_x*size, y:_y*size, z:_z*size } ); ground.addChild( cube, name ); return cube; } public function pvCreateSphere( name:String, radius:Number=50, _x:Number=0, _y:Number=0, _z:Number=0 ) { var material:ColorMaterial = new ColorMaterial( 0xF06A1A, 1 ); var segmentsW:int = 8; var segmentsH:int = 6; var initObject:Object = { x:_x, y:_y, z:_z }; var sphere:Sphere = new Sphere( material, radius, segmentsW, segmentsH, initObject ); ground.addChild( sphere, name ); return sphere; } private function getMaterial( flag:Boolean ):MaterialsList { var materials:MaterialsList; if ( flag ) { var matBox:Array = ["Front", "Back", "Left", "Right", "Top", "Bottom"]; matBox = materialRotationX( matBox , Math.random()*4>>0 ); matBox = materialRotationY( matBox , Math.random()*4>>0 ); matBox = materialRotationZ( matBox , Math.random()*4>>0 ); materials = new MaterialsList( { //all: front: new MovieAssetMaterial( matBox[0], true ), back: new MovieAssetMaterial( matBox[1], true ), left: new MovieAssetMaterial( matBox[2], true ), right: new MovieAssetMaterial( matBox[3], true ), top: new MovieAssetMaterial( matBox[4], true ), bottom: new MovieAssetMaterial( matBox[5], true ) } ); } else { materials = new MaterialsList( { //all: front: new MovieAssetMaterial( "Rect", true ), back: new MovieAssetMaterial( "Rect", true ), right: new MovieAssetMaterial( "Rect", true ), left: new MovieAssetMaterial( "Rect", true ), top: new MovieAssetMaterial( "Rect", true ), bottom: new MovieAssetMaterial( "Rect", true ) } ); } return materials; } private function materialRotationX( mat:Array , len:int ):Array { var res:Array = mat.concat(); for (var i:int = 0; i < len; i++ ) { var f:String = res[0]; var k:String = res[1]; var t:String = res[4]; var b:String = res[5]; res = [ b, t, res[2], res[3], f, k ]; } return res; } private function materialRotationY( mat:Array , len:int ):Array { var res:Array = mat.concat(); for (var i:int = 0; i < len; i++ ) { var f:String = res[0]; var k:String = res[1]; var l:String = res[2]; var r:String = res[3]; res = [ l, r, k, f, res[4], res[5] ]; } return res; } private function materialRotationZ( mat:Array , len:int ):Array { var res:Array = mat.concat(); for (var i:int = 0; i < len; i++ ) { var l:String = res[2]; var r:String = res[3]; var t:String = res[4]; var b:String = res[5]; res = [ res[0], res[1], b, t, l, r ]; } return res; } // ___________________________________________________________________ Box2D private function initBox2D() { // Add event for main loop //addEventListener(Event.ENTER_FRAME, Update, false, 0, true); // Creat world AABB var worldAABB:b2AABB = new b2AABB(); worldAABB.minVertex.Set(-1000.0, -1000.0); worldAABB.maxVertex.Set(1000.0, 1000.0); // Define the gravity vector var gravity:b2Vec2 = new b2Vec2(0.0, 300.0); // Allow bodies to sleep var doSleep:Boolean = true; // Construct a world object m_world = new b2World(worldAABB, gravity, doSleep); } public function b2CreateBall( target:*, radius:Number, ix:Number , iy:Number ) { // Add some objects var bodyDef:b2BodyDef = new b2BodyDef(); // Circle var circleDef:b2CircleDef = new b2CircleDef(); circleDef.radius = radius; circleDef.density = 1.0; // 比重 circleDef.friction = 0.5; // 摩擦 circleDef.restitution = 0.5; // 跳ね返り bodyDef.AddShape( circleDef ); bodyDef.position.x = ix; bodyDef.position.y = iy; bodyDef.userData = target; //bodyDef.userData = new PhysCircle(); //bodyDef.userData.width = circleDef.radius*2; //bodyDef.userData.height = circleDef.radius*2; //bodyDef.userData.name = "ball"; //container.addChild( bodyDef.userData ); m_world.CreateBody( bodyDef ); } public function b2CreateBox( target:*, size:Number, ix:Number , iy:Number ):b2BodyDef { var bodyDef:b2BodyDef; var boxDef:b2BoxDef; // Add ground body bodyDef = new b2BodyDef(); boxDef = new b2BoxDef(); boxDef.extents.Set( size*0.48 , size*0.48 ); boxDef.friction = 0.3; bodyDef.position.Set( ix*size, iy*size ); bodyDef.AddShape( boxDef ); bodyDef.userData = target; //bodyDef.userData = new PhysGround(); //bodyDef.userData.width = boxDef.extents.x * 2; //bodyDef.userData.height = boxDef.extents.y * 2; //container.addChild(bodyDef.userData); m_world.CreateBody( bodyDef ); return bodyDef; } } }