cocos2dx之Box2D

_Proxy發表於2020-04-07
Box2D是與Cocos2d-x一起釋出的一套開源物理引擎,也是Cocos2d-x遊戲需要使用物理引擎時的首選。二者同樣提供C++開發介面,所使用的座標系也一致,因此Box2D與Cocos2d-x幾乎可以做到無縫對接。

Box2D是一套基於剛體模擬的物理引擎,它的核心概念為世界、物體、形狀、約束和關節.


void MyBox2DLayer::initLayer() {
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    this->setTouchEnabled(true);
    this->setAccelerometerEnabled(true);// 設定加速鍵
    /*
    *Init the box2d physics
    */
    initPhysics();
    //
    CCSpriteBatchNode *batch = CCSpriteBatchNode::create("Images/ball-hd.png", 100);
    m_SpriteNode = batch->getTexture();

    this->addChild(batch, 0, KSPRITE_BATCH);
    addAnNewSprite(ccp(size.width / 2.0f, size.height / 2.0f));

    scheduleUpdate();// update the time,時刻更新物體狀態
}

void MyBox2DLayer::initPhysics() {
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    b2Vec2 gravity;// step: 1

    /*
    |^(y) gravity ,if the second param is negative number that the sprite is running down(y is decreasing)or is running up(y is increasing)
    |
    |
    |
    |
    |________________________________________________________>(x)
    (0, 0)
    */

    gravity.Set(0.0f, -10.0f); // direction of the sprite runs,base on the GL position,
    world = new b2World(gravity);

    //step: 2
    world->SetAllowSleeping(true); // pause all ,init the box2d world
    world->SetContinuousPhysics(true); // resume the box2d

    //step: 3, defint the body
    b2BodyDef groundbody;
    groundbody.position.Set(0, 0);
    b2Body *body = world->CreateBody(&groundbody);

    //step: 3, define the edge
    // define the 4 edges
    b2EdgeShape edgeBox;
    edgeBox.Set(b2Vec2(0, size.height / PTM_RATIO), b2Vec2(0, 0));
    body->CreateFixture(&edgeBox, 0);

    edgeBox.Set(b2Vec2(0, 0), b2Vec2(size.width / PTM_RATIO, 0));
    body->CreateFixture(&edgeBox, 0);
 
    edgeBox.Set(b2Vec2(0, size.height / PTM_RATIO), b2Vec2(size.width / PTM_RATIO, size.height / PTM_RATIO));
    body->CreateFixture(&edgeBox, 0);

    edgeBox.Set(b2Vec2(size.width / PTM_RATIO, size.height / PTM_RATIO), b2Vec2(size.width / PTM_RATIO, 0));
    body->CreateFixture(&edgeBox, 0);
    
}

void MyBox2DLayer::addAnNewSprite(const CCPoint &point) {
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    CCNode* parent = getChildByTag(KSPRITE_BATCH);
    sprite = new MyBox2DSprite;
    sprite->initWithTexture(m_SpriteNode);
    sprite->setAnchorPoint(ccp(0.5f, 0.5f));
    sprite->setPosition(point);
    parent->addChild(sprite, 1);
    sprite->retain();    

    //
    b2BodyDef bodydef;
    bodydef.type = b2_dynamicBody; // set the kind of the sprite
    bodydef.position.Set(point.x / PTM_RATIO, point.y / PTM_RATIO);

    //body
    b2Body *body = world->CreateBody(&bodydef);
    
    //shape
    b2PolygonShape dynamicShape;
    dynamicShape.SetAsBox(.5f, .5f);
    
    b2FixtureDef fixtureDef;//set the 精靈新增夾具
    fixtureDef.shape = &dynamicShape;    
    fixtureDef.density = 1.0f;
    fixtureDef.friction = 0.3f;
    fixtureDef.restitution = 0.8f;
    
    //set bodydef values;
    body->CreateFixture(&fixtureDef);

    sprite->setPhysicsBody(body);
}

void MyBox2DLayer::update(float dt) {
    int velocityIterations = 1;
    int positionIterations = 1;

    world->Step(dt, velocityIterations, positionIterations);
}

//物體

MyBox2DSprite::MyBox2DSprite() {

}

void MyBox2DSprite::setPhysicsBody(b2Body * body) {
    m_pBody = body;
}

bool MyBox2DSprite::isDirty(void) {
    return true;
}

CCAffineTransform MyBox2DSprite::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;
    }

    // Make matrix
    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;
    }

    // Rot, Translate Matrix
    m_tTransform = CCAffineTransformMake( c,  s,
        -s,    c,
        x,    y );

    return m_tTransform;
}




相關文章