第一步,构建一个物理世界。
b2Vec2 gravity; gravity.Set(0.0f,-10.0f);//物理世界的重力(垂直向下掉落) world = new b2World(gravity,true);//创建世界对象,true参数表示刚体可以进入睡眠模式b2Vec2相当于cocos2d中的CGPoint,用于表示一个点。
看一下b2World的构造函数:
b2World::b2World(const b2Vec2& gravity, bool doSleep) { m_destructionListener = NULL; m_debugDraw = NULL; m_bodyList = NULL;//初始化刚体列表 m_jointList = NULL;//初始化关节列表 m_bodyCount = 0;//世界中刚体的数量 m_jointCount = 0; m_warmStarting = true; m_continuousPhysics = true; m_allowSleep = doSleep;//运动过慢的刚体 是否进入睡眠模式 m_gravity = gravity; m_flags = e_clearForces; m_inv_dt0 = 0.0f; m_contactManager.m_allocator = &m_blockAllocator; }它初始化了数据然后返回一个b2World对象。
到这里,物理世界已经创建完毕了,可是这个世界是没有边界的,也就是说刚体可能会跳出手机屏幕之外。
只要给物理世界加4条边缘就可以了:
b2PolygonShape worldShape; // bottom worldShape.SetAsEdge(b2Vec2(0,0), b2Vec2(screenSize.width/PTM_RATIO,0)); worldBody->CreateFixture(&worldShape,0); // top worldShape.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO)); worldBody->CreateFixture(&worldShape,0); // left worldShape.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(0,0)); worldBody->CreateFixture(&worldShape,0); // right worldShape.SetAsEdge(b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,0)); worldBody->CreateFixture(&worldShape,0);在CreateFixture函数中,通过以下代码把刚体和形状关联到一起:
b2Fixture* b2Body::CreateFixture(const b2FixtureDef* def) { ... fixture->m_body = this; ... }
第二步,向世界中加入刚体:
b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody;//默认是静态刚体 bodyDef.position.Set(touchPoint.x/PTM_RATIO,touchPoint.y/PTM_RATIO); b2Body *body = world->CreateBody(&bodyDef);CreateBody函数就是把bodyDef的内容拷贝到Body里,看看它的实现把:
b2Body* b2World::CreateBody(const b2BodyDef* def) { ... b2Body* b = new (mem) b2Body(def, this); m_bodyList = b;//把刚体保存到刚体列表 ++m_bodyCount; ... }
设置形状、摩擦力、密度:
b2PolygonShape shape; shape.SetAsBox(0.5f,0.5f); b2FixtureDef fixtureDef; fixtureDef.shape = &shape; fixtureDef.density = 1.0f; fixtureDef.friction = 0.3f; body->CreateFixture(&fixtureDef);
在init中加入:
[self scheduleUpdate];然后实现update函数:
- (void)update:(ccTime)dt{ int32 velocityIterations = 8; int32 positionIterations = 1; world->Step(dt, velocityIterations, positionIterations); for (b2Body *b = world->GetBodyList(); b; b = b->GetNext()) { if (b->GetUserData() != NULL) { CCSprite *spr = (CCSprite *)b->GetUserData(); float x = b->GetPosition().x; float y = b->GetPosition().y; spr.position = ccp(x*PTM_RATIO,y*PTM_RATIO); spr.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()); } } }