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

来源:互联网 发布:剑三插件数据库 编辑:程序博客网 时间:2024/05/05 05:36

接着上次的界面,这次添加了武器主界面,原文出处         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);};#endifDefenderGameLayer.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;}inlinefloat getMovespeed(){ //得到子弹移动速度return movespeed;}inline void setHurt(float hurt){//设置伤害this->hurt=hurt;}inlinefloat 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;}inlinecocos2d::CCArray* getRunBulletsPool(){//得到正在运动的子弹对象池数组return pRunBulletsPool;}inlinecocos2d::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 10USING_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));// 设置子弹的移动速度为50pbullet->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){   //如果上膛的子弹数组的数量不等于5CCArray* 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);//如果没有子弹了,创建子弹精灵,并将精灵添加进batchNodepbullet->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();}}




0 0
原创粉丝点击