注意:以下内容纯属个人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; }
物体由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 来定义
质量为0的东西 物理引擎不能动他.
//-----------------------------------------------------------------------------------------------------------
4. 来个例子:
a.创建一个 b2World,给世界设定一个重力大小和方向,b2World管理所有模拟的东西
// 创建一个 world b2Vec2 gravity; gravity.Set(0.5, -0.5); world = new b2World(gravity);
墙壁这东西,一般为静态物体,所以直接默认值就可以
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);
球也是个物体,所以创建步骤和 墙壁类似
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了.