失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 仿《雷霆战机》飞行射击手游开发--飞机(含源码库地址)

仿《雷霆战机》飞行射击手游开发--飞机(含源码库地址)

时间:2023-12-03 10:01:56

相关推荐

仿《雷霆战机》飞行射击手游开发--飞机(含源码库地址)

本游戏正式开放源代码啦~~

代码库(可在附件中下载Windows下的试玩程序):/thorqq/RaidenFree

下面我们继续分析这款游戏。

飞机

这是一款打飞机游戏,所以主角当然是飞机。游戏里,飞机包括以下几种:

玩家飞机:玩家控制的主飞机

僚机:在玩家飞机左右的小飞机,相对于玩家飞机的位置是固定不变的。

普通敌机:不会变形的敌机

变形敌机:飞到指定位置后变形,然后开始射击。被击落时,屏幕会震动

BOSS:从屏幕上方飞下来,飞到指定位置后变形,然后开始左右移动,同时开始射击。boss可以有多次变形,当血量低于一定值时会触发变形,同时攻击力增强。Boss被击落后,飞机上会产生多次爆炸,屏幕会伴随着震动。

必杀僚机:必杀技。当玩家点击必杀按钮时,会从屏幕下方出现一个庞大的飞机,发射超级激光

飞机的基本属性

名字

类型

骨骼动画(飞行、左右侧飞、变形、暴走、尾部火焰)

生命值

攻击值:当飞机与飞机相撞时,对对方飞机产生的伤害值

碰撞体(刚体)的中心坐标和大小(只有当子弹的碰撞体与飞机的碰撞体发生重叠时,才会产生伤害)

缩放比例

血槽的样式和位置

飞机的初始位置(对于玩家飞机来说,一般是从屏幕下方飞入;对于敌机来说,一般是从上半个屏幕的某个地方飞出来)

子弹(弹夹BulletGroup+子弹Bullet)

僚机

飞机爆炸帧动画和音效

扩展属性(可扩展,用map来实现)

我们用结构体TAircraftData来表示:

struct TAircraftData

{

int id;

std::string name;//名字

std::string type;//类型,值为AircraftType

//飞机动画即支持帧动画,又支持骨骼动画

std::vectorstd::string styleArray; //飞机动画

float aniDura; //动画帧时长

std::string armatureName; //骨骼动画名称

int hp; //当前生命值int maxHp; //最大生命值float defence; //防御int attack; //攻击float bodyCenterX; //刚体中心坐标float bodyCenterY;float bodySizeW; //刚体尺寸float bodySizeH;float scale; //缩放比例std::string hpBgStyle; //血槽背景样式std::string hpStyle; //血槽样式float hpPosX;//血槽的位置float hpPosY;//血槽的位置std::vector<std::vector<int>*> bulletIdArray; //多种子弹std::vector<std::string> fireFameNameArray; //尾部火焰动画,图片列表float fireAniDura; //动画帧时长int fireOnTop;float fireOffsetX;//火焰中心点相对于飞机底部中心点的偏移。如果等于0,则只有一个火焰;否则是两个火焰float fireOffsetY;float startPosX; //飞机的起始位置float startPosY;std::vector<int> wingmanArray; //僚机std::vector<std::string> blastStyleArray; //飞机爆炸的动画float blastAniDura;int blastMusicId; //飞机爆炸的音效idstd::map<std::string, std::string> paramMap; //飞机参数

}

基本方法

初始化、复位、销毁

生命的减少或增加、判断是否活着

开始射击、停止射击、是否正在射击

飞行

爆炸

高级方法

开始自动射击、停止自动射击、自动改变子弹级别

子弹升一个等级

子弹升到最高等级

子弹降一个等级

是否是最高级别子弹

是否是最低级别子弹

获取子弹等级

重置子弹等级

子弹用完发出的通知

更新装备

防御效果的增加、去除

详细代码如下:

//飞机的基类

class Aircraft : public GameObject, public IBulletUseUpListener

{

public:

Aircraft();

virtual ~Aircraft();

virtual bool init(Node* parent, const TAircraftData* pData, const TAircraftLevelData* pLevelData = nullptr);virtual void reset();virtual void destory();virtual void reduceHp(int hp);virtual void recoverHp(int hp);virtual bool isAlive();virtual void startShoot();virtual void stopShoot();virtual bool isShooting();virtual void autoShoot();virtual void stopAutoShoot();virtual void autoChangeBulletGrade();//自动飞行virtual void fly(){};//爆炸virtual void blast();//更新装备bool updateEquip();//子弹升级virtual bool upgradeBullet();virtual bool upgradeMaxBullet();//子弹降级virtual bool downgradeBullet();//是否暴走virtual bool isMaxLevelBullet();//是否最低级子弹virtual bool isMinLevelBullet();//获取子弹等级virtual int getBulletLevel();//重置子弹级别virtual bool resetBulletLevel();//子弹用完通知virtual void bulletUseUp() override;//量子护盾void addShield();void removeShield();//防御效果结束virtual void defenceDone(float dt);//碰撞检测virtual bool isCollsion(const Rect& rect, Rect* pCollsionRect = nullptr);//获取攻击、防御、导弹、僚机、综合性能inline int getAttrAttack(){ return m_iAttrAttack; }inline int getAttrArmor() { return m_iAttrArmor; }inline int getAttrMissile(){ return m_iAttrMissile; }inline int getAttrWingman() { return m_iAttrWingman; }inline int getAttrTotal() { return m_iAttrTotal; }void calculateAttr();inline int getId(){return m_data.id;}inline int getLevelId(){if (m_data.pAircraftLevelData){return m_data.pAircraftLevelData->id;}else{return -1;}}inline int getHp(){return m_data.hp;}inline void setHp(int hp){m_data.hp = hp;}inline int getMaxHp(){return m_data.maxHp;}inline void setMaxHp(int max){m_data.maxHp = max;}inline int getAttack(){//两机相撞时,对对方产生的伤害就是自己的血量return getHp();}inline void setAttack(int a){m_data.attack = a;}void setNoDie(bool b);inline bool isNoDie(){return m_bNoDie;}inline Vector<BulletGroup*>* getBulletGroupArray(){return &m_bulletGroupArray;}inline EAircraftType getAircraftType(){return m_eAircraftType;}inline const std::string& getAttr(const std::string& key){static std::string empty = "";auto it = m_data.paramMap.find(key);if (it != m_data.paramMap.end()){return it->second;}else{return empty;}}inline int getAircraftLevelId(){if (m_data.pAircraftLevelData){return m_data.pAircraftLevelData->id;}else{return -1;}}Vector<Aircraft*>* getOtherSidePlane() const;void setOtherSidePlane(Vector<Aircraft*>* const planes);//回收virtual void recycle();//重用virtual void reuse();//是否已回收(是否可用)bool isRecycled();

protected:

virtual void setBulletGrade(unsigned grade){ m_iBulletGrade = grade; }

virtual void setAttackAdjust(float adjust){ m_fAttackAdjust = adjust; }

virtual void setMissileAdjust(float adjust){ m_fMissileAdjust = adjust; }

virtual void setBulletSpeedAdjust(float adjust){ m_fBulletSpeedAdjust = adjust; }

virtual bool initBody(Node* parent, const TAircraftData* pData);virtual bool initPosition(Node* parent, const TAircraftData* pData);virtual bool initFire(Node* parent, const TAircraftData* pData);virtual bool initHpBar(Node* parent, const TAircraftData* pData);virtual bool initBullet(Node* parent, const TAircraftData* pData);virtual bool initWingman(Node* parent, const TAircraftData* pData);//添加尾部的左右两个火焰动画bool addFire(float offsetX, float offsetY, bool isFlipped);

protected:

EAircraftType m_eAircraftType;

TAircraftData m_data;

const TAircraftData* m_pDataCopy;

//战机所有的装备const TEquipmentData* m_pEquipAircraft;const TEquipmentData* m_pEquipArmature;const TEquipmentData* m_pEquipMissile;const TEquipmentData* m_pEquipWingman;int m_iBulletGrade;float m_fAttackAdjust;float m_fMissileAdjust;float m_fBulletSpeedAdjust;float m_fVipRelifeAttrAdjust;float m_fDefence; //防御系数float m_fDefenceDura; //防御持续时间int m_iCurBulletGrade; //当前子弹等级bool m_bNoDie; //无敌cocostudio::Armature* m_pDefenceBall;//护盾球HpBar* m_pHpBar; //血槽精灵Vector<BulletGroup*> m_bulletGroupArray; //多种子弹Vector<Aircraft*> m_wingmanArray;//僚机精灵Vector<Aircraft*>* m_otherSideArray; //对方飞机。对于玩家来说就是敌机,对于敌机来说就是玩家int m_iAttrAttack;int m_iAttrArmor;int m_iAttrMissile;int m_iAttrWingman;int m_iAttrTotal;bool m_bRecycled;bool m_bAutoShoot;int m_orignBulletGrade;

};

为了构建不同的飞机对象,我们增加一个飞机工厂。工厂的create函数中TAircraftData参数是从配置(sqlite数据库)中获取到的。

template

class PlaneCreator

{

public:

static T* create(Node* parent, const TAircraftData* data)

{

T *pRet = new(std::nothrow) T();

if (pRet && pRet->init(parent, data))

{

pRet->autorelease();

return pRet;

}

else

{

delete pRet;

pRet = NULL;

return NULL;

}

}

};

飞机池

当界面上的飞机较多,并且频繁出现、被击落的时候,系统会不停的创建、销毁飞机对象,这样会严重影响游戏的帧率,所以,我们增加了一个简单的飞机池:当飞机被击落时,飞机对象并没有被销毁掉,而只是停止射击、停止所有动画并隐藏起来。当需要创建新的飞机时,会从池中查找有没有对应的已回收的飞机,如果找到,则对此对象重新进行初始化。代码如下:

class AircraftPool

{

public:

static AircraftPool* getInstance();

//获取一架飞机template<typename T>T* get(Node* parent, const TAircraftData* pAircraftData, const TAircraftLevelData* pAircraftLevelData){//AircraftPool 只在急速模式下使用。其他两种模式反而会增加内存if (GameData::getInstance()->getValueToInt(GAMEDATA::MODE) != ModeBase::ModeRapid){return PlaneCreator<T>::create(parent, pAircraftData, pAircraftLevelData);}auto it = m_aircraftMap.find(pAircraftLevelData->id);std::vector<Aircraft*>* pArray = nullptr;if (it != m_aircraftMap.end()){pArray = it->second;}else{pArray = new std::vector<Aircraft*>;m_aircraftMap.insert(std::map<int, std::vector<Aircraft*>*>::value_type(pAircraftLevelData->id, pArray));}//查找可用的飞机for (Aircraft* p : *pArray){if (p && p->isRecycled()){p->reuse();T* ret = dynamic_cast<T*>(p);if (ret){parent->addChild(ret);return ret;}else{DEBUG_LOG("fuck error type of aircraft");}}}//没找到,新建一个auto p = PlaneCreator<T>::create(parent, pAircraftData, pAircraftLevelData);p->retain();for (unsigned i = 0; i < pArray->size(); i++){if ((*pArray)[i] == nullptr){(*pArray)[i] = p;return p;}}pArray->push_back(p);return p;}//回收一架飞机void recycle(Aircraft* pAircraft);//清空poolvoid release();

protected:

AircraftPool();

private:

static AircraftPool* m_pInstance;

std::map<int, std::vector<Aircraft*>*> m_aircraftMap;

};

AircraftPool* AircraftPool::m_pInstance = nullptr;

AircraftPool* AircraftPool::getInstance()

{

if (!m_pInstance)

{

m_pInstance = new AircraftPool();

}

return m_pInstance;

}

AircraftPool::AircraftPool()

{

}

//回收一架飞机

void AircraftPool::recycle(Aircraft* pAircraft)

{

//如果在池中,则回收;否则直接销毁

auto it = m_aircraftMap.find(pAircraft->getAircraftLevelId());

std::vector<Aircraft*>* pArray = nullptr;

if (it != m_aircraftMap.end())

{

pArray = it->second;

for (Aircraft* p : *pArray)

{

if (p == pAircraft)

{

p->recycle();

return;

}

}

}

pAircraft->destory();

}

//清空pool

void AircraftPool::release()

{

for (auto it : m_aircraftMap)

{

bool bInUse = false;

std::vector<Aircraft*>* pArray = it.second;

for (Aircraft* p : *pArray)

{

if (p && p->isRecycled())

{

p->destory();

p->release();

}

else if §

{

bInUse = true;

DEBUG_LOG(“Aircraft[%d] can’t release”, p->getId());

//CCASSERT(false, “Release error aircraft”);

}

}

if (!bInUse){pArray->clear();delete pArray;}}m_aircraftMap.clear();

}

//

//下面是Aircraft对象中的回收、重用等方法

//回收

void Aircraft::recycle()

{

if (m_bRecycled)

{

return;

}

setNoDie(false);//for (int i = 0; i < m_bulletGroupArray.size(); i++)//{// m_bulletGroupArray.at(i)->setPlane(NULL);//}stopShoot();for (int i = 0; i < m_wingmanArray.size(); i++){//m_wingmanArray.at(i)->recycle();AircraftPool::getInstance()->recycle(m_wingmanArray.at(i));}pause();m_bRecycled = true;

}

//重用

void Aircraft::reuse()

{

if (!m_bRecycled)

{

return;

}

if (m_pHpBar){m_pHpBar->setMaxValue(m_data.maxHp);m_pHpBar->setCurValue(m_data.maxHp);}m_data.hp = m_data.maxHp;//for (int i = 0; i < m_bulletGroupArray.size(); i++)//{// m_bulletGroupArray.at(i)->setPlane(this);//}m_iCurBulletGrade = 0;for (int i = 0; i < m_wingmanArray.size(); i++){m_wingmanArray.at(i)->reuse();}if (m_pArmature){m_pArmature->setColor(Color3B::WHITE);m_pArmature->getAnimation()->play(GlobalData::getInstance()->getArmatureData(m_data.armatureName)->defaultAction);}else{this->setColor(Color3B::WHITE);}resume();m_bRecycled = false;

}

//是否已回收(是否可用)

bool Aircraft::isRecycled()

{

return m_bRecycled;

}

如果觉得《仿《雷霆战机》飞行射击手游开发--飞机(含源码库地址)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。