cocos2d-x 3.0游戏实例学习笔记 《跑酷》 第六步--金币&岩石加入而且管理
发布日期:2021-06-24 18:10:56 浏览次数:3 分类:技术文章

本文共 6837 字,大约阅读时间需要 22 分钟。

说明:这里是借鉴:前辈的博客,他是将泰然网的跑酷教程,用cocos2d-x 2.X 版本号重写的,眼下我正在学习cocos2d-X3.0 于是就用cocos2d-X 3.0重写,并做相关笔记

这一步基本思路也是借鉴了前辈重写的泰然教程,金币和岩石抽象出一个基类,可是总的细节设计和前辈的非常大的不同,后面写完,我认为事实上Runner也能够继承自那个基类,只是因为自己还有其它事。就没去尝试啦。

那么这里我是这样设计的:基类Base ,主要就是 setSprite,和 getSprite,以及getConSize--这个主要是为了后面金币和岩石的物理刚体绑定,那么金币Coin里面就 initBody--初始物理刚体。createAnimate--创建金币的旋转动画。Rock里面就是一个initBody。。

当时因为这里是自己设计的。想得比較乱,然后发现,事实上initBody 也能够抽象在基类里面。这里就没有改了。

然后,有了Coin 和 Rock,它们的出现,隐藏。以及位置放置,我们就用一个BaseManager来完毕,那么这里我是学习了 笨木头的方法: 为了反复的 create 金币,每次金币走出屏幕外。或者被主角吃了,我们就让它不可见,然后在BaseManager里面用一个update函数。对于不可见的金币我们让它重现江湖。。

OK上马:Base.h  & Base.cpp

[cpp] 
  1. #ifndef __Base__H__  
  2. #define __Base__H__  
  3.   
  4. #include "cocos2d.h"  
  5.   
  6. class Base : public cocos2d::Node{  
  7. public:  
  8.     Base();  
  9.   
  10.     void setSprite(cocos2d::Sprite* sprite);  
  11.     cocos2d::Sprite* getSprite();  
  12.   
  13.     cocos2d::Size getConSize();  
  14.   
  15. private:  
  16.     cocos2d::Sprite* m_sprite;  
  17. };/**/  
  18.   
  19. #endif  

[html] 
  1. #include "Base.h"  
  2.   
  3. USING_NS_CC;  
  4.   
  5. Base::Base(){  
  6.     m_sprite = NULL;  
  7. }  
  8.   
  9. void Base::setSprite(Sprite* sprite){  
  10.     m_sprite = sprite;   
  11.     //要加入到子节点中 ,才干被显示出来  
  12.     this->addChild(m_sprite);  
  13. }  
  14.   
  15. Sprite* Base::getSprite(){  
  16.     return m_sprite;  
  17. }  
  18.   
  19. Size Base::getConSize(){  
  20.     return m_sprite->getContentSize();  
  21. }  
金币 Coin.h & .cpp

[cpp] 
  1. #ifndef __Coin__H__  
  2. #define __Coin__H__  
  3.   
  4. #include "Base.h"  
  5.   
  6. class Coin : public Base{  
  7. public:  
  8.     virtual bool init();  
  9.     CREATE_FUNC(Coin);  
  10.   
  11.     //金币动作  
  12.     cocos2d::Animate* createAnimate(cocos2d::SpriteFrameCache* frameCache);  
  13.     //物理刚体  
  14.     void initBody();  
  15.   
  16. private:   
  17. };/**/  
  18.   
  19. #endif  
  20. ------------------------.cpp---------------------------------  
  21. #include "Coin.h"  
  22.   
  23. USING_NS_CC;  
  24.   
  25. bool Coin::init(){  
  26.     if(!Node::init()){  
  27.         return false;  
  28.     }  
  29.   
  30.     //缓存池  
  31.     auto frameCache = SpriteFrameCache::getInstance();  
  32.     frameCache->addSpriteFramesWithFile("parkour.plist","parkour.png");  
  33.   
  34.     auto sprite = Sprite::createWithSpriteFrameName("coin0.png");  
  35.   
  36.     //绑定  
  37.     setSprite(sprite);  
  38.     //运行动作  
  39.     getSprite()->runAction(createAnimate(frameCache));  
  40.     //绑定刚体  
  41.     initBody();  
  42.   
  43.     return true;  
  44. }  
  45.   
  46. Animate* Coin::createAnimate(SpriteFrameCache* frameCache){  
  47.   
  48.   
  49.     SpriteFrame* frame = NULL;  
  50.     //数组不行 要用vector  
  51.     //auto frameArray = Array::create();  
  52.     //frameArray->retain();  
  53.     Vector<SpriteFrame*>frameArray;  
  54.   
  55.     // 用一个列表保存全部SpriteFrame对象   
  56.     for(int i = 0; i <= 7; i++) {  
  57.         /* 从SpriteFrame缓存池中获取CCSpriteFrame对象 */  
  58.         frame = frameCache->spriteFrameByName(String::createWithFormat("coin%d.png", i)->getCString());  
  59.         frameArray.pushBack(frame);  
  60.   
  61.     }   
  62.     /* 使用SpriteFrame列表创建动画对象 */  
  63.     auto animation = Animation::createWithSpriteFrames(frameArray);  
  64.   
  65.     animation->setLoops(-1);  
  66.   
  67.     animation->setDelayPerUnit(0.1f);  
  68.   
  69.     /* 将动画包装成一个动作 */  
  70.     auto action = Animate::create(animation);  
  71.   
  72.     return action;  
  73. }  
  74.   
  75. void Coin::initBody(){  
  76.     auto phyBody = PhysicsBody::createEdgeBox(getSprite()->getContentSize());  
  77.     phyBody->setCategoryBitmask(1);  
  78.     phyBody->setCollisionBitmask(1);  
  79.     phyBody->setContactTestBitmask(1);  
  80.       
  81.     this->setPhysicsBody(phyBody);  
  82. }  
岩石Rock.h & .cpp

[cpp] 
  1. <span style="font-size:14px;">#ifndef __Rock__H__  
  2. #define __Rock__H__  
  3.   
  4. #include "Base.h"  
  5. #include "cocos2d.h"  
  6.   
  7. class Rock : public Base{  
  8. public:  
  9.     virtual bool init();  
  10.     CREATE_FUNC(Rock);  
  11.   
  12.     void initBody();  
  13. };/**/  
  14.   
  15. #endif  
  16. -------------------------------------------  
  17. #include "Rock.h"  
  18.   
  19. USING_NS_CC;  
  20.   
  21. bool Rock::init(){  
  22.     if(!Node::init()){  
  23.         return false;  
  24.     }  
  25.   
  26.     auto frameCache = SpriteFrameCache::getInstance();  
  27.     frameCache->addSpriteFramesWithFile("parkour.plist","parkour.png");  
  28.   
  29.     auto sprite = Sprite::createWithSpriteFrameName("rock.png");  
  30.   
  31.     setSprite(sprite);  
  32.   
  33.     initBody();  
  34.   
  35.     return true;  
  36. }  
  37.   
  38. void Rock::initBody(){  
  39.     auto phyBody = PhysicsBody::createEdgeBox(getSprite()->getContentSize());  
  40.     phyBody->setCategoryBitmask(1);  
  41.     phyBody->setCollisionBitmask(1);  
  42.     phyBody->setContactTestBitmask(1);  
  43.       
  44.     this->setPhysicsBody(phyBody);  
  45. }</span><span style="font-size:18px;">  
  46. </span>  
那么这里主要重点看 管理类BaseManager.h & .cpp

[cpp] 
  1. #ifndef __BaseManager__H__  
  2. #define __BaseManager__H__  
  3.   
  4. #include "cocos2d.h"  
  5. #include "Coin.h"  
  6. #include "Rock.h"  
  7.   
  8.   
  9. #define coinNum 4  
  10. #define coinTag 2  //这里关于Tag 用于后面的碰撞检測  
  11. #define rockNum 2  
  12. #define rockTag 3  
  13.   
  14. class BaseManager : public cocos2d::Node{  
  15. public:  
  16.     CREATE_FUNC(BaseManager);  
  17.     virtual bool init();  
  18.     virtual void update(float dt);  
  19.   
  20. private:  
  21.     void createCoin();  
  22.     cocos2d::Array* m_coinArr;  
  23.   
  24.     void createRock();  
  25.     cocos2d::Array* m_rockArr;  
  26. };/**/  
  27.   
  28. #endif  
  29. --------------------------------------------------------  
  30. #include "BaseManager.h"  
  31.   
  32. #define ground_hight 59  
  33.   
  34. USING_NS_CC;  
  35.   
  36. bool BaseManager::init(){  
  37.     if(!Node::init()){  
  38.         return false;  
  39.     }  
  40.   
  41.     createCoin();  
  42.   
  43.     createRock();  
  44.   
  45.     this->scheduleUpdate();  
  46.   
  47.     return true;  
  48. }  
  49.   
  50. void BaseManager::createCoin(){  
  51.     m_coinArr = Array::create();  
  52.     m_coinArr->retain();  
  53.   
  54.     Coin* coin = NULL;  
  55.   
  56.     for(int i = 1; i <= coinNum; ++ i){  
  57.         coin = Coin::create();  
  58.   
  59.         coin->setVisible(false);  
  60.   
  61.         coin->setTag(coinTag);  
  62.   
  63.         //记得加入  
  64.         this->addChild(coin);  
  65.   
  66.         m_coinArr->addObject(coin);  
  67.     }/**/  
  68. }  
  69.   
  70. void BaseManager::createRock(){  
  71.     m_rockArr = Array::create();  
  72.     m_rockArr->retain();  
  73.   
  74.     Rock* rock = NULL;  
  75.   
  76.     float dis = 960;//两岩石的间距  
  77.   
  78.     for(int i = 1; i <= rockNum; ++ i){  
  79.         rock = Rock::create();  
  80.   
  81.         rock->setTag(rockTag);  
  82.   
  83.         rock->setPosition(dis,ground_hight+rock->getConSize().height/2);  
  84.         dis += 640;  
  85.   
  86.         //记得加入  
  87.         this->addChild(rock);  
  88.   
  89.         m_rockArr->addObject(rock);  
  90.     }/**/  
  91. }  
  92.   
  93. void BaseManager::update(float dt){  
  94.     Ref* obj = NULL;  
  95.     Coin* coin = NULL;  
  96.   
  97.     //须要重置金币的个数  
  98.     int setNum = 0;  
  99.     CCARRAY_FOREACH(m_coinArr,obj){  
  100.         coin = (Coin*)obj;  
  101.   
  102.         //不在屏幕  
  103.         if(coin->getPositionX() < -coin->getConSize().width/2){  
  104.             coin->setVisible(false);  
  105.         }  
  106.   
  107.         //要是不可见,要不就是不在屏幕里,要不就是被碰撞了  
  108.         if( !coin->isVisible() ){  
  109.             setNum ++;  
  110.         }  
  111.   
  112.         //让金币移动  
  113.         coin->setPositionX(coin->getPositionX()-2);  
  114.     }  
  115.   
  116.     //4个所有重置  
  117.     if(setNum == 4){  
  118.         int i = 0;  
  119.         float posX = 640+50;  
  120.         float posY = ground_hight + 15 + CCRANDOM_0_1()*60;  
  121.         CCARRAY_FOREACH(m_coinArr,obj){  
  122.             coin = (Coin*)obj;  
  123.             //不在屏幕  
  124.             if(coin->getPositionX() < -coin->getConSize().width/2){  
  125.                 coin->setVisible(false);  
  126.             }  
  127.             //要是不可见。要不就是不在屏幕里。要不就是被碰撞了  
  128.             if( !coin->isVisible() ){  
  129.                 //两个两个一起  
  130.                 if(i < 2){  
  131.                     posX += 30;//两个金币同一高度,间隔30  
  132.                 }else{  
  133.                     //又一次重置位置   
  134.                     i = -1;  
  135.                     posY = ground_hight + 15 + CCRANDOM_0_1()*60;  
  136.                     posX += 400;  
  137.                 }  
  138.                 i ++;//重置金币个数记录  
  139.                 //  
  140.                 coin->setVisible(true);  
  141.                 coin->setPosition(posX,posY);  
  142.             }  
  143.         }  
  144.     }  
  145.   
  146.     Ref* rockObj = NULL;  
  147.     Rock* rock = NULL;  
  148.   
  149.     CCARRAY_FOREACH(m_rockArr,rockObj){  
  150.         rock = (Rock*)rockObj;  
  151.   
  152.         if(rock->getPositionX() < -rock->getConSize().width/2){  
  153.             rock->setVisible(false);  
  154.         }  
  155.         if(rock->isVisible() == false){  
  156.             float posX = 1280;  
  157.             float posY = ground_hight + rock->getConSize().height/2;  
  158.             if(CCRANDOM_MINUS1_1() > 0){  
  159.                 posY += 50;  
  160.             }  
  161.             rock->setPosition(posX,posY);  
  162.             rock->setVisible(true);  
  163.         }  
  164.   
  165.         rock->setPositionX(rock->getPositionX()-2);  
  166.     }  
  167. }  
代码中,我们主要看看 两个Create 函数,以及update函数。

createCoin :我们先确定整个过程仅仅有4个金币,而且一開始都设置为 不可见,那么在update 函数中,我们对全部的金币遍历,假设是不可见,那么我们就让它可见,而且两个一起 间隔30 ,同一高度放置,然后 高度不一致。可能出现地面,可能须要主角跳起来才可以到,而createRock。我们整个屏幕就放两个就够了。这两个也有两个位置,一个在地面。一个在空中须要主角crouch或者Jump也可以。。。事实上这里的位置放置算法(应该算是有点算法的味道吧) 写得非常乱,这里就所有是我自己设计的。。

。感觉金币岩石出现的非常没有 美观。

只是也还算是能够执行。

。。。。

那么我们能够測试一下。在PlayScene中加入成员

BaseManager* m_manager;

然后在init函数中 create 增加 this的addChild中

可是这里的话,我们建议把 Coin & Rock 两个类里面的 init 函数中的 initBody 先凝视掉,然后再測试。不然带着刚体,主角跑起来非常不顺利。測试例如以下:

以下就要来利用物理碰撞检測了---全部的也就快结束啦

个人愚昧观点,欢迎指正与讨论

转载地址:https://blog.csdn.net/weixin_34248258/article/details/85893335 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:设计模式三—抽象工厂模式
下一篇:WifiStateMachine学习笔记

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年04月22日 00时55分28秒