(三)cocos2dx-碰撞檢測

cocos2d 作爲遊戲引擎,提供了基本的模擬現實物理世界中的一些屬性,比如物體有摩擦力,重力,加速度,角速度等等

這裏簡單介紹一下cocos2dx 物理世界裏面的碰撞檢測

啓用physicsWorld

Scene* HelloWorld::createScene()
{
    // 'scene' is an autorelease object
    //auto scene = Scene::create();
	// 創建帶物理特性的場景
	auto  scene = Scene::createWithPhysics();
	scene->getPhysicsWorld()->setGravity(Vec2(0, 0));// 設置重力,是x,y 方向合成的,比如 x=0,y=-980,則是豎直向下的
	//scene->getPhysicsWorld()->setAutoStep(false);//這個是爲了避免物體間接觸,不定時的發生跳動的情況,但是有些電腦上不加也不會出現問題
	//scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);// 這個是爲了方便開發時調試,將所有body的邊框顯示出來
    // 'layer' is an autorelease object
    auto layer = HelloWorld::create();


    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

如何給基本的sprite 加上物理屬性

通過.setPhysicsBody() 方法給sprite 增加一個body,所有的物理屬性都體現在這個body裏面

示例代碼:

以下代碼演示了給bigPlane 對象設置上密度爲1,彈力系數爲0,摩擦係數爲0的物理屬性

#define PHYSICS_MATERIAL2  PhysicsMaterial(1,0,0)// 這裏是定義了全局的物理材質對象,三個參數依次代表  密度,彈力系數,摩擦係數
auto  bigPlane = rootNode->getChildByName("bigEnemy");
auto bigBody = PhysicsBody::createBox(bigPlane->getContentSize(), PHYSICS_MATERIAL2);
bigPlane->setPhysicsBody(bigBody);

body 的類型: 一般使用 Box就夠了,因爲這個形狀在關閉
setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL) 之後是肉眼看不見的

    PhysicsShape:物理形狀的基類
    PhysicsShapeCircle:實心的圓形,無法用它實現一個空心圓
    PhysicsShapePolygon:實心且外凸的多邊形
    PhysicsShapeBox:矩形,它是一種特殊的外凸多邊形
    PhysicsShapeEdgeSegment:表示一種線段.
    PhysicsShapeEdgePolygon:空心多邊形,由多個線段構成的多邊形邊緣。
    PhysicsShapeEdgeBox:空心矩形,由四個線段組成的矩形邊緣
    PhysicsShapeEdgeChain: 鍊形,它可以有效的把許多邊緣連接起來

physicsBody 的常用方法:

  • [1] .setDynamic(bool) :設置body是否可以移動,如果是false,就是固定在某一個位置
  • [2 ] .setContactTestBitMask(int):設置接觸掩碼 // 默認值爲 0
  • [3 ] .setCollisonBitMask(int); 設置碰撞掩碼// 默認值爲 0xffffffff,
  • [4 ] .setCategoryBitMask(int):設置分類掩碼,定義該body所屬分類// 默認值同上

是否允許穿透

**場景:**物體A與物體B 相撞,如果想讓A能夠穿過B
則需要滿足條件:
bodyA 的 的CollisonBitMask 與bodyB的CategoryBitMask 按位與結果爲0,則表示A可以穿過B
否則不能穿過
示例代碼:

// 允許小敵機穿過大敵機
		smallBody->setCollisionBitmask(1);// 二進制也就是 001
		bigBody->setCategoryBitmask(2);//    二進制也就是 010 ,位與結果爲0,表示可以穿過
		

注意: 這不是對稱的 ,如果A能穿過B 並不能代表B也能穿過A
B能否穿過A,則取決於B的碰撞掩碼A的分類掩碼位與是否爲0來決定

監聽接觸事件發生

場景:

  1. 當物體A與物體B 剛發生接觸,觸發一個事件處理(Begin)
  2. 當物體A與物體B 接觸在一起時,觸發一個事件處理(pre-solve)
  3. 當物體A與物體B接觸,並且碰撞已經被處理(post-solve)
  4. 兩個物體剛剛脫離接觸,觸發一個事件處理(separate)

上訴四種情形,cocos 的 EventListenerPhysicsContact 類已經考慮到了,我們需要做的則是
將A 和B 的對應的body 的 接觸掩碼(ContactTestBitMask) 設置一下,如果按位與爲結果不爲0則A.B 物體接觸時,會觸發這個監聽器,執行相關的處理
示例代碼:

       smallBody->setContactTestBitmask(1);
		heroBody->setContactTestBitmask(3);
	// 註冊監聽事件
	EventListenerPhysicsContact * hitListener = EventListenerPhysicsContact::create();
		hitListener->onContactBegin = [=](PhysicsContact & contact) {
		// 通過contact 獲取發生接觸的兩個node
			auto nodeA = contact.getShapeA()->getBody()->getNode();
			auto nodeB = contact.getShapeB()->getBody()->getNode();
			if (nodeA && nodeB) {
				auto node = nodeA;	
			 if (nodeB->getTag() == 40) {
					 node = nodeB;
				}
				 node->getPhysicsBody()->setVelocity(Vec2(0, 0));
					 // doSth,比如增加爆炸效果
			}
			return true;
		};
		Director::getInstance()->getEventDispatcher()
				->addEventListenerWithSceneGraphPriority(hitListener, this);	

注意:

  1. 碰撞檢測這裏的掩碼都是設置自己的接觸掩碼
  2. tag 要設置到sprite 對象上,而不是body上

奉上個小demo:
實現飛機下落,撞上主角飛機發生爆炸,並且從屏幕消失

github 鏈接
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章