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


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

  • 相关阅读:
    快速删除段落间多余的空行
    平时一些mysql小技巧及常识
    mysql中常用的控制流函数
    按年、季度、月分组&&计算日期和时间的函数
    Excel通过身份证获取出生年月,性别,年龄,生肖,星座,省份等信息总结归纳
    统计图表类型选择应用总结&表数据挖掘方法及应用
    EXCEL如何提取文字中包含的数字?
    一篇说尽Excel常见函数用法
    RStudio中,出现中文乱码问题的解决方案
    R-RMySQL包介绍学习
  • 原文地址:https://www.cnblogs.com/lytwajue/p/7101745.html
Copyright © 2020-2023  润新知