《简单的飞机大战》其实不简单(1)

原创 2015年07月10日 11:47:48

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><span style="white-space:pre">	</span>这是一个非常简单的《经典飞机大战》游戏,实现的基本功能:包括Boss的随机生成,击中销毁;分数根据击毁Boss的数量增加。附加功能有:道具的不定时产生,当英雄飞机碰撞到道具产生该道具的道具效果。</span>
</pre><pre name="code" class="cpp">

这里只实现最基本功能。

环境搭配:

1.操作系统;Win7

2.cocos2d-x版本:3.2

3.VS版本:VS2013


一、首先确定飞机基类

1.在这里,由于节点的getBoundingBox()的到的矩形比实际要检测碰撞的矩形大效果不好,还有一些英雄飞、和Boss飞机和子弹的相同的功能,首先写出一个公共基类:

class BoxTest :public cocos2d::Sprite
{
public:
	//CREATE_FUNC(BoxTest);
	//virtual bool init();

	cocos2d::Rect getBox();

	virtual void setStep(int step){ _step = step; }
	//是否爆炸
	virtual void setIsbomb(bool bomb) { _isbomb = bomb; }
	virtual bool getIsbomb() const { return _isbomb; }

	//被击中后减少最多击中次数
	virtual void reduceHP(){ ; };
	virtual int getHP() const { return _HP; };
	virtual void setHP(int hp){ _HP = hp; }
	virtual void setIsRemove(bool isremove){ _isremove = isremove; }
	virtual bool getIsRemove() const { return _isremove; }

	//击中动画
	virtual Animate *animateHit(){ return nullptr; };
	//爆炸动画
	virtual Animate *animateBomb(){ return nullptr; };

protected:
	float Minx;
	float Miny;

	//移动步数 速度
	int _step;
	//是否爆炸
	bool _isbomb;
	//最多被击中次数,为0时爆炸
	int _HP;

	bool _isremove;


};


2.实现该类的部分方法:

Rect BoxTest::getBox()
{
	Minx = this->getPosition().x - this->getContentSize().width / 2 * 0.5;
	Miny = this->getPosition().y - this->getContentSize().height / 2 * 0.5;

	return Rect(Minx, Miny, this->getContentSize().width * 0.5, this->getContentSize().height * 0.5);
}
二、创建英雄飞机和Boss飞机

1.继承上述公共基类:

class Boss1 :public BoxTest
{
public:
	CREATE_FUNC(Boss1);
	virtual bool init();

	virtual void update(float dt);

	//击中时减少挤肿次数
	virtual void reduceHP();

	//击中动画
	virtual Animate *animateHit();
	//爆炸动画
	virtual Animate *animateBomb();
	
};
class Boss2 :public BoxTest
{
public:
	CREATE_FUNC(Boss2);
	virtual bool init();

	virtual void update(float dt);

	//击中时减少挤肿次数
	virtual void reduceHP();

	//击中动画
	virtual Animate *animateHit();
	//爆炸动画
	virtual Animate *animateBomb();

};
//最牛逼的飞机
class Boss3 :public BoxTest
{
public:
	CREATE_FUNC(Boss3);
	virtual bool init();

	virtual void update(float dt);

	//击中时减少挤肿次数
	virtual void reduceHP();
	void actionMove();
	Animate *animateMove();
	//击中动画
	virtual Animate *animateHit();
	//爆炸动画
	virtual Animate *animateBomb();

};
//英雄飞机
class Plane :public BoxTest
{
public:
	CREATE_FUNC(Plane);
	virtual bool init();
	virtual	void update(float dt);
};


class Bullet :public BoxTest
{
public:
	CREATE_FUNC(Bullet);
	virtual bool init();

	virtual void update(float dt);
};
2.实现继承方法:

bool Plane::init()
{
	if (Sprite::initWithSpriteFrameName("hero1.png") == false)
		return false;
	//log("1%f    %f", this->getContentSize().width, this->getContentSize().height);
	//this->setContentSize(Size(this->getContentSize().width * 0.7f, this->getContentSize().height * 0.7f));
	//this->setScale(0.7f);
	//log("2%f    %f", this->getContentSize().width, this->getContentSize().height);
	this->scheduleUpdate();
	return true;
}

void Plane::update(float dt)
{
	auto VisbelSize = Director::getInstance()->getVisibleSize();
	if ((this->getPosition().x > (VisbelSize.width - this->getContentSize().width / 2)))
	{
		this->setPositionX(VisbelSize.width - this->getContentSize().width / 2 - 6);
	}
	else if ((this->getPosition().x < this->getContentSize().width / 2))
	{
		this->setPositionX(this->getContentSize().width / 2 - 6);
	}
	else if ((this->getPosition().y >(VisbelSize.height - this->getContentSize().height / 2)))
	{
		this->setPositionY(VisbelSize.height - this->getContentSize().height / 2);
	}
	else if ((this->getPosition().y < this->getContentSize().height / 2))
	{
		this->setPositionY(this->getContentSize().height / 2);
	}
}

//最小的Boss
bool Boss1::init()
{
	if (Sprite::initWithSpriteFrameName("enemy1.png") == false)
		return false;

	//移动速度
	this->_step = 3;
	this->_HP = 0;
	this->_isbomb = false;


	this->scheduleUpdate();
	return true;
}

void Boss1::reduceHP()
{
	if (_HP > 0)
	{
		this->runAction(this->animateHit());
		_HP--;
	}
	else
	{
		setIsbomb(true);
	}
}


Animate *Boss1::animateHit()
{
	SpriteFrame *frame = nullptr;
	Vector<SpriteFrame *> frameVec;


	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy2.png");
	frameVec.pushBack(frame);
	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy2_hit.png");
	frameVec.pushBack(frame);
	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy2.png");
	frameVec.pushBack(frame);


	Animation *animation = Animation::createWithSpriteFrames(frameVec);
	animation->setLoops(1);//设置次数
	animation->setDelayPerUnit(0.2f);//设置帧间隔
	Animate *animate = Animate::create(animation);

	return animate;
}


Animate *Boss1::animateBomb()
{
	SpriteFrame *frame = nullptr;
	Vector<SpriteFrame *> frameVec;


	int frameNum = 4;
	for (int i = 0; i < frameNum; i++)
	{
		frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(StringUtils::format("enemy1_down%d.png", i + 1).c_str());
		frameVec.pushBack(frame);
	}

	Animation *animation = Animation::createWithSpriteFrames(frameVec);
	animation->setLoops(1);//设置次数
	animation->setDelayPerUnit(0.1f);//设置帧间隔
	Animate *animate = Animate::create(animation);

	return animate;
}


void Boss1::update(float dt)
{
	this->setPositionY(this->getPositionY() - _step);
	if (this->getPositionY() < 0)
	{
		this->setIsRemove(true);
		this->removeFromParent();
	}
	else if (_isbomb == true)
	{
		this->setPositionY(this->getPositionY() - _step);
		if (this->getPositionY() < 0)
		{
			this->setIsRemove(true);
			this->removeFromParent();
		}
		else if (_isbomb == true)
		{
			auto callfunc = [this](){
				this->setIsRemove(true);
				this->removeFromParent();
			};
			//先停住
			_step = 0;
			//爆炸
			this->unscheduleUpdate();
			//this->runAction(animateBomb());
			this->runAction(Sequence::create(animateBomb(), CallFunc::create(callfunc), nullptr));
		}
	}

}




//中间Boss
bool Boss2::init()
{
	if (Sprite::initWithSpriteFrameName("enemy2.png") == false)
		return false;

	//移动速度
	this->_step = 2;
	this->_HP = 1;
	this->_isbomb = false;


	this->scheduleUpdate();
	return true;
}

void Boss2::reduceHP()
{
	if (_HP > 0)
	{
		this->runAction(animateHit());
		_HP--;
	}
	else
	{
		setIsbomb(true);
	}
}


Animate *Boss2::animateHit()
{
	SpriteFrame *frame = nullptr;
	Vector<SpriteFrame *> frameVec;


	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy2.png");
	frameVec.pushBack(frame);
	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy2_hit.png");
	frameVec.pushBack(frame);
	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy2.png");
	frameVec.pushBack(frame);


	Animation *animation = Animation::createWithSpriteFrames(frameVec);
	animation->setLoops(1);//设置次数
	animation->setDelayPerUnit(0.1f);//设置帧间隔
	Animate *animate = Animate::create(animation);

	return animate;
}


Animate *Boss2::animateBomb()
{
	SpriteFrame *frame = nullptr;
	Vector<SpriteFrame *> frameVec;


	int frameNum = 4;
	for (int i = 0; i < frameNum; i++)
	{
		frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(StringUtils::format("enemy2_down%d.png", i + 1).c_str());
		frameVec.pushBack(frame);
	}

	Animation *animation = Animation::createWithSpriteFrames(frameVec);
	animation->setLoops(1);//设置次数
	animation->setDelayPerUnit(0.1f);//设置帧间隔
	Animate *animate = Animate::create(animation);

	return animate;
}

void Boss2::update(float dt)
{
	this->setPositionY(this->getPositionY() - _step);
	if (this->getPositionY() < 0)
	{
		this->setIsRemove(true);
		this->removeFromParent();
	}
	else if (_isbomb == true)
	{
		this->setPositionY(this->getPositionY() - _step);
		if (this->getPositionY() < 0)
			this->setIsRemove(true);
		else if (_isbomb == true)
		{
			auto callfunc = [this](){
				this->setIsRemove(true);
				this->removeFromParent();
			};
			//先停住
			_step = 0;
			//爆炸
			this->unscheduleUpdate();
			//this->runAction(animateBomb());
			this->runAction(Sequence::create(animateBomb(), CallFunc::create(callfunc), nullptr));
		}
	}
		
}
 

//


bool Boss3::init()
{
	if (Sprite::initWithSpriteFrameName("enemy3_n1.png") == false)
		return false;

	//移动速度
	this->_step = 1;
	this->_HP = 2;
	this->_isbomb = false;

	actionMove();
	this->scheduleUpdate();
	return true;
}
void Boss3::actionMove()
{
	this->runAction(RepeatForever::create(animateMove()));
}
//
void Boss3::reduceHP()
{
	if (_HP > 0)
	{
		this->stopAllActions();
		this->runAction(Sequence::create(animateHit(), RepeatForever::create(animateMove()), nullptr));//animateHit());
		log("%d", _HP);
		_HP--;
	}
	else
	{
		setIsbomb(true);
	}
}
Animate *Boss3::animateMove()
{
	Animate * animate = nullptr;
	
	SpriteFrame *frame = nullptr;
	Vector<SpriteFrame *> frameVec;


	int frameNum = 2;
	for (int i = 0; i < frameNum; i++)
	{
		frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(StringUtils::format("enemy3_n%d.png", i + 1).c_str());
		frameVec.pushBack(frame);
	}

	Animation *animation = Animation::createWithSpriteFrames(frameVec);
	animation->setLoops(1);//设置次数
	animation->setDelayPerUnit(0.4f);//设置帧间隔
	animate = Animate::create(animation);

	return animate;
}


Animate *Boss3::animateHit()
{
	SpriteFrame *frame = nullptr;
	Vector<SpriteFrame *> frameVec;


	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy3_n1.png");
	frameVec.pushBack(frame);
	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy3_n2.png");
	frameVec.pushBack(frame);
	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy3_hit.png");
	frameVec.pushBack(frame);
	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy3_n1.png");
	frameVec.pushBack(frame);

	Animation *animation = Animation::createWithSpriteFrames(frameVec);
	animation->setLoops(1);//设置次数
	animation->setDelayPerUnit(0.1f);//设置帧间隔
	Animate *animate = Animate::create(animation);

	return animate;
}


Animate *Boss3::animateBomb()
{
	SpriteFrame *frame = nullptr;
	Vector<SpriteFrame *> frameVec;


	int frameNum = 6;
	for (int i = 0; i < frameNum; i++)
	{
		frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(StringUtils::format("enemy3_down%d.png", i + 1).c_str());
		frameVec.pushBack(frame);
	}

	Animation *animation = Animation::createWithSpriteFrames(frameVec);
	animation->setLoops(1);//设置次数
	animation->setDelayPerUnit(0.1f);//设置帧间隔
	Animate *animate = Animate::create(animation);

	return animate;
}
//
//void Boss3::SelfToRemove()
//{
//	this->removeFromParent();
//}
//

void Boss3::update(float dt)
{
	this->setPositionY(this->getPositionY() - _step);
	if (this->getPositionY() < 0)
	{
		this->setIsRemove(true);
		this->removeFromParent();
	}
	else if (_isbomb == true)
	{
		auto callfunc = [this](){
			this->setIsRemove(true);
			this->removeFromParent();
		};
		//先停住
		_step = 0;
		//爆炸
		this->unscheduleUpdate();
		this->stopAllActions();
		//this->runAction(animateBomb());
		this->runAction(Sequence::create(animateBomb(), CallFunc::create(callfunc), nullptr));
	}

}
//
//void Boss3::setStep(int step)
//{
//	_step = step;
//}
//
//


bool Bullet::init()
{
	if (Sprite::initWithSpriteFrameName("bullet1.png") == false)
		return false;

	this->setStep(20);
	this->scheduleUpdate();
	return true;
}

void Bullet::update(float dt)
{
	this->setPositionY(getPositionY() + _step);
	if (getIsbomb() == true)
	{
		this->setIsRemove(true);
		this->removeFromParent();
	}
	else if (this->getPositionY() > (Director::getInstance()->getVisibleSize().height + getContentSize().height / 2))
	
		this->setIsRemove(true);
		this->removeFromParent();
	}
}
三、实现基本游戏场景的基本功能

1.在场景的init()方法中生成英雄飞机和一定数量的Boss飞机,初始化英雄飞机的触摸时间(根据触摸点移动英雄飞机,生成子弹)。

bool GameScene::init()
{
	Layer::init();
	SpriteFrameCache::getInstance()->addSpriteFramesWithFile("shoot.plist", "shoot.png");
	VisbelSize = Director::getInstance()->getVisibleSize();

	initHero();
	initListener();
	initBoss();
	initaddBoss();

	this->scheduleUpdate();
	return true;
}

2.在定时随机产生Boss飞机和检测子弹、英雄飞机对Boss的碰撞:

//产生Boss
void GameScene::addBoss(float dt)
{
	int number = 0;
	for (int i = 0; i < 1; i++)
	{
		number = rand() % 10;
		//log("%d", number);
		if (number < 1)
		{
			auto boss = Boss3::create();
			auto x = boss->getContentSize().width / 2 + rand() % (int)(VisbelSize.width - boss->getContentSize().width * 2);
			boss->setPosition(Vec2(x, VisbelSize.height + boss->getContentSize().height / 2));
			this->addChild(boss);

			_bosses.pushBack(boss);;
		}
		else if (number > 2 && number < 4)
		{
			auto boss = Boss2::create();
			auto x = boss->getContentSize().width / 2 + rand() % (int)(VisbelSize.width - boss->getContentSize().width * 2);
			boss->setPosition(Vec2(x, VisbelSize.height + boss->getContentSize().height / 2));
			this->addChild(boss);

			_bosses.pushBack(boss);
		}
		else
		{
			auto boss = Boss1::create();
			auto x = boss->getContentSize().width / 2 + rand() % (int)(VisbelSize.width - boss->getContentSize().width * 2);
			boss->setPosition(Vec2(x, VisbelSize.height + boss->getContentSize().height / 2));
			this->addChild(boss);

			_bosses.pushBack(boss);
		}

	}
}


这里通过两个Vector管理子弹和Boss飞机的碰撞检测和销毁,这里有个bug,是有时候碰撞检测不准确。望高手指点。


void GameScene::update(float dt)
{
	for (auto ieBoss = _bosses.begin(); ieBoss != _bosses.end(); ieBoss++)
	{
		//log("%d", _bosses.size());
		if ((*ieBoss)->getBox().intersectsRect(_hero->getBox()))
		{
			(*ieBoss)->setIsbomb(true);
		}
		for (auto ieBullet = _bullets.begin(); ieBullet != _bullets.end(); ieBullet++)
		{
			if ((*ieBoss)->getBoundingBox().intersectsRect((*ieBullet)->getBoundingBox()))
			{
				(*ieBullet)->setIsRemove(true);
				(*ieBoss)->reduceHP();
			}
		}
	}
	for (auto ieBoss = _bosses.begin(); ieBoss != _bosses.end(); ieBoss++)
	{
		if ((*ieBoss)->getIsRemove() == true)
		{
			_bosses.erase(ieBoss);
			break;
		}
	}

	for (auto ieBoss = _bullets.begin(); ieBoss != _bullets.end(); ieBoss++)
	{
		if ((*ieBoss)->getIsRemove() == true)
		{
			_bullets.erase(ieBoss);
			break;
		}
	}
}


源码和资源下载:

http://download.csdn.net/detail/shinhwalin/8886755



相关文章推荐

其实,前端一点也不简单

大多人都认为前端开发是一个「相对于其他技术来说更简单的技术」,在他们心中的前端工程师是这样工作的: 把 Photoshop 文件、图片或者线框放进一个网页; 偶尔设计 Photoshop 文...

C语言其实不简单:sizeof

首先谈点题外话:C语言中一共有多少个关键字?答:32个。答不上来的没关系,很正常,我们玩的是程序的艺术,而不是背数字。不过这个特殊的数字1...

C++中的单例模式其实也不简单

单例模式也称为单件模式、单子模式,可能是使用最广泛的设计模式。其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。有很多地方需要这样的功能模块,如系统的日志输出,G...

java微信飞机大战,简单实现 -swing界面

import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage; import java.io.*; i...
  • zwyjg
  • zwyjg
  • 2014年01月11日 17:54
  • 22332

项目开源其实不简单-从一段开源经历说起

以下是mogotest负责人在将项目过程中的一个心路历程自白,从中我们可以学习到将项目开源过程中需要注意的很多事项,总结一下: 1.必须明确开源的范围。可能一个完整的项目包括很多的组件和模块,要对其...

简单的飞机大战的原理

  • 2015年08月01日 09:44
  • 74KB
  • 下载

飞机大战简单版

  • 2015年05月15日 19:53
  • 481KB
  • 下载

UI设计-不简单?简单(1)

UI设计是一门很重要的技术,代码谁都能学会,谁都能做。但是做设计的不一定谁都能做的了。因为UI是直接和用户相关的,用户才不管你的后台代码是如何实现的。用户关系的是直接和用户“碰面”的UI,只有UI设计...

飞机大战cocos2d-x简单版

  • 2015年11月15日 15:36
  • 722KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:《简单的飞机大战》其实不简单(1)
举报原因:
原因补充:

(最多只允许输入30个字)