<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;
};
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);
}
}
}
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