zoukankan      html  css  js  c++  java
  • 《简单的飞机大战》事实上不简单(1)

    <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><span style="white-space:pre">	</span>这是一个很easy的《经典飞机大战》游戏。实现的基本功能:包含Boss的随机生成,击中销毁;分数依据击毁Boss的数量添加。

    附加功能有:道具的不定时产生,当英雄飞机碰撞到道具产生该道具的道具效果。</span>

    </pre><pre name="code" class="cpp">

    这里仅仅实现最基本功能。

    环境搭配:

    1.操作系统;Win7

    2.cocos2d-x版本号:3.2

    3.VS版本号:VS2013


    一、首先确定飞机基类

    1.在这里,因为节点的getBoundingBox()的到的矩形比实际要检測碰撞的矩形大效果不好,另一些英雄飞、和Boss飞机和子弹的同样的功能。首先写出一个公共基类:

    class BoxTest :public cocos2d::Sprite
    {
    public:
    	//CREATE_FUNC(BoxTest);
    	//virtual bool init();
    
    	cocos2d::Rect getBox();
    
    	virtual void setStep(int step){ _step = step; }
    	//是否爆炸
    	virtual void setIsbomb(bool bomb) { _isbomb = bomb; }
    	virtual bool getIsbomb() const { return _isbomb; }
    
    	//被击中后降低最多击中次数
    	virtual void reduceHP(){ ; };
    	virtual int getHP() const { return _HP; };
    	virtual void setHP(int hp){ _HP = hp; }
    	virtual void setIsRemove(bool isremove){ _isremove = isremove; }
    	virtual bool getIsRemove() const { return _isremove; }
    
    	//击中动画
    	virtual Animate *animateHit(){ return nullptr; };
    	//爆炸动画
    	virtual Animate *animateBomb(){ return nullptr; };
    
    protected:
    	float Minx;
    	float Miny;
    
    	//移动步数 速度
    	int _step;
    	//是否爆炸
    	bool _isbomb;
    	//最多被击中次数,为0时爆炸
    	int _HP;
    
    	bool _isremove;
    
    
    };


    2.实现该类的部分方法:

    Rect BoxTest::getBox()
    {
    	Minx = this->getPosition().x - this->getContentSize().width / 2 * 0.5;
    	Miny = this->getPosition().y - this->getContentSize().height / 2 * 0.5;
    
    	return Rect(Minx, Miny, this->getContentSize().width * 0.5, this->getContentSize().height * 0.5);
    }
    
    二、创建英雄飞机和Boss飞机

    1.继承上述公共基类:

    class Boss1 :public BoxTest
    {
    public:
    	CREATE_FUNC(Boss1);
    	virtual bool init();
    
    	virtual void update(float dt);
    
    	//击中时降低挤肿次数
    	virtual void reduceHP();
    
    	//击中动画
    	virtual Animate *animateHit();
    	//爆炸动画
    	virtual Animate *animateBomb();
    	
    };
    class Boss2 :public BoxTest
    {
    public:
    	CREATE_FUNC(Boss2);
    	virtual bool init();
    
    	virtual void update(float dt);
    
    	//击中时降低挤肿次数
    	virtual void reduceHP();
    
    	//击中动画
    	virtual Animate *animateHit();
    	//爆炸动画
    	virtual Animate *animateBomb();
    
    };
    //最牛逼的飞机
    class Boss3 :public BoxTest
    {
    public:
    	CREATE_FUNC(Boss3);
    	virtual bool init();
    
    	virtual void update(float dt);
    
    	//击中时降低挤肿次数
    	virtual void reduceHP();
    	void actionMove();
    	Animate *animateMove();
    	//击中动画
    	virtual Animate *animateHit();
    	//爆炸动画
    	virtual Animate *animateBomb();
    
    };
    //英雄飞机
    class Plane :public BoxTest
    {
    public:
    	CREATE_FUNC(Plane);
    	virtual bool init();
    	virtual	void update(float dt);
    };
    
    
    class Bullet :public BoxTest
    {
    public:
    	CREATE_FUNC(Bullet);
    	virtual bool init();
    
    	virtual void update(float dt);
    };
    2.实现继承方法:

    bool Plane::init()
    {
    	if (Sprite::initWithSpriteFrameName("hero1.png") == false)
    		return false;
    	//log("1%f    %f", this->getContentSize().width, this->getContentSize().height);
    	//this->setContentSize(Size(this->getContentSize().width * 0.7f, this->getContentSize().height * 0.7f));
    	//this->setScale(0.7f);
    	//log("2%f    %f", this->getContentSize().width, this->getContentSize().height);
    	this->scheduleUpdate();
    	return true;
    }
    
    void Plane::update(float dt)
    {
    	auto VisbelSize = Director::getInstance()->getVisibleSize();
    	if ((this->getPosition().x > (VisbelSize.width - this->getContentSize().width / 2)))
    	{
    		this->setPositionX(VisbelSize.width - this->getContentSize().width / 2 - 6);
    	}
    	else if ((this->getPosition().x < this->getContentSize().width / 2))
    	{
    		this->setPositionX(this->getContentSize().width / 2 - 6);
    	}
    	else if ((this->getPosition().y >(VisbelSize.height - this->getContentSize().height / 2)))
    	{
    		this->setPositionY(VisbelSize.height - this->getContentSize().height / 2);
    	}
    	else if ((this->getPosition().y < this->getContentSize().height / 2))
    	{
    		this->setPositionY(this->getContentSize().height / 2);
    	}
    }
    
    //最小的Boss
    bool Boss1::init()
    {
    	if (Sprite::initWithSpriteFrameName("enemy1.png") == false)
    		return false;
    
    	//移动速度
    	this->_step = 3;
    	this->_HP = 0;
    	this->_isbomb = false;
    
    
    	this->scheduleUpdate();
    	return true;
    }
    
    void Boss1::reduceHP()
    {
    	if (_HP > 0)
    	{
    		this->runAction(this->animateHit());
    		_HP--;
    	}
    	else
    	{
    		setIsbomb(true);
    	}
    }
    
    
    Animate *Boss1::animateHit()
    {
    	SpriteFrame *frame = nullptr;
    	Vector<SpriteFrame *> frameVec;
    
    
    	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy2.png");
    	frameVec.pushBack(frame);
    	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy2_hit.png");
    	frameVec.pushBack(frame);
    	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy2.png");
    	frameVec.pushBack(frame);
    
    
    	Animation *animation = Animation::createWithSpriteFrames(frameVec);
    	animation->setLoops(1);//设置次数
    	animation->setDelayPerUnit(0.2f);//设置帧间隔
    	Animate *animate = Animate::create(animation);
    
    	return animate;
    }
    
    
    Animate *Boss1::animateBomb()
    {
    	SpriteFrame *frame = nullptr;
    	Vector<SpriteFrame *> frameVec;
    
    
    	int frameNum = 4;
    	for (int i = 0; i < frameNum; i++)
    	{
    		frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(StringUtils::format("enemy1_down%d.png", i + 1).c_str());
    		frameVec.pushBack(frame);
    	}
    
    	Animation *animation = Animation::createWithSpriteFrames(frameVec);
    	animation->setLoops(1);//设置次数
    	animation->setDelayPerUnit(0.1f);//设置帧间隔
    	Animate *animate = Animate::create(animation);
    
    	return animate;
    }
    
    
    void Boss1::update(float dt)
    {
    	this->setPositionY(this->getPositionY() - _step);
    	if (this->getPositionY() < 0)
    	{
    		this->setIsRemove(true);
    		this->removeFromParent();
    	}
    	else if (_isbomb == true)
    	{
    		this->setPositionY(this->getPositionY() - _step);
    		if (this->getPositionY() < 0)
    		{
    			this->setIsRemove(true);
    			this->removeFromParent();
    		}
    		else if (_isbomb == true)
    		{
    			auto callfunc = [this](){
    				this->setIsRemove(true);
    				this->removeFromParent();
    			};
    			//先停住
    			_step = 0;
    			//爆炸
    			this->unscheduleUpdate();
    			//this->runAction(animateBomb());
    			this->runAction(Sequence::create(animateBomb(), CallFunc::create(callfunc), nullptr));
    		}
    	}
    
    }
    
    
    
    
    //中间Boss
    bool Boss2::init()
    {
    	if (Sprite::initWithSpriteFrameName("enemy2.png") == false)
    		return false;
    
    	//移动速度
    	this->_step = 2;
    	this->_HP = 1;
    	this->_isbomb = false;
    
    
    	this->scheduleUpdate();
    	return true;
    }
    
    void Boss2::reduceHP()
    {
    	if (_HP > 0)
    	{
    		this->runAction(animateHit());
    		_HP--;
    	}
    	else
    	{
    		setIsbomb(true);
    	}
    }
    
    
    Animate *Boss2::animateHit()
    {
    	SpriteFrame *frame = nullptr;
    	Vector<SpriteFrame *> frameVec;
    
    
    	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy2.png");
    	frameVec.pushBack(frame);
    	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy2_hit.png");
    	frameVec.pushBack(frame);
    	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy2.png");
    	frameVec.pushBack(frame);
    
    
    	Animation *animation = Animation::createWithSpriteFrames(frameVec);
    	animation->setLoops(1);//设置次数
    	animation->setDelayPerUnit(0.1f);//设置帧间隔
    	Animate *animate = Animate::create(animation);
    
    	return animate;
    }
    
    
    Animate *Boss2::animateBomb()
    {
    	SpriteFrame *frame = nullptr;
    	Vector<SpriteFrame *> frameVec;
    
    
    	int frameNum = 4;
    	for (int i = 0; i < frameNum; i++)
    	{
    		frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(StringUtils::format("enemy2_down%d.png", i + 1).c_str());
    		frameVec.pushBack(frame);
    	}
    
    	Animation *animation = Animation::createWithSpriteFrames(frameVec);
    	animation->setLoops(1);//设置次数
    	animation->setDelayPerUnit(0.1f);//设置帧间隔
    	Animate *animate = Animate::create(animation);
    
    	return animate;
    }
    
    void Boss2::update(float dt)
    {
    	this->setPositionY(this->getPositionY() - _step);
    	if (this->getPositionY() < 0)
    	{
    		this->setIsRemove(true);
    		this->removeFromParent();
    	}
    	else if (_isbomb == true)
    	{
    		this->setPositionY(this->getPositionY() - _step);
    		if (this->getPositionY() < 0)
    			this->setIsRemove(true);
    		else if (_isbomb == true)
    		{
    			auto callfunc = [this](){
    				this->setIsRemove(true);
    				this->removeFromParent();
    			};
    			//先停住
    			_step = 0;
    			//爆炸
    			this->unscheduleUpdate();
    			//this->runAction(animateBomb());
    			this->runAction(Sequence::create(animateBomb(), CallFunc::create(callfunc), nullptr));
    		}
    	}
    		
    }
     
    
    //
    
    
    bool Boss3::init()
    {
    	if (Sprite::initWithSpriteFrameName("enemy3_n1.png") == false)
    		return false;
    
    	//移动速度
    	this->_step = 1;
    	this->_HP = 2;
    	this->_isbomb = false;
    
    	actionMove();
    	this->scheduleUpdate();
    	return true;
    }
    void Boss3::actionMove()
    {
    	this->runAction(RepeatForever::create(animateMove()));
    }
    //
    void Boss3::reduceHP()
    {
    	if (_HP > 0)
    	{
    		this->stopAllActions();
    		this->runAction(Sequence::create(animateHit(), RepeatForever::create(animateMove()), nullptr));//animateHit());
    		log("%d", _HP);
    		_HP--;
    	}
    	else
    	{
    		setIsbomb(true);
    	}
    }
    Animate *Boss3::animateMove()
    {
    	Animate * animate = nullptr;
    	
    	SpriteFrame *frame = nullptr;
    	Vector<SpriteFrame *> frameVec;
    
    
    	int frameNum = 2;
    	for (int i = 0; i < frameNum; i++)
    	{
    		frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(StringUtils::format("enemy3_n%d.png", i + 1).c_str());
    		frameVec.pushBack(frame);
    	}
    
    	Animation *animation = Animation::createWithSpriteFrames(frameVec);
    	animation->setLoops(1);//设置次数
    	animation->setDelayPerUnit(0.4f);//设置帧间隔
    	animate = Animate::create(animation);
    
    	return animate;
    }
    
    
    Animate *Boss3::animateHit()
    {
    	SpriteFrame *frame = nullptr;
    	Vector<SpriteFrame *> frameVec;
    
    
    	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy3_n1.png");
    	frameVec.pushBack(frame);
    	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy3_n2.png");
    	frameVec.pushBack(frame);
    	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy3_hit.png");
    	frameVec.pushBack(frame);
    	frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("enemy3_n1.png");
    	frameVec.pushBack(frame);
    
    	Animation *animation = Animation::createWithSpriteFrames(frameVec);
    	animation->setLoops(1);//设置次数
    	animation->setDelayPerUnit(0.1f);//设置帧间隔
    	Animate *animate = Animate::create(animation);
    
    	return animate;
    }
    
    
    Animate *Boss3::animateBomb()
    {
    	SpriteFrame *frame = nullptr;
    	Vector<SpriteFrame *> frameVec;
    
    
    	int frameNum = 6;
    	for (int i = 0; i < frameNum; i++)
    	{
    		frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(StringUtils::format("enemy3_down%d.png", i + 1).c_str());
    		frameVec.pushBack(frame);
    	}
    
    	Animation *animation = Animation::createWithSpriteFrames(frameVec);
    	animation->setLoops(1);//设置次数
    	animation->setDelayPerUnit(0.1f);//设置帧间隔
    	Animate *animate = Animate::create(animation);
    
    	return animate;
    }
    //
    //void Boss3::SelfToRemove()
    //{
    //	this->removeFromParent();
    //}
    //
    
    void Boss3::update(float dt)
    {
    	this->setPositionY(this->getPositionY() - _step);
    	if (this->getPositionY() < 0)
    	{
    		this->setIsRemove(true);
    		this->removeFromParent();
    	}
    	else if (_isbomb == true)
    	{
    		auto callfunc = [this](){
    			this->setIsRemove(true);
    			this->removeFromParent();
    		};
    		//先停住
    		_step = 0;
    		//爆炸
    		this->unscheduleUpdate();
    		this->stopAllActions();
    		//this->runAction(animateBomb());
    		this->runAction(Sequence::create(animateBomb(), CallFunc::create(callfunc), nullptr));
    	}
    
    }
    //
    //void Boss3::setStep(int step)
    //{
    //	_step = step;
    //}
    //
    //
    
    
    bool Bullet::init()
    {
    	if (Sprite::initWithSpriteFrameName("bullet1.png") == false)
    		return false;
    
    	this->setStep(20);
    	this->scheduleUpdate();
    	return true;
    }
    
    void Bullet::update(float dt)
    {
    	this->setPositionY(getPositionY() + _step);
    	if (getIsbomb() == true)
    	{
    		this->setIsRemove(true);
    		this->removeFromParent();
    	}
    	else if (this->getPositionY() > (Director::getInstance()->getVisibleSize().height + getContentSize().height / 2))
    	
    		this->setIsRemove(true);
    		this->removeFromParent();
    	}
    }
    
    三、实现基本游戏场景的基本功能

    1.在场景的init()方法中生成英雄飞机和一定数量的Boss飞机。初始化英雄飞机的触摸时间(依据触摸点移动英雄飞机,生成子弹)。

    bool GameScene::init()
    {
    	Layer::init();
    	SpriteFrameCache::getInstance()->addSpriteFramesWithFile("shoot.plist", "shoot.png");
    	VisbelSize = Director::getInstance()->getVisibleSize();
    
    	initHero();
    	initListener();
    	initBoss();
    	initaddBoss();
    
    	this->scheduleUpdate();
    	return true;
    }

    2.在定时随机产生Boss飞机和检測子弹、英雄飞机对Boss的碰撞:

    //产生Boss
    void GameScene::addBoss(float dt)
    {
    	int number = 0;
    	for (int i = 0; i < 1; i++)
    	{
    		number = rand() % 10;
    		//log("%d", number);
    		if (number < 1)
    		{
    			auto boss = Boss3::create();
    			auto x = boss->getContentSize().width / 2 + rand() % (int)(VisbelSize.width - boss->getContentSize().width * 2);
    			boss->setPosition(Vec2(x, VisbelSize.height + boss->getContentSize().height / 2));
    			this->addChild(boss);
    
    			_bosses.pushBack(boss);;
    		}
    		else if (number > 2 && number < 4)
    		{
    			auto boss = Boss2::create();
    			auto x = boss->getContentSize().width / 2 + rand() % (int)(VisbelSize.width - boss->getContentSize().width * 2);
    			boss->setPosition(Vec2(x, VisbelSize.height + boss->getContentSize().height / 2));
    			this->addChild(boss);
    
    			_bosses.pushBack(boss);
    		}
    		else
    		{
    			auto boss = Boss1::create();
    			auto x = boss->getContentSize().width / 2 + rand() % (int)(VisbelSize.width - boss->getContentSize().width * 2);
    			boss->setPosition(Vec2(x, VisbelSize.height + boss->getContentSize().height / 2));
    			this->addChild(boss);
    
    			_bosses.pushBack(boss);
    		}
    
    	}
    }


    这里通过两个Vector管理子弹和Boss飞机的碰撞检測和销毁,这里有个bug,是有时候碰撞检測不准确。

    望高手指点。


    void GameScene::update(float dt)
    {
    	for (auto ieBoss = _bosses.begin(); ieBoss != _bosses.end(); ieBoss++)
    	{
    		//log("%d", _bosses.size());
    		if ((*ieBoss)->getBox().intersectsRect(_hero->getBox()))
    		{
    			(*ieBoss)->setIsbomb(true);
    		}
    		for (auto ieBullet = _bullets.begin(); ieBullet != _bullets.end(); ieBullet++)
    		{
    			if ((*ieBoss)->getBoundingBox().intersectsRect((*ieBullet)->getBoundingBox()))
    			{
    				(*ieBullet)->setIsRemove(true);
    				(*ieBoss)->reduceHP();
    			}
    		}
    	}
    	for (auto ieBoss = _bosses.begin(); ieBoss != _bosses.end(); ieBoss++)
    	{
    		if ((*ieBoss)->getIsRemove() == true)
    		{
    			_bosses.erase(ieBoss);
    			break;
    		}
    	}
    
    	for (auto ieBoss = _bullets.begin(); ieBoss != _bullets.end(); ieBoss++)
    	{
    		if ((*ieBoss)->getIsRemove() == true)
    		{
    			_bullets.erase(ieBoss);
    			break;
    		}
    	}
    }


    源代码和资源下载:

    http://download.csdn.net/detail/shinhwalin/8886755



  • 相关阅读:
    047.Python前端html
    Python利用PyExecJS库执行JS函数-实战破解字段加密
    Frida用法之函数操作
    Frida的安装步骤基于Android系统组合Python语言
    利用Python多线程来测试并发漏洞
    微信公众号:Mysticbinary
    Windows系统下解决PhPStudy MySQL启动失败
    crontab 定时任务没有响应 检测步骤
    解决Android killer APK 编译失败,无法继续下一步签名
    Python操作MySQL的一些坑
  • 原文地址:https://www.cnblogs.com/wzzkaifa/p/6724415.html
Copyright © 2011-2022 走看看