Box2d---闲时复习

来源:互联网 发布:靓坤与乌鸦知乎 编辑:程序博客网 时间:2024/06/05 14:21

定义重力,新建世界:

b2Vec2 gravity;

gravity.Set(0.0f,-10.0f);

world = new b2World(gravity);

允许刚体休眠和创建地面:

world->SetAllowSleeping(true);

world->SetContinuousPhysics(true);

静态刚体:没有质量,没有速度,只可以手动来改变它的位置。

棱柱刚体:没有质量,但是可以有速度,可以自己更新位置。

动态刚体:有质量,也有速度。

创建刚体步骤:

1)生成一个刚体定义

2)根据刚体定义生成刚体

通常在Box2D引擎中新建一个物体需要经历如下步骤:

1)使用位置和阻尼等参数定义物体

2)使用世界对象创建物体

3)使用几何结构、摩擦和密度等参数定义对象

4)调整物体质量和形状相匹配

定义物体:

b2BodyDef groundBodyDef;

groundBodyDef.position.Set(0,0);

创建物体:

b2Body* groundBody = world->CreateBody(&groundBodyDef);

定义物体边界:

b2EdgeShape groundBox;

groundBox.Set(b2Vec2(0,0),b2Vec2(s.width/PTM_RATIO,0));//bottom

groundBody->CreateFixture(&groundBox,0);

groundBox.Set(b2Vec2(0,s.height/PTM_RATIO),b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO));//top

groundBody->CreateFixture(&groundBox,0);

groundBox.Set(b2Vec2(0,s.height/PTM_RATIO),s.height/PTM_RATIO,b2Vec2(0,0));//left

groundBody->CreateFixture(&groundBox,0);

groundBox.Set(b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO),b2Vec2(s.width/PTM_RATIO,0));

groundBody->CreateFixture(&groundBox,0);

//先定义4条边,最后把他定义到物体中。四条边包围了一个“空心”的世界.setAsBox创建的世界是实心的。

//Box2D采用米、千克、秒作单位。把游戏中像素级的长度单位转换为米就要除以PTM_RATIO(0.1-10m范围较好,32pixel=1m)。

注:和物体定义一样,它只是把数据复制到物体中。这个形状的定义可以重新被利用,定义的形状

必须和物体绑定在一起,形状才有意义。

定义动态刚体:

void Box2DTestLayer::addNewSpriteAtPosition(CCPoint p){

CCLOG("Add sprite %0.2f x %02.f",p.x,p.y);

CCNode* parent = getChildByTag(kTagParentNode);

int idx = (CCRANDOM_0_1() > 0.5?0:1);

int idy = (CCRANDOM_0_1() > 0.5?0:1);

PhysicsSprite* sprite = new PhysicsSprite();

sprite->initWithTexture(m_pSpriteTexture,CCRectMake(32*idx,32*idy,32,32));

sprite->autorelease();

parent->addChild(sprite);

sprite->setPosition(CCPointMake(p.x,p.y));

b2BodyDef bodyDef; //刚体定义

bodyDef.type = b2_dynamicBody;

bodyDef.position.Set(p.x/PTM_RADIO,p.y/PTM_RATIO);

b2Body* body = world->CreateBody(&bodyDef); //生成刚体

b2PolygonShap dynamicBox; //刚体形状

dynamicBox.SetAsBox(.5f,.5f);

b2FixtureDef fixtureDef; //刚体支架

fixtureDef.shap = & dynamicBox;

fixtureDef.density = 1.0f; //密度

fixtureDef.friction = 0.3f; //摩擦

body->CreateFixture(&fixtureDef);

sprite->setPhysicsBody(body);

}

声明物理精灵类:

class PhysicsSprite : public CCSprite{

public:

PhysicsSprite();

void setPhysicsBody(b2Body* body);

virtual bool isDirty(void);

virtual CCAFFineTransform nodeToParentTransform(void);

private:

b2Body* m_pBody;

};

//以上代码用“has-a”将渲染的精灵类和刚体绑定在一个类中,函数中先定义精灵类,然后定义刚体。

接下来需要在初始化方法里调用scheduleUpdate函数模拟出每个时间步更新,并在update函数中进行更新。

Box2D是通过定期调用step函数来更新动画的。

step函数第一个参数是时间步。这里进行了修改,因为dt会不同,所以不建议用dt作为时间步,而要给它

一个固定的时间步才不会显得动画时快时慢。第二个参数是速度迭代次数,建议8次,超过10次的基本看不出

效果的提升。第三个参数是位置迭代,1次就可以。

时间步更新:

void  Box2DTestLayer::update(float dt){

int velocityIterations = 8;

int positionIterations = 1;

world->Step(0.03,velocityIterations,positionIterations);

}

同时,渲染的函数也需要更新,在自己的nodeToParentTransform函数中更新节点位置。

更新节点位置:

CCAffineTransform PhysicsSprite::nodeToParentTransform(void){

b2Vec2 pos = m_pBody->GetPosition();

float x = pos.x * PTM_RATIO;

float y = pos.y * PTM_RATIO;

if(isIgnoreAnchorPointForPosition()){

x+=m_tAnchorPointInPoints.x;

y+=m_tAnchorPointInPoints.y;

}

float radians = m_pBody->GetAngle();

float c = cosf(radians);

float s = sinf(radians);

if(!CCPoint::CCPointEqualToPoint(m_tAnchorPointInPoints,CCPointZero)){

x += c*-m_tAnchorPointInPoints.x + -s*-m_tAnchorPointInPoints.y;

y += s&-m_tAnchorPointInPoints.x + c*-m_tAnchorPointInPoints.y;

}

m_tTransform = CCAffineTransformMake(c,s,-s,c,x,y);

return m_tTransform;

}

删除世界对象:

Box2DTestLayer::~Box2DTestLayer(){

delete world;

world = NULL;

}






0 0