说明:这里是借鉴:晓风残月前辈的博客,他是将泰然网的跑酷教程,用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文件 就可以运行看到结果啦
个人愚昧观点,欢迎指正与讨论!