1. 程式人生 > >實例介紹Cocos2d-x中Box2D物理引擎:碰撞檢測

實例介紹Cocos2d-x中Box2D物理引擎:碰撞檢測

函數實現 pda creates pty blank oid rtu and 重構

在Box2D中碰撞事件通過實現b2ContactListener類函數實現,b2ContactListener是Box2D提供的抽象類,它的抽象函數:
virtual void BeginContact(b2Contact* contact)。兩個物體開始接觸時會響應,但僅僅調用一次。


virtual void EndContact(b2Contact* contact)。分離時響應。

但僅僅調用一次。


virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)。持續接觸時響應,它會被多次調用。


virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse)。持續接觸時響應,調用完preSolve後調用。


以下通過將12.2.3一節的實例採用Box2D技術重構。了解一下Box2d物理引擎中怎樣檢測碰撞。
首先我們須要在project中加入一個新類。

使用Visual Studio 2012中加入一個新類。須要分別加入C++源文件和頭文件。詳細操作,如圖所看到的。右鍵點擊projectHelloBox2D下的Classes目錄。在右鍵菜單中選擇。“加入”→ “新項目”。

彈出如後面的圖所看到的加入新項對話框,我們在對話框中選擇文件的種類,在“名稱”中輸入文件名稱ContactListener,然後點擊“加入”button加入文件。


技術分享
Visual Studio 2012中加入新類
技術分享加入新項對話框加入完畢新類ContactListener。我們還須要改動它的代碼,ContactListener.h文件代碼例如以下:
#include "cocos2d.h"
#include "Box2D/Box2D.h"


USING_NS_CC;


class ContactListener : public b2ContactListener
{
private:
	//兩個物體開始接觸時會響應
	virtual void BeginContact(b2Contact* contact);


	//持續接觸時響應
	virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);
	//持續接觸時響應,調用完preSolve後調用
	virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse);
	
	//分離時響應
	virtual void EndContact(b2Contact* contact);
};
在頭文件裏須要引入cocos2d.h和Box2D/Box2D.h頭文件,否則會有編譯錯誤。ContactListener採用共同擁有繼承b2ContactListener。
ContactListener.cpp文件代碼例如以下:
#include "ContactListener.h"


void ContactListener::BeginContact(b2Contact* contact)							①
{
	log("BeginContact");


	b2Body* bodyA = contact->GetFixtureA()->GetBody();							②
	b2Body* bodyB = contact->GetFixtureB()->GetBody();							③
	auto spriteA = (Sprite*)bodyA->GetUserData();								④
	auto spriteB = (Sprite*)bodyB->GetUserData();								⑤
	
	if (spriteA != nullptr && spriteB != nullptr)									⑥
	{
        spriteA->setColor(Color3B::YELLOW);
        spriteB->setColor(Color3B::YELLOW);
	}
}


void ContactListener::EndContact(b2Contact* contact)							⑦
{
	log("EndContact");


	b2Body* bodyA = contact->GetFixtureA()->GetBody();
	b2Body* bodyB = contact->GetFixtureB()->GetBody();
	auto spriteA = (Sprite*)bodyA->GetUserData();
	auto spriteB = (Sprite*)bodyB->GetUserData();
	
	if (spriteA != nullptr && spriteB != nullptr)
	{
        spriteA->setColor(Color3B::WHITE);
        spriteB->setColor(Color3B::WHITE);
	}
}


void ContactListener::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)			⑧
{
	log("PreSolve");
}


void ContactListener::PostSolve(b2Contact* contact, const b2ContactImpulse* impulse)		⑨
{
	log("PostSolve");
}


上述代碼第①行是實現碰撞事件BeginContact函數,第②代碼和第③行代碼是獲得接觸兩方物體對象。第④代碼和第⑤行代碼是從物體對象的UserData屬性中確定精靈對象,UserData屬性可以放置不論什麽對象,這裏我們可以通過bodyA->GetUserData()語句取得精靈,那是由於在定義物體的時候通過body->SetUserData(sprite)語句,將精靈放入到物體的UserData屬性。

第⑥行代碼是推斷兩個精靈是否存在。


代碼第⑦行是實現碰撞事件EndContact函數。函數的實現與BeginContact函數相似。第⑧和第⑨行代碼是實現碰撞事件PreSolve和PostSolve函數。這兩個函數通經常使用的不多。


我們還須要在要監聽事件的層中,加入相關碰撞檢測代碼。在HelloWorld.h的代碼例如以下:

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__


#include "cocos2d.h"
#include "Box2D/Box2D.h"
#include "ContactListener.h"												①


#define PTM_RATIO 32


class HelloWorld : public cocos2d::Layer
{
	b2World* world;
	ContactListener* contactListener;											②


public:


	~HelloWorld();
    
    static cocos2d::Scene* createScene();
    virtual bool init();  


	virtual void update(float dt);
	virtual bool onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);
    CREATE_FUNC(HelloWorld);
	
	void initPhysics();
	void addNewSpriteAtPosition(cocos2d::Vec2 p);


};


#endif // __HELLOWORLD_SCENE_H__


上述代碼第①行是引入頭文件ContactListener.h。第②行代碼是聲明ContactListener類型的成員變量contactListener。


我們還須要改動HelloWorld.cpp中的HelloWorld::initPhysics()代碼例如以下:

void HelloWorld::initPhysics()
{
	… …
   contactListener = new ContactListener();
	world->SetContactListener(contactListener);
	… …
}


函數中的contactListener = new ContactListener()語句是創建ContactListener對象,採用了newkeyword分配內存,創建成員變量contactListener,須要自己釋放contactListener對象。這些釋放過程是在析構函數中進行。它的析構函數代碼例如以下:
HelloWorld::~HelloWorld()
{
CC_SAFE_DELETE(world);
CC_SAFE_DELETE(contactListener);
}

使用CC_SAFE_DELETE(contactListener)安全釋放contactListener成員變量的內存。


很多其它內容請關註最新Cocos圖書《Cocos2d-x實戰 C++卷》本書交流討論站點:http://www.cocoagame.net
很多其它精彩視頻課程請關註智捷課堂Cocos課程:http://v.51work6.com
歡迎增加Cocos2d-x技術討論群:257760386


《Cocos2d-x實戰 C++卷》現已上線,各大商店均已開售:

京東:http://item.jd.com/11584534.html

亞馬遜:http://www.amazon.cn/Cocos2d-x%E5%AE%9E%E6%88%98-C-%E5%8D%B7-%E5%85%B3%E4%B8%9C%E5%8D%87/dp/B00PTYWTLU

當當:http://product.dangdang.com/23606265.html

互動出版網:http://product.china-pub.com/3770734

《Cocos2d-x實戰 C++卷》源代碼及樣章下載地址:

源代碼下載地址:http://51work6.com/forum.php?mod=viewthread&tid=1155&extra=page%3D1

樣章下載地址:http://51work6.com/forum.php?mod=viewthread&tid=1157&extra=page%3D1

歡迎關註智捷iOS課堂微信公共平臺技術分享

實例介紹Cocos2d-x中Box2D物理引擎:碰撞檢測