敵方飛機應該不定時的出現,有自己的生命周期、運動軌跡。這個類用來管理敵機的產生、移動、爆炸、銷毀等。
敵機管理類主要函數如下
~~~
//綁定控制器(更新分數)
void bindController(Controller* controller);
//根據分數決定添加敵機速度
void addSpeed(float dt);
// 添加敵機1
void addEnemy1(float dt);
// 添加敵機2
void addEnemy2(float dt);
// 添加敵機3
void addEnemy3(float dt);
// 添加敵機4
void addEnemy4(float dt);
// 敵機爆炸
void blowupEnemy(Enemy* pEnemySprite);
// 移除敵機pNode
void removeEnemy(Node *pNode);
~~~
其成員變量如下
~~~
Vector<Enemy*> vecEnemy;// 敵機容器,用于遍歷碰撞問題
Controller* m_controlLayer; //控制器
float m_fSpeed; //添加敵機速度
float m_fEnemy1;
float m_fEnemy2;
float m_fEnemy3;
float m_fEnemy4;
~~~
敵機產生后,要先存儲在容器中,通過容器來進行與子彈、我方飛機的碰撞檢測,之后統一銷毀。
還有就是,因為分數是要存儲在數據庫中的,所以我們用一個控制器來管理分數。對于我方飛機的觸摸移動,也可以用控制器來控制,由于本游戲中的我方飛機操作簡單,代碼就嵌在了我方飛機類中。(⊙o⊙)…扯遠了,先介紹敵機管理類的實現,再講控制器。
~~~
bool EnemyManager::init()
{
if (!Layer::init())
{
return false;
}
cocos2d::Vector<SpriteFrame*> vecTemp;
vecTemp.clear();
// 敵機1爆炸
for (int i = 0; i < 4; i++)
{
auto blowUpName = __String::createWithFormat("enemy1_down%d.png", i + 1);
auto tempBlowUp = SpriteFrameCache::getInstance()->getSpriteFrameByName(
blowUpName->getCString());
vecTemp.pushBack(tempBlowUp);
}
Animation* pAnimation1 = Animation::createWithSpriteFrames(vecTemp, 0.1f);
// 添加到AnimationCache,并且命名為Enemy1Blowup
AnimationCache::getInstance()->addAnimation(pAnimation1, "Enemy1Blowup");
// 敵機2爆炸
vecTemp.clear();
for (int i = 0; i < 4; i++)
{
auto blowUpName = __String::createWithFormat("enemy2_down%d.png", i + 1);
auto tempBlowUp = SpriteFrameCache::getInstance()->getSpriteFrameByName(
blowUpName->getCString());
vecTemp.pushBack(tempBlowUp);
}
Animation *pAnimation2 = Animation::createWithSpriteFrames(vecTemp,0.1f);
AnimationCache::getInstance()->addAnimation(pAnimation2, "Enemy2Blowup");
// 敵機3爆炸
vecTemp.clear();
for (int i = 0; i < 4; i++)
{
auto blowUpName = __String::createWithFormat("enemy3_down%d.png", i + 1);
auto tempBlowUp = SpriteFrameCache::getInstance()->getSpriteFrameByName(
blowUpName->getCString());
vecTemp.pushBack(tempBlowUp);
}
Animation *pAnimation3 = Animation::createWithSpriteFrames(vecTemp,0.1f);
AnimationCache::getInstance()->addAnimation(pAnimation3, "Enemy3Blowup");
// 敵機4爆炸
vecTemp.clear();
for (int i = 0; i < 4; i++)
{
auto blowUpName = __String::createWithFormat("enemy4_down%d.png", i + 1);
auto tempBlowUp = SpriteFrameCache::getInstance()->getSpriteFrameByName(
blowUpName->getCString());
vecTemp.pushBack(tempBlowUp);
}
Animation *pAnimation4 = Animation::createWithSpriteFrames(vecTemp, 0.1f);
AnimationCache::getInstance()->addAnimation(pAnimation4, "Enemy4Blowup");
//根據當前分數來設定添加各種敵機的速度
this->schedule(schedule_selector(EnemyManager::addSpeed), 0.1f);
return true;
}
//綁定控制器(更新分數)
void EnemyManager::bindController(Controller* controller)
{
this->m_controlLayer = controller;
m_controlLayer->retain();
}
//根據分數決定添加敵機速度
void EnemyManager::addSpeed(float dt)
{
m_fSpeed = m_controlLayer->getSaveData()->getScore() / 1000 + 1;
this->schedule(schedule_selector(EnemyManager::addEnemy1), m_fEnemy1 / m_fSpeed); // 每1秒出現一架敵機1
this->schedule(schedule_selector(EnemyManager::addEnemy2), m_fEnemy2 / m_fSpeed);
this->schedule(schedule_selector(EnemyManager::addEnemy3), m_fEnemy3 / m_fSpeed);
this->schedule(schedule_selector(EnemyManager::addEnemy4), m_fEnemy4 / m_fSpeed);
}
void EnemyManager::addEnemy1(float dt)
{
Size size = Director::getInstance()->getVisibleSize();
Enemy *pEnemySprite = Enemy::create();
pEnemySprite->setEnemyByType(Enemy1);
pEnemySprite->setTag(Enemy1);
this->addChild(pEnemySprite);
vecEnemy.pushBack(pEnemySprite);
// 設置運動軌跡 以及到終點時調用的函數
ccBezierConfig m_bezier;
m_bezier.controlPoint_1 = ccp(size.width/20, size.height*0.7);
m_bezier.controlPoint_2 = ccp(size.width/2, size.height/2);
m_bezier.endPosition = ccp(size.width*0.9, size.height*0.9);
auto actionMove = BezierTo::create(2.0f, m_bezier);
auto actionDone = CallFuncN::create(CC_CALLBACK_1(EnemyManager::removeEnemy, this));
Sequence* sequence = Sequence::create(actionMove, actionDone, NULL);
pEnemySprite->runAction(sequence);
//根據分數改變敵機數量
}
void EnemyManager::addEnemy2(float dt)
{
Size size = Director::getInstance()->getVisibleSize();
Enemy *pEnemySprite = Enemy::create();
pEnemySprite->setEnemyByType(Enemy2);
pEnemySprite->setTag(Enemy2);
this->addChild(pEnemySprite);
vecEnemy.pushBack(pEnemySprite);
// 設置運動軌跡 以及到終點時調用的函數
ccBezierConfig m_bezier;
m_bezier.controlPoint_1 = ccp(40, 500);
m_bezier.controlPoint_2 = ccp(250, 400);
m_bezier.endPosition = ccp(400, 700);
auto actionMove = BezierTo::create(4.0f, m_bezier);
auto actionDone = CallFuncN::create(CC_CALLBACK_1(EnemyManager::removeEnemy, this));
Sequence* sequence = Sequence::create(actionMove, actionDone, NULL);
pEnemySprite->runAction(sequence);
}
void EnemyManager::addEnemy3(float dt)
{
Size size = Director::getInstance()->getVisibleSize();
Enemy *pEnemySprite = Enemy::create();
pEnemySprite->setEnemyByType(Enemy3);
pEnemySprite->setTag(Enemy3);
this->addChild(pEnemySprite);
vecEnemy.pushBack(pEnemySprite);
// 設置運動軌跡 以及到終點時調用的函數
ccBezierConfig m_bezier;
m_bezier.controlPoint_1 = ccp(60, 550);
m_bezier.controlPoint_2 = ccp(100, 400);
m_bezier.endPosition = ccp(400, 700);
auto actionMove = BezierTo::create(6.0f, m_bezier);
auto actionDone = CallFuncN::create(CC_CALLBACK_1(EnemyManager::removeEnemy, this));
Sequence* sequence = Sequence::create(actionMove, actionDone, NULL);
pEnemySprite->runAction(sequence);
}
// 添加敵機4
void EnemyManager::addEnemy4(float dt)
{
Enemy *pEnemySprite = Enemy::create();
pEnemySprite->setEnemyByType(Enemy4);
pEnemySprite->setTag(Enemy4);
this->addChild(pEnemySprite);
vecEnemy.pushBack(pEnemySprite);
// 設置運動軌跡 以及到終點時調用的函數
ccBezierConfig m_bezier;
m_bezier.controlPoint_1 = ccp(80, 650);
m_bezier.controlPoint_2 = ccp(350, 450);
m_bezier.endPosition = ccp(400, 700);
auto actionMove = BezierTo::create(8.0f, m_bezier);
auto actionDone = CallFuncN::create(CC_CALLBACK_1(EnemyManager::removeEnemy, this));
// 按順序執行 敵機飛到邊緣,敵機移動結束
Sequence* sequence = Sequence::create(actionMove, actionDone, NULL);
pEnemySprite->runAction(sequence);
}
void EnemyManager::removeEnemy(Node *pNode)
{
Enemy* enemy = (Enemy*)pNode;
if (enemy != NULL)
{
this->removeChild(enemy, true);
vecEnemy.eraseObject(enemy);
}
}
void EnemyManager::blowupEnemy(Enemy* pEnemySprite)
{
auto saveData = m_controlLayer->getSaveData();
Animation *pAnimation = NULL;
if (Enemy1 == pEnemySprite->getTag())
{
// 之前緩存的爆炸動作
pAnimation = AnimationCache::getInstance()->getAnimation("Enemy1Blowup");
if (CocosDenshion::SimpleAudioEngine::getInstance()->isBackgroundMusicPlaying())
{
}
if (CocosDenshion::SimpleAudioEngine::getInstance()->isBackgroundMusicPlaying())
{
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("sound/enemy1_down.wav");
}
saveData->setScore(saveData->getScore() + ENEMY1_SCORE);
}
else if (Enemy2 == pEnemySprite->getTag())
{
pAnimation = AnimationCache::getInstance()->getAnimation("Enemy2Blowup");
if (CocosDenshion::SimpleAudioEngine::getInstance()->isBackgroundMusicPlaying())
{
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("sound/enemy2_down.wav");
}
saveData->setScore(saveData->getScore() + ENEMY2_SCORE);
}
else if (Enemy3 == pEnemySprite->getTag())
{
pAnimation = AnimationCache::getInstance()->getAnimation("Enemy3Blowup");
if (CocosDenshion::SimpleAudioEngine::getInstance()->isBackgroundMusicPlaying())
{
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("sound/enemy3_down.wav");
}
saveData->setScore(saveData->getScore() + ENEMY3_SCORE);
}
else if (Enemy4 == pEnemySprite->getTag())
{
pAnimation = AnimationCache::getInstance()->getAnimation("Enemy4Blowup");
if (CocosDenshion::SimpleAudioEngine::getInstance()->isBackgroundMusicPlaying())
{
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("sound/enemy4_down.wav");
}
saveData->setScore(saveData->getScore() + ENEMY4_SCORE);
}
else
{
return;
}
Animate *pAnimate = Animate::create(pAnimation);
// 爆炸完,要移除敵機
auto pActionDone = CallFuncN::create(CC_CALLBACK_0(EnemyManager::removeEnemy, this, pEnemySprite));
Sequence* pSequence = Sequence::create(pAnimate, pActionDone, NULL);
pEnemySprite->getSprite()->runAction(pSequence);
}
~~~
每種類型的敵機的爆炸代碼比較短,直接在init()函數中進行初始化。為了使游戲難度不斷增加,會根據分數來改變添加敵機的速度。敵機的運動軌跡大同小異,不過貝塞爾曲線看起來確實挺不錯的。