cocos2d-x for android:士兵听我的命令移动

it2022-05-09  29

上一篇文章讲述了利用cocos2d-x构建精灵的动画效果,今天打算以此为引子,创建一个在移动时同时指挥角色到我手指触摸的移动地点,那么就开始吧。

开始

本篇要点

角色(Sprite)缓存动画(Animation)缓存触摸(Touch)精灵到我指定的移动地点动作(Action)移动和切换 涉及到的要学的学习点: 角色移动点击由此进入-->cocos2d-x for android:SimpleGame分析播放动画点击由此进入-->cocos2d-x for android:CCSprite 精灵动画­

角色缓存

角色缓存使用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  

转载于:https://www.cnblogs.com/TerryBlog/archive/2012/11/11/2765413.html

相关资源:数据结构—成绩单生成器

最新回复(0)