cocos2dx Box2d 学习

注意:以下内容纯属个人YY,切勿当真

1.  box2d就是用来模拟现实的,为了限制模拟的范围,所以需要来个容器限制范围,所有有了 b2World,为了模拟现实中的重力,b2World可以设置重力和方向

     为了能将现实世界的计算公式放到这个 虚拟的世界中,所以需要将屏幕里面的坐标转换为现实世界中的单位

    

 2. 现实世界中的物体在世界坐标系中都有形状 大小 位置 角度  速度  摩擦力 质量 等属性.还有的东西不能进行移动,为了模拟这些东西

    box 将这些物体分为 3种类型:

   

/// The body type.
/// static: zero mass, zero velocity, may be manually moved
/// kinematic: zero mass, non-zero velocity set by user, moved by solver
/// dynamic: positive mass, non-zero velocity determined by forces, moved by solver
enum b2BodyType
{
    b2_staticBody = 0,
    b2_kinematicBody,
    b2_dynamicBody

    // TODO_ERIN
    //b2_bulletBody,
};

由于物体的形状和碰撞息息相关,不同的形状之前的碰撞都不一样,所以为了模拟这个,box2d里面定义了一些形状

这些形状为   b2ChainShape,b2CircleShape,b2EdgeShape,b2PolygonShape,

这些类都继承自 b2Shape,所以在创建物体的时候,一定要给物体定义一个形状。


3. 所以对于物体来讲,就要有  物体的类型、物体的形状、物体的物理属性(质量,密度,摩擦力)

在box2d中,表示物体基本类型定义的类为: b2BodyDef,看下其构造函数初始化了哪些东西:

    /// This constructor sets the body definition default values.
    b2BodyDef()
    {
        userData = NULL;
        position.Set(0.0f, 0.0f);
        angle = 0.0f;
        linearVelocity.Set(0.0f, 0.0f);
        angularVelocity = 0.0f;
        linearDamping = 0.0f;
        angularDamping = 0.0f;
        allowSleep = true;
        awake = true;
        fixedRotation = false;
        bullet = false;
        type = b2_staticBody;
        active = true;
        gravityScale = 1.0f;
    }

有了 b2BodyDef 这个物体类型的东西,我们就可以创建一个基本的对象了。

物体由b2World来创建:

    /// Create a rigid body given a definition. No reference to the definition
    /// is retained.
    /// @warning This function is locked during callbacks.
    b2Body* CreateBody(const b2BodyDef* def);

这样就创建了个物体。但是如何设置这物体的形状,和物理属性呢?

b2Body提供了一些方法:

    /// Creates a fixture and attach it to this body. Use this function if you need
    /// to set some fixture parameters, like friction. Otherwise you can create the
    /// fixture directly from a shape.
    /// If the density is non-zero, this function automatically updates the mass of the body.
    /// Contacts are not created until the next time step.
    /// @param def the fixture definition.
    /// @warning This function is locked during callbacks.
    b2Fixture* CreateFixture(const b2FixtureDef* def);

    /// Creates a fixture from a shape and attach it to this body.
    /// This is a convenience function. Use b2FixtureDef if you need to set parameters
    /// like friction, restitution, user data, or filtering.
    /// If the density is non-zero, this function automatically updates the mass of the body.
    /// @param shape the shape to be cloned.
    /// @param density the shape density (set to zero for static bodies).
    /// @warning This function is locked during callbacks.
    b2Fixture* CreateFixture(const b2Shape* shape, float32 density);


通过这方法,就能给物体设置其  外观,和物理属性.

外观就是 b2Shape,物理属性就由 b2FixtureDef 来定义


3. box2d里面一些设定 

   质量为0的东西 物理引擎不能动他.



//-----------------------------------------------------------------------------------------------------------

4. 来个例子:

a.创建一个 b2World,给世界设定一个重力大小和方向,b2World管理所有模拟的东西

    // 创建一个 world
    b2Vec2 gravity;
    gravity.Set(0.5, -0.5);
    world = new b2World(gravity);

b.把手机屏幕四周设置为"墙壁",

       墙壁这东西,一般为静态物体,所以直接默认值就可以

b2BodyDef groundBodyDef;
      创建墙壁

b2Body* groundBody = world->CreateBody(&groundBodyDef);
     给这墙壁一个形状,让墙壁进行碰撞,然后再把这样的外观作用到物体上,由于有4个墙壁,所以作用4次

    // Define the ground box shape.
    b2EdgeShape groundBox;
    
    // bottom
    groundBox.Set(b2Vec2(VisibleRect::leftBottom().x/PTM_RATIO,VisibleRect::leftBottom().y/PTM_RATIO), b2Vec2(VisibleRect::rightBottom().x/PTM_RATIO,(VisibleRect::rightBottom().y)/PTM_RATIO));
    groundBody->CreateFixture(&groundBox,0);
    
    // top
    groundBox.Set(b2Vec2(VisibleRect::leftTop().x/PTM_RATIO,VisibleRect::leftTop().y/PTM_RATIO), b2Vec2(VisibleRect::rightTop().x/PTM_RATIO,VisibleRect::rightTop().y/PTM_RATIO));
    groundBody->CreateFixture(&groundBox,0);
    
    // left
    groundBox.Set(b2Vec2(VisibleRect::leftTop().x/PTM_RATIO,VisibleRect::leftTop().y/PTM_RATIO), b2Vec2(VisibleRect::leftBottom().x/PTM_RATIO,VisibleRect::leftBottom().y/PTM_RATIO));
    groundBody->CreateFixture(&groundBox,0);
    
    // right
    groundBox.Set(b2Vec2(VisibleRect::rightBottom().x/PTM_RATIO,VisibleRect::rightBottom().y/PTM_RATIO), b2Vec2(VisibleRect::rightTop().x/PTM_RATIO,VisibleRect::rightTop().y/PTM_RATIO));
    groundBody->CreateFixture(&groundBox,0);

c. 添加一个球

    球也是个物体,所以创建步骤和 墙壁类似

    1.先来个b2BodyDef,为了让其能模拟,设置为 b2_dynamicBody 类型

    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
     2. 创建球
b2Body *body = world->CreateBody(&bodyDef);
     3. 给球加上外观,并且设置半径
    b2CircleShape dynamicCircle;
    dynamicCircle.m_radius = 22.0/PTM_RATIO;
     4.定义这个球的物理属性 ,并作用在球上
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &dynamicCircle;
    fixtureDef.density = 1.0f;
    fixtureDef.friction = 0.3f;
    body->CreateFixture(&fixtureDef);
     5.cocos2dx 定义个 CCPhysicsSprite 类,能让我们用一个sprite 和 这个 球关联起来
    CCPhysicsSprite* sprite = CCPhysicsSprite::create("ball_2.png");
    sprite->setB2Body(body);
    sprite->setPTMRatio(PTM_RATIO);
    sprite->setPosition(point);
    addChild(sprite);
          注意,创建了 CCPhysicsSprite后,一定先调用setB2Body(xxx)方法

          并且还要设置PTM_RATIO,这个就是将  屏幕里面的坐标转换为现实世界中的单位的比例

         例如:PTM_RATIO = 32, 则表示 32 个像素为1米 

    6. 进行模型,在游戏循环中调用 world的Step方法

void HelloWorld::update(float dt)
{
    int velocityIterations = 8;
    int positionIterations = 1;
    
    world->Step(0.03,velocityIterations,positionIterations);
}
 看看 b2World的Step方法说明
    /// Take a time step. This performs collision detection, integration,
    /// and constraint solution.
    /// @param timeStep the amount of time to simulate, this should not vary.
    /// @param velocityIterations for the velocity constraint solver.
    /// @param positionIterations for the position constraint solver.
    void Step(    float32 timeStep,
                int32 velocityIterations,
                int32 positionIterations);
那个速度迭代次数和物理迭代次数就按推荐的来就ok了.

       



     

  





        

你可能感兴趣的:(cocos2dx Box2d 学习)