實例介紹Cocos2d-x物理引擎:HelloPhysicsWorld

咱們經過一個實例介紹一下,在Cocos2d-x 3.x中使用物理引擎的開發過程,熟悉這些API的使用。這個實例的運行後的場景,當場景啓動後,玩家能夠觸摸點擊屏幕,每次觸摸時候,就會在觸摸點生成一個新的精靈,精靈的運行是自由落體運動。



html

HelloPhysicsWorld實例微信



使用物理引擎的通常步驟,以下圖所示。

函數



這個過程與上帝建立世界的過程相似,上帝首先建立了世界,而後爲世界指定了邊界,不然萬物就會掉到世界以外的混沌裏去了,最後上帝建立了萬物。
固然這只是一個最基本的步驟,有的時候還須要碰撞檢測和使用關節等處理。下面咱們就按照這個步驟介紹一下代碼部分。首先看一下看HelloWorldScene.h文件,它的代碼以下:網站

[html] view plaincopythis

 

  1. #ifndef __HELLOWORLD_SCENE_H__  spa

  2. #define __HELLOWORLD_SCENE_H__  .net

  3.   

  4.   

  5. #include "cocos2d.h"  調試

  6. USING_NS_CC;  rest

  7.   

  8.   

  9. class HelloWorld : public cocos2d::Layer  orm

  10. {  

  11. public:  

  12.     static cocos2d::Scene* createScene();  

  13.   

  14.   

  15.    

  16.     virtual bool init();    

  17.     virtual bool onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);            ①  

  18.   

  19.   

  20.     CREATE_FUNC(HelloWorld);  

  21.   

  22.   

  23.     void addNewSpriteAtPosition(Vec2 p);                                    ②  

  24. };  

  25.   

  26.   

  27. #endif // __HELLOWORLD_SCENE_H__  



上述第①行代碼是聲明瞭單點觸摸函數onTouchBegan,以便於響應單點觸摸事件。第②行代碼是定義建立精靈函數,這個函數是在觸摸點擊位置建立一個精靈對象。
HelloWorldScene.cpp中建立物理世界,代碼以下:

[html] view plaincopy

 

  1. Scene* HelloWorld::createScene()  

  2. {  

  3.     auto scene = Scene::createWithPhysics();                                    ①  

  4.     scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);      ②  

  5.       

  6.     auto layer = HelloWorld::create();  

  7.   

  8.   

  9.     scene->addChild(layer);  

  10.   

  11.   

  12.     return scene;  

  13.   

  14.   

  15. }  



上述第①行代碼Scene::createWithPhysics()語句是建立場景,這個是帶物理引擎世界場景,使用createWithPhysics()函數會在場景中進行初始化物理引擎,咱們能夠經過場景的getPhysicsWorld()函數獲取初始化的物理世界(PhysicsWorld)對象。咱們也能夠根據須要在這裏設置物理世界,其中第②行代碼設置在物理世界中繪製調試遮罩,這會把物體的形狀繪製出來。由於世界中的物體,若是沒有與精靈綁定到一塊兒,咱們是看不到它的。這主要用於調試,當調試結束後,遊戲發佈的時候,咱們須要把它關閉。關閉繪製調試遮罩的場景以下圖所示。



HelloWorldScene.cpp中指定世界的邊界,代碼以下:

[html] view plaincopy

 

  1. bool HelloWorld::init()  

  2. {  

  3.     if ( !Layer::init() )  

  4.     {  

  5.         return false;  

  6.     }  

  7.       

  8.     Size visibleSize = Director::getInstance()->getVisibleSize();  

  9.     Vec2 origin = Director::getInstance()->getVisibleOrigin();  

  10.   

  11.   

  12.     //定義世界的邊界  

  13.         auto body = PhysicsBody::createEdgeBox(visibleSize,  

  14.                         PHYSICSBODY_MATERIAL_DEFAULT,5.0f);                     ①  

  15.     auto edgeNode = Node::create();                                         ②  

  16.     edgeNode->setPosition(Vec2(visibleSize.width/2,visibleSize.height/2));               ③  

  17.     edgeNode->setPhysicsBody(body);                                      ④  

  18.     this->addChild(edgeNode);                                            ⑤  

  19.   

  20.   

  21.     setTouchEnabled(true);                                              ⑥  

  22.     //設置爲單點觸摸  

  23.     setTouchMode(Touch::DispatchMode::ONE_BY_ONE);                          ⑦  

  24.   

  25.   

  26.     return true;  

  27. }  



上述代碼HelloWorld::init是初始化層函數,在這個函數中咱們能夠指定世界的邊界,世界邊界也是一個物體,代碼第①行PhysicsBody::createEdgeBox是建立物體對象,靜態函數createEdgeBox指定世界邊界是矩形盒子,createEdgeBox函數的第一個參數指定矩形的大小。第二個參數是設置材質,PHYSICSBODY_MATERIAL_DEFAULT常量是默認材質,材質是由結構體PhysicsMaterial定義的,結構體PhysicsMaterial成員有:density(密度)、friction(磨擦係數)和restitution(彈性係數)。密度能夠用來計算物體的質量,密度能夠爲零或者爲正數。摩擦係數常常會設置在0.0~1.0之間,0.0表示沒有摩擦力,1.0會產生強摩擦。彈性係數的值一般設置到0.0~1.0之間,0.0表示物體不會彈起,1.0表示物體會徹底反彈,即稱爲彈性碰撞。createEdgeBox函數的第三個參數是設置邊的寬度。
代碼第②行是建立邊界節點對象,這個節點對象做爲世界邊界對象,第③行代碼是設置節點對象的位置。第④行代碼edgeNode->setPhysicsBody(body)是設置與節點相關的物體對象。經過這條語句使得遊戲場景中的節點對象(精靈等)與物體關聯起來。第⑤行代碼是將節點對象添加到層中。
代碼第⑥行setTouchEnabled(true)是使層開始觸摸事件支持。第⑦行代碼setTouchMode(Touch::DispatchMode::ONE_BY_ONE)是設置觸摸模式爲單點觸摸。
HelloWorldScene.cpp其餘代碼以下:

[html] view plaincopy

 

  1. bool HelloWorld::onTouchBegan(Touch* touch, Event* event)                       ①  

  2. {  

  3.     Vec2 location = touch->getLocation();  

  4.     addNewSpriteAtPosition(location);  

  5.     return false;  

  6. }     

  7.   

  8.   

  9. void HelloWorld::addNewSpriteAtPosition(Vec2 p)                                 ②  

  10. {      

  11.     auto sp = Sprite::create("Ball.png");                                       ③  

  12.     sp->setTag(1);                                                       ④  

  13.       

  14.     auto body = PhysicsBody::createCircle(sp->getContentSize().width / 2);               ⑤  

  15.     //auto body = PhysicsBody::createBox(sp->getContentSize());                      ⑥  

  16.     sp->setPhysicsBody(body);                                            ⑦  

  17.     sp->setPosition(p);                                                    

  18.     this->addChild(sp);  

  19. }  



上述代碼第①行是單點觸摸時候調用的函數,在這個函數中調用addNewSpriteAtPosition(location)函數,在觸摸點建立一個精靈對象。
第②行代碼是定義addNewSpriteAtPosition函數,第③行代碼Sprite::create("Ball.png")是建立一個精靈對象,第④行代碼sp->setTag(1)是設置精靈的tag屬性,在檢查碰撞時候能夠經過tag屬性判斷並得到精靈對象。
第⑤行代碼是經過PhysicsBody的靜態createCircle函數建立圓圈形狀物體。PhysicsBody還有不少相似的create函數,如createBox、createCircle、createPolygon和createEdgePolygon等函數,這些函數與物理形狀對應的。這裏只詳細解釋createCircle函數, createCircle函數API以下:
static PhysicsBody* createCircle(float radius,
const PhysicsMaterial & material = PHYSICSBODY_MATERIAL_DEFAULT,
const Vec2 & offset = Vec2::ZERO 
)
其中第一個參數radius是設置圓圈的半徑,第二參數material是材質,這能夠省略,默認值是PHYSICSBODY_MATERIAL_DEFAULT,因此在HelloWorld::init()函數中定義世界的邊界時候,PhysicsBody::createEdgeBox語句中的material參數也是能夠省略的。第三個參數offset是偏移量,能夠省略,默認值是Vec2::ZERO。

第⑥行代碼PhysicsBody::createBox(sp->getContentSize())是建立一個沒有邊的矩形盒子。第⑦行代碼sp->setPhysicsBody(body)是設置與精靈相關的物體對象。

 

 

 

更多內容請關注國內第一本Cocos2d-x 3.2版本圖書《Cocos2d-x實戰:C++卷》

本書交流討論網站:http://www.cocoagame.net
更多精彩視頻課程請關注智捷課堂Cocos課程:http://v.51work6.com

歡迎加入Cocos2d-x技術討論羣:257760386

 

歡迎關注智捷iOS課堂微信公共平臺

相關文章
相關標籤/搜索