• 【cocos2d-x 3.7 飞机大战】 决战南海I (四) 敌机管理


            敌方飞机应该不定时的出现,有自己的生命周期、运动轨迹。这个类用来管理敌机的产生、移动、爆炸、销毁等。


    敌机管理类主要函数例如以下


    	//绑定控制器(更新分数)
    	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()函数中进行初始化。为了使游戏难度不断添加,会依据分数来改变加入敌机的速度。敌机的运动轨迹大同小异,只是贝塞尔曲线看起来确实挺不错的。






  • 相关阅读:
    命令行构建Unity项目
    Android AIDL实例解析
    Android aidl Binder框架浅析
    Uri详解之——Uri结构与代码提取
    Glide使用详解(一)
    ImageView的scaleType详解
    关于Android导入开源项目:Error:Unable to load class 'org.gradle.api.publication.maven.internal.DefaultMavenFa
    15 个 Android 通用流行框架大全
    动画 节拍器
    Android background tint颜色渲染
  • 原文地址:https://www.cnblogs.com/clnchanpin/p/7028879.html
Copyright © 2020-2023  润新知