当前位置:编程学习 > wap >>

cocos2d-x学习笔记(20)-- box2d入门

cocos2d-x学习笔记(20)-- box2d入门
        在看本次的文章前,最好先看我写的box2d物理引擎自学笔记整理1做做一些准备工作,以便更好地理解代码。
step1:创建coco2d-win32工程,注意在创建时记得勾上Box2D选项,命名为box2d;
step2:在HelloWorldScene.h中添加如下类:
[plain]
class Box2DTest:public CCLayer 

protected: 
    b2World* m_world; 
 
public: 
    Box2DTest(); 
    ~Box2DTest(); 
 
    void addSprite(CCPoint point); 
    void update(ccTime dt); 
}; 
step3:在HelloWorldScene.cpp中添加下面的代码:
const int tagSprite = 1;
#define PTM_RATIO 32
[plain] 
/************************************************************************/ 
/* Box2DTest                                                                     */ 
/************************************************************************/ 
Box2DTest::Box2DTest() 

    setIsTouchEnabled(true); 
    setIsAccelerometerEnabled(true);//设置加速 
 
    CCSize size = CCDirector::sharedDirector()->getWinSize(); 
 
    b2Vec2 gravity(0.0f, -10.0f); 
    bool doSleep = true; 
 
    m_world = new b2World(gravity); 
    m_world->SetAllowSleeping(doSleep); 
    m_world->SetContinuousPhysics(true); 
 
    //定义地表物体 
    b2BodyDef groundBodyDef; 
     
    b2Body* groundBody = m_world->CreateBody(&groundBodyDef); 
    b2PolygonShape groundBox; 
 
    //墙底 
    groundBox.SetAsBox(size.width / PTM_RATIO, 0, b2Vec2(0,0), 0); 
    groundBody->CreateFixture(&groundBox, 0); 
 
    //墙顶 
    groundBox.SetAsBox(size.width / PTM_RATIO, 0, b2Vec2(0,size.height/PTM_RATIO), 0); 
    groundBody->CreateFixture(&groundBox, 0); 
 
    //左墙 
    groundBox.SetAsBox(0, size.height / PTM_RATIO, b2Vec2(0,0), 0); 
    groundBody->CreateFixture(&groundBox, 0); 
 
    //右墙 
    groundBox.SetAsBox(0,  size.height / PTM_RATIO, b2Vec2(size.width/PTM_RATIO,0), 0); 
    groundBody->CreateFixture(&groundBox, 0); 
 
    CCSpriteBatchNode* brick = CCSpriteBatchNode::batchNodeWithFile("brick.png"); 
    addChild(brick, 2, tagSprite); 
 
    addSprite(ccp(size.width / 2, size.height / 2)); 
 
    scheduleUpdate(); 

[plain]
Box2DTest::~Box2DTest() 

 delete m_world; 
 m_world = NULL; 

首先是创建世界对象并设置重力场。
接着是想世界对象添加地表物体,这里地表物体是一个空心的四边形,相当于四幅墙壁,由于地表物体是静态物体,故groundBody->CreateFixture()第二个参数密度设置为0;
在构造函数里调用scheduleUpdate()函数用于模拟时间更新,并在update中实现更新。
在box2d中,通过不停调用step来更新画面。
[plain] 
void Box2DTest::addSprite(CCPoint point) 

    CCSpriteBatchNode* batch = (CCSpriteBatchNode*)getChildByTag(tagSprite); 
 
    CCSprite *sprite = CCSprite::spriteWithTexture(batch->getTexture(), CCRectMake(0,0,32,32)); 
    batch->addChild(sprite); 
 
    sprite->setPosition(ccp(point.x, point.y)); 
 
    //创建动态物体 
    b2BodyDef bodyDef; 
    bodyDef.type = b2_dynamicBody; 
    bodyDef.position.Set(point.x / PTM_RATIO, point.y/ PTM_RATIO); 
    bodyDef.userData = sprite; 
    b2Body * body = m_world->CreateBody(&bodyDef); 
 
    b2PolygonShape dynamicBox; 
    dynamicBox.SetAsBox(0.5f, 0.5f); 
 
    b2FixtureDef fixtureDef; 
    fixtureDef.shape = &dynamicBox; 
    fixtureDef.friction = 0.3f; 
    fixtureDef.density = 1.0; 
    body->CreateFixture(&fixtureDef); 
 

在这里要说说box2d中的单位,由于box2d中使用的是米作为长度单位。但在编程中,我们使用的图片都是使用像素作为基本单位。
为此,我总结了一个原则:凡是要向世界对象中添加物体的,都需要将像素单位转化为米单位。凡是要将世界对象中的物体显示在屏幕上时,要将物体的米单位转化为像素单位。
[plain]
b2BodyDef bodyDef; 
    bodyDef.type = b2_dynamicBody; 
    bodyDef.position.Set(point.x / PTM_RATIO, point.y/ PTM_RATIO); 
    bodyDef.userData = sprite; 
[plain] view plaincopy
//将sprite精灵和物体对象绑定 
[plain] 
b2Body * body = m_world->CreateBody(&bodyDef); 

这里由于我们需要向世界对象中添加一个动态物体,则按照我说的原则凡是入世界对象的就需要转为为米单位,这里我是使用了32像素为1米(见PTM_RATIO定义)。
[plain]
b2PolygonShape dynamicBox; 
    dynamicBox.SetAsBox(0.5f, 0.5f); 
还有这里,由于SetAsBox设置的是实际距离的一般,那么实际的长度和宽度是1米和1米,即相当于32像素长和32像素宽,正好是我使用的图片大小。

[plain]
for(b2Body* b = m_world->GetBodyList(); b; b = b->GetNext()) 

    if(b->GetUserData() != NULL) 
    { 
        CCSprite* sprite = (CCSprite*)b->GetUserData(); 
        sprite->setPosition(ccp(b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO));  
    } 

这段代码首先是便利世界对象中的所有物体对象,然后将物体对象显示在屏幕上。注意,由于这里我们是将世界对象中的物体显示在屏幕中,故需要将米单位转为为像素单位。
[plain]
void Box2DTest::update(ccTime dt) 

 
    int velocityIterations = 8; 
    int positionIterations = 1; 
 
    //每次游戏循环你都应该调用b2World::Step 
    m_world->Step(dt, velocityIterations, positionIterations); 
 
     
    for(b2Body* b = m_world->GetBodyList(); b; b = b->GetNext()) 
    { 
        if(b->GetUserData() != NULL) 
 

补充:移动开发 , 其他 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,