cocos2d-x for android:士兵聽我的命令移動


上一篇文章講述了利用cocos2d-x構建精靈的動畫效果,今天打算以此為引子,創建一個在移動時同時指揮角色到我手指觸摸的移動地點,那么就開始吧。

開始

本篇要點

  1. 角色(Sprite)緩存
  2. 動畫(Animation)緩存
  3. 觸摸(Touch)精靈到我指定的移動地點
  4. 動作(Action)移動和切換

角色緩存

角色緩存使用CCSpriteFrameCache ,配合CCSpriteBatchNode將圖片*.plist和*.png 加載進內存,方便以后調用。

 

以上為動作序列圖,圖片名稱為:sg.png.圖片來源於博客園:nowpaper.

角色緩存代碼如下:

CCSpriteFrameCache* cache=CCSpriteFrameCache::sharedSpriteFrameCache();
cache->addSpriteFramesWithFile( " sg.plist ");

    sprite=CCSprite::createWithSpriteFrameName( " A1_6.png ");
    sprite->setPosition(ccp(size.width-sprite->getContentSize().width,size.height/ 2));
    spriteBatchNode=CCSpriteBatchNode::create( " sg.png ");
    spriteBatchNode->addChild(sprite);
     addChild(spriteBatchNode);

 以上代碼,CCSpriteFrameCache負責加載sg.plist,CCSpriteBatchNode負責加載sg.png,然后創建一個精靈指定初始化位置和精靈紋理,並添加進CCSpriteBatchNode。通過上面的代碼即可以將一個plist序列圖加載進緩存了,你要做的就是將這些緩存的數據拿出來操作它。

 

動畫緩存

上面己經將數據加載進緩存了,可以使用其中的那些節點來制作動畫緩存了。

緩存動畫使用 CCAnimationCache,該動畫同樣需要使用到plist文件,代碼如下

 

 

CCAnimationCache *animCache = CCAnimationCache::sharedAnimationCache();

    animCache->addAnimationsWithFile( " sg.plist ");

 在將plist文件添加完后,即可以通過動畫Animation將每一個動畫的Animation添加進CCAnimationCache了,這里我寫了一個函數,代碼見下方

 

CCAction* HelloWorld::createAction( int begin, int end, char* cacheActionName,CCPoint point){
    CCAnimationCache *animCache = CCAnimationCache::sharedAnimationCache();//得到一個緩存對象
    CCArray *array = CCArray::createWithCapacity(end-begin);

     char name[ 20];
     for( int i = begin ;i<end;i++){
        sprintf(name, " A1_%d.png ",i);
        CCSpriteFrame* frame =cache->spriteFrameByName(name);
        array->addObject(frame);
    }//以上創建一個動作序列集合

    CCAnimation *plistAnimation = CCAnimation::createWithSpriteFrames(array, 0.2f);//通過動作序列集合創建animation
     animCache->addAnimation(plistAnimation, cacheActionName);//添加進緩存並指定緩存名稱

    array->removeAllObjects();

    CCAnimation *animation = animCache->animationByName(cacheActionName);//通過緩存名稱得到一個動畫
    animation->setRestoreOriginalFrame( true);
    CCAnimate *ani=CCAnimate::create(animation);
    CCActionInterval* plistSeq=(CCActionInterval*)(CCSequence::create(ani,
        CCFlipX::create(point.x> 0true: false),
        ani->copy()->autorelease(),
        NULL
    ));
     return CCRepeatForever::create(plistSeq);//創建動畫並返回Action
}

 

觸摸精靈到我指定的移動地點

設定好讓程序允許Touch之后,在回調函數ccTouchesEnded 里面通過捕獲觸摸位置指定精靈移動,代碼見下方

 

CCTouch* touch=(CCTouch*)(touches->anyObject());  
     CCPoint location = touch ->getLocation();
      float offX=location.x-sprite->getPosition().x; 
      float offY=location.y-sprite->getPosition().y; 
     
     walkAction=createAction( 4, 6, " move ",ccp(offX,offY));
     
     sprite->setFlipX(offX> 0? true: false);

    
      float realX=offY/offX;
      CCPoint realDeast =ccp(location.x,location.y);
      CCActionInterval *actionTo=CCMoveTo::create( 2.2f,realDeast);
    CCAction *moveToAction=CCSequence::create(
        actionTo,
        CCCallFunc::create( this,callfunc_selector(HelloWorld::moveDone)),
        NULL
    );

  sprite->runAction(moveToAction);

ok了,精靈移動了,但你會發現,你想讓精靈移動的時候不是一整張圖片移動,而是邊移動邊兩只腳在走路的移動,就像是我們人類一樣,是走着過去的,而不是幽靈飄過去的,那么,我們要做些什么呢?

動作移動

其實,很簡單 ,只要記住要精靈移動的時候即:MoveTo時,同時再讓精靈執行一個動作即walk的動作,代碼如下:

sprite->stopAllActions();  //因為Touch是無時無刻的,所以每當touch一次即停止當前的action
walkAction=createAction( 4, 6, " move ",ccp(offX,offY));//構建一個walk的action

sprite->runAction(walkAction);//播放走的action
sprite->runAction(moveToAction);//播放moveTo的action

 當到達指定地點時,希望讓角色以站立的姿勢站在屏幕上,這時我們需要在moveTo的callback函數里面調用,讓其停止當前action,並重新執行站立的action,代碼如下:


void HelloWorld::moveDone(){
    sprite->stopAllActions();
    CCAnimationCache *animCache = CCAnimationCache::sharedAnimationCache();


    CCAnimation *standAnimation = animCache->animationByName( " stand ");
        standAnimation->setRestoreOriginalFrame( true);
        CCAnimate *standAni=CCAnimate::create(standAnimation);
        CCActionInterval* s=(CCActionInterval*)(CCSequence::create(standAni,
            standAni->copy()->autorelease(),
            NULL
        ));
        CCAction *frameAction=CCRepeatForever::create(s);

    
    sprite->runAction(frameAction);
}

 

全部代碼如下:

View Code 
  1  using  namespace cocos2d;
  2  using  namespace CocosDenshion;
  3 
  4  #define  LOG_TAG    "main"                                                                                                              ||-   function
  5  #define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)  
  6 
  7 CCScene* HelloWorld::scene()
  8 {
  9      //  'scene' is an autorelease object
 10      CCScene *scene = CCScene::create();
 11     
 12      //  'layer' is an autorelease object
 13      HelloWorld *layer = HelloWorld::create();
 14 
 15      //  add layer as a child to scene
 16      scene->addChild(layer);
 17 
 18      //  return the scene
 19       return scene;
 20 }
 21 
 22  //  on "init" you need to initialize your instance
 23  bool HelloWorld::init()
 24 {
 25      //////////////////////////////
 26       //  1. super init first
 27       if ( !CCLayer::init() )
 28     {
 29          return  false;
 30     }
 31 
 32      this->setTouchEnabled( true);
 33 
 34     CCSize size = CCDirector::sharedDirector()->getWinSize();
 35     CCAnimationCache::purgeSharedAnimationCache();
 36     CCAnimationCache *animCache = CCAnimationCache::sharedAnimationCache();
 37 
 38     animCache->addAnimationsWithFile( " sg.plist ");
 39     
 40 
 41 
 42     cache=CCSpriteFrameCache::sharedSpriteFrameCache();
 43     cache->addSpriteFramesWithFile( " sg.plist ");
 44 
 45     sprite=CCSprite::createWithSpriteFrameName( " A1_6.png ");
 46     sprite->setPosition(ccp(size.width-sprite->getContentSize().width,size.height/ 2));
 47     spriteBatchNode=CCSpriteBatchNode::create( " sg.png ");
 48     spriteBatchNode->addChild(sprite);
 49      addChild(spriteBatchNode);
 50 
 51     cache->addSpriteFramesWithFile( " hero.plist ");
 52     hero=CCSprite::createWithSpriteFrameName( " Hero02_0.png ");
 53     hero->setPosition(ccp(hero->getContentSize().width,size.height/ 2));
 54     heroBatchNode=CCSpriteBatchNode::create( " hero.png ");
 55     heroBatchNode ->addChild(hero);
 56     hero->setFlipX( true);
 57     
 58     addChild(heroBatchNode);
 59     
 60 
 61 
 62     attackArray =CCArray::createWithCapacity( 4);
 63      char attackName[ 20];
 64      for( int i= 0;i< 4;i++){
 65         sprintf(attackName,
 66  " A1_%d.png ",i);
 67         CCSpriteFrame* frame =cache->spriteFrameByName(attackName);
 68         attackArray->addObject(frame);
 69     }
 70     CCAnimation *attackAnimation =CCAnimation::createWithSpriteFrames(attackArray, 0.2f);
 71     CCAnimationCache::sharedAnimationCache()->addAnimation(attackAnimation,  " attack ");
 72     
 73     attackArray->removeAllObjects();
 74 
 75     
 76 
 77     standArray= CCArray::createWithCapacity( 1);
 78      char standName[ 20];
 79          for( int i= 6;i< 7;i++){
 80             sprintf(standName,
 81  " A1_%d.png ",i);
 82             CCSpriteFrame* frame =cache->spriteFrameByName(standName);
 83             standArray->addObject(frame);
 84         }
 85         CCAnimation *standAnimation =CCAnimation::createWithSpriteFrames(standArray, 0.2f);
 86         CCAnimationCache::sharedAnimationCache()->addAnimation(standAnimation,  " stand ");
 87         standArray->removeAllObjects();
 88     
 89     
 90      return  true;
 91 }
 92 
 93  void HelloWorld::moveDone(){
 94      //
 95      sprite->stopAllActions();
 96     CCAnimationCache *animCache = CCAnimationCache::sharedAnimationCache();
 97 
 98 
 99     CCAnimation *standAnimation = animCache->animationByName( " stand ");
100         standAnimation->setRestoreOriginalFrame( true);
101         CCAnimate *standAni=CCAnimate::create(standAnimation);
102         CCActionInterval* s=(CCActionInterval*)(CCSequence::create(standAni,
103             standAni->copy()->autorelease(),
104             NULL
105         ));
106         CCAction *frameAction=CCRepeatForever::create(s);
107 
108     
109     sprite->runAction(frameAction);
110 }
111 
112 CCAction* HelloWorld::createAction( int begin, int end, char* cacheActionName,CCPoint point){
113     CCAnimationCache *animCache = CCAnimationCache::sharedAnimationCache();
114     CCArray *array = CCArray::createWithCapacity(end-begin);
115 
116      char name[ 20];
117      for( int i = begin ;i<end;i++){
118         sprintf(name, " A1_%d.png ",i);
119         CCSpriteFrame* frame =cache->spriteFrameByName(name);
120         array->addObject(frame);
121     }
122 
123     CCAnimation *plistAnimation = CCAnimation::createWithSpriteFrames(array, 0.2f);
124     CCAnimationCache::sharedAnimationCache()->addAnimation(plistAnimation, cacheActionName);
125 
126     array->removeAllObjects();
127 
128     CCAnimation *animation = animCache->animationByName(cacheActionName);
129     animation->setRestoreOriginalFrame( true);
130     CCAnimate *ani=CCAnimate::create(animation);
131     CCActionInterval* plistSeq=(CCActionInterval*)(CCSequence::create(ani,
132         CCFlipX::create(point.x> 0true: false),
133         ani->copy()->autorelease(),
134         NULL
135     ));
136      return CCRepeatForever::create(plistSeq);
137 }
138 
139 
140  void HelloWorld::registerWithTouchDispatcher(){                                                                                    
141     CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate( this, 0);
142 }
143  void HelloWorld::ccTouchesEnded(cocos2d::CCSet * touches,cocos2d::CCEvent *  event){
144 
145     sprite->stopAllActions();
146     
147     
148     CCTouch* touch=(CCTouch*)(touches->anyObject());  
149      CCPoint location = touch ->getLocation();
150       float offX=location.x-sprite->getPosition().x; 
151       float offY=location.y-sprite->getPosition().y; 
152      
153      walkAction=createAction( 4, 6, " move ",ccp(offX,offY));
154      
155      sprite->setFlipX(offX> 0? true: false);
156 
157     
158       float realX=offY/offX;
159       CCPoint realDeast =ccp(location.x,location.y);
160       CCActionInterval *actionTo=CCMoveTo::create( 2.2f,realDeast);
161     CCAction *moveToAction=CCSequence::create(
162         actionTo,
163         CCCallFunc::create( this,callfunc_selector(HelloWorld::moveDone)),
164         NULL
165     );
166 
167   sprite->runAction(walkAction);
168   sprite->runAction(moveToAction);
169 }
170 
171 
172  void HelloWorld::menuCloseCallback(CCObject* pSender)
173 {
174     CCDirector::sharedDirector()->end();
175 
176  #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
177     exit( 0);
178  #endif
179

 

 

 注意點

CCAnimation *attackAnimation =CCAnimation::createWithSpriteFrames(attackArray,0.2f); 與
CCAnimation *attackAnimation =CCAnimation::createWithSpriteFrames(attackArray);因為站立action才一幀,所以我不打算指定時間,但是如果不指定時間,它無法成功切換action,這個目前還不清楚是為什么。

 

 

 

 

 最后實現的效果如下:

 

由於是在ubuntu下開發,好像沒有什么抓取屏幕gif 圖片的軟件可用,簡單截一屏!!!

代碼沒有做任何的處理,很多多余的代碼,做個DEMO可以看看就行!!!

代碼下載:https://github.com/terryyhl/SpriteAnimation.git 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM