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 里面的某一部分來作為碰撞的檢測部分
