<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><span style="white-space:pre"> </span>这是一个很easy的《经典飞机大战》游戏。实现的基本功能:包含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
时间: 2024-10-12 02:26:17