带有武器发射子弹的游戏主界面

接着上次的界面,这次添加了武器主界面,原文出处         http://subject.9ria.com/cocos2d/index.html

现分析如下:


DefenderGameLayer.h

#ifndef __DEFENDERGAME_LAYER_H__
#define __DEFENDERGAME_LAYER_H__
#include "BaseLayer.h"
#include"math.h"
// 这个类是游戏主类
class DefenderGameLayer:public BaseLayer{      
public:
	static cocos2d::CCScene* scene();     //创建场景
	virtual bool init();                  //初始化
	CREATE_FUNC(DefenderGameLayer);       //创建层
	virtual void onEnter();               //加载
	virtual bool ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);//开始触摸
	virtual void ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);//触摸点移动
	virtual void ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);//结束触摸
	virtual void ccTouchCancelled(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);//取消触摸
	
private:
	bool setUpdateViews(); //创建纹理
	void detectd(float tim);// 这个方法用来获取判断子弹是否相撞 是否可以获取子弹
	// 武器的旋转动画执行完的时候执行这个回调函数
	void weapCallBack(cocos2d::CCNode* pSend);
};
#endif

DefenderGameLayer.cpp
#include "DefenderGameLayer.h"
#include "WeaponSprite.h"
#include"math.h"
USING_NS_CC;
CCScene* DefenderGameLayer::scene(){
	CCScene* scene=CCScene::create(); //创建场景
	DefenderGameLayer* layer=DefenderGameLayer::create();//创建该层
	scene->addChild(layer); //将层添加进场景
	return scene;
}
bool DefenderGameLayer::init(){
	bool isRet=false;
	do 
	{
	 CC_BREAK_IF(!BaseLayer::init());
	 CC_BREAK_IF(!setUpdateViews());
	 this->schedule(schedule_selector(DefenderGameLayer::detectd),0.1f);
	 isRet=true;
	} while (0);
	return isRet;
}
bool DefenderGameLayer::setUpdateViews(){
	bool isRet=false;
	do 
	{
	// 设置背景图片
	CCTexture2D* ptext2dBg=CCTextureCache::sharedTextureCache()->textureForKey("gmbg/gamebg.png");
	CCSprite* pSpribg=CCSprite::createWithTexture(ptext2dBg);
	CC_BREAK_IF(!pSpribg);
	pSpribg->setPosition(getWinCenter());
	this->addChild(pSpribg,1);
	//初始化武器系统

	//初始化武器系统
	CCTexture2D* texture=CCTextureCache::sharedTextureCache()->textureForKey("game/weapon.png");
	WeaponSprite* pweapon=WeaponSprite::createWithTexture(texture);
	pweapon->setAnchorPoint(ccp(0.3,0.5));
	pweapon->setPosition(ccp(0,getWinSize().height/2));	
	this->addChild(pweapon,3,2);
	pweapon->setHudu(0);
	pweapon->initIdleBulletSpool(this);// 初始化 子弹系统
	isRet=true;
	} while (0);
	return isRet;
}


 void DefenderGameLayer::onEnter(){
	 BaseLayer::onEnter();
	 CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(  
		 this,//在那个类中实现触屏回调函数  
		 0, //优先级  
		 true);//触摸时间是否被该目标截获  
 }
 bool DefenderGameLayer::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){
	  WeaponSprite* pweapon=(WeaponSprite*) this->getChildByTag(2);
	 CCPoint dpoint=pTouch->getLocation();  //触点坐标
	 CCPoint ypoint=pweapon->getPosition(); //武器坐标
	 float chy=dpoint.y-ypoint.y;  
	 float chx=dpoint.x-ypoint.x;	 
	 float hud=atan(chy/chx);	 //计算弧度

	 float rota=-(hud*(180/PI));	
	  
	  CCActionInterval* paction= CCRotateTo::create(0.2,rota);//转过了rota的角度,是负的

	  CCCallFuncN *onComplete =  CCCallFuncN::create(this, callfuncN_selector(DefenderGameLayer::weapCallBack));  
	  CCSequence* pse=CCSequence::create(paction,onComplete,NULL);
	  pweapon->runAction(pse);//执行武器旋转和子弹旋转动作
	  pweapon->setHudu(-hud);//设置弧度为-hud,因为表示的是转过的角度,而不是真正的角度,顺时针为正
	  pweapon->setStop(true);
	 
	  return true;

 }

 void DefenderGameLayer::weapCallBack(CCNode* pSend){
	   WeaponSprite* pweapon=(WeaponSprite*)pSend;
	   pweapon->rotateLoadedBullets();    //将子弹旋转装载
	    CCLOG("wobiezhixingle");
 }

 void DefenderGameLayer::ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){//触摸移动和触摸时的方法效果是一样的
	 WeaponSprite* pweapon=(WeaponSprite*) this->getChildByTag(2);
	 CCPoint dpoint=pTouch->getLocation();
	 CCPoint ypoint=pweapon->getPosition();
	 float chy=dpoint.y-ypoint.y;
	 float chx=dpoint.x-ypoint.x;	 
	 float hud=atan(chy/chx);		
	 float rota=-(hud*(180/PI));
	
	 CCActionInterval* paction= CCRotateTo::create(0.2,rota);

	 CCCallFuncN *onComplete =  CCCallFuncN::create(this, callfuncN_selector(DefenderGameLayer::weapCallBack));  
	 CCSequence* pse=CCSequence::create(paction,onComplete,NULL);
	 pweapon->runAction(pse);
	 pweapon->setStop(true);
	 pweapon->setHudu(-hud);

 }
 void DefenderGameLayer::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){
	 WeaponSprite* pweapon=(WeaponSprite*) this->getChildByTag(2);//如果触摸结束则武器停止移动
	 pweapon->setStop(false);
 }
 void DefenderGameLayer::ccTouchCancelled(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){
	
 } 
 void DefenderGameLayer::detectd(float tim){     //检测子弹是否碰撞,武器重新上弹
	 WeaponSprite* pweapon=(WeaponSprite*) this->getChildByTag(2);//得到武器精灵对象
	 if(pweapon->getRunBulletsPool()){
		 CCArray* tem=CCArray::create();
		 for(int i=0;i<pweapon->getRunBulletsPool()->count();i++){//子弹池的子弹数量
			 BulletsSprite* pbu=(BulletsSprite*) pweapon->getRunBulletsPool()->objectAtIndex(i);//取得子弹对象池的当前索引的子弹
			 if (pbu->boundingBox().getMinX()>=getWinSize().width||pbu->boundingBox().getMinY()<0||pbu->boundingBox().getMinY()>=getWinSize().height){				
				 pweapon->recoverBullet(pbu); //如果子弹出界则子弹调用重新上弹方法
				 tem->addObject(pbu);//将子弹添加进数组
			 }else {				
				 pbu->mymove();// 调用子弹移动方法
			 }
		 }
		 for(int j=0;j<tem->count();j++){ //
			 pweapon->getRunBulletsPool()->removeObject(tem->objectAtIndex(j),false);
		 }
		 tem->removeAllObjects();
	 }
	 
 }
BulletsSprite.h

#ifndef __BULLETS_SPRITE_H__
#define __BULLETS_SPRITE_H__
#include "cocos2d.h"
class BulletsSprite :public cocos2d::CCSprite
{
public:
	BulletsSprite(void);
	~BulletsSprite(void);
	//virtual bool initWithTexture(cocos2d::CCTexture2D *pTexture);//初始化纹理
	static BulletsSprite* createWithTexture(cocos2d::CCTexture2D *pTexture);//创建对象
	inline void setMovespeed(float movespeed){//设置子弹移动速度
		this->movespeed=movespeed;
	}

	inline	float getMovespeed(){ //得到子弹移动速度
		return movespeed;
	}

	inline void setHurt(float hurt){//设置伤害
		this->hurt=hurt;
	}
	inline	float getHurt(){//得到伤害值
		return hurt;
	}
	cocos2d::CCPoint getMovePoint();// 这个是根据当前速度获取精灵的坐标

	void mymove();//  移动函数
	// 第一次被设置为弓箭的角度
	CC_SYNTHESIZE(float,firstRoto,FirstRoto);//用来设置getter和setter属性
	// 最后一次被弓箭的角度
	CC_SYNTHESIZE(float,lastRoto,LastRoto);
private:
	float movespeed;// 移动速度
	float hurt;// 攻击力伤害值
};
#endif

BulletsSprite.cpp

#include "BulletsSprite.h"
#include "BaseLayer.h"
#include <cmath>
USING_NS_CC;
BulletsSprite* BulletsSprite::createWithTexture(CCTexture2D *pTexture){
	 BulletsSprite *pobSprite = new BulletsSprite();
	if (pobSprite && pobSprite->initWithTexture(pTexture))
	{
		pobSprite->autorelease();
		return pobSprite;
	}
	CC_SAFE_DELETE(pobSprite);
	return NULL;
}
CCPoint  BulletsSprite::getMovePoint(){
	// 这里使用了 三角函数 主要是为了计算当前子弹所移动的位置
	float temhud= (this->getLastRoto()*PI)/180;//将最后的弧度转换成角度
	float tex= std::cos(temhud)*this->movespeed;//将速度乘以cos值得到横坐标
	float tey= std::sin(temhud)*this->movespeed;
	tex=std::fabs(tex);// x 方向不存在负数
	return ccp(tex,-tey);//取得移动的坐标

}
void  BulletsSprite::mymove(){
	CCPoint cp=getMovePoint();
	float x=cp.x+this->getPositionX();
	float y=cp.y+this->getPositionY();//起始位置+移动的坐标	
	this->setPosition(ccp(x,y));//设置位置
}


BulletsSprite::BulletsSprite(void):movespeed(2)//设置速度为2,初始化firstRoto和lastRoto为0
{
	this->firstRoto=0;
	this->lastRoto=0;
}


BulletsSprite::~BulletsSprite(void)
{
}
WeaponSprite.h

#ifndef __WEAPON_SPRITE_H__
#define __WEAPON_SPRITE_H__
#include "cocos2d.h"
#include "BulletsSprite.h"
// 这个是武器系统 用来发射子弹
class WeaponSprite:public cocos2d::CCSprite{
public:
	WeaponSprite();
	
	~WeaponSprite();
	
	CREATE_FUNC(WeaponSprite);//创建WeaponSprite对象
	
	virtual bool initWithTexture(cocos2d::CCTexture2D *pTexture);//初始化纹理
	
	static WeaponSprite* createWithTexture(cocos2d::CCTexture2D *pTexture);
	cocos2d::CCArray* getIdleBullet(int cout);// 根据目前武器系 的级别获取当前子弹的数量默认级别是1个空闲的子弹 
	void recoverBullet(BulletsSprite* pbullet);// 回收掉一个子弹
	void initIdleBulletSpool(cocos2d::CCLayer* pLayer);// 初始化子弹池 
	CC_SYNTHESIZE(bool,stop,Stop);
	// 设置当前的武器旋转的弧度制
	void setHudu(float hudu);
	inline cocos2d::CCSpriteBatchNode* getBatchNode(){//得到批量穿件节点
		return batchNode;
	}
	inline	cocos2d::CCArray* getRunBulletsPool(){//得到正在运动的子弹对象池数组
		return pRunBulletsPool;
	}
	
	inline	cocos2d::CCArray* getLoadedArray(){//得到上膛的子弹
		return loadedArray;
	}
	// 当武器旋转的时候 正在枪膛里面的弹药也是需要旋转的
	void rotateLoadedBullets();
private:
	cocos2d::CCArray* pIdleBulletsPool;// 空闲子弹池
	cocos2d::CCArray* pRunBulletsPool;// 正在运行的子弹池
	cocos2d::CCSpriteBatchNode* batchNode;// 批量穿件子弹  优化方法
	cocos2d::CCArray* loadedArray;// 这是上膛的子弹 其实就是在弓箭上显示的子弹 这个时候的子弹是待发状态
	float hudu;// 武器所旋转的弧度值
	// 给武器装备子弹 cout 表示 一次上的子弹的个数
	void loadedBullet(int cout=1);
	void loade(float tim);
	
};
#endif

WeaponSprite.cpp

#include "WeaponSprite.h"
#include "BaseLayer.h"
// 定义 每个弓箭之间的间距是20
#define  SPA 10

USING_NS_CC;
bool WeaponSprite::initWithTexture(CCTexture2D *pTexture){
	bool bRet=false;
	do 
	{
		CC_BREAK_IF(!CCSprite::initWithTexture(pTexture));	
		// 初始话跑动的子弹
		this->pRunBulletsPool=CCArray::create();//初始化子弹池数组
		this->pRunBulletsPool->retain();//保留子弹池
		//this->speed=10;
		this->hudu=0;
		bRet=true;
	} while (0);
	return bRet;
}


void WeaponSprite::initIdleBulletSpool(CCLayer* player){    //初始化空闲子弹池
	// 创建50个子弹的纹理图片 这样做的目的是为了加速游戏的运行速度  
	CCTexture2D* texture=CCTextureCache::sharedTextureCache()->textureForKey("game/wq0.png");
	batchNode = CCSpriteBatchNode::createWithTexture(texture,50);//创建50个子弹的纹理图片		
	batchNode->setPosition(CCPointZero); 
	player->addChild(batchNode,2); //将batchNode精灵对象加入该层,zOrder为2
	// 初始化子弹池
	pIdleBulletsPool=CCArray::create();
	pIdleBulletsPool->retain();

	this->loadedArray=CCArray::create();//创建上膛的子弹数组
	loadedArray->retain();
	this->setZOrder(1);
	for(int i=0;i<50;i++){
		// 创建子弹
		BulletsSprite* pbullet=BulletsSprite::createWithTexture(batchNode->getTexture());
		// 把子弹的坐标设置成和当前武器的坐标是一样的
		pbullet->setPosition(this->getPosition());

		pbullet->setAnchorPoint(ccp(0,0.5));

		
		// 设置子弹的移动速度为50
		pbullet->setMovespeed(50);
		// 把子弹放到子弹池中
		this->pIdleBulletsPool->addObject(pbullet);
		pbullet->setVisible(false);
		// 把创建好的子弹放到 CCSpriteBatchNode 让其一次渲染
		batchNode->addChild(pbullet,-1);
	}
	this->schedule(schedule_selector(WeaponSprite::loade),1);
}
void WeaponSprite::recoverBullet(BulletsSprite* pbullet){//回收掉子弹
	pbullet->setPosition(this->getPosition());//子弹回到初始位置
	pbullet->setRotation(0);
	pbullet->setVisible(false);//设置为不可见
	pbullet->setFirstRoto(0);
	pbullet->setLastRoto(0);
	this->pIdleBulletsPool->addObject(pbullet);//添加到空闲子弹池

}

WeaponSprite* WeaponSprite::createWithTexture(CCTexture2D *pTexture)
{
	WeaponSprite *pobSprite = new WeaponSprite();
	if (pobSprite && pobSprite->initWithTexture(pTexture))
	{
		pobSprite->autorelease();
		return pobSprite;
	}
	CC_SAFE_DELETE(pobSprite);
	return NULL;
}

void WeaponSprite::loade(float tim){

	this->loadedBullet(5);        //一次上5个子弹

}
void WeaponSprite::loadedBullet(int cout){  
	if (this->loadedArray->count()!=cout){   //如果上膛的子弹数组的数量不等于5
		CCArray* tem=this->getIdleBullet(cout);//从空闲子弹池中取得子弹
		for(int i=0;i<tem->count();i++){//循环取得子弹
		 BulletsSprite* pbul=(BulletsSprite*)tem->objectAtIndex(i);//根据索引取得相应的子弹
		 this->loadedArray->addObject(pbul);//将子弹加入上膛的子弹数组
		}
	
	}
	// 表示需要发射 需要把 在枪膛中的子弹添加到 发射子弹中
	if(this->stop){    //如果stop函数为true则发射
		if(this->loadedArray->count()>0){	
			this->pRunBulletsPool->addObjectsFromArray(this->loadedArray);//将枪膛中的子弹加入发射子弹数组中
			for(int i=0;i<this->loadedArray->count();i++){
				this->loadedArray->removeObjectAtIndex(0,false);//依次将子弹从枪膛中的子弹数组中移除
				i--;
			}
		}
	}

}
CCArray* WeaponSprite::getIdleBullet(int cout){
	CCArray* ptemar=CCArray::create();

	float zhuwuqi= this->hudu*180/PI;      //将弧度转换成角度
	for(int i=0;i<cout;i++){
		CCObject* pbul=this->pIdleBulletsPool->objectAtIndex(0);//获取空闲子弹池的子弹		
		if(pbul){      //如果获取到了
			BulletsSprite* pbullet=(BulletsSprite*)pbul;
			ptemar->addObject(pbul);//将获取的子弹添加进数组
			pbullet->setVisible(true);//设置子弹为可见
			// 这些要特别注意在获取子弹的时候进行初始化
			pbullet->setFirstRoto(0);
			pbullet->setLastRoto(zhuwuqi);//设置当前的角度
			pbullet->setRotation(zhuwuqi);//初始化角度
			this->pIdleBulletsPool->removeObjectAtIndex(0,false);	
		}else {
			BulletsSprite* pbullet=(BulletsSprite*)BulletsSprite::createWithTexture(batchNode->getTexture());
			pbullet->setMovespeed(50);//如果没有子弹了,创建子弹精灵,并将精灵添加进batchNode
			pbullet->setPosition(this->getPosition());
			pbullet->setRotation(0);
			pbullet->setVisible(false);
			pbullet->setFirstRoto(0);
			pbullet->setLastRoto(0);
			batchNode->addChild(pbullet,2);
			i--;

		}

	}


	if(cout>1){	
		// 如果 在箭堂里面的子弹是 大于 2 的时候需要均匀的分布在 箭堂 里面  规定两个 弓箭之间的角度是20度
		bool isEven=cout%2==0?true:false;// 判断箭堂里面的弓箭是不是偶数
		int  pair=cout/2;// 能分成几对	
		int  temsp=(cout-1)*SPA;// 得到所有弓箭之间的夹角
		for(int i=0;i<ptemar->count();i++){		
			BulletsSprite* pbul=(BulletsSprite*)ptemar->objectAtIndex(i);
			
		
			
			// 表示中间哪里没有弓箭 反之刚好中间哪里有弓箭
			if (isEven){		//如果是偶数个箭头			
				if(i<pair){ // 表示上半部分 
					// 旋转 计算出旋转的角度
					float temro=i*SPA+SPA/2;
					
					pbul->setRotation(-temro+zhuwuqi);
					pbul->setFirstRoto(-temro);
					pbul->setLastRoto(-temro+zhuwuqi);
				}else{   //表示的是下半部分的角度
					float temro=(i-pair)*SPA+SPA/2;
					pbul->setRotation(temro+zhuwuqi);
					pbul->setFirstRoto(temro+zhuwuqi);
					pbul->setLastRoto(temro+zhuwuqi);
				}			
			}else{       //如果是奇数的话,则增加一个中间箭头的角度的设置
				if(i<pair){ // 表示上半部分 
					// 旋转 计算出旋转的角度
					float temro=i*SPA+SPA;
					pbul->setRotation(-temro+zhuwuqi);
					pbul->setFirstRoto(-temro);
					pbul->setLastRoto(-temro+zhuwuqi);
				}else if (i==pair){
					pbul->setRotation(zhuwuqi);
					pbul->setFirstRoto(0);
					pbul->setLastRoto(zhuwuqi);
				}
				else{
					float temro=(i-pair-1)*SPA+SPA;
					pbul->setRotation(temro+zhuwuqi);
					pbul->setFirstRoto(temro);
					pbul->setLastRoto(temro+zhuwuqi);
				}
			}
		}
		
	}



	return ptemar;
}

void WeaponSprite::setHudu(float hudu){
	this->hudu=hudu;	
}
void WeaponSprite::rotateLoadedBullets(){	
	// 获取当前武器旋转的角度
	float zhuwuqi= this->hudu*180/PI;	
	
	if(this->loadedArray){
		if(this->loadedArray->count()>0){
			for(int i=0;i<this->loadedArray->count();i++){
			BulletsSprite* pbul=(BulletsSprite*)loadedArray->objectAtIndex(i);			
			float temr=pbul->getFirstRoto();
			pbul->setRotation(temr+zhuwuqi);
			// 设置最后当前武器最后一次的旋转角度
			pbul->setLastRoto(temr+zhuwuqi);
			}
		}
	}
}


WeaponSprite::WeaponSprite(void){
	this->stop=false;
	this->hudu=0;
}


WeaponSprite::~WeaponSprite()  //将所有有子弹的对象全都release
{
	if (this->pIdleBulletsPool)
	{
		this->pIdleBulletsPool->release();
	}
	if (this->pRunBulletsPool)
	{
		this->pRunBulletsPool->release();
	}
	if (this->loadedArray)
	{
		this->loadedArray->release();
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值