• cocos2dx打飞机项目笔记六:GameScene类和碰撞检测 boundingbox


    GameScene类虽然是占用游戏最多时间的类,但是里面的东西不是很多,最重要的就是碰撞检测了,碰撞检测代码如下:

      1 void GameScene::detectionCrash()
      2 {
      3 
      4     CCArray* bulletsToDelete = CCArray::create();//创建一个CCArray,用以存放待删除的子弹,也就是此帧中被检测到碰撞的子弹 
      5     bulletsToDelete->retain();//必须调用retain,CCArray内部调用了autoRelease
      6     CCObject* bt,*et;
      7 
      8     CCArray* enemyToDelete = CCArray::create();//创建一个CCArray,用以存放待删除的敌机,也就是此子弹击中的敌机
      9     enemyToDelete->retain();//调用retain  
     10 
     11     CCRect rectHero = this->heroLayer->getHero()->boundingBox();
     12     float x = rectHero.origin.x + rectHero.size.width * 0.3;
     13     float y = rectHero.origin.y + rectHero.size.height * 0.4;
     14     float width = rectHero.size.width * 0.3;
     15     float height = rectHero.size.height * 0.6;
     16     CCRect rect_HeroForCrash = CCRectMake(x, y, width, height);
     17 
     18     //检测敌机和hero是否相撞
     19     CCARRAY_FOREACH(this->enemyLayer->m_enemys,et)//遍历所有敌机
     20     {
     21         //break;
     22 
     23         Enemy* enemy = (Enemy*)et;
     24         if (enemy->getLife() == 0)
     25         {
     26             break;
     27         }
     28 
     29         
     30     //    CCPoint rect1 = this->heroLayer->getHero()->getPosition();
     31         //boundingBox 获取的是相对于父节点的左下角为原点的一个rect,所以要比较两个精灵是否相交,他们的父节点的坐标原点和大小应该一样
     32         if(enemy->boundingBox().intersectsRect(rect_HeroForCrash)) 
     33         {
     34 
     35             this->heroLayer->setIsHeroLive(false);
     36             this->heroLayer->setHeroLifes(this->heroLayer->getHeroLifes() - 1);
     37 
     38             enemyLayer->stopTakeEnemy();
     39             enemyLayer->bomb(enemy);
     40             enemyLayer->removeAllEnmeys();
     41 
     42             SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
     43 
     44             int tempHightScore = GameScene::getHightestScore();
     45             if (this->m_totalScore > tempHightScore)
     46             {
     47                 GameScene::saveHightestScore(this->m_totalScore);
     48             }
     49 
     50             char life[64];
     51             sprintf(life, "%d", this->heroLayer->getHeroLifes());
     52             CCLabelTTF* lbLife = (CCLabelTTF*)this->getChildByTag(tagOfLife);
     53             lbLife->setString(life);
     54 
     55 
     56             this->heroLayer->heroBomb(0.1f);
     57             if (this->heroLayer->getHeroLifes() == 0)
     58             {
     59 
     60                 this->scheduleOnce(schedule_selector(GameScene::gameOverCallback), 2.0f);
     61             } 
     62             else
     63             {
     64                 this->scheduleOnce(schedule_selector(GameScene::newLife), 2.0f);
     65             }
     66 
     67             return;
     68         }
     69     }
     70 
     71     //检测敌机和子弹是否相撞
     72     CCARRAY_FOREACH(this->heroLayer->getBullets()->m_bullets,bt)//遍历所有子弹    
     73     {    
     74         CCSprite* bullet = (CCSprite*)bt;
     75 
     76         CCARRAY_FOREACH(this->enemyLayer->m_enemys,et)//遍历所有敌机
     77         {
     78             Enemy* enemy3 = (Enemy*)et;
     79             
     80 
     81             if(enemy3->boundingBox().intersectsRect(bullet->boundingBox())) 
     82             {
     83 
     84                 if (enemy3->getLife() > 1)
     85                 {
     86                     enemy3->loseLife();
     87                     bulletsToDelete->addObject(bullet);//把待删除子弹放入CCArray  
     88                 }
     89                 else if (enemy3->getLife() == 1)
     90                 {
     91                     enemy3->loseLife();
     92                     bulletsToDelete->addObject(bullet);//把待删除子弹放入CCArray  
     93                     enemyToDelete->addObject(enemy3);//把待删除敌机放入CCArray 
     94 
     95                     this->m_totalScore += enemy3->getScore();
     96 
     97                     char str1[20];
     98                     sprintf(str1, "%d",(int)this->m_totalScore);
     99 
    100                     CCLabelTTF* label1 = (CCLabelTTF*)this->getChildByTag(tagOfScore);
    101 
    102                     label1->setString(str1);
    103                 }
    104                 
    105             }
    106         }
    107 
    108     }
    109 
    110     CCARRAY_FOREACH(enemyToDelete,et)//遍历所有此帧中碰撞死亡的敌机,必须是死亡
    111     {
    112         CCSprite* enemy3 = (CCSprite*)et;
    113         this->enemyLayer->bomb(enemy3);//执行爆炸
    114     }
    115     enemyToDelete->release();//release
    116 
    117     CCARRAY_FOREACH(bulletsToDelete,bt)//遍历所有此帧中碰撞的子弹
    118     {
    119         CCSprite* bullet = (CCSprite*)bt;
    120         this->heroLayer->getBullets()->removeBullet(bullet);//执行移除
    121     }
    122     bulletsToDelete->release();//release
    123 }

    还记得之前说过 boundingbox 方法是获取节点以父节点左下角为原点的一个矩形吧,该矩形的大小就是节点各种变形后的大小,矩形的左下角坐标就是节点变形后的左下角坐标

    bullet是加到 ccspriteBatchNode 上的,ccspriteBatchNode是加到 BulletLayer上面的,ccspriteBatchNode和bulletLayer都是铺满屏幕的。所以子弹调用 boundingbox 获得的矩形是以屏幕左下角为原点的。敌机的原理也是如此。hero是直接加到 herolayer 上的,父节点同样是铺满屏幕的,所以他们的父节点的左下角的坐标都一样的,这就是通过 boundingbox 检测他们是否碰撞的前提。

    有些纹理周围有比较大的空白地方,这就会造成两个节点看起来还没有接触就会发生碰撞,这就需要对碰撞进行更精确的判断,可以通过什么像素判断法之类的。我这里采取最简单的处理方法,就是通过节点的boundingbox获取到一个rect,然后对这个rect加工一下:

    1     CCRect rectHero = this->heroLayer->getHero()->boundingBox();
    2     float x = rectHero.origin.x + rectHero.size.width * 0.3;
    3     float y = rectHero.origin.y + rectHero.size.height * 0.4;
    4     float width = rectHero.size.width * 0.3;
    5     float height = rectHero.size.height * 0.6;
    6     CCRect rect_HeroForCrash = CCRectMake(x, y, width, height);

    这样子可以获取节点 boundingbox 里面的某一部分来作为碰撞的检测部分

  • 相关阅读:
    jacascript 数组
    jacascript 基础数据类型(一)
    JS checkbox 全选 全不选
    sql 循环处理表数据中当前行和上一行中某值相+/-
    C# 围棋盘的画法
    C 中读取键盘码
    C# string.format、string.connect和+=运算 效率计算
    Sqlserver 中exists 和 in
    urldecode解码方法
    SQL server 临时表
  • 原文地址:https://www.cnblogs.com/zouzf/p/3490852.html
Copyright © 2020-2023  润新知