跟着BOY学习开发cocos2d-x 游戏 实战篇(3)之 游戏主界面 -----武器系统---散花弹

来源:互联网 发布:2016淘宝618大促报名 编辑:程序博客网 时间:2024/05/18 06:19

from:http://blog.csdn.net/wuyakenihao/article/details/9348367

非常抱歉,我也不找什么借口了今天的这篇博客比原来预计完了2天。这一章 写的东西比较多 不过分模块理解就好 主要模块有 武器 弹药 武器+弹药组合成 武器系统 ,当武器里面没有子弹的时候自动上膛 给加子弹,子弹会随着武器的跟着旋转。不过这里实现的并不是很完美。(兄弟们可以看看这一点如何优化)我是这么实现的当武器旋转完之后通过回调函数来设置武器系统的中在枪膛中的子弹的方向。虽然实现了但是看起来有卡顿的感觉。因为没有实现真正的子弹随着武器的旋转 

      由于代码比较多我就不贴贴出 全部代码了需要的兄弟们 可以通过下面的连接去下载所有源码。

      武器系统中散花弹的实现

     主要代码   在这里说明一下 对于三角函数不是很明白的请百度一下 还有角度和弧度的转化不是很明白的这这里写一下

    

        弧度=角度乘以π后再除以180          角度=弧度除以π再乘以180

    这个方法就是为了从子弹池中获取空闲的子弹 

[cpp] view plaincopy
  1. CCArray* WeaponSprite::getIdleBullet(int cout){  
  2.     CCArray* ptemar=CCArray::create();  
  3.   
  4.     float zhuwuqi= this->hudu*180/PI;  
  5.     for(int i=0;i<cout;i++){  
  6.         CCObject* pbul=this->pIdleBulletsPool->objectAtIndex(0);        
  7.         if(pbul){  
  8.             BulletsSprite* pbullet=(BulletsSprite*)pbul;  
  9.             ptemar->addObject(pbul);  
  10.             pbullet->setVisible(true);  
  11.             // 一下这些特别注意在获取  在获取子弹的时候进行初始化  
  12.             pbullet->setFirstRoto(0);  
  13.             pbullet->setLastRoto(zhuwuqi);  
  14.             pbullet->setRotation(zhuwuqi);  
  15.             this->pIdleBulletsPool->removeObjectAtIndex(0,false);       
  16.         }else {  
  17.             BulletsSprite* pbullet=(BulletsSprite*)BulletsSprite::createWithTexture(batchNode->getTexture());  
  18.             pbullet->setMovespeed(50);         
  19.             pbullet->setPosition(this->getPosition());  
  20.             pbullet->setRotation(0);  
  21.             pbullet->setVisible(false);  
  22.             pbullet->setFirstRoto(0);  
  23.             pbullet->setLastRoto(0);  
  24.             batchNode->addChild(pbullet,2);  
  25.             i--;  
  26.   
  27.         }  
  28.   
  29.     }  
  30.   
  31.   
  32.     if(cout>1){    
  33.         // 如果 在箭堂里面的子弹是 大于 2 的时候需要均匀的分布在 箭堂 里面  规定两个 弓箭之间的角度是20度  
  34.         bool isEven=cout%2==0?true:false;// 判断箭堂里面的弓箭是不是偶数  
  35.         int  pair=cout/2;// 能分成几对     
  36.         int  temsp=(cout-1)*SPA;// 得到所有弓箭之间的夹角  
  37.         for(int i=0;i<ptemar->count();i++){         
  38.             BulletsSprite* pbul=(BulletsSprite*)ptemar->objectAtIndex(i);  
  39.               
  40.           
  41.               
  42.             // 表示中间哪里没有弓箭 反之刚好中间哪里有弓箭  
  43.             if (isEven){                      
  44.                 if(i<pair){ // 表示上半部分   
  45.                     // 旋转 计算出旋转的角度  
  46.                     float temro=i*SPA+SPA/2;  
  47.                       
  48.                     pbul->setRotation(-temro+zhuwuqi);  
  49.                     pbul->setFirstRoto(-temro);  
  50.                     pbul->setLastRoto(-temro+zhuwuqi);  
  51.                 }else{  
  52.                     float temro=(i-pair)*SPA+SPA/2;  
  53.                     pbul->setRotation(temro+zhuwuqi);  
  54.                     pbul->setFirstRoto(temro+zhuwuqi);  
  55.                     pbul->setLastRoto(temro+zhuwuqi);  
  56.                 }             
  57.             }else{  
  58.                 if(i<pair){ // 表示上半部分   
  59.                     // 旋转 计算出旋转的角度  
  60.                     float temro=i*SPA+SPA;  
  61.                     pbul->setRotation(-temro+zhuwuqi);  
  62.                     pbul->setFirstRoto(-temro);  
  63.                     pbul->setLastRoto(-temro+zhuwuqi);  
  64.                 }else if (i==pair){  
  65.                     pbul->setRotation(zhuwuqi);  
  66.                     pbul->setFirstRoto(0);  
  67.                     pbul->setLastRoto(zhuwuqi);  
  68.                 }  
  69.                 else{  
  70.                     float temro=(i-pair-1)*SPA+SPA;  
  71.                     pbul->setRotation(temro+zhuwuqi);  
  72.                     pbul->setFirstRoto(temro);  
  73.                     pbul->setLastRoto(temro+zhuwuqi);  
  74.                 }  
  75.             }  
  76.         }  
  77.           
  78.     }  
  79.   
  80.   
  81.   
  82.     return ptemar;  
  83. }  
上面的代码可以先不用了解 
[cpp] view plaincopy
  1. pbul->setFirstRoto(temro);  
  2. pbul->setLastRoto(temro+zhuwuqi)  

这两行代码什么意思 下面我会讲解

上面的是主要代码 实现后 会出现这样的效果



哈哈看到我们的五颗弹药已经在枪膛上了 是不是很激动啊 哈哈别急 显示个这其实就是一个小儿科 最重要的是如何让武器旋转的弹药也跟着旋转

主要代码如下

[cpp] view plaincopy
  1. void WeaponSprite::rotateLoadedBullets(){     
  2.     // 获取当前武器旋转的角度  
  3.     float zhuwuqi= this->hudu*180/PI;      
  4.       
  5.     if(this->loadedArray){  
  6.         if(this->loadedArray->count()>0){  
  7.             for(int i=0;i<this->loadedArray->count();i++){  
  8.             BulletsSprite* pbul=(BulletsSprite*)loadedArray->objectAtIndex(i);             
  9.             float temr=pbul->getFirstRoto();  
  10.             pbul->setRotation(temr+zhuwuqi);  
  11.             // 设置最后当前武器最后一次的 旋转角度  
  12.             pbul->setLastRoto(temr+zhuwuqi);  
  13.             }  
  14.         }  
  15.     }  
  16. }  

看到这段代码 或许大家发现没什么 我为了这段代码折腾了3个小时 特别提醒一下命名变量的时候千万不要随便弄 特别是 变量类型 我这里犯了一个和弱智的错误 就是float 写成了int 倒着我弄了很多时间 

float temr=pbul->getFirstRoto();

看到这段代码 大家或许就明白为什么上面要那么的去设置 因为只要让原来旋转的度数+现在武器旋转的角度 才是现在子弹的角度 大家不要犯迷糊啊。

当你把这一点弄清楚的时候你大概就可以出来这样的效果了


是不是看到武器和弹药一起旋转了  哈哈 看到这里大家是不是感觉还是不过瘾啊   是不是希望吧子弹发射出去。那么发射该怎么弄 呵呵别急听我慢慢道来

其实子弹的发射就是不断的更新他的坐标 这样用户看起来就是在移动了

贴出子弹移动主要代码

[cpp] view plaincopy
  1. CCPoint  BulletsSprite::getMovePoint(){  
  2.     // 这里使用了 三角函数 主要是为了计算当前子弹所移动的位置  
  3.     float temhud= (this->getLastRoto()*PI)/180;  
  4.     float tex= std::cos(temhud)*this->movespeed;  
  5.     float tey= std::sin(temhud)*this->movespeed;  
  6.     tex=std::fabs(tex);// x 方向不存在负数  
  7.     return ccp(tex,-tey);  
  8.   
  9. }  
  10. void  BulletsSprite::mymove(){  
  11.     CCPoint cp=getMovePoint();  
  12.     float x=cp.x+this->getPositionX();  
  13.     float y=cp.y+this->getPositionY();     
  14.     this->setPosition(ccp(x,y));  
  15. }  

对你没看错就是这么的简单的两个方法实现了子弹的坐标的重设  上面的第一个方法不用我讲了吧初中的物理知识 速度的分解 把你的速度分解到X方向和Y 方向  这样就可以得知每次X和Y 的坐标变化了 当大家看到-tye 这个Y 方向为什么加了一个负号 这里我要解释一下主要是因为  cocos2d-x 中的坐标系 和咱们现实物理中的坐标系不一样 所以取反 这一点不理解的 多尝试几次就明白了 下面的那个方法就不用我解释了吧  小学生都明白 。

当然有以上的代码还不能实现 子弹的移动 这个是 游戏主界面有一个 定时任务是实时的调用它

下面贴出部分代码

[cpp] view plaincopy
  1. void DefenderGameLayer::detectd(float tim){  
  2.  WeaponSprite* pweapon=(WeaponSprite*) this->getChildByTag(2);  
  3.  if(pweapon->getRunBulletsPool()){  
  4.      CCArray* tem=CCArray::create();  
  5.      for(int i=0;i<pweapon->getRunBulletsPool()->count();i++){  
  6.          BulletsSprite* pbu=(BulletsSprite*) pweapon->getRunBulletsPool()->objectAtIndex(i);  
  7.          if (pbu->boundingBox().getMinX()>=getWinSize().width||pbu->boundingBox().getMinY()<0||pbu->boundingBox().getMinY()>=getWinSize().height){                  
  8.              pweapon->recoverBullet(pbu);  
  9.              tem->addObject(pbu);  
  10.          }else {                  
  11.              pbu->mymove();// 调用移动方法  
  12.          }  
  13.      }  
  14.      for(int j=0;j<tem->count();j++){  
  15.          pweapon->getRunBulletsPool()->removeObject(tem->objectAtIndex(j),false);  
  16.      }  
  17.      tem->removeAllObjects();  
  18.  }  
  19.    
  20. }  

 然后 就可以 出现下面的界面 虽不能说万剑齐发了



呵呵看起来还像那么回事吧  由于这两天事情比较多有些代码没加注释 大家看起来可能比较吃力 不过我给大家说下我的大概设计思路 我整体是这样的一个思路

首先武器系统负责 生产弹药  这个弹药包裹3部分 一部分是 正在运行中的弹药  一部分是正在发射架上的弹药 一部分是 在子弹池里等待被发射的弹药,当你设计一个这样的武器系统的时候你就会发现  缺少了一个东西 那就 弹药回收  弹药是否上膛有武器决定 。 我这里在武器这个类里面定义了一个任务调度任务来时刻为武器装上待发射的弹药

这样一个武器系统就诞生了 是不是很简单 。

    我给大家提供一个我做游戏的思路  我一般是把要做的部分分解成小模块 把小模块 拿出来看看能否分解成自己会做的 这样你就可以有一点点的成就感 不要一上来就想着我想实现那些功能,有些东西必须做了 才能更清楚。 呵呵不多说了 我把源码放在下面的连接里面需要的下载一下看看。


       对于下一章大家是不是很期待 呵呵下一张将写怪物系统 让咱们的万剑归宗 去消灭哪些鬼子  是不是很期待 那就关注我的博客把或者关注我的微薄 搜索郑州_boy 看好了千万别打错了


本节源码下载



其它:

1、不知你是否有觉得弹药的发射貌似不太好用。触摸了好久都不太明白他是什么时候能触发发射出去的。


这个BUG 也算上BUG 其实我发射子弹的速度 是根据上膛的速度一样的 没一秒钟上一次堂 这个时候你需要点击屏幕不要松开就可以看到源源不断的子弹发射了。后面我会修改成点击也发射和按着不送卡 也发射这两种形式。

原创粉丝点击