cocos2d-x游戏开发 跑酷(八) 对象管理 碰撞检测

对象管理类的原理是这样的:

ObjectManager类是一个单例类,全局只有一个对象实例存在。初始化的时候创建两个数组CCArray来保存金币和岩石。为什么要保存,因为在地图重载的时候,要销毁看不见的那些对象。金币和岩石是随机添加的,每个金币和岩石都有一个地图索引,就是说它是在第几个地图上的,删除的时候根据这个来删除。

我的博客:http://blog.csdn.net/dawn_moon,欢迎转载

CCArray有个遍历的宏CCARRAY_FOREACH,如果你在遍历的时候进行增删的操作就会导致错误,这里我用了一个临时的CCArray来保存要删除的对象,然后再遍历这个临时数组对源数组进行删除,最后清空临时数组。

    CCArray* tempCoins = CCArray::create();
    CCArray* tempRocks = CCArray::create();
    CCObject* itor;
    
    // 遍历CCArray的时候不能做增删操作,否则会出错
    // 这里分两步来完成,第一次遍历,将要删除的对象存到一个临时CCArray里
    // 第二步遍历临时CCArray,将里面的对象从源数组里删掉,最后清空临时数组
    CCARRAY_FOREACH(mCoins,itor)
    {
        Coin* coin = dynamic_cast<Coin*>(itor);
        if ((coin != NULL) && (coin->getMap() == mapIndex)) {
            tempCoins->addObject(coin);
            coin->destroy();
        }
    }
    
    CCARRAY_FOREACH(tempCoins,itor)
    {
        mCoins->fastRemoveObject(itor);
    }
    
    tempCoins->removeAllObjects();

这个类在PlayScene的init里面初始化:

    ObjectManager* ObjM= ObjectManager::sharedObjectManager();
    ObjM->initManager(spriteBatch, mWorld);
    ObjM->setObjectToMap(1, mMapManager->getMapWidth());

然后在PlayScene的update里面添加金币和岩石,

    // 如果发生地图重载,就回收废的金币和岩石,添加新的金币和岩石
    if (mMapManager->chechReloadMap(mLastEyeX)) {
        ObjectManager::sharedObjectManager()->recycleObjectOfMap(mMapManager->getCurMapIndex() - 1);
        ObjectManager::sharedObjectManager()->setObjectToMap(mMapManager->getCurMapIndex() + 1, mMapManager->getMapWidth());
    }

好了,看碰撞检测。box2d的碰撞检测由物理世界维护,物理世界能知道所有发生的碰撞事件,并用一个回调来处理。我们要自己处理碰撞检测,就要实现这个回调b2ContactListener

让PlayScene继承这个类,实现里面的一个函数BeginContact,然后给world设置碰撞监听器

mWorld->SetContactListener(this);

看下碰撞检测的实现:

void PlayScene::BeginContact(b2Contact *contact)
{
//    CCLog("begin contact!");
    
    void* bodyUserDataA = contact->GetFixtureA()->GetBody()->GetUserData();
    void* bodyUserDataB = contact->GetFixtureB()->GetBody()->GetUserData();
    
    if (bodyUserDataA && bodyUserDataB)
    {
        B2Sprite* contactA = static_cast<B2Sprite*>(bodyUserDataA);
        BaseObject* obj = NULL;
        if (contactA == mRunner->getRunnerSprite())
        {
            obj = static_cast<BaseObject*>(bodyUserDataB);
        }else
        {
            obj = static_cast<BaseObject*>(bodyUserDataA);
        }
        
        if (COINTAG == obj->getObjSprite()->getTag()) {
            ((Status*)(this->getParent()->getChildByTag(STATUSTAG)))->addCoin(1);
            mRemoveObjs->addObject(obj);
            SimpleAudioEngine::sharedEngine()->playEffect(pickUpCoins);
        }else if(ROCKTAG == obj->getObjSprite()->getTag())
        {
            mRunner->die();
            unscheduleUpdate();
            mState = GameOverState;
            GameOver* over = GameOver::create();
            this->getParent()->addChild(over);
        }
        
    }
}

碰撞发生后,通过body的用户数据来进行辨别。这个用户数据userData是一个void*指针,存放用户的任何数据。在做物理精灵的时候对它进行设置,就是为了这个时候用的。

地板的userData是NULL,所以如果这个userData不为NULL的话,那么它要么是Runner要么是金币要么是岩石。Runner的userData是一个B2Sprite,金币和岩石的userData都是BaseObject的子类,所以做类型转换。再用tag来区分金币和岩石。如果是金币,就添加到一个CCArray里面,然后在update里面做清除,如果是岩石,就GameOver了。

分数和跑酷的距离是一个单独的CCLayer,因为PlayScene是一个无限的Layer,所以分数要单独出来,不然它会跑出屏幕。GameOver是一个CCLayerColor,因为要做一个有透明度的层,表示游戏结束了。

图我就不上了,稍后放出源码。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
CocosCreator实现的 解救人质 游戏,学会碰撞检测rescue.7z // Bullet.js cc.Class({ extends: cc.Component, properties: { mSpeed: 300, }, // LIFE-CYCLE CALLBACKS: // onLoad () {}, start() { var manager = cc.director.getCollisionManager(); // 获取碰撞检测系统 manager.enabled = true; }, update(dt) { // 设置子弹移动,当超出屏幕范围未发生碰撞时自动销毁 this.node.y += this.mSpeed * dt; if (this.node.y > 580) { console.log('超出屏幕范围,子弹销毁!'); this.node.destroy(); } }, /** * 当碰撞产生的时候调用 * @param {Collider} other 产生碰撞的另一个碰撞组件 * @param {Collider} self 产生碰撞的自身的碰撞组件 */ onCollisionEnter: function (other, self) { console.log('on collision enter'); if (other.tag == 1) { // 子弹碰到人质时,解救失败! console.log('解救人质失败!'); var failLabel = this.node.parent.getChildByName('failLabel'); failLabel.active = true; this.node.destroy(); } else if (other.tag == 2) { // 子弹碰到敌人时,解救成功! console.log('解救人质成功!'); var successLabel = this.node.parent.getChildByName('successLabel'); successLabel.active = true; this.node.destroy(); } }, /** * 当碰撞产生后,碰撞结束前的情况下,每次计算碰撞结果后调用 * @param {Collider} other 产生碰撞的另一个碰撞组件 * @param {Collider} self 产生碰撞的自身的碰撞组件 */ onCollisionStay: function (other, self) { console.log('on collision stay'); }, /** * 当碰撞结束后调用 * @param {Collider} other 产生碰撞的另一个碰撞组件 * @param {Collider} self 产生碰撞的自身的碰撞组件 */ onCollisionExit: function (other, self) { console.log('on collision exit'); } });

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值