林炳文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