C++ 与cocos2d-x-4.0完成太空飞机大战 (五)

本文详细介绍使用C++与cocos2d-x-4.0框架进行太空飞机大战游戏开发的过程,涵盖敌人精灵、控制器及关卡设计。通过具体代码展示如何创建不同类型的敌人、实现动画效果以及碰撞检测。

动画演示

游戏画面演示

敌人精灵编码:EnemySprite.cpp

#include "EnemySprite.h"
#include "ActionBase.h"
#include "Util.h"

namespace SpaceWar {

	EnemySprite::EnemySprite()
	{
	}

	EnemySprite::~EnemySprite()
	{
	}

	void EnemySprite::update(float dt)
	{

	}
}

敌人精灵编码:EnemySprite.h

#pragma once
#include "cocos2d.h"
#include "SpriteBase.h"

using namespace std;
using namespace cocos2d;

namespace SpaceWar
{
	class ActionBase;

	class EnemySprite : public SpriteBase
	{
	public:
		EnemySprite();
		virtual ~EnemySprite();

		void update(float dt);

		ActionBase* actBase = nullptr;

		/*敌人类型*/
		int enemyType = 0;

		/*杀死得分*/
		int killScore = 0;

		/*敌人速度*/
		float enemySpeed = 10.0f;

		/*武器威力*/
		int armPower = 6;

		/*武器类型*/
		int armType = 0;

		/*武器上次发射时间*/
		long armTime = 0;

		/*碰撞次数*/
		int collisionCount = 0;

		/*最大碰撞次数*/
		int maxCollisionCount = 0;

		/*碰撞类型掩码*/
		int category = 0b111;

		/*碰撞掩码*/
		int collision = 0b000;

		/*碰撞事件掩码*/
		int contact = 0b110;

		/*是否允许重力*/
		bool gravityEnable = false;

		/*是否允许碰撞*/
		bool collisionEnable = false;
	};
}


敌人编码:Enemy.cpp

#include "Enemy.h"
#include "ActionBase.h"

namespace SpaceWar {

	Enemy::Enemy()
	{
	}

	Enemy::~Enemy()
	{
	}

	bool Enemy::createEnemy(int eType)
	{
		enemyType = eType;
		string enemyImg = getEnemyImg();
		auto pinfo = AutoPolygon::generatePolygon(enemyImg);
		sprite = new EnemySprite();
		sprite->actBase = this->actBase;
		EnemySprite::create(sprite, pinfo);
		if (sprite != nullptr)
		{
			sprite->setName(Util::getGUID(32));
			int tag = 10;
			sprite->enemyType = eType;
			auto size = sprite->getContentSize();
			auto body = Util::getPhysicsBody(pinfo, size, tag, sprite->category, sprite->collision, sprite->contact, sprite->gravityEnable);
			sprite->setPhysicsBody(body);
			sprite->setTag(tag);
			return true;
		}
		return false;
	}

	void Enemy::setMaxCollisionCount(EnemySprite* es, int eType)
	{
		Size ssize = es->getBoundingBox().size;
		float wh = ssize.width;
		if (ssize.height > ssize.width)
		{
			wh = ssize.height;
		}
		es->maxCollisionCount = 1;
		es->killScore = 1;
		if (eType==0) 
		{
			if (wh > 300)
			{
				es->maxCollisionCount = 20;
				es->killScore = 20;
			}
			else if (wh > 250)
			{
				es->maxCollisionCount = 16;
				es->killScore = 16;
			}
			else if (wh > 200)
			{
				es->maxCollisionCount = 12;
				es->killScore = 12;
			}
			else if (wh > 150)
			{
				es->maxCollisionCount = 8;
				es->killScore = 8;
			}
			else if (wh > 100)
			{
				es->maxCollisionCount = 6;
				es->killScore = 6;
			}
			else if (wh > 50)
			{
				es->maxCollisionCount = 4;
				es->killScore = 4;
			}
			else if (wh > 20)
			{
				es->maxCollisionCount = 2;
				es->killScore = 2;
			}
		}
	}

	string Enemy::getEnemyImg() {
		string s = "";
		if (enemyType == 0)
		{
			s = "ys" + to_string(random(1, 4)) + ".png";
		}
		else if (enemyType == 1)
		{
			s = "enemy/e_air01.png";
		}
		return s;
	}
}

敌人编码:Enemy.h

#pragma once
#include <vector>
#include "cocos2d.h"
#include "Util.h"
#include "EnemySprite.h"

using namespace std;
using namespace cocos2d;

namespace SpaceWar
{
	class ActionBase;

	class Enemy
	{
	public:
		Enemy();
		virtual ~Enemy();

		ActionBase* actBase = nullptr;

		/*敌人精灵*/
		EnemySprite* sprite;

		/*敌人类型*/
		int enemyType = 0;

		/*初始化敌人*/
		virtual bool createEnemy(int aType);

		/*设置最大碰撞次数*/
		void setMaxCollisionCount(EnemySprite * es, int eType);

		/*根据敌人类型返回对应图片*/
		string getEnemyImg();

	};
}


关卡1敌人编码:EnemyScene1.cpp

#include "EnemyScene1.h"
#include "renderer/backend/Device.h"
#include "ActionBase.h"

USING_NS_CC;

namespace SpaceWar {

	EnemyScene1::EnemyScene1()
	{
	}

	EnemyScene1::~EnemyScene1()
	{
	}

	bool EnemyScene1::createEnemys()
	{
		if (!Util::isIntervalTime(100, &baseTime, &enemyTime[0]))
		{
			return false;
		}
		createMeteorite();
		createEnemyAircraft();
	}

	bool EnemyScene1::createMeteorite()
	{
		if (baseTime < 100000)
		{
			return createMeteorite(200, 0.1f, 0.5f, 10.0f);
		}
		else if (baseTime < 200000)
		{
			return createMeteorite(200, 0.1f, 1.0f, 10.0f);
		}
		else
		{
			return createMeteorite(200, 0.1f, 1.5f, 8.0f);
		}
	}

	bool EnemyScene1::createEnemyAircraft()
	{
		if (baseTime < 10000) 
		{
		}
		else if (baseTime < 100000)
		{
			return createEnemyAircraft(10000, 100, 100, 20.0f);
		}
		else if (baseTime < 200000)
		{
			return createEnemyAircraft(10000, 200, 200, 20.0f);
		}
		else
		{
			return createEnemyAircraft(10000, 400, 400, 20.0f);
		}
	}

	bool EnemyScene1::createMeteorite(int delayTime, float sScale, float eScale, float speed)
	{
		if (!Util::isIntervalTime(delayTime, &enemyTime[500]))
		{
			return false;
		}
		Enemy enemy;
		enemy.actBase = this->actBase;
		if (enemy.createEnemy(0))
		{
			enemy.sprite->enemySpeed = speed;
			enemy.sprite->setScale(random(sScale, eScale));
			enemy.sprite->setRotation(random(0.0f, 360.0f));
			enemy.setMaxCollisionCount(enemy.sprite, enemy.enemyType);
			int sHeight = enemy.sprite->getContentSize().height;
			float px = actBase->origin.x + random(0.0f, actBase->vSize.width);
			float py = actBase->vSize.height + actBase->origin.y + sHeight * 2 + random(0.0f, actBase->vSize.height);
			enemy.sprite->setPosition(Vec2(px, py));
			actBase->addChild(enemy.sprite, 0);
			auto moveTo = MoveTo::create(enemy.sprite->enemySpeed, Vec2(px, -(sHeight * 2)));
			auto actRuin = CallFunc::create(std::bind(&EnemyScene1::removeRuin, this, enemy.sprite));
			auto sequence = Sequence::create(moveTo, actRuin, NULL);
			enemy.sprite->runAction(sequence);
			return true;
		}
		return false;
	}

	bool EnemyScene1::createEnemyAircraft(int delayTime, int score, int collision, float speed)
	{
		if (!Util::isIntervalTime(delayTime, &enemyTime[501]))
		{
			return false;
		}
		Enemy enemy;
		enemy.actBase = this->actBase;
		if (enemy.createEnemy(1))
		{
			enemy.sprite->enemySpeed = speed;
			enemy.sprite->maxCollisionCount = collision;
			enemy.sprite->killScore = score;
			enemy.sprite->enemySpeed = 20.0f;
			int sHeight = enemy.sprite->getContentSize().height;
			float px = actBase->origin.x + random(0.0f, actBase->vSize.width);
			float py = actBase->vSize.height + actBase->origin.y + sHeight * 2 + random(0.0f, actBase->vSize.height);
			enemy.sprite->setPosition(Vec2(px, py));
			actBase->addChild(enemy.sprite, 4);
			auto moveTo = MoveTo::create(enemy.sprite->enemySpeed, Vec2(px, -(sHeight * 2)));
			auto actRuin = CallFunc::create(std::bind(&EnemyScene1::removeRuin, this, enemy.sprite));
			auto sequence = Sequence::create(moveTo, actRuin, NULL);
			enemy.sprite->runAction(sequence);
			return true;
		}
		return false;
	}

	void EnemyScene1::createRuinAnimate(Node* node)
	{
		EnemySprite* eSprite = dynamic_cast<EnemySprite*>(node);
		if (eSprite->enemyType==1) 
		{
			createSerialBombRuinAnimate(eSprite);
		}
		else 
		{
			createRuinAnimate(eSprite);
		}
	}

	void EnemyScene1::createChangeColorAnimate(Node* node)
	{
		EnemySprite* eSprite = dynamic_cast<EnemySprite*>(node);
		if (eSprite->enemyType == 1)
		{
			createChangeColorAnimate(eSprite);
		}
	}

	void EnemyScene1::createChangeColorAnimate(EnemySprite* eSprite)
	{
		/*auto * fu = FileUtils::getInstance();
		auto vertexShader = fu->getStringFromFile("shaders/example_ColorBars.vsh");
		auto fragmentShader = fu->getStringFromFile("shaders/example_ColorBars.fsh");
		auto program = backend::Device::getInstance()->newProgram(vertexShader.c_str(), fragmentShader.c_str());
		auto programState = new backend::ProgramState(program);
		eSprite->setProgramState(programState);*/
	}

	void EnemyScene1::createRuinAnimate(EnemySprite* eSprite)
	{
		auto size = eSprite->getBoundingBox().size;
		auto position = eSprite->getPosition();
		SpriteFrameCache::getInstance()->addSpriteFramesWithFile("ysbz.plist");
		auto frames = Util::getAnimation("ysbz-%d.png", 16);
		auto sprite = Sprite::createWithSpriteFrame(frames.front());
		auto ssize = sprite->getContentSize();
		auto wf = size.width / ssize.width;
		auto hf = size.height / ssize.height;
		sprite->setScale(wf, hf);
		sprite->setPosition(position.x, position.y);
		actBase->addChild(sprite);

		auto animation = Animation::createWithSpriteFrames(frames, 1.0f / 16);
		auto animate = Animate::create(animation);
		auto repeat = Repeat::create(animate, 1);
		auto actRuin = CallFunc::create(std::bind(&EnemyScene1::removeRuin, this, sprite));
		auto sequence = Sequence::create(repeat, actRuin, NULL);
		playBOMB(eSprite);
		sprite->runAction(sequence);
	}

	void EnemyScene1::createSerialBombRuinAnimate(EnemySprite* eSprite)
	{
		Vec2 svec = eSprite->getPosition();
		Size size = eSprite->getBoundingBox().size;
		float sw = svec.x - size.width / 2;
		float ew = svec.x + size.width / 2;
		float sh = svec.y - size.height / 2;
		float eh = svec.y + size.height / 2;
		SpriteFrameCache::getInstance()->addSpriteFramesWithFile("fjbz.plist");
		auto frames = Util::getAnimation("fjbz(%d).png", 16);
		int tag = 6;
		for (int i = 0; i < 50; ++i)
		{
			auto delayAnimate = CallFunc::create(std::bind(&EnemyScene1::createSerialBombRuin, this, frames, sw, ew, sh, eh));
			auto dtime = DelayTime::create(random(0.0f, 1.0f));
			auto sequence = Sequence::create(dtime, delayAnimate, NULL);
			actBase->runAction(sequence);
		}
	}

	void EnemyScene1::createSerialBombRuin(Vector<SpriteFrame*> frames, float sw, float ew, float sh, float eh)
	{
		auto bsprite = Sprite::createWithSpriteFrame(frames.front());
		bsprite->setScale(random(1.0f, 2.0f));
		bsprite->setPosition(Vec2(random(sw, ew), random(sh, eh)));
		auto animation = Animation::createWithSpriteFrames(frames, 1.0f / 16);
		auto animate = Animate::create(animation);
		auto repeat = Repeat::create(animate, 1);
		auto actRuin = CallFunc::create(std::bind(&EnemyScene1::removeRuin, this, bsprite));
		auto sequence = Sequence::create(repeat, actRuin, NULL);
		bsprite->runAction(sequence);
		float mtime = random(0.2f, 1.0f);
		Vec2 move = Vec2(0.0f, random(-100.0f, -50.0f));
		auto moveBy = MoveBy::create(mtime, move);
		bsprite->runAction(moveBy);
		actBase->addChild(bsprite, 3);
		AudioEngine::play2d("BOMB1.ogg", false, 0.5f);
	}

	void EnemyScene1::playBOMB(EnemySprite* eSprite)
	{
		auto size = eSprite->getBoundingBox().size;
		float sz = size.height;
		if (size.width > size.height)
		{
			sz = size.width;
		}
		if (eSprite->enemyType == 0)
		{
			if (sz > 300)
			{
				AudioEngine::play2d("BOMB6.ogg", false, 0.5f);
			}
			else if (sz > 250)
			{
				AudioEngine::play2d("BOMB5.ogg", false, 0.5f);
			}
			else if (sz > 200)
			{
				AudioEngine::play2d("BOMB4.ogg", false, 0.5f);
			}
			else if (sz > 100)
			{
				AudioEngine::play2d("BOMB3.ogg", false, 0.5f);
			}
			else if (sz > 50)
			{
				AudioEngine::play2d("BOMB2.ogg", false, 0.5f);
			}
			else
			{
				AudioEngine::play2d("BOMB1.ogg", false, 0.5f);
			}
		}
	}

	void EnemyScene1::removeRuin(Sprite* sprite)
	{
		actBase->enemyNodes.erase(sprite->getName());
		sprite->removeFromParentAndCleanup(true);
	}

	Sprite* EnemyScene1::createRuinSprite()
	{
		SpriteFrameCache::getInstance()->addSpriteFramesWithFile("ysbz.plist");
		auto frames = Util::getAnimation("ysbz-%d.png", 16);
		auto sprite = Sprite::createWithSpriteFrame(frames.front());
		return sprite;
	}
}

关卡1敌人编码:EnemyScene1.h

#pragma once
#include <vector>
#include "cocos2d.h"
#include "audio/include/AudioEngine.h"
#include "Enemy.h"
#include "Util.h"

using namespace std;
using namespace cocos2d;

namespace SpaceWar
{
	class ActionBase;

	class EnemyScene1
	{
	public:
		EnemyScene1();

		virtual ~EnemyScene1();

		bool createEnemys();

		ActionBase* actBase = nullptr;
		
		bool createMeteorite();

		bool createEnemyAircraft();

		bool createMeteorite(int delayTime, float sScale, float eScale, float speed);

		bool createEnemyAircraft(int delayTime, int score, int collision, float speed);

		void createRuinAnimate(Node * node);

		void createChangeColorAnimate(Node * node);

		void createChangeColorAnimate(EnemySprite * eSprite);

		void createRuinAnimate(EnemySprite * eSprite);

		void createSerialBombRuinAnimate(EnemySprite * eSprite);

		void createSerialBombRuin(Vector<SpriteFrame*> frames, float sw, float ew, float sh, float eh);

		void playBOMB(EnemySprite * eSprite);

		void removeRuin(Sprite * sprite);

		Sprite * createRuinSprite();

		long enemyTime[1000];

		long baseTime = 0;
	};
}


控制器编码:Control.cpp

#include "Control.h"

namespace SpaceWar {

	Control::Control()
	{
	}

	Control::~Control()
	{
	}
}

控制器编码:Control.h

#pragma once
namespace SpaceWar
{
	class Control
	{
	public:
		Control();
		virtual ~Control();
		int controlAct[400];
	};
}


全文完

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值