zoukankan      html  css  js  c++  java
  • [box2d] Box2d学习笔记 Class.01 2012.10.5

    怎么样创建一个box2d的世界。


    step.1 :  

    创建一个世界。 

    var world:b2World = new World( new b2Vec2(0,10) , true );

    var1 : (gravity:b2Vec2) , 即重力。

    var2 : (doSleep:Boolean) , 用来管理世界中的物体是否可以休眠。

    step.2 :

    创建一个地面,把地面看成一个巨大的四边形刚体。所以我们现在要做的也相对于创建一个四边形刚体。

    首先创建一个地面的definition,即b2BodyDef。
    var _groundDef:b2BodyDef = new b2BodyDef(); 

    _groundDef.position.Set(SWF_HALF_WIDTH/PIXELS_TO_METER,(SWF_HEIGHT-20)/PIXELS_TO_METER);

    _groundDef.type = b2Body.b2_staticBody;

    b2BodyDef是用来存放刚体在这个世界中的所有数据。

    这里要注意一下box2d的特性,1:所有object的注册点都在中心。2:box2d中的单位是米。

    所以如果我们想将地面放置在舞台底部往上20个像素的地方。我们需要这样处理

     _groundDef.position.Set(SWF_HALF_WIDTH/PIXELS_TO_METER,(SWF_HEIGHT-20)/PIXELS_TO_METER);

    其中SWF_HALF_WIDTH即舞台宽度的一半,SWF_HEIGHT即舞台高度,PIXEL_TO_METER是一个比例尺,用来描述多少个像素对应1米(一般是30)。

    type是刚体类型。分为三种:staticBody , kinematicBody , dynamicBody 。由于地面是静止的刚体,所以我们给他设置为staticBody。

    至于kinematicBody和dynamicBody的区别我们以后再研究。

    然后创建地面刚体,即b2Body。

    var _groundBody:b2Body = _world.CreateBody(_groundDef);

    b2Body就是刚体啦。

    这里我们可以注意到,box2d采取的是工厂模式。即通过world完成所有创建刚体的工作。

    接着我们需要创建这个刚体的形状,这里我们使用b2PolygonShape。当然还有一些其他的形状,我们以后再去了解。

    var _groundBox = new b2PolygonShape();
    _groundBox.SetAsBox(SWF_HALF_WIDTH/PIXELS_TO_METER,20/PIXELS_TO_METER);

    b2PolygonShape就是这个刚体的形状啦。

    通常要创建四边形的话会用到SetAsBox()或者SetAsOrientedBox(),其中后者可以指定注册点和角度。

    另外需要注意的是,在这个方法中传递的宽度值和高度值都是半宽和半高。当然还需要转换到以米为单位。

    我们刚才创建的形状只是这个刚体的definition的一部分。最终我们需要创建的是我们这个地面刚体的definition。

    var _groundFixtureDef:b2FixtureDef = new b2FixtureDef();
    _groundFixtureDef.shape = _groundBox;
    _groundFixtureDef.density = 1;
    _groundFixtureDef.friction = 1;
    _groundFixtureDef.restitution = 0;
                
    _groundBody.CreateFixture(_groundFixtureDef);

    b2FixtureDef与之前的b2BodyDef的区别在于。

    b2BodyDef是用来存放刚体在世界中的数据,比如position(x,y) , angle 等等属性。

    b2FixtureDef则是用来存放刚体自身的数据,比如shape(polygonShape,等等),density,friction等等属性。


    这样我们就已经完成了创建地面刚体的整个过程。 

    接下来我们需要让他们动起来。


    step.3:

    stage.addEventListener(Event.ENTER_FRAME, update);

    private function update(e:Event):void
    {
      var timeStep:Number = 1 / 30;
      var velocityIterations:int = 6;
      var positionIterations:int = 2;
               
      _world.Step(timeStep,velocityIterations,positionIterations);
      _world.ClearForces();
    }

    我们通过b2World的step方法来刷新整个世界。

    step方法要传递三个参数,timeStep,velocityIterations, positionIterations。

    timeStep,时步。通常建议设置为1/60,这样的话你的fps最好也设置到60。但是我发现更好的办法就是把timeStep设置为fps的倒数即可。如果你的fps是30,那么就设置为1/30。

    velocityIterations,速度迭代

    positionIterations,位置迭代

    这两个值通常建议设置为10,更低的迭代值会让你牺牲一些准确性,相反的为你的程序提升一部分性能。


    另外在box2d version2.1中我们需要清除力。

    _world.ClearForces();

    step.4:

    现在我们尝试在空中放置一个小小的刚体让他自由下落。

    这跟我们刚才创建地面刚体的做法基本上一致,唯一不同的是需要把刚体的种类设置为dynamicBody。 

    所以我们把创建四边形刚体的所有步骤集合在一个方法内。方便反复调用。

    createBox(new Point(SWF_HALF_WIDTH, 4), 30, 30, true, 1, 0.3);       

    private function createBox(position:Point,hw:Number,hh:Number,isDynamic:Boolean,density:Number=0,friction:Number=0,restitution:Number=0):void
    {
      var bodyDef:b2BodyDef = new b2BodyDef();
      if( isDynamic )
      {
        bodyDef.type = b2Body.b2_kinematicBody.b2_dynamicBody;
      }
      else
      {
        bodyDef.type = b2Body.b2_staticBody;
      }
      bodyDef.position.Set(position.x/PIXELS_TO_METER,position.y/PIXELS_TO_METER);          
      var body:b2Body = _world.CreateBody(bodyDef);
      var shape:b2PolygonShape = new b2PolygonShape();
      shape.SetAsBox(hw/PIXELS_TO_METER,hh/PIXELS_TO_METER);
      var fixtureDef:b2FixtureDef = new b2FixtureDef();
      fixtureDef.shape = shape;
      fixtureDef.density = density;
      fixtureDef.friction = friction;
      fixtureDef.restitution = restitution;
      body.CreateFixture(fixtureDef);


    同时把刚才创建地面刚体的过程通过我们写好的方法来实现。

    createBox(new Point(SWF_HALF_WIDTH, SWF_HEIGHT - 20), SWF_HALF_WIDTH, 20, false, 1, 1);


    这样我们基本上已经完成了一个世界的搭建。

    可是当我们编译的时候却看不到任何东西。

    什么情况!!

    step.5 :

    不要急,原来我们刚才创建的世界只是一个虚拟的世界。我们并没有给他付于实质性的ui,所以我们压根什么都看不见。

    我们现在没有ui,那该怎么办呢?

    没关系,box2d已经提供给我们一个debug模式,可以让我们在没有ui的时候看到我们的世界。

    private function createDebug():void
    {
      _debugSprite = new Sprite();
      addChild(_debugSprite);
                
      _debugDraw = new b2DebugDraw();
      _debugDraw.SetSprite(_debugSprite);
      _debugDraw.SetDrawScale(PIXELS_TO_METER);
      _debugDraw.SetLineThickness(1);
      _debugDraw.SetAlpha(1);
      _debugDraw.SetFillAlpha(0.4);
      _debugDraw.SetFlags(b2DebugDraw.e_shapeBit);
      _world.SetDebugDraw(_debugDraw);
    }

    b2DebugDraw中有一些属性可以自定义,来改变debug模式的外观,这个看个人喜好就行啦。

    flag可以有以下几种选择。如果你想复用的话,这样即可:  b2DebugDraw.e_aabbBit | b2DebugDraw.e_jointBit 

    b2DebugDraw.e_aabbBit :表示显示刚体的边界盒

    b2DebugDraw.e_jointBit :表示显示刚体相连时的节点和连线

    b2DebugDraw.e_obbBit :显示凸多边形的边界,不显示圆的边界

    b2DebugDraw.e_pairBit:draw broad-phase pairs

    b2DebugDraw.e_coreShapeBit:draw core (TOI) shapes

    b2DebugDraw.e_shapeBit:显示刚体的形状,不管是何种形状

    b2DebugDraw.e_centerOfMassBit:显示重心

    另外还需要在帧监听中添加语句

    _world.DrawDebugData(); 


    编译一下。 

    OK,大功告成~

    附源码:

      1 package
      2 {
      3     import Box2D.Collision.Shapes.b2PolygonShape;
      4     import Box2D.Common.Math.b2Vec2;
      5     import Box2D.Dynamics.b2Body;
      6     import Box2D.Dynamics.b2BodyDef;
      7     import Box2D.Dynamics.b2DebugDraw;
      8     import Box2D.Dynamics.b2FixtureDef;
      9     import Box2D.Dynamics.b2World;
     10     
     11     import flash.display.Sprite;
     12     import flash.events.Event;
     13     import flash.geom.Point;
     14     
     15     [SWF(frameRate=60,width=800,height=600)]
     16     public class Box2dClass_1 extends Sprite
     17     {
     18         private const PIXELS_TO_METER:int = 30;
     19         private const SWF_WIDTH:int = 800;
     20         private const SWF_HEIGHT:int = 600; 
     21         private const SWF_HALF_WIDTH:int = SWF_WIDTH>>1;
     22         private const SWF_HALF_HEIGHT:int = SWF_HEIGHT>>1;
     23         
     24         private var _world:b2World;
     25         private var _groundDef:b2BodyDef;
     26         private var _groundBody:b2Body;
     27         private var _groundBox:b2PolygonShape;
     28         private var _groundFixtureDef:b2FixtureDef;
     29         private var _debugSprite:Sprite;
     30         private var _debugDraw:b2DebugDraw;
     31         
     32         public function Box2dClass_1()
     33         {
     34             stage.color = 0x333333;
     35             createWorld();
     36             createGround();
     38             createBox(new Point(SWF_HALF_WIDTH, 4), 10, 10, true, 1, 0.3);
     39             createDebug();
     40             stage.addEventListener(Event.ENTER_FRAME, update);
     41         }
     42             
     43         private function createWorld():void
     44         {
     45             _world = new b2World(new b2Vec2(0,10),true );    
     46         }
     47         
     48         private function createDebug():void
     49         {
     50             _debugSprite = new Sprite();
     51             addChild(_debugSprite);
     52             
     53             _debugDraw = new b2DebugDraw();
     54             _debugDraw.SetSprite(_debugSprite);
     55             _debugDraw.SetDrawScale(PIXELS_TO_METER);
     56             _debugDraw.SetLineThickness(1);
     57             _debugDraw.SetAlpha(1);
     58             _debugDraw.SetFillAlpha(0.4);
     59             _debugDraw.SetFlags(b2DebugDraw.e_shapeBit);
     60             _world.SetDebugDraw(_debugDraw);
     61         }
     62         
     63         private function createGround():void
     64         {
     65             _groundDef = new b2BodyDef();
     66             _groundDef.position.Set(SWF_HALF_WIDTH/PIXELS_TO_METER,(SWF_HEIGHT-20)/PIXELS_TO_METER);
     67             _groundDef.type = b2Body.b2_staticBody;
     68             
     69             _groundBody = _world.CreateBody(_groundDef); 
     70             
     71             _groundBox = new b2PolygonShape();
     72             _groundBox.SetAsBox(SWF_HALF_WIDTH/PIXELS_TO_METER,20/PIXELS_TO_METER);
     73             
     74             _groundFixtureDef = new b2FixtureDef();
     75             _groundFixtureDef.shape = _groundBox;
     76             _groundFixtureDef.density = 0;
     77             _groundFixtureDef.friction = 0;
     78             _groundFixtureDef.restitution = 0;
     79             
     80             _groundBody.CreateFixture(_groundFixtureDef);
     81         }
     82         
     83         private function createBox(position:Point,hw:Number,hh:Number,isDynamic:Boolean,density:Number=0,friction:Number=0,restitution:Number=0):void
     84         {
     85             var bodyDef:b2BodyDef = new b2BodyDef();
     86             if( isDynamic )
     87             {
     88                 bodyDef.type = b2Body.b2_dynamicBody;
     89             }
     90             else
     91             {
     92                 bodyDef.type = b2Body.b2_staticBody;
     93             }
     94             bodyDef.position.Set(position.x/PIXELS_TO_METER,position.y/PIXELS_TO_METER);
     95             
     96             var body:b2Body = _world.CreateBody(bodyDef);
     97             
     98             var shape:b2PolygonShape = new b2PolygonShape();
     99             shape.SetAsBox(hw/PIXELS_TO_METER,hh/PIXELS_TO_METER);
    100             
    101             var fixtureDef:b2FixtureDef = new b2FixtureDef();
    102             fixtureDef.shape = shape;
    103             fixtureDef.density = density;
    104             fixtureDef.friction = friction;
    105             fixtureDef.restitution = restitution;
    106             
    107             body.CreateFixture(fixtureDef);
    108             
    109         }
    110         
    111         protected function update(event:Event):void
    112         {
    113             var timeStep:Number = 1 / 30;
    114             var velocityIterations:int = 6;
    115             var positionIterations:int = 2;
    116             
    117             _world.Step(timeStep,velocityIterations,positionIterations);
    118             _world.ClearForces();
    119             _world.DrawDebugData();
    120         }
    121     }
    122 }

    另附上box2d结构图一枚: 

     

  • 相关阅读:
    从零开始学Kotlin-使用接口(7)
    从零开始学Kotlin-类的继承(6)
    从零开始学Kotlin-类和对象(5)
    从零开始学Kotlin-控制语句(4)
    从零开始学Kotlin-操作符(3)
    从零开始学Kotlin-数据类型(2)
    从零开始学Kotlin-基础语法(1)
    Java设计模式之单例模式(七种写法)
    一个简单的可控的头像列表叠加控件
    使用NestedScrollView+ViewPager+RecyclerView+SmartRefreshLayout打造酷炫下拉视差效果并解决各种滑动冲突
  • 原文地址:https://www.cnblogs.com/Memo/p/2712400.html
Copyright © 2011-2022 走看看