林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka
本文从设计模式中的策略模式入手,主讲了飞机大战中英雄飞机切换不同的子弹。这里分为三种子弹。第一种:每次发一个子弹,垂直发射;第二种:每次发两个子弹,两个都是垂直发射:第三种;每次发三个子弹,两边的子弹有一定的角度,而中间的子弹垂直发射;设计模式是游戏开发经常用到的思想,建议有兴趣的同学可以好好研究下!好了,下面开始吧。
效果如下:
Cocos2d-x版本:3.4
工程环境:VS30213
Strategy模式也叫策略模式是行为模式之一,它对一系列的算法加以封装,为所有算法定义一个抽象的算法接口,并通过继承该抽象算法接口对所有的算法加以封装和实现,具体的算法选择交由客户端决定(策略)。Strategy模式主要用来平滑地处理算法的切换 。
定义一系列的算法,把它们一个个封装起来,并且它们可相互替换。使得算法可独立于使用它的客户而变化。
/** *功能 创建子弹的基类 *作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka) *时间 2015.3.31 */ #pragma once #ifndef __BulletStyle_H__ #define __BulletStyle_H__ #include "cocos2d.h" USING_NS_CC; class BulletStyle : public cocos2d::Node{ public: ~BulletStyle(); /** * 移除所有的东西 */ void removeAllObject(); /** *移除超出屏幕可视范围的子弹或者碰撞后的子弹清除 *@param pNode 要删除的子弹 */ void removeBullet(Node* pNode); /** *根据传入的飞机,子弹跟随发射 *@param plane为传入飞机,可为英雄飞机或敌机 */ virtual void createBullet(Node* plane); /** *发射子弹,在其中进行子弹的渲染和子弹的飞行动作,默认为单子弹 *@param dt子弹间隔发时间 */ virtual void shootBullet(float dt){} protected: //子弹容器 Vector <Sprite *> vecBullet; //批次渲染节点 SpriteBatchNode* bulletBatchNode; //传入的飞机 Node* plane; }; #endif实现文件BulletStyle.cpp
/** *功能 创建子弹的基类 *作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka) *时间 2015.3.31 */ #include "BulletStyle.h" BulletStyle::~BulletStyle(){ //removeAllObject(); } /** * 移除所有的东西 */ void BulletStyle::removeAllObject(){ bulletBatchNode->removeAllChildren(); vecBullet.clear(); this->removeAllChildren(); } /** * 移除子弹,将子弹从容器中移除,同时也从SpriteBatchNode中移除 */ void BulletStyle::removeBullet(Node* pNode) { if (NULL == pNode) { return; } Sprite* bullet = (Sprite*)pNode; bulletBatchNode->removeChild(bullet, true); vecBullet.eraseObject(bullet); } /** *根据传入的飞机,子弹跟随发射 *@param plane为传入飞机,可为英雄飞机或敌机 */ void BulletStyle::createBullet(Node* plane){ this->plane = plane; //创建BatchNode节点 bulletBatchNode = SpriteBatchNode::create("bullet1.png"); this->addChild(bulletBatchNode); //每隔0.2S调用一次发射子弹函数 schedule(schedule_selector(BulletStyle::shootBullet), 0.2f);//注意,这里的发射方法留给子类来实现!!! }
/** *功能 每次只发射一个子弹 *作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka) *时间 2015.3.31 */ #pragma once #ifndef __HeroBulletOne_H__ #define __HeroBulletOne_H__ #include "cocos2d.h" #include "BulletStyle.h" USING_NS_CC; class HeroBulletOne : public BulletStyle { public: virtual void shootBullet(float dt); }; #endif实现文件:
/** *功能 每次只发射一个子弹 *作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka) *时间 2015.3.31 */ #include "HeroBulletOne.h" void HeroBulletOne::shootBullet(float dt) { Size winSize = Director::getInstance()->getWinSize(); auto PlanePos = plane->getPosition(); //从缓存中创建子弹 auto spritebullet = Sprite::createWithTexture(bulletBatchNode->getTexture()); //将创建好的子弹添加到BatchNode中进行批次渲染 bulletBatchNode->addChild(spritebullet); //将创建好的子弹添加到容器 vecBullet.pushBack(spritebullet); Point bulletPos = (Point(PlanePos.x, PlanePos.y + plane->getContentSize().height / 2 + 20)); spritebullet->setPosition(bulletPos); spritebullet->setScale(0.8f); float flyVelocity = 500;//运行速度,可以自己控制,每秒所走的像素 float flyLen = winSize.height - PlanePos.y; float realFlyDuration = flyLen / flyVelocity;//实际飞行的时间 //子弹运行的距离和时间,从飞机处开始运行到屏幕顶端 auto actionMove = MoveTo::create(realFlyDuration, Point(bulletPos.x, winSize.height)); //子弹执行完动作后进行函数回调,调用移除子弹函数 auto actionDone = CallFuncN::create( CC_CALLBACK_1(HeroBulletOne::removeBullet, this)); //子弹开始跑动 Sequence* sequence = Sequence::create(actionMove, actionDone, NULL); spritebullet->runAction(sequence); }
/** *功能 每次发射二个子弹 *作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka) *时间 2015.3.31 */ #pragma once #ifndef __HeroBulletTwo_H__ #define __HeroBulletTwo_H__ #include "cocos2d.h" #include "BulletStyle.h" USING_NS_CC; class HeroBulletTwo : public BulletStyle { public: virtual void shootBullet(float dt); }; #endif实现文件:
/** *功能 每次发射二个子弹 *作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka) *时间 2015.3.31 */ #include "HeroBulletTwo.h" void HeroBulletTwo::shootBullet(float dt) { Size winSize = Director::getInstance()->getWinSize(); auto PlanePos = plane->getPosition(); //从缓存中创建子弹 auto spritebullet1 = Sprite::createWithTexture(bulletBatchNode->getTexture()); auto spritebullet2 = Sprite::createWithTexture(bulletBatchNode->getTexture()); //将创建好的子弹添加到BatchNode中进行批次渲染 bulletBatchNode->addChild(spritebullet1); bulletBatchNode->addChild(spritebullet2); //将创建好的子弹添加到容器 vecBullet.pushBack(spritebullet1); vecBullet.pushBack(spritebullet2); Point bulletPos1 = (Point(PlanePos.x - plane->getContentSize().width / 4, PlanePos.y + plane->getContentSize().height / 2+10 )); Point bulletPos2 = (Point(PlanePos.x + plane->getContentSize().width / 4, PlanePos.y + plane->getContentSize().height / 2+10)); spritebullet1->setPosition(bulletPos1); spritebullet1->setScale(0.8f); spritebullet2->setPosition(bulletPos2); spritebullet2->setScale(0.8f); float flyVelocity = 500;//运行速度,可以自己控制,每秒所走的像素 float flyLen = winSize.height - PlanePos.y; float realFlyDuration = flyLen / flyVelocity;//实际飞行的时间 //子弹运行的距离和时间,从飞机处开始运行到屏幕顶端 auto actionMove1 = MoveTo::create(realFlyDuration, Point(bulletPos1.x, winSize.height)); auto actionMove2 = MoveTo::create(realFlyDuration, Point(bulletPos2.x, winSize.height)); //子弹执行完动作后进行函数回调,调用移除子弹函数 auto actionDone = CallFuncN::create( CC_CALLBACK_1(HeroBulletTwo::removeBullet, this)); //子弹开始跑动 Sequence* sequence1 = Sequence::create(actionMove1, actionDone, NULL); spritebullet1->runAction(sequence1); Sequence* sequence2 = Sequence::create(actionMove2, actionDone, NULL); spritebullet2->runAction(sequence2); }
/** *功能 每次发射三个子弹 *作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka) *时间 2015.3.31 */ #pragma once #ifndef __HeroBulletThree_H__ #define __HeroBulletThree_H__ #include "cocos2d.h" #include "BulletStyle.h" USING_NS_CC; class HeroBulletThree : public BulletStyle { public: virtual void shootBullet(float dt); }; #endif实现文件:
/** *功能 每次发射三个子弹 *作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka) *时间 2015.3.14 */ #include "HeroBulletThree.h" void HeroBulletThree::shootBullet(float dt) { Size winSize = Director::getInstance()->getWinSize(); auto PlanePos = plane->getPosition(); double angle = M_PI * 80 / 180;//旋轉的角度 //从缓存中创建子弹 auto spritebullet = Sprite::createWithTexture(bulletBatchNode->getTexture()); auto spritebullet1 = Sprite::createWithTexture(bulletBatchNode->getTexture()); spritebullet1->setRotation(-angle); auto spritebullet2 = Sprite::createWithTexture(bulletBatchNode->getTexture()); spritebullet2->setRotation(angle); //将创建好的子弹添加到BatchNode中进行批次渲染 bulletBatchNode->addChild(spritebullet); bulletBatchNode->addChild(spritebullet1); bulletBatchNode->addChild(spritebullet2); //将创建好的子弹添加到容器 vecBullet.pushBack(spritebullet); vecBullet.pushBack(spritebullet1); vecBullet.pushBack(spritebullet2); Point bulletPos = (Point(PlanePos.x, PlanePos.y + plane->getContentSize().height / 2 + 20)); Point bulletPos1 = (Point(PlanePos.x - plane->getContentSize().width / 4-10, PlanePos.y + plane->getContentSize().height / 2+10 )); Point bulletPos2 = (Point(PlanePos.x + plane->getContentSize().width / 4+10, PlanePos.y + plane->getContentSize().height / 2+10)); spritebullet->setPosition(bulletPos); spritebullet->setScale(0.8f); spritebullet1->setPosition(bulletPos1); spritebullet1->setScale(0.8f); spritebullet2->setPosition(bulletPos2); spritebullet2->setScale(0.8f); float flyVelocity = 500;//运行速度,可以自己控制,每秒所走的像素 float flyLen = winSize.height - PlanePos.y; float flyLen1 = PlanePos.x / cos(angle);//按照度來算 float flyLen2 = (winSize.width - PlanePos.x) / cos(angle); float realFlyDuration = flyLen / flyVelocity;//实际飞行的时间 float realFlyDuration1 = flyLen1 / flyVelocity;//实际飞行的时间 float realFlyDuration2 = flyLen2 / flyVelocity;//实际飞行的时间 //子弹运行的距离和时间,从飞机处开始运行到屏幕顶端 auto actionMove = MoveTo::create(realFlyDuration, Point(bulletPos.x, winSize.height)); auto actionMove1 = MoveTo::create(realFlyDuration1, Point(0, PlanePos.x*tan(angle) + PlanePos.y)); auto actionMove2 = MoveTo::create(realFlyDuration2, Point(winSize.width, (winSize.width - PlanePos.x)*tan(angle) + PlanePos.y)); //子弹执行完动作后进行函数回调,调用移除子弹函数 auto actionDone = CallFuncN::create( CC_CALLBACK_1(HeroBulletThree::removeBullet, this)); //子弹开始跑动 Sequence* sequence = Sequence::create(actionMove, actionDone, NULL); spritebullet->runAction(sequence); Sequence* sequence1 = Sequence::create(actionMove1, actionDone, NULL); spritebullet1->runAction(sequence1); Sequence* sequence2 = Sequence::create(actionMove2, actionDone, NULL); spritebullet2->runAction(sequence2); }
/** *功能 管理子弹、切换不同的子弹 *作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka) *时间 2015.3.31 */ #pragma once #ifndef __HeroBulletLayer_H__ #define __HeroBulletLayer_H__ #include "cocos2d.h" #include "BulletStyle.h" #include "HeroBulletOne.h" #include "HeroBulletTwo.h" #include "HeroBulletThree.h" class HeroBulletLayer : public cocos2d::Layer { public: HeroBulletLayer(Node* heroPlane); virtual bool init(); //根据英雄飞机创建子弹 static HeroBulletLayer* create(Node* heroPlane); //改变子弹 void changeBullet(int bulletNumber); public: Node* heroPlane;//传入的英雄飞机 BulletStyle *mBulletStyle;//子弹类型 int bulletNumber;//当前子弹编号 }; #endif实现文件:
/** *功能 管理子弹、切换不同的子弹 *作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka) *时间 2015.3.31 */ #include "HeroBulletLayer.h" HeroBulletLayer::HeroBulletLayer(Node* heroPlane) { this->heroPlane = heroPlane; mBulletStyle = NULL; bulletNumber = 1; } /** *创建子弹的静态方法 *@param heroPlane为英雄飞机 */ HeroBulletLayer* HeroBulletLayer::create(Node* heroPlane){ HeroBulletLayer* pRet = new HeroBulletLayer(heroPlane); if (pRet&&pRet->init()){ pRet->autorelease(); return pRet; } else{ delete pRet; pRet = NULL; return NULL; } } bool HeroBulletLayer::init() { bool bRet = false; do { CC_BREAK_IF(!Layer::init()); mBulletStyle = new HeroBulletOne(); mBulletStyle->autorelease(); mBulletStyle->createBullet(heroPlane); this->addChild(mBulletStyle); bRet = true; } while (0); return bRet; } /** *切换不同的子弹 *@param number 表示子弹的数目 */ void HeroBulletLayer::changeBullet(int number){ switch (number) { case 1: if (bulletNumber != 1){ this->removeChild(mBulletStyle, true); mBulletStyle = new HeroBulletOne(); bulletNumber = 1; mBulletStyle->createBullet(heroPlane); mBulletStyle->autorelease(); this->addChild(mBulletStyle); } break; case 2: if (bulletNumber != 2){ this->removeChild(mBulletStyle, true); mBulletStyle = new HeroBulletTwo(); bulletNumber = 2; mBulletStyle->createBullet(heroPlane); mBulletStyle->autorelease(); this->addChild(mBulletStyle); } break; case 3: if (bulletNumber != 3){ this->removeChild(mBulletStyle, true); mBulletStyle = new HeroBulletThree(); bulletNumber = 3; mBulletStyle->createBullet(heroPlane); mBulletStyle->autorelease(); this->addChild(mBulletStyle); } break; default: break; } }
#include "HeroBulletLayer.h"//这是子弹管理的层增加变量:
HeroBulletLayer *mHeroBulletLayer;
//加子弹 mHeroBulletLayer = HeroBulletLayer::create(mHeroPlane); this->addChild(mHeroBulletLayer,1);注意mHeroPlane是你的英雄飞机类,是上文中可以跟随手指运动的手机,不懂看这里,Cocos2d-x《雷电大战》(2)-精灵随手指移动,你点哪我走哪! 这里还没写成单例模式的,后头会再来改!
mHeroBulletLayer->changeBullet(1);发射二个子弹
mHeroBulletLayer->changeBullet(2);发射三个子弹
mHeroBulletLayer->changeBullet(3);
int number;//表示当前子弹的类型
//每隔5S改變一次子子彈類型 number = 1; schedule(schedule_selector(GameMain::changeBullet),5.0f);
void GameMain::changeBullet(float dt){ if (number == 1){ mHeroBulletLayer->changeBullet(2); number = 2; } else if (number == 2){ mHeroBulletLayer->changeBullet(3); number = 3; } else if (number == 3) { mHeroBulletLayer->changeBullet(1); number = 1; } CCLOG("CHANGE"); }
林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka
Cocos2d-x《雷电大战》(4)-策略模式实现不同子弹切换!!
原文地址:http://blog.csdn.net/evankaka/article/details/44783337