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文件 就能够执行看到结果啦


个人愚昧观点。欢迎指正与讨论!

posted @ 2017-07-01 11:16  lytwajue  阅读(266)  评论(0编辑  收藏  举报