9RIA-ladeng6666 发表于 2018-2-5 16:06:38

【9RIA—ladeng6666】—【Box2D系列教程 7】Box2D能再简单点吗——LDEasyBox2D

转载:9RIA游戏开发者社区(天地会)
作者:ladeng6666(拉登大叔)
作者博客:http://www.ladeng6666.com/blog/


【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;
                }
            }
      }

    }

}

效果是一样的
attach://778.swf


下载:

页: [1]
查看完整版本: 【9RIA—ladeng6666】—【Box2D系列教程 7】Box2D能再简单点吗——LDEasyBox2D

感谢所有支持论坛的朋友:下面展示最新的5位赞助和充值的朋友……更多赞助和充值朋友的信息,请查看:永远的感谢名单

SGlW(66139)、 anghuo(841)、 whdsyes(255)、 longxia(60904)、 囫囵吞澡(58054)

下面展示总排行榜的前3名(T1-T3)和今年排行榜的前3名的朋友(C1-C3)……更多信息,请查看:总排行榜今年排行榜

T1. fhqu1462(969)、 T2. lwlpluto(14232)、 T3. 1367926921(962)  |  C1. anghuo(147)、 C2. fdisker(27945)、 C3. 囫囵吞澡(58054)