近期又弄了物理引擎。寫一下吧,如下有在其它博客學習到的知識。加上本身的理解,總結下。node
cocos2d-x 3.X 中全新的封裝的物理引擎給了開發人員最大的便捷,你不用再繁瑣與各類物理引擎的細節,全然的封裝讓開發人員可以更快更好的將物理引擎的機制加入到本身的遊戲中,簡化的設計是從2.0到3.X的一個質的飛躍。ide
cocos2d-x 3.0+中的物理屬性:函數
一、物理世界被集成到場景中。當你建立一個場景。你可以直接建立基於物理世界或者不使用物理世界的場景。學習
二、Node擁有它本身的body屬性。ui
(sprite也是node)‘this
三、cocos2d-x 3.0 已經封裝了物理屬性Body(PhysicsBody),Shape(PhysicsShape),Contact(PhysicsContact),Joint(PhysicsJoint)和World(PhysicsWorld),更加方便使用。spa
四、方便的使用listener-EventListenerPhysicsContact進行碰撞檢測。.net
固然,封裝好的物理引擎可以簡化開發難度,假設有能力的話也可以直接使用Box2D和Chipmunk的原生的物理引擎進行開發,這樣難度會有所提高。設計
如下的代碼建立一個帶物理世界的場景,並傳遞到場景中的層上。調試
PhysicsLayer.h中
- class PhysicsLayer : public cocos2d::Layer
- {
- ...
-
- void setPhyWorld(PhysicsWorld* world){m_world = world;}
-
- private:
- PhysicsWorld* m_world;
- ...
- }
PhysicsLayer.cpp中的createScene()方法中加入如下代碼:
- Scene* PhysicsLayer::createScene()
- {
- ...
-
- auto scene = Scene::createWithPhysics();
- scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
-
- auto layer = HelloWorld::create();
- layer->setPhyWorld(scene->getPhysicsWorld());
- scene->addChild(layer);
- return scene;
- }
Scene類有一個新的static工廠方法createWithPhysics()建立一個帶物理世界的場景。可以經過getPhysicsWorld()來獲取PhysicsWorld的實例。
上述代碼中凝視爲調試的代碼在調試中很實用,它會顯示遊戲中物體所帶有的物理邊界,便於觀察碰撞中的細節等。
同一時候一個場景中僅僅能有一個物理世界,所有屬於這個場景的子層都共享這一個物理世界。因此在子層中用到物理世界時都會有這個定義的函數
- void setPhyWorld(PhysicsWorld* world){m_world = world;}
進而來設置子層中的物理世界。
PhysicsWorld擁有默認的重力設置,Vector(0.0f,-98.0f),固然你也可以任意設置你想要的重力加速度。setGravity(Vect(0.0f,-200.0f)),設置重力加速度爲20米每二次方秒。
建立物理邊界
如下的代碼建立一個物理邊界,事實上就是作外面的邊界框
- Size visibleSize = Director::getInstance()->getVisibleSize();
- auto body = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3); ,這個Box是不受碰撞檢測的!!!
- auto edgeNode = Node::create();
- edgeNode->setPosition(Point(visibleSize.width/2,visibleSize.height/2));
- edgeNode->setPhysicsBody(body);
- scene->addChild(edgeNode);場景中加入建立的物理節點
PhysicsWorld有很是多工廠方法。如createEdgeBox建立一個矩形的邊框,參數:
一、矩形區域,設置做爲VisibleSize
二、可選參數,物理材料,默以爲PHYSICSBODY_MATERIAL_DEFAULT。
三、可選參數,邊框大小,默以爲1.
建立受重力影響的精靈
如下的代碼建立一個受重力影響的精靈,3.0中的建立精靈代碼也大大簡化
- void HelloWorld::addNewSpriteAtPosition(Point p)
- {
- auto sprite = Sprite::create("circle.png");
- sprite->setTag(1);
- auto body = PhysicsBody::createCircle(sprite->getContentSize().width / 2);
- sprite->setPhysicsBody(body);
- sprite->setPosition(p);
- this->addChild(sprite);
- }
如下講一下真正的重點所在——物理碰撞檢測
上次作《NotOneLess》項目的時候用到了物理引擎。事實上物理引擎的碰撞檢測就是 對 三個掩碼屬性值的設置,來來回回就是設置值得問題,搞懂了這個。物理碰撞學會了80%了
看懂這個吧:
點擊打開連接 http://www.tuicool.com/articles/nAZbuy
如下代碼註冊碰撞響應事件和回調函數
- auto contactListener = EventListenerPhysicsContact::create();
- contactListener->onContactBegin = CC_CALLBACK_1(HelloWorld::onContactBegin, this);
- _eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);
每一次碰撞檢測事件是有EventListenerPhysicsContact來進行監聽的。監聽到碰撞事件時,會回調響應事件onContactBegin()來進行碰撞事件的處理。_eventDispatcher是事件派發器,由它管理所有的註冊事件。
EventListenerPhysicsContact是碰撞檢測中的一種。也可以運用如下的來進行碰撞事件的註冊EventListenerPhysicsContactWithBodies,EventListenerPhysicsContactWithShapes,EventListenerPhysicsContactWithGroup來進行你感興趣的bodys,shape和group事件監聽。
在上面說了這麼多的東西,最重要的東西就是如下的。沒有如下的東西,碰撞事件根本不起做用,這就是我第一次運用碰撞時遇到的問題。也就是設置物理接觸相關的位掩碼值,默認的接觸事件不會被接受,需要設置必定的掩碼值來使接觸事件響應。
接觸掩碼值有三個值。各自是:
一、CategoryBitmask,默認值爲0xFFFFFFFF
二、ContactTestBitmask,默認值爲 0x00000000
三、CollisionBitmask。默認值爲0xFFFFFFFF
這三個掩碼值都有相應的set/get方法來設置和獲取。
一個body的CategoryBitmask和還有一個body的ContactTestBitmask的邏輯與的結果不等於0時。接觸事件將被髮出,不然不發送。
一個body的CategoryBitmask和還有一個body的CollisionBitmask的邏輯與結果不等於0時,他們將碰撞,不然不碰撞
默認狀況下的body屬性會進行物理碰撞。但不會發送碰撞檢測的信號,也就不會響應碰撞回調函數。這個可以看下默認狀況下的掩碼值的邏輯與
- CategoryBitmask = 0xFFFFFFFF;
- ContactTestBitmask = 0x00000000;
- CategoryBitmask & ContactTestBitmask = 0,因此不會發送碰撞信號
-
- CollisionBitmask = 0xFFFFFFFF;
-
- CategoryBitmask & CollisionBitmask = 0xFFFFFFFF
- 因此物體會碰撞,但是不會響應碰撞回調函數。
上面介紹的掩碼值是碰撞檢測回調中最重要的,沒有上面的掩碼值。所有的碰撞回調函數都不會發生。
EventListenerPhysicsContact有四個接觸回調函數:
一、onContactBegin,在接觸開始時被調用,僅調用一次,經過放回true或者false來決定兩個物體是否有碰撞。
同一時候可以使用PhysicsContact::setData()來設置接觸操做的用戶數據。
當返回false時。onContactPreSolve和onContactPostSolve將不會被調用,但是onContactSeperate將被調用一次。
二、onContactPreSlove ,會在每一次被調用。經過放回true或者false來決定兩個物體是否有碰撞,相同可以用ignore()來跳過興許的onContactPreSolve和onContactPostSolve回調函數。(默認返回true)
三、onContactPostSolve,在兩個物體碰撞反應中的每個步驟中被處理調用。可以在裏面作一些興許的接觸操做。如銷燬body
四、onContactSeperate。在兩個物體分開時被調用,在每次接觸時僅僅調用一次,和onContactBegin配對使用。
上述中最重要的就是碰撞檢測事件的解說,這是遊戲中用到碰撞經常要用到的。
好了。這篇解說了遊戲中的物理碰撞機制。