Cocos2d-x 3.x物理引擎概述(2)


上篇node




碰撞dom

你是否經歷過車禍?是否跟什麼物體相撞過?就像車同樣,物理剛體對象能夠互相接觸。當它們接觸的時候,就發生了碰撞。當碰撞發生時,它能夠被徹底忽略,也能夠引發一系列事件。ide

碰撞篩選函數

碰撞篩選容許你啓用或者阻止形狀之間碰撞的發生。物理引擎支持使用類型、組位掩碼來篩選碰撞。post

Cocos2d-x中支持32種碰撞類型。對於每一個形狀均可以指定其所屬的類型。還能夠指定有哪些類型能夠與這個形狀進行碰撞。這些是經過掩碼來完成的。例如this

autospa

 sprite1 = addSpriteAtPosition(Vec2(s_centre.x - 150,s_centre.y));orm

sprite1->getPhysicsBody()->setCategoryBitmask(0x02);// 0010對象

sprite1->getPhysicsBody()->setCollisionBitmask(0x01);  // 0001blog

 

sprite1

 = addSpriteAtPosition(Vec2(s_centre.x - 150,s_centre.y + 100));

sprite1->getPhysicsBody()->setCategoryBitmask(0x02);// 0010

sprite1->getPhysicsBody()->setCollisionBitmask(0x01);  //

 0001

 

auto

 sprite2 = addSpriteAtPosition(Vec2(s_centre.x + 150,s_centre.y),1);

sprite2->getPhysicsBody()->setCategoryBitmask(0x01);// 0001

sprite2->getPhysicsBody()->setCollisionBitmask(0x02);  // 0010

 

auto

 sprite3 = addSpriteAtPosition(Vec2(s_centre.x + 150,s_centre.y + 100),2);

sprite3->getPhysicsBody()->setCategoryBitmask(0x03);// 0011

sprite3->getPhysicsBody()->setCollisionBitmask(0x03);  // 0011

能夠經過檢測、類型比較和碰撞掩碼,來肯定碰撞的發生:

if((shapeA->getCategoryBitmask() & shapeB->getCollisionBitmask()) == 0 || (shapeB->getCategoryBitmask() & shapeA->getCollisionBitmask()) == 0)

{

   //

 shapes can't collide

   ret

 = false;

}


碰撞組容許你指定一個綜合組的索引。你可讓具備同一組之索引的形狀全都一直碰撞(正索引)或者永不碰撞(負索引或零索引)。組指數不一樣的形狀間進行的碰撞,能夠根據類型和掩碼來進行篩選。換句話說,組篩選比類型篩選的優先級更高。

鏈接/關節

還記得以前的術語嗎?關節是一種把接觸點聯結在一塊兒的方式。沒錯,你能夠把它類比爲本身身體上的關節。每個關節都有一個從PhysicsJoint對象得到的定義。在兩個不一樣的剛體之間,全部的關節都是聯結在一塊兒的。剛體能夠是靜態的。你可使用joint->setCollisionEnable(false)來避免相關聯的剛體相互碰撞。不少關節的定義須要你提供一些幾何數據。不少狀況下,關節由錨點來定義。其他的關節定義數據取決於關節的類型。

  • PhysicsJointFixed:固定關節在一個特定的點上,將兩個剛體結合在了一塊兒。若是要建立一些之後會斷裂的複雜形狀,固定關節是很是有用的。

  • PhysicsJointLimit:一種限制關節,它利用了兩個剛體間最大距離,就如同兩個剛體被繩子連在一塊兒同樣。

  • PhysicsJointPin:針式關節可讓兩個剛體獨立地圍繞錨點進行旋轉,就如同它們被釘在一塊兒了同樣。

  • PhysicsJointDistance:設定兩個剛體間的固定距離。

  • PhysicsJointSpring:用彈簧來聯結兩個物理剛體

  • PhysicsJointGroove:將一個剛體連到線上,另外一個連到點上。

  • PhysicsJointRotarySpring:與彈簧關節類似,可是增長了自旋

  • PhysicsJointRotaryLimit:與限制關節類似,可是增長了自旋

  • PhysicsJointRatchet:與套筒扳手的工做相似

  • PhysicsJointGear:使一對剛體的角速度比率保持是一個常數。

  • PhysicsJointMotor:使一對剛體的相對角速度保持是一個常數。 


碰撞檢測

碰撞(Contacts)是一種由物理引擎建立的用以管理兩個形狀間碰撞的對象。Contact對象會自動建立,而非由用戶建立。這裏有幾個與之相關聯的術語。

  • contact point:contact point是兩個形狀相接觸的那個點。

  • contact normal:contact normal指的是從一個形狀指向另外一個形狀的單位向量。

你能夠從一個碰撞中獲取PhysicsShape。從中,你能夠獲取剛體。

boolonContactBegin(PhysicsContact& contact)

{

    auto

 bodyA = contact.getShapeA()->getBody();

    auto

 bodyB = contact.getShapeB()->getBody();

    returntrue;

}

你能夠經過使用contact listener來訪問碰撞。contact listener支持多種事件:begin,pre-solve,post-solve,以及separate

  • begin:在這一步驟中,兩個形狀剛剛開始接觸。從回調函數中返回true,可使碰撞正常發生,若返回false,則物理引擎會將碰撞整個忽略掉。若是返回false值,preSolve()postSolve()回調函數會被禁止運行,不過當兩個形狀中止重疊時,你仍然能夠收到一個單獨的事件。

  • pre-solve:在這一步驟中,兩個形狀接觸在一塊兒。若是在回調函數中返回false值,則物理引擎會忽略掉這次碰撞;若返回true,碰撞則會正常進行。此外,你可使用setRestitution()setSurfaceVelocity()函數來忽略碰撞值,這樣就能夠提供自定義的恢復係數、摩擦係數和表面速度值。

  • post-solve:兩個形狀相接觸,而它們之間的碰撞已被處理。

  • separate:在這一步驟中,兩個形狀剛剛中止接觸。

也可使用EventListenerPhysicsContactWithBodies,EventListenerPhysicsContactWithShapes,EventListenerPhysicsContactWithGroup來監聽你感興趣的剛體、形狀和組的一些事件。除此以外,你還須要設定與物理接觸相關的掩碼,由於就算你建立了相關的EventListener,碰撞事件仍是不會在默認狀態下被接收。

例如:



boolinit()

{

    //create

 a static PhysicsBody

    auto

 sprite = addSpriteAtPosition(s_centre,1);

    sprite->setTag(10);

    sprite->getPhysicsBody()->setContactTestBitmask(0xFFFFFFFF);

    sprite->getPhysicsBody()->setDynamic(false);

 

    //adds

 contact event listener

    auto

 contactListener = EventListenerPhysicsContact::create();

    contactListener->onContactBegin

 = CC_CALLBACK_1(PhysicsDemoCollisionProcessing::onContactBegin, this);

    _eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener,this);

 

        schedule(CC_SCHEDULE_SELECTOR(PhysicsDemoCollisionProcessing::tick),

 0.3f);

    returntrue;

 

returnfalse;

}

 

voidtick(floatdt)

{

    auto

 sprite1 = addSpriteAtPosition(Vec2(s_centre.x + cocos2d::random(-300,300),

  s_centre.y

 + cocos2d::random(-300,300)));

    auto

 physicsBody = sprite1->getPhysicsBody();

    physicsBody->setVelocity(Vec2(cocos2d::random(-500,500),cocos2d::random(-500,500)));

    physicsBody->setContactTestBitmask(0xFFFFFFFF);

}

 

boolonContactBegin(PhysicsContact& contact)

{

    auto

 nodeA = contact.getShapeA()->getBody()->getNode();

    auto

 nodeB = contact.getShapeB()->getBody()->getNode();

 

    if(nodeA && nodeB)

    {

        if(nodeA->getTag() == 10)

        {

            nodeB->removeFromParentAndCleanup(true);

        }

        elseif (nodeB->getTag() == 10)

        {

            nodeA->removeFromParentAndCleanup(true);

        }

    }

 

    //bodies

 can collide

    returntrue;

}

查詢

你有沒有過站在一個地方往四周看的經歷?你能看到離你近的東西,也能看到離你遠的東西。你能判斷出它們離你有多遠。物理引擎提供相似的空間查詢功能。PhysicsWorld對象目前支持的查詢包括點查詢、射線查詢和矩形查詢。

點查詢

當你碰到什麼東西,好比說你的桌子的時候,你能夠將此認爲是一個點查詢的例子。這使你可以檢查在一個點周圍的必定距離內是否有形狀存在。對於鼠標拾取和簡單的傳感器來講,點查詢是很是有用的。你還能夠找到在一個形狀上離某定點最近的點,或者找到離某個點最近的形狀。

射線查詢

當你四處看的時候,在你視線內的某些物體確定會引發你的注意。像這樣的時候,你基本上就算是執行了一次射線查詢。你不停地掃描,直到有什麼有趣的東西讓你停下來。你可使用對某個形狀使用射線查詢來獲取第一個交叉點。例如:

void tick(float dt)

{

    Vec2

 d(300 * cosf(_angle), 300 * sinf(_angle));

    Vec2

 point2 = s_centre + d;

    if(_drawNode)

    {

        removeChild(_drawNode);

    }

    _drawNode

 = DrawNode::create();

 

    Vec2

 points[5];

    intnum = 0;

    auto

 func = [&points, &num](PhysicsWorld& world,

    constPhysicsRayCastInfo& info, void*

 data)->bool

    {

        if(num < 5)

        {

            points[num++]

 = info.contact;

        }

        returntrue;

    };

 

    s_currScene->getPhysicsWorld()->rayCast(func,

 s_centre, point2, nullptr);

 

    _drawNode->drawSegment(s_centre,

 point2, 1, Color4F::RED);

    for(inti = 0; i < num; ++i)

    {

        _drawNode->drawDot(points[i],

 3, Color4F(1.0f, 1.0f, 1.0f, 1.0f));

    }

    addChild(_drawNode);

 

    _angle

 += 1.5f * (float)M_PI

 / 180.0f;

}

矩形查詢

矩形查詢提供了一個大體檢查區域中存在的形狀的一種快捷方式。它很是容易實現:

auto

 func = [](PhysicsWorld& world, PhysicsShape& shape, void*

 userData)->bool

{

    //Return

 true from the callback to continue rect queries

    returntrue;

}

 

scene->getPhysicsWorld()->queryRect(func,

 Rect(0,0,200,200), nullptr);

A few examples of using a Rect query while doing a logo smash:

這裏是在製做撞擊logo時使用矩形查詢的幾個例子:  

禁用物理引擎

使用內置的物理引擎是個不錯的想法。它又穩定又強大。然而,有時候你會想要使用一些其餘的物理引擎。這時候你只須要在base/ccConfig.h中把CC_USE_PHYSICS禁用就行了。



上篇

相關文章
相關標籤/搜索