Hello Box2dAs3

以前做化学课件,发现Flash里处理对象的碰撞是个很麻烦的问题,即使是对于规则的对象,比如某个仪器(滴管,试剂瓶等),也查过很多资料来解决碰撞问题,但都很复杂,看了后一头雾水。一次偶然发现box2dAs3,它竟然能把对象碰撞模拟得如此真实,并且Box2dAs3中处理碰撞并不需要开发者处理,开发者只需要创建一个一个的对象(box2d中称为刚体),它会自动处理每个刚体的碰撞,即物理特性。下面是我的第一篇关于box2dAs3的入门。

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;
	
	/**
	 * Box2dAs3 Version 2.0.1 
	 * @author ywxgod--http://www.cnblogs.com/ywxgod/
	 * 
	 */
	[SWF(backgroundColor="333333",frameRate="30",width="550",height="400")]
	public class HelloBox2dAs3 extends Sprite 
	{
		private var physcale:Number = 30.0;
		private var timeStep:Number = 1 / physcale;
		private var iteration:int = 10;
		
		private var body:b2Body;
		private var world:b2World;
		
		private const FLOOR_WIDTH:int = 550;
		private const FLOOR_HEIGHT:int = 20;
		private const WALL_WIDTH:int = 20;
		private const WALL_HEIGHT:int = 400;
		
		private var maxBodysNum:int = 50;
		private var count:int = 0;
		
		public function HelloBox2dAs3():void 
		{
			init();
		}
		
		private function init():void 
		{
			createWorld();
			createFloorAndWalls();
			showDebuger();
			run();
			addEventListener(Event.ENTER_FRAME,onFrame);
		}
		
		private function createWorld():void 
		{
			var aabb:b2AABB = new b2AABB();
			aabb.lowerBound.Set( -100, -100);
			aabb.upperBound.Set(100, 100);
			var gravity:b2Vec2 = new b2Vec2(0, 9.8);
			world = new b2World(aabb, gravity, true);
		}
		
		private function createFloorAndWalls():void 
		{
			var floorShapeDef:b2PolygonDef = new b2PolygonDef();
			floorShapeDef.density = 0;
			floorShapeDef.friction = 0.3;
			floorShapeDef.restitution = 0.4;
			floorShapeDef.SetAsBox(FLOOR_WIDTH / 2 / physcale, FLOOR_HEIGHT / 2 / physcale);
			var floorBodyDef:b2BodyDef = new b2BodyDef();
			floorBodyDef.position.Set(FLOOR_WIDTH / 2 / physcale, (WALL_HEIGHT-FLOOR_HEIGHT/2) / physcale);
			var floorBody:b2Body = world.CreateBody(floorBodyDef);
			floorBody.CreateShape(floorShapeDef);
			floorBody.SetMassFromShapes();
			
			var leftWallShapeDef:b2PolygonDef = new b2PolygonDef();
			leftWallShapeDef.density = 0;
			leftWallShapeDef.friction = 0.3;
			leftWallShapeDef.restitution = 0.4;
			leftWallShapeDef.SetAsBox(WALL_WIDTH / 2 / physcale, WALL_HEIGHT / 2 / physcale);
			var leftWallBodyDef:b2BodyDef = new b2BodyDef();
			leftWallBodyDef.position.Set(WALL_WIDTH / 2 / physcale, (WALL_HEIGHT / 2) / physcale);
			var leftWallBody:b2Body = world.CreateBody(leftWallBodyDef);
			leftWallBody.CreateShape(leftWallShapeDef);
			leftWallBody.SetMassFromShapes();
			
			var rightWallShapeDef:b2PolygonDef = new b2PolygonDef();
			rightWallShapeDef.density = 0;
			rightWallShapeDef.friction = 0.3;
			rightWallShapeDef.restitution = 0.4;
			rightWallShapeDef.SetAsBox(WALL_WIDTH / 2 / physcale, WALL_HEIGHT / 2 / physcale);
			var rightWallBodyDef:b2BodyDef = new b2BodyDef();
			rightWallBodyDef.position.Set((FLOOR_WIDTH-WALL_WIDTH / 2) / physcale, (WALL_HEIGHT / 2) / physcale);
			var rightWallBody:b2Body = world.CreateBody(rightWallBodyDef);
			rightWallBody.CreateShape(rightWallShapeDef);
			rightWallBody.SetMassFromShapes();
		}
		
		private function createActors(count:int):void 
		{
			
			var boxShapeDef:b2PolygonDef = new b2PolygonDef();
                 boxShapeDef.density = 2;
                 boxShapeDef.friction = 0.3;
                 boxShapeDef.restitution = 0.4;
                 boxShapeDef.SetAsBox(40 / 2 / physcale, 15 / 2 / physcale);
                 var boxShapeBodyDef:b2BodyDef = new b2BodyDef();
                 boxShapeBodyDef.position.Set((275) / physcale, (-count*15) / physcale);
                 var boxShapeBody:b2Body = world.CreateBody(boxShapeBodyDef);
                 boxShapeBody.CreateShape(boxShapeDef);
                 boxShapeBody.SetMassFromShapes();
		}
		
		private function onFrame(e:Event):void
		{
			world.Step(timeStep, iteration);
			
			if (count--<5&&world.m_bodyCount< maxBodysNum)
			{
				createActors(count);
				count = 5;
			}
		}
		
		private function showDebuger():void
		{
			var sprite:Sprite = new Sprite();
			addChild(sprite);
			var dbg:b2DebugDraw = new b2DebugDraw();
			dbg.m_sprite = sprite;
			dbg.m_alpha = 0.5;
			dbg.m_drawScale = physcale;
			dbg.m_drawFlags = b2DebugDraw.e_obbBit;
			dbg.m_fillAlpha = 0.5;
			world.SetDebugDraw(dbg);
		}
		
		private function run():void 
		{
			
		}
	}
	
}

18行 定义swf文件的舞台背景,帧频,宽度,高度

21-23行 定义物理世界与flash世界中长度单位,box2d模拟频率及迭代次数

50-57行 创建一个物理世界world,所有的刚体都是存在其中,world的作用就像flash中的stage,所有的显示对象都被添加到stage一样。创建world需要三个参数:边界盒,重力加速度,是否休眠。

59-93行 创建地面,墙壁等。

95-108行 创建方形刚体,跟59-93行中唯一不同的地方是密度的赋值。

110-119行 在EnterFrameEvent中创建刚体。

121-132行 利用box2dAs3本身的调试显示函数来显示创建的刚体。因为box2das3中没有显示对象的概念,所以无法像flash添加显示对象到舞台一样去做了。

 

 

总结:

  1。flash中的长度是以像素为单位,box2d中的长度是以米为单位,且一米等于30个像素。

  2。flash中有显示对象,且显示对象都是位于stage上,box2d中有刚体,且刚体都是存在于world中。

  3。flash中创建对象是需要制定其宽度和高度,box2d中定义形状只需要其高度宽度的各一半。

  4。创建刚体的步骤:

    a。定义形状,在形状定义中定义摩擦系数friction,反弹系数restitution,密度density,形状的大小SetAsBox

    b。刚体定义,在刚体定义中设置刚体的位置position

    c。创建刚体,传入刚体定义,由world来创建刚体

    d。创建于刚体关联的形状,传入形状定义,有刚体来创建自己关联的形状。

    e。设置质量。

  5。设置b2DebugDraw时的参数

    a。m_sprite 用来显示刚体的显示对象

    b。m_alpha 显示对象的透明度

    c。m_drawScale 放大系数,这个只应该跟长度单位相同,否则显示的刚体将会只有原来的1/30。

    d。m_fillAlpha 绘制刚体时的填充色透明度。

    e。m_drawFlags 标志,告诉b2DebugDraw要绘制刚体哪些相关属性,具体值为b2DebugDraw.e_obbBit,b2DebugDraw.e_aabbBit,b2DebugDraw.e_centerOfMassBit等,也可以是几个值的和。

posted @ 2010-03-21 13:07  ywxgod  阅读(989)  评论(2编辑  收藏  举报