cocos2d-x 3.0遊戲實例學習筆記 《跑酷》第七步--物理碰撞檢測(1)

說明:這裏是借鑑:曉風殘月前輩的博客,他是將泰然網的跑酷教程,用cocos2d-x 2.X 版本重寫的,目前我正在學習cocos2d-X3.0 於是就用cocos2d-X 3.0重寫,並做相關筆記

那麼這一步,我們先不急着給主角和金幣岩石碰撞檢測,我這裏把cocos2d-x 3.0 的物理碰撞檢測單獨抽取出來,之前看了cocos的官網,有一個教程:用新物理引擎完成碰撞檢測,就是一個車和貓的碰撞檢測,車撞倒貓,貓就消失。我之前也單獨試了下。但是那個教程的代碼好像完整性不好,不能運行。。。於是我又借鑑了笨木頭的的實例教程,完成了這個簡單的碰撞檢測。

檢測如下:有一個受重力影響的小球1,會下落,然後下面有一個靜態剛體的小球2,不受重力影響的固定在小球1的正下方。然後小球1撞到小球2,小球2就消失。並且碰撞的時候,小球1不會受到小球2的阻力而停一下。那麼這裏實際上就是爲了給主角和金幣的碰撞檢測。只是爲了簡單,這裏先單獨把碰撞檢測抽離出來。

下面來完成:

先新建一個新的項目:修改HelloWorld.h & .cpp文件內容如下:

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

class HelloWorld : public cocos2d::Layer
{
public:
    static cocos2d::Scene* createScene();
    virtual bool init();  
    CREATE_FUNC(HelloWorld);

	cocos2d::PhysicsWorld* m_world;
	void setPhyWorld(cocos2d::PhysicsWorld* world){ m_world = world;};
        //下面的內容就是爲了物理碰撞檢測
	cocos2d::EventDispatcher* dispatcher;
	void onEnter();
	void onExit();
	bool onContactBegin(cocos2d::PhysicsContact& contact);
};/**/

#endif // __HELLOWORLD_SCENE_H__

-------------------.cpp-----------------------
#include "HelloWorldScene.h"

USING_NS_CC;

Scene* HelloWorld::createScene()
{
	//創建物理scene
	auto scene = Scene::createWithPhysics();
	//開啓調試
	scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);

	auto layer = HelloWorld::create();

	layer->setPhyWorld(scene->getPhysicsWorld());

	scene->addChild(layer);

	return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
	
	auto ball_1 = Sprite::create("11.png");
	//創建剛體
	auto body1 = PhysicsBody::createBox(ball_1->getContentSize());

	//使得可以檢測到物理碰撞
	body1->setCategoryBitmask(1);
	body1->setCollisionBitmask(1);
	body1->setContactTestBitmask(1);

	//綁定
	ball_1->setPhysicsBody(body1);
	ball_1->setPosition(205,300);
	//設置標籤,爲碰撞做判斷
	ball_1->setTag(1);
	this->addChild(ball_1);

	//同上
	auto ball_2 = Sprite::create("22.png");
	auto body2 = PhysicsBody::createEdgeBox(ball_2->getContentSize());
	body2->setCategoryBitmask(1);
	body2->setCollisionBitmask(1);
	body2->setContactTestBitmask(1);

	ball_2->setPhysicsBody(body2);
	ball_2->setPosition(205,150);
	ball_2->setTag(2);
	this->addChild(ball_2);

    return true;
}

void HelloWorld::onEnter(){
	Layer::onEnter();
	auto contactListenner = EventListenerPhysicsContact::create();

	//----1-----好像兩個方法都可以
	//contactListenner->onContactBegin = CC_CALLBACK_1(HelloWorld::onContactBegin,this);

	//----2-----
	contactListenner->onContactPreSolve = CC_CALLBACK_1(HelloWorld::onContactBegin,this);

	//事件派發機制
	dispatcher = Director::getInstance()->getEventDispatcher();
	dispatcher->addEventListenerWithSceneGraphPriority(contactListenner,this);
}
void HelloWorld::onExit(){
	Layer::onExit();
	//取消事件派發機制
	dispatcher->removeAllEventListeners();
}
bool HelloWorld::onContactBegin(PhysicsContact& contact){

	auto b_1 = (Sprite*)contact.getShapeA()->getBody()->getNode();
	auto b_2 = (Sprite*)contact.getShapeB()->getBody()->getNode();

	CCLOG("ssssss");

	if(b_1->getTag() == 2){
		b_1->setVisible(false);
	}
	if(b_2->getTag() == 2){
		b_2->setVisible(false);
	}

	//返回false 使得物理世界忽略這次碰撞帶來的速度改變,反彈什麼的
	return false;
}


在init函數中,我們就弄了兩個小球,按上面說的分別綁定剛體,而且爲了讓剛體能被碰撞檢測到,應該添加三個語句:

setCategoryBitmask(1);
setCollisionBitmask(1);
setContactTestBitmask(1);
可以查看源碼註釋,這裏不解釋

關於碰撞檢測:

這裏主要就是 onEnter onExit 函數,過程如下:

onEnter:

弄一個碰撞的事件監聽 contactListenner  那麼這個碰撞監聽應該設置它的回調函數----當有碰撞發生的時候就調用

那麼3.0裏面的事件管理都交給了事件派發機制  我們也需要一個 dispatcher  ,把那個事件監聽 contactListenner   交給它管理;

碰撞的回調函數就會有一個參數 :PhysicsContact& contact  它就可以獲得這兩個發生碰撞的Node。。。。做出相應處理

然後就是onExit函數 ,應該取消掉事件派發的監聽。。。(其實這裏我也說不清,這個函數在哪裏調用也不知道),好吧反正這裏能打到目的就行,運行測試截圖如下:


下落的小球穿過了靜態小球,對於這裏碰撞,我們只是把 下面的小球讓它看不到,這裏就和我們前面一步有關係了,因爲爲了避免重複的create 金幣,我們不管是主角吃了的金幣,還是到屏幕外面看不到的金幣,都設置爲不可見,然後再重新出現

OK,,有了這裏,我們就運用到下面的遊戲中,讓金幣和岩石 與主角發生碰撞,到後面一步,也就是最後一步啦。。。。

哦哦差點忘了,這一部分的代碼和兩個小球的資源已經上傳,0 積分下載:碰撞檢測例子

我們新建一個項目,直接複製代碼,以及把兩個小球加入Resource文件 就可以運行看到結果啦


個人愚昧觀點,歡迎指正與討論!

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