💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
敌方飞机应该不定时的出现,有自己的生命周期、运动轨迹。这个类用来管理敌机的产生、移动、爆炸、销毁等。 敌机管理类主要函数如下 ~~~ //绑定控制器(更新分数) 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()函数中进行初始化。为了使游戏难度不断增加,会根据分数来改变添加敌机的速度。敌机的运动轨迹大同小异,不过贝塞尔曲线看起来确实挺不错的。