Box2D能再简单点吗

 

认识了Box2D世界,学习了刚体的创建,细细回想一下,总感觉Box2D的创建过程稍有繁琐,每每都要创建世界、环境、重力、刚体需求、形状需求…等等。能不能再简单点?

在下面的LDEasyBox2D中,我把这些基本固定不变的创建过程封装到了一个静态类中:

package
{
	import Box2D.Collision.b2AABB;
	import Box2D.Collision.Shapes.b2CircleDef;
	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;
	/**
	 * ...
	 * @author ladeng6666
	 */
	public class LDEasyBox2D
	{

		public function LDEasyBox2D()
		{

		}
		/**
		 * 创建并返回一个重力为10的Box2D世界
		 * @return b2World
		 */
		public static function createWorld():b2World {
			//1.创建一个环境
			var environment:b2AABB = new b2AABB();
			environment.lowerBound = new b2Vec2( -100, -100);
			environment.upperBound = new b2Vec2(100, 100);
			//2.声明重力
			var gravity:b2Vec2 = new b2Vec2(0, 10);
			//3.睡着的对象是否模拟
			var doSleep:Boolean = true;
			//4.创建b2World世界
			var world:b2World = new b2World(environment, gravity, doSleep);

			return world;
		}
		public static function createDebug(world:b2World):Sprite
		{
			var debugSprite:Sprite = new Sprite();

			var debugDraw:b2DebugDraw = new b2DebugDraw();
			debugDraw.m_sprite = debugSprite;
			debugDraw.m_drawScale = 30.0;
			debugDraw.m_fillAlpha = 0.5;
			debugDraw.m_lineThickness = 1.0;
			debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit;

			world.SetDebugDraw(debugDraw);
			return debugSprite;
		}
		/**
		 * 创建并返回一个矩形的b2Body刚体对象
		 * @param	world
		 * @param	posX box的x坐标,以像素为单位
		 * @param	posY box的y坐标,以像素为单位
		 * @param	boxWidth box的宽度,以像素为单位
		 * @param	boxHeight box的高度,以像素为单位
		 * @param	isStatic box是否静止不动
		 * @param	userData box的外观
		 * @return b2Body
		 */
		public static function createBox(world:b2World,posX:Number,posY:Number,boxWidth:Number,boxHeight:Number,isStatic:Boolean=false,userData:*=null):b2Body {
			//1.创建刚体需求b2BodyDef
			var bodyRequest:b2BodyDef = new b2BodyDef();
			bodyRequest.position.Set(posX / 30, posY / 30);//记得米和像素的转换关系
			//Ladeng6666是Flash元件库中的一个图片
			if ( userData != null) {
				bodyRequest.userData = userData;
				//设定上衣的尺寸
				bodyRequest.userData.width = boxWidth;
				bodyRequest.userData.height = boxHeight;
				//需手动将上衣添加到舞台上
				//addChild(bodyRequest.userData);
			}

			//2.Box2D世界工厂更具需求创建createBody()生产刚体
			var box:b2Body = world.CreateBody(bodyRequest);

			//3.创建敢提形状需求b2ShapeDef的子类
			var shapeRequest:b2PolygonDef = new b2PolygonDef();
			//详细说明我们的需求
			shapeRequest.density = isStatic?0:3;
			shapeRequest.friction = 0.3;
			shapeRequest.restitution = 0.2;
			shapeRequest.SetAsBox(boxWidth/2/30 , boxHeight/2/30);

			//4.b2Body刚体工厂根据需求createShape生产形状
			box.CreateShape(shapeRequest);
			box.SetMassFromShapes();

			return box;
		}
		/**
		 * 创建并返回一个圆形敢提,同样所有涉及到坐标的参数都是以像素为单位
		 * @param	world
		 * @param	posX
		 * @param	posY
		 * @param	radius
		 * @param	isStatic
		 * @param	userData
		 * @return 返回一个圆形刚体
		 */
		public static function createCircle(world:b2World, posX:Number, posY:Number, radius:Number, isStatic:Boolean = false, userData:*=null):b2Body {
			//1.创建刚体需求b2BodyDef
			var bodyRequest:b2BodyDef = new b2BodyDef();
			bodyRequest.position.Set(posX / 30, posY / 30);//记得米和像素的转换关系
			//Ladeng6666是Flash元件库中的一个图片
			if ( userData != null) {
				bodyRequest.userData = userData;
				//设定上衣的尺寸
				bodyRequest.userData.width = radius * 2;
				bodyRequest.userData.height = radius * 2;
				//需手动将上衣添加到舞台上
				//addChild(bodyRequest.userData);
			}

			//2.Box2D世界工厂更具需求创建createBody()生产刚体
			var circle:b2Body = world.CreateBody(bodyRequest);

			//3.创建敢提形状需求b2ShapeDef的子类
			var shapeRequest:b2CircleDef = new b2CircleDef();
			//详细说明我们的需求
			shapeRequest.density = isStatic?0:3;
			shapeRequest.friction = 0.3;
			shapeRequest.restitution = 0.2;
			shapeRequest.radius = radius / 30;

			//4.b2Body刚体工厂根据需求createShape生产形状
			circle.CreateShape(shapeRequest);
			circle.SetMassFromShapes();

			return circle;
		}
	}

}

这样,再创建一个”刚体的上衣——b2BodyDef.userData“的示例就简单多了:

package
{
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2World;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;

	/**
	 * http://www.ladeng6666.com
	 * @author ladeng6666
	 */
	public class Main extends Sprite
	{
		private var world:b2World;
		private var debugSprite:Sprite;

		public function Main()
		{
			world=LDEasyBox2D.createWorld();
			debugSprite=LDEasyBox2D.createDebug(world);
			addChild(debugSprite);

			//创建地面,
			LDEasyBox2D.createBox(world,stage.stageWidth/2,stage.stageHeight,stage.stageWidth,10,true);

			addEventListener(Event.ENTER_FRAME, loop);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown);
		}

		private function onStageMouseDown(e:MouseEvent):void
		{
			//因为静态类中不是DisplayObject的子类,所以要事先创建好userData,
			//并添加到舞台上
			var userData:Sprite = new Ladeng6666();
			addChild(userData);
			//创建有上衣的刚体盒子
			LDEasyBox2D.createBox(world, mouseX, mouseY, 60, 60, false, userData);
		}

		private function loop(e:Event):void
		{
			world.Step(1 / 30, 10);
			for (var body:b2Body = world.m_bodyList; body; body=body.GetNext()) {
				if (body.m_userData != null) {
					body.m_userData.x = body.GetPosition().x * 30;
					body.m_userData.y = body.GetPosition().y * 30;
					body.m_userData.rotation = body.GetAngle() * 180 / Math.PI;
				}
			}
		}

	}

}

效果是一样的

源代码下载

联系作者

公众号:拉小登 | 微博:拉登Dony | B站:拉小登Excel

One Reply to “Box2D能再简单点吗”

  1. LDEasyBox2D.getBodyAtMouse()下的
    function callBack( fixture:b2Fixture ):void
    编译错误:找不到类型或不是编译时常数。

    拉登兄这是怎么回事 给看看呗

回复 xiaoxin999

您的电子邮箱地址不会被公开。 必填项已用 * 标注