本篇博客主要实现碰撞检测,这个碰撞检测算是这个小demo最主要的逻辑了,完成了这个游戏就快大功告成了,我在写的时候遇到了不少的bug,不过最后都解决了。实现的方法就是从管理器中获得子弹和敌机,然后判断子弹是否在敌机的rect内,如果打中了生命值就要减小,有可能爆炸,有可能播放受伤的动画,好了我们在上篇博客写碰撞检测的代码处加入碰撞检测吧!

//碰撞检测
void MainGame::isHitEnemy(float tm)
{
	//从管理器中获得子弹和敌机的数组引用
	auto & enemyVector = Manager::getInstance()->getEnemyVector();
	auto & bulletVector = Manager::getInstance()->getBulletVector();
	for(int i=enemyVector.size()-1;i>=0;i--)
	{
		//如果敌机毁灭会播放动画暂时还不会从管理器中移除,所以这里要判断一下是否已经毁灭
		if(enemyVector.at(i)->getHp() == 0)
		{
			//如果已经毁灭就不要进行碰撞检测了
			continue;
		}
		//获得敌机的rect
		auto rect = enemyVector.at(i)->getBoundingBox();
		for(int j=bulletVector.size()-1;j>=0;j--)
		{
			//判断子弹的位置是否在敌机的rect范围内,如果在,则满足碰撞
			auto point = bulletVector.at(j)->getPosition();
			if(rect.containsPoint(point))
			{
				//敌机的生命值减掉
				enemyVector.at(i)->setHp(enemyVector.at(i)->getHp()-1);
				//从屏幕和管理器中移除子弹,敌机的移除已经写在了blowup函数中,注意以下俩句话的调用顺序,否则
				//产生的bug很难排除
				bulletVector.at(j)->removeFromParentAndCleanup(true);
				bulletVector.eraseObject(bulletVector.at(j));
				//生命值为0敌机爆炸,如果敌机已经死亡就不要和剩下的子弹进行判断了,所以要break
				if(enemyVector.at(i)->getHp() == 0)
				{
					enemyVector.at(i)->blowUp();
					break;
				}
				else
				{
					//播放敌机受伤的动画
					enemyVector.at(i)->hit();
				}
			}
		}
	}
}

上边就是碰撞检测的代码,写起来需要注意不少细节的问题,不算容易。敌机受伤的动画是我后来加在enemy类中的,代码如下。

void EnemyBase::hit()
{
	int index = m_frameName[5]-'0';
	//敌机1没有受伤的动画
	if(index == 1)
		return;
	auto animation = Animation::create();
	//使用以下俩张图片播放动画效果
	std::string frameName1 = m_frameName+"_hit.png";
	auto spriteFrame1 = SpriteFrameCache::getInstance()->getSpriteFrameByName(frameName1);
	std::string frameName2 = m_frameName+".png";
	auto spriteFrame2 = SpriteFrameCache::getInstance()->getSpriteFrameByName(frameName2);
	animation->addSpriteFrame(spriteFrame1);
	animation->addSpriteFrame(spriteFrame2);
	animation->setDelayPerUnit(0.05f);
	animation->setLoops(2);
	auto animate = Animate::create(animation);
	this->runAction(animate);
}

用3.0实现飞机大战——碰撞检测

.plist文件中的一些文件的名称我给改了,每篇博客我都会把自己的工程打包,大家可以下载本篇博客的工程。