前面讲了那么多概念,今天就直接用Box2D引擎来写个例子:
第一步:创建物理世界
//初始化物理引擎
void Box2DTestLayer::initPhysics()
{
CCSize s = CCDirector::sharedDirector()->getWinSize();
//设置重力
b2Vec2 gravity;
gravity.Set(0.0f,-10.0f);
//创建物理世界
world = new b2World(gravity);
//设置是否让物体进入休眠
world->SetAllowSleeping(true);
//设置是否使用连续物理模拟
world->SetContinuousPhysics(true);
//定义边界物体
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));
//创建框架
groundBody->CreateFixture(&groundBox,0);
//上面物体
groundBox.Set(b2Vec2(0,s.height/PTM_RATIO),b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO));
groundBody->CreateFixture(&groundBox,0);
//左侧物体
groundBox.Set(b2Vec2(0,s.height/PTM_RATIO),b2Vec2(0,0));
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);
}
这里创建四个静态的物体,它们在物理世界组成一个矩形矿体,矩形框体的面积,正好是游戏的全部画面。
在已经完成的物理世界的创建后,接下来就是创建物理世界中的物体。Box2DTest项目提供了一种精灵和刚体的混合对象,这样就具备了两个引擎中元素的共同属性:
精灵刚体就是类PhysicsSprite,它是Cocos2dx中类CCSrite的派生
//精灵刚体
class PhysicsSprite:public CCSrite
{
public:
//构造函数
PhysicsSprite();
//设置刚体对象
void setPhysicsBody(b2Body *body);
virtual bool isDirty(void);
virtual CCAffineTransform node ToParentTransform(void);
pritive:
b2Body *m_body;
};
添加精灵刚体的函数
void Box2DTestLayer::addNewSpriteAtPosition(CCPoint p)
{
//输出添加精灵刚体的位置
CCNode *parent = getChildByTag(kTagParentNode);
//随机选择精灵所用的纹理
int idx = (CCRANDOM_0_1() >.5?0:1);
int idy = (CCRANDOM_0_1() >.5?0:1);
//创建一个新的精灵刚体对象
PhysicsSprite *sprite = new PhysicsSprite();
//初始化纹理图片
sprite->initWithTexture(m_pSpriteTexture,CCRectMak(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.postion.Set(p.x/PTM_RATIO,p.y/PTM_RATIO);
//创建物体
b2Body *body = world->CreateBody(&bodyDef);
//定义矩形外形
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(.5f,.5f);
//定义动态物体的框架
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicBox;
fixtureDef.density = 1.0f;
fixtureDef.firction = 0.3f;
//创建框架
body->CreateFixture(&fixtureDef);
//将物体传递给精灵刚体
sprite->setPhysicsBody(body);
}
上述代码可以将一个精灵刚体添加到两个世界当中,在具备了创建精灵刚体的功能后,就剩下最后一部分内容,那就是应该如何来同步两个世界的运转:下面给出其中的一种
//引擎绘制时,将会自动调用。返回值为精灵的位置以及角度变换矩阵
CCAffineTransform PhysicsSprite::node ToParentTransform(void)
{
//获得物理世界中刚体的坐标
b2Vec2 pos = m_pBody->GetPostion();
//将物理世界坐标转换为绘制世界坐标
float x = pox.x *PTM_RATIO;
float y = pox.y *PTM_RATIO;
//获得物体的角度
float radians = m_pBody->GetAngle();
float c = cosf(radians);
float s = sinf(radians);
//创建转换矩阵
m_tTransform = CCAffineTransformMake(c,s,-s,c,x,y);
return m_tTransform;
}
其实,两个世界同步的信息主要是物体和精灵之间的交互,而交互的内容主要是位置和角度。