• Cocos2d-x《雷电大战》(3)-子弹无限发射


        林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka

       本文要实现雷电游戏中,游戏一開始,英雄飞机就无限发射子弹的功能。

    这里的思想是单独给子弹弄一个层。在这个层不设置一个定时器,每隔一个时间,依据当前英雄飞机传入的位置,生成子弹,并设置子弹的移动事件,和移动后的事件(就是把子弹删除掉,节省内存)。

    终于效果:


    Cocos2d-x版本号:3.4

    project环境:VS30213


    一、英雄子弹层

    1、HeroBulletLayer.h

    /**
    *功能 创建子弹并初始化子弹的运动
    *作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka)
    *时间 2015.3.14
    */
    #include "cocos2d.h"
    USING_NS_CC;
    const float FlYVElOCITY = 500;//执行速度,能够自己控制。每秒所走的像素
    class HeroBulletLayer : public cocos2d::Layer
    {
    public:
    	HeroBulletLayer(Node* heroPlane);
    	~HeroBulletLayer();
    	virtual bool init();
    
    	//依据英雄飞机创建子弹
    	static HeroBulletLayer* create(Node* heroPlane);
    
    	//移除超出屏幕可视范围的子弹或者碰撞后的子弹清除
    	void removeBullet(Node* pNode);
    
    	//发射子弹。在当中进行子弹的渲染和子弹的飞行动作,默觉得单子弹
    	void ShootBullet(float dt);
    
    	//返回子弹列表
    	Vector <Sprite *>& GetBullet();
    public:
    	Vector <Sprite *>vecBullet;//子弹容器
    	SpriteBatchNode* bulletBatchNode;//批次渲染节点
    	Node* heroPlane;//传入的英雄飞机
    };


    2、HeroBulletLayer.cpp

    /**
    *功能 创建子弹并初始化子弹的运动
    *作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka)
    *时间 2015.3.14
    */
    #include "HeroBulletLayer.h"
    HeroBulletLayer::HeroBulletLayer(Node* heroPlane) {
    	this->heroPlane = heroPlane;
    }
    HeroBulletLayer::~HeroBulletLayer() {
    }
    /**
    *创建子弹的静态方法
    *@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());
    
    		//创建BatchNode节点
    		bulletBatchNode = SpriteBatchNode::create("bullet1.png");
    		this->addChild(bulletBatchNode);
    
    		//每隔0.2S调用一次发射子弹函数
    		this->schedule(schedule_selector(HeroBulletLayer::ShootBullet), 0.2f);
    		bRet = true;
    	} while (0);
    	return bRet;
    }
    /**
    *用缓存的方法创建子弹,并初始化子弹的运动和运动后的事件
    */
    void HeroBulletLayer::ShootBullet(float dt) {
    	Size winSize = Director::getInstance()->getWinSize();
    	auto PlanePos = heroPlane->getPosition();
    	//从缓存中创建子弹
    	auto spritebullet = Sprite::createWithTexture(bulletBatchNode->getTexture());
    	//将创建好的子弹加入到BatchNode中进行批次渲染
    	bulletBatchNode->addChild(spritebullet);
    	//将创建好的子弹加入到容器
    	vecBullet.pushBack(spritebullet);
    
    	Point bulletPos = (Point(PlanePos.x,
    		PlanePos.y + heroPlane->getContentSize().height / 2 + 20));
    	spritebullet->setPosition(bulletPos);
    	spritebullet->setScale(0.8f);
    
    
    	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(HeroBulletLayer::removeBullet, this));
    
    	//子弹開始跑动
    	Sequence* sequence = Sequence::create(actionMove, actionDone, NULL);
    	spritebullet->runAction(sequence);
    
    
    }
    
    /**
     * 移除子弹,将子弹从容器中移除。同一时候也从SpriteBatchNode中移除
     */
    void HeroBulletLayer::removeBullet(Node* pNode) {
    	if (NULL == pNode) {
    		return;
    	}
    	Sprite* bullet = (Sprite*)pNode;
    	this->bulletBatchNode->removeChild(bullet, true);
    	vecBullet.eraseObject(bullet);
    }
    /**
    *返回子弹列表,用来与敌机做碰撞检測
    */
    Vector <Sprite *>& HeroBulletLayer::GetBullet(){
    	return vecBullet;
    }
    

    注意:

    1、

    //创建BatchNode节点
    bulletBatchNode = SpriteBatchNode::create("bullet1.png");
    这里用了把子弹的图片加入到缓存中的方法,然后须要创建子弹时候调用

     //从缓存中创建子弹
        auto spritebullet = Sprite::createWithTexture(bulletBatchNode->getTexture());
    假设不这样做的话,游戏会非常耗内存。就会非常卡!

    2、这里重写了create方法。让它带一个參数,用它来传入英雄飞机

    二、用法

    	//加子弹
    	HeroBulletLayer *mHeroBulletLayer = HeroBulletLayer::create(mHeroPlane);
    	this->addChild(mHeroBulletLayer,1);

    效果:


    要注意mHeroPlane是上一讲中尾随手指移动的英雄飞机,看这里Cocos2d-x《雷电大战》(2)-精灵随手指移动。你点哪我走哪!

    三、思路说明

        1、上面的英雄子弹类非常好用,你仅仅要传入一个英雄飞机的位置。它就会生成英雄子弹层不断调用定时器生成子弹,同一时候加入到当前层中和Vector中(用来保存全部的子弹)

        2、 依据当前英雄飞机的位置。计算子弹移动的距离。然后速度是自己设定的,就能够计算子弹要移动的直线距离的时间。

       3、 当子弹移动到视野外后,就删除掉这个子弹,vector中也要删除。

      4、GetBullet();是用来得到当前的vector子弹集合,然后我们须要一个一个的取出来。推断是否和敌机相撞,假设是,就调用removeBullet(Node* pNode);就是这样了。

    比方:

    void GameMain::update(float dt){
    	auto *mEnemyPlane = getChildByTag(200);
    	Vector <Sprite *> mVecHeroBullet = mHeroBulletLayer->GetBullet();
    	for (int i = 0; i<mVecHeroBullet.size();i++){
    		if (mEnemyPlane->boundingBox().intersectsRect(mVecHeroBullet.at(i)->boundingBox())){
    			mHeroBulletLayer->removeBullet(mVecHeroBullet.at(i));
    		}
    
    	}
    
    }

    效果例如以下:这里要注意下vector的遍历用法,不能[],cocos2dx没有重载这个,要用at.

    这里仅仅是演示样例了下怎么用,子弹碰到飞机后就把它删除掉,敌机还没有做处理

        林炳文Evankaka原创作品。

    转载请注明出处http://blog.csdn.net/evankaka

  • 相关阅读:
    复习题之后缀表达式
    专项训练之枚举
    专项训练之二分
    深夜毒物
    笑面的学校日常(14)最近一次更新2017 04 06
    了不起的竞赛生(7)(最近一次更新2017 04 06)
    水题日常——动态规划 洛谷
    Bzoj 1926: [Sdoi2010]粟粟的书架(二分答案+乱搞+主席树)
    Cogs 1708. 斐波那契平方和(矩阵乘法)
    Codevs 1482 路线统计(矩阵乘法)
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7214299.html
Copyright © 2020-2023  润新知