林炳文Evankaka原创作品。转载请注明出处http://www.jb51.cc/tag/http://blog.csdn.net/evankaka
本文从设计模式中的策略模式入手,主讲了飞机大战中英雄飞机切换不同的子d。这里分为三种子d。第一种:每次发一个子d,垂直发射;第二种:每次发两个子d,两个都是垂直发射:第三种;每次发三个子d,两边的子d有一定的角度,而中间的子d垂直发射;设计模式是游戏开发经常用到的思想,建议有兴趣的同学可以好好研究下!好了,下面开始吧。
效果如下:
Cocos2d-x版本:3.4
工程环境:VS30213
一、策略模式(Stragegy Pattern) 1、简介Strategy模式也叫策略模式是行为模式之一,它对一系列的算法加以封装,为所有算法定义一个抽象的算法接口,并通过继承该抽象算法接口对所有的算法加以封装和实现,具体的算法选择交由客户端决定(策略)。Strategy模式主要用来平滑地处理算法的切换 。
2、意图定义一系列的算法,把它们一个个封装起来,并且它们可相互替换。使得算法可独立于使用它的客户而变化。
3、适用性 如果一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。 一个系统需要动态的在几种算法中选择一种。那么这些算法可以包装到一个个的具体算法类里面,而这些算法类都是一个抽象算法类的子类。换言之,这些具体算法类均有统一的接口,由于多态性原则,客户端可以选择使用任何一个具体算法类,并只持有一个数据类型是抽象算法的对象。 一个系统的算法使用的数据不可以让客户端知道。策略模式可以避免让客户端涉及到不必要接触到的和复杂的只与算法有关的数据。 如果一个类定义了多种行为,并且这些行为在这个类的 *** 作中以多个条件语句的形式出现。将相关的条件分支移到它们各自的Strategy类中以代替这些条件语句。 更多详细的策略模式看这里吧: 24天学会设计模式------策略模式二.子d类与子d管理类的代码编写首先来看下本文的类UML图:
这里的思路是把子d发射当成是一个函数,基类子d中定义成虚函数,然后实现类子d中HeroBulletone、HeroBulletTwo、HeroBulletThree分别实现不同的发射功能。然后在子d管理类中HeroBulletLayer中有一个私有的成员变量BulletStyle *mBulletStyle.当需要切换不同的子d时,就将new不同的HeroBulletone或HeroBulletTwo或HeroBulletThree,赋给mBulletStyle。
下面我们来看看代码吧!!!
2.1 首先是子d的基类:BulletStyle.h,这里注意到virtual voID shootBullet(float dt){}为虚函数,表示这里要根据的子类不同,发射不同的子d数目;
/***功能 创建子d的基类*作者 林炳文(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(); /** *移除超出屏幕可视范围的子d或者碰撞后的子d清除 *@param pNode 要删除的子d */ voID removeBullet(Node* pNode); /** *根据传入的飞机,子d跟随发射 *@param plane为传入飞机,可为英雄飞机或敌机 */ virtual voID createBullet(Node* plane); /** *发射子d,在其中进行子d的渲染和子d的飞行动作,默认为单子d *@param dt子d间隔发时间 */ virtual voID shootBullet(float dt){} protected: //子d容器 Vector <Sprite *> vecBullet; //批次渲染节点 SpriteBatchNode* bulletBatchNode; //传入的飞机 Node* plane;};#endif实现文件BulletStyle.cpp
/***功能 创建子d的基类*作者 林炳文(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(); }/*** 移除子d,将子d从容器中移除,同时也从SpriteBatchNode中移除*/voID BulletStyle::removeBullet(Node* pNode) { if (NulL == pNode) { return; } Sprite* bullet = (Sprite*)pNode; bulletBatchNode->removeChild(bullet,true); vecBullet.eraSEObject(bullet);}/***根据传入的飞机,子d跟随发射*@param plane为传入飞机,可为英雄飞机或敌机*/voID BulletStyle::createBullet(Node* plane){ this->plane = plane; //创建BatchNode节点 bulletBatchNode = SpriteBatchNode::create("bullet1.png"); this->addChild(bulletBatchNode); //每隔0.2S调用一次发射子d函数 schedule(schedule_selector(BulletStyle::shootBullet),0.2f);//注意,这里的发射方法留给子类来实现!!!}2.2 只发射一个子d的类HeroBulletone.h,注意,直接继承
/***功能 每次只发射一个子d*作者 林炳文(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实现文件:
/***功能 每次只发射一个子d*作者 林炳文(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(); //从缓存中创建子d auto spritebullet = Sprite::createWithTexture(bulletBatchNode->getTexture()); //将创建好的子d添加到BatchNode中进行批次渲染 bulletBatchNode->addChild(spritebullet); //将创建好的子d添加到容器 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;//实际飞行的时间 //子d运行的距离和时间,从飞机处开始运行到屏幕顶端 auto actionMove = Moveto::create(realFlyDuration,Point(bulletPos.x,winSize.height)); //子d执行完动作后进行函数回调,调用移除子d函数 auto actionDone = CallFuncN::create( CC_CALLBACK_1(HeroBulletone::removeBullet,this)); //子d开始跑动 Sequence* sequence = Sequence::create(actionMove,actionDone,NulL); spritebullet->runAction(sequence); }2.3 发射二个子d的类HeroBulletTwo.h,注意,直接继承
/***功能 每次发射二个子d*作者 林炳文(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实现文件:
/***功能 每次发射二个子d*作者 林炳文(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(); //从缓存中创建子d auto spritebullet1 = Sprite::createWithTexture(bulletBatchNode->getTexture()); auto spritebullet2 = Sprite::createWithTexture(bulletBatchNode->getTexture()); //将创建好的子d添加到BatchNode中进行批次渲染 bulletBatchNode->addChild(spritebullet1); bulletBatchNode->addChild(spritebullet2); //将创建好的子d添加到容器 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;//实际飞行的时间 //子d运行的距离和时间,从飞机处开始运行到屏幕顶端 auto actionMove1 = Moveto::create(realFlyDuration,Point(bulletPos1.x,winSize.height)); auto actionMove2 = Moveto::create(realFlyDuration,Point(bulletPos2.x,winSize.height)); //子d执行完动作后进行函数回调,调用移除子d函数 auto actionDone = CallFuncN::create( CC_CALLBACK_1(HeroBulletTwo::removeBullet,this)); //子d开始跑动 Sequence* sequence1 = Sequence::create(actionMove1,NulL); spritebullet1->runAction(sequence1); Sequence* sequence2 = Sequence::create(actionMove2,NulL); spritebullet2->runAction(sequence2); }2.4 发射三个子d的类HeroBulletThree.h,注意,直接继承
/***功能 每次发射三个子d*作者 林炳文(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实现文件:
/***功能 每次发射三个子d*作者 林炳文(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;//旋轉的角度 //从缓存中创建子d auto spritebullet = Sprite::createWithTexture(bulletBatchNode->getTexture()); auto spritebullet1 = Sprite::createWithTexture(bulletBatchNode->getTexture()); spritebullet1->setRotation(-angle); auto spritebullet2 = Sprite::createWithTexture(bulletBatchNode->getTexture()); spritebullet2->setRotation(angle); //将创建好的子d添加到BatchNode中进行批次渲染 bulletBatchNode->addChild(spritebullet); bulletBatchNode->addChild(spritebullet1); bulletBatchNode->addChild(spritebullet2); //将创建好的子d添加到容器 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;//实际飞行的时间 //子d运行的距离和时间,从飞机处开始运行到屏幕顶端 auto actionMove = Moveto::create(realFlyDuration,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)); //子d执行完动作后进行函数回调,调用移除子d函数 auto actionDone = CallFuncN::create( CC_CALLBACK_1(HeroBulletThree::removeBullet,NulL); spritebullet->runAction(sequence); Sequence* sequence1 = Sequence::create(actionMove1,NulL); spritebullet2->runAction(sequence2); }
2.5、子d管理器编写
/***功能 管理子d、切换不同的子d*作者 林炳文(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(); //根据英雄飞机创建子d static HeroBulletLayer* create(Node* heroPlane); //改变子d voID changeBullet(int bulletNumber);public: Node* heroPlane;//传入的英雄飞机 BulletStyle *mBulletStyle;//子d类型 int bulletNumber;//当前子d编号};#endif实现文件:
/***功能 管理子d、切换不同的子d*作者 林炳文(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;}/***创建子d的静态方法*@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;}/***切换不同的子d*@param number 表示子d的数目*/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; }}
2.6、调用方法 游戏入口主文件 GameMain.h添加头文件
#include "HeroBulletLayer.h"//这是子d管理的层增加变量:
HeroBulletLayer *mHeroBulletLayer;
然后是实现方法中GameMain.cpp的init()函数中增加
//加子d mHeroBulletLayer = HeroBulletLayer::create(mHeroPlane); this->addChild(mHeroBulletLayer,1);注意mHeroPlane是你的英雄飞机类,是上文中可以跟随手指运动的手机,不懂看这里, Cocos2d-x《雷电大战》(2)-精灵随手指移动,你点哪我走哪! 这里还没写成单例模式的,后头会再来改!
然后就是切换子d啦:
你只需要在要切换子d的地方:
发射一个子d
mHeroBulletLayer->changeBullet(1);发射二个子d
mHeroBulletLayer->changeBullet(2);发射三个子d
mHeroBulletLayer->changeBullet(3);
这里我为了测试,设置成每个5秒自动切换子d类型:
GameMain.h加个变量
int number;//表示当前子d的类型
GameMain.cpp中init()函数中增加:
@H_502_154@//每隔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");}
效果:
这里它会自动每隔5s切换不同的子d,由于上传图片的限制。只能这样了。
三、总结 是不是很方便呢?当我需要增加一个子d类型时,我只需要继承BulletStyle.然后重写函数shootBullet(float dt) 即可。然后在需要更改子d的位置bool HeroBulletLayer::changeBullet(int number)增加每4种子d。第5种子d......这样就增加了代码的复用性,而且很容易懂。也省去了一大堆的if-else判断。
林炳文Evankaka原创作品。转载请注明出处http://www.jb51.cc/tag/http://blog.csdn.net/evankaka
总结以上是内存溢出为你收集整理的Cocos2d-x《雷电大战》(4)-策略模式实现不同子d切换!!全部内容,希望文章能够帮你解决Cocos2d-x《雷电大战》(4)-策略模式实现不同子d切换!!所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)