cocos2d-x不得不说的 CCAction

根据M了个J老师cocos2d-iphone修改cocos2d-x记录

先来看看CCAction的继承结构图


这里我省略了瞬时动作(CCActionInstant)和间隔动作(CCActionInterval)的子类,因为它们又包含了非常多的子类,待会再介绍它们的子类。

CCAction和CCFiniteTimeAction都是抽象类,只定义了一些基本属性和方法,没有实际用途,我们需要使用它们的子类来初始化动作,然后运行到节点上。

间隔动作

间隔动作就是指需要经过一段时间才能完成的动作,所有的间隔动作 都继承自CCActionInterval。比如CCRotateBy, 可以在指定时间内旋转指定的角度

// 1秒内顺时针旋转360°
	CCRotateBy *rotate = CCRotateBy::create(1,360);
        sprite->runAction(rotate);
间隔动作的继承结构图:(只列出部分常用的)



由于CCActionInterval的子类太多了,这里就不一一介绍了,可以查阅下API文档

下面列举一下常见的CCActionInterval的子类:

1.CCBlink

闪烁效果

 // 5秒内闪烁20次
	 CCBlink *blink =CCBlink::create(5,20); 
	 sprite->runAction(blink);

2.CCMoveBy和CCMoveTo

CCMoveBy是移动一段固定的距离,CCMoveTo是动到指定的位置

// 在1秒内,向右移动100单位,同时向上移动80单位
        CCMoveBy *moveBy = CCMoveBy:: create(3, CCPointMake(100, 80));
	sprite->runAction(moveBy);


// 在1秒内,从节点的当前位置移动到(100, 80)这个位置
	CCMoveTo *moveTo = CCMoveTo:: create(3, CCPointMake(100, 80));
	sprite->runAction(moveTo);

3.CCRotateBy和CCRotateTo

CCRotateBy是在当前旋转角度的基础上再旋转固定的角度,CCRotateTo是从当前旋转角度旋转到指定的角度

假设精灵在初始化的时候已经顺时针旋转了 45°

sprite->setRotation(45);
如果使用了CCRotateBy

// 在1秒内,再顺时针旋转90°,那么sprite的最终旋转角度是45° + 90° = 135°
      CCRotateBy *rotateBy = CCRotateBy create(1,90);
      sprite->runAction(rotateBy);
如果使用了CCRotateTo

// 在1秒内,顺时针旋转到90°,sprite的最终旋转角度就是90° 
      CCRotateTo *rotateTo = CCRotateTo create(1,90);
      sprite->runAction(*rotateTo);

4.CCScaleBy和CCScaleTo

CCScaleBy是在当前缩放比例的基础上再缩放固定的比例,CCScaleTo是从当前缩放比例缩放到指定的比例
假设精灵在初始化的时候的缩放比例为0.8

 sprite->setScale(0.8);
如果使用了 CCScaleBy

// 在1秒内,宽度和高度再缩小50%,那么sprite最终缩放比例是0.8 * 0.5 = 0.4  
     CCScaleBy *scaleBy = CCScaleBy::create(1,0.5);
     sprite ->runAction(scaleBy);

如果使用了 CCScaleTo
// 在1秒内,宽度和高度缩小为0.5倍,那么sprite最终缩放比例是就0.5  
     CCScaleTo *scaleTo = CCScaleTo::create(1,0.5);
     sprite ->runAction(*scaleTo);

5.CCFadeIn和CCFadeOut和CCFadeTo

CCFadeIn是淡入,即由暗转亮,从没有到有;CCFadeOut是淡出,即由亮转暗,从有到没有;CCFadeTo用来修改节点的不透明度
// 在2秒内,从没有到有
        CCFadeIn *fadeIn = CCFadeIn::create(2);
// 在2s内,从有到没有
	CCFadeOut *fadeOut = CCFadeOut::create(2);
// 在2s内,不透明度变为120,即变为半透明 (不透明度取值范围是0-255)
	CCFadeTo *fadeTo = CCFadeTo ::create(2,120);

6.CCRepeat

重复执行某个动作,可以指定重复的次数

// 1秒中顺时针旋转360°
     CCRotateBy *rotateBy = CCRotateBy ::create(1,360);;
// 重复执行2次旋转动画
     CCRepeat *repeat = CCRepeat ::create(rotateBy,2);
     sprite->runAction(repeat);

7.CCAnimate

按顺序地播放图片,可以实现帧动画。

例如有下面10张图片:(玩过街机的同学应该很熟悉,赵云的大鹏展翅)

里是将10帧分为10张不同的png图片。为了性能着想,其实最好将10帧打包成一个图片,到时从这张图片上面切割每一帧,这种图片我们可以称为"纹理相册",可以用TexturePacker制作纹理相册


下面用CCAnimate实现动画效果

CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("zcmains.plist","zcmains.png");
/* 创建CCTexture2D对象*/
CCTexture2D *texture=CCTextureCache::sharedTextureCache()->textureForKey("zcmains.png"); 
/* 使用CCTexture2D对象创建BatchNode */
CCSpriteBatchNode *node=CCSpriteBatchNode::createWithTexture(texture);
/* 添加BatchNode到场景*/
this->addChild(node);
// 加载所有的图片
for(int i= 0;i<10;i++){
	// 由SpriteFrame缓存池里图片名字生成一帧
    CCSpriteFrame *farmes = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(CCString::createWithFormat("%da.png", i)->getCString());
	// 当前帧添加进数组
	frames-> addObject(farmes); 
}
// 初始化动画
CCAnimation *walkAnim = CCAnimation::createWithSpriteFrames(frames, 0.2f); [注 1]
// 创建精灵 由该精灵执行动画
CCSprite* bear = CCSprite::createWithSpriteFrameName("0a.png");   
//CCSprite *bear = CCSprite::createWithSpriteFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("0a.png"));
bear->setPosition(ccp(size.width/2, size.height/2)); 
CCRepeatForever* walkAction = CCRepeatForever::create( CCAnimate::create(walkAnim) ); 
bear->runAction(walkAction); 
this->addChild(bear);  



8.CCSequence

一般情况下,如果给节点同时添加几个动作时,它们会同时运行。比如下面的代码效果是一边旋转一边缩放

	CCRotateBy *rotateBy = CCRotateBy::create(1,360); 
	CCScaleBy *scaleBy = CCScaleBy::create(1,2); 
	sprite-> runAction(rotateBy);
	sprite->runAction(scaleBy);  
但是有时候我们想让动作一个接着一个运行,那么就要用到 CCSequence
下面演示的效果是,让精灵先变为红色,再从红色变为绿色,再从绿色变为蓝色
	CCTintTo *tintTo1 = CCTintTo::create(1,255,0,0);
	CCTintTo *tintTo2 = CCTintTo::create(1,0,255,0);
	CCTintTo *tintTo3 = CCTintTo::create(1,0,0,255); 
// CCTintTo也是CCActionInterval的子类,可以用于更改精灵的颜色。  
        CCSequence *sequence = CCSequence ::create(tintTo1, tintTo2, tintTo3, NULL);//:tintTo1, tintTo2, tintTo3, nil];  
        sprite-> runAction(sequence);  
CCSequence会 按顺序执行参数中传入的所有动作

9.CCActionEase

当对节点使用CCMoveTo动作时,它会匀速移动到目的地,如果使用CCActionEase就可以使节点由慢到快或者由快到慢地移向目的地。因此CCActionEase是用来改变动作的运行时速度的。

CCActionEase是个非常强大的类,子类非常多,这里只说明其中的几个:

CCEaseIn:由慢到快

CCEaseOut:由快到慢

CCEaseInOut:先由慢到快,再由快到慢

举个代码例子:

CCMoveTo *moveTo = CCMoveTo ::create(4,ccp(300,200));
CCEaseInOut *easeInOut = CCEaseInOut ::create(moveTo,5); 
sprite ->runAction(easeInOut);
你会看到精灵先由慢到快,再由快到慢。rate参数决定了速率变化的明显程度,当它大于1时才 有效


瞬时动作


瞬时动作(CCActionInstant)是指能够瞬间完成的动作,可用于改变节点位置、翻转节点形成镜像、设置节点的可视性等。

下面大致看下瞬时动作的继承结构图:


看完这个图,你可能觉得CCActionInstant好像没有一点使用价值,因为它的好多动作都可以通过修改节点属性来完成。比如可以通过设置节点的visible属性来代替使用CCShow\CCHide\CCToggleVisibility、可以通过修改节点的position属性来代替使用CCPlace其实当它们与CCSequence结合使用时才有价值。比如,我们想先让节点运行一个CCMoveTo移动到某个位置,移动完毕后再隐藏节点,这时候我们就可以将CCMoveTo、CCHide两个动作按顺序放进CCSequence中达到想要的效果

// 移动到(300, 200)  
CCMoveTo *moveTo = CCMoveTo::create(2,ccp(300,200));//:2 position:ccp(300, 200)];  
// 隐藏节点  
CCHide *hide =CCHide::create();
CCSequence *sequence = CCSequence ::create(moveTo,hide,NULL);
sprite-> runAction(sequence);  

有时候,在一个动作 序列(CCSequence)里面,我们需要在一个动作运 行完毕后,调用某个方法执行一些操作,然后再执行下一个动作。那我们就可以 结合CCCallFunc和CCSequence完成 这个功能。

比如,我们让精灵先变为红色,再从红色变为绿色,再从绿色变为蓝色,而且在每次变换颜色后都调用某个方法执行一些操作:

// 变为红色  
CCTintTo *tintTo1 = CCTintTo ::create(2,255,0,0);
// 变为红色后调用self的turnRed方法  
CCCallFunc *fn1 = CCCallFunc::create(this,callfunc_selector(HelloWold::turnRed),NULL);
// 变为绿色  
CCTintTo *tintTo2 = CCTintTo ::create(2,0,255,0);
// 变为绿色后调用self的turnGreen:方法,参数是运行当前动作的节点  
CCCallFuncN *fn2 = CCCallFuncN::create(this,callfuncN_selector(HelloWold::turnGreen));
// 变为蓝色  
CCTintTo *tintTo3 = CCTintTo ::create(2,0,0,255);//[CCTintTo actionWithDuration:2 red:0 green:0 blue:255];  
// 变为蓝色后调用self的turnBlue:data:方法,第一个参数是运行当前动作的节点,第二个参数是data的值  
CCCallFuncND *fn3 = CCCallFuncND::create(this,callfuncND_selector(HelloWold::turnBlue),(void * )"blue");
// 最后调用turnDone:方法,传递了一个@"done"字符串作为参数  
CCCallFuncO *fn4 = CCCallFuncO::create(this,callfuncO_selector(HelloWold::turnBlue),(CCObject * )"done"); 
CCSequence *sequence = CCSequence ::create(tintTo1, fn1, tintTo2, fn2, tintTo3, fn3, fn4, NULL);
sprite-> runAction(sequence);  


下面是回调方法的实现:

void HelloWorld::turnRed() { 
        CCLog("变为红色");  
} 
// node是运行当前动作的节点  
void HelloWorld::turnGreen(CCObject *node) { 
	string s = "变为绿色:"+node;
        CCLog( s.c_str());  
} 
// node是运行当前动作的节点  
void HelloWorld::turnBlue(CCObject *node,void *data) {  
      CCLog( "变为蓝色:"); 
}  
  
void HelloWorld::turnDone(CCObject *done) {  
       CCLog( "变换完毕:"); 
}  
你会发现,精灵变为红色后 就会调用turnRed方法,变为绿色后会调用turnGreen:方法,变为蓝色后会先调用turnBlue:data:方法,最后调用turnDone:方法

最后做一个总结:

下面这几个类都会在运行动作时调用一个方法

CCCallFunc :调用方法时不传递参数

CCCallFuncN :调用方法时,可以传递1个参数,参数值是运行当前动作的节点

CCCallFuncND :调用方法时,可以传递2个参数,第1个参数是运行当前动作的节点,第2个参数是actionWithTarget:selector:data:方法中的data值

CCCallFuncO :调用方法时,可以传递1个参数,参数值是actionWithTarget:selector:object:方法中的object值


CCRepeatForever

CCRepeatForever直接继承自CCAction,可以不停地运行某个间隔动作(CCActionInterval)。

如果你想让精灵不停地旋转,可以这样写:

// 1秒内顺时针旋转360°  
   CCRotateBy *rotate = CCRotateBy ::create(1,360);
// 使用CCRepeatForever重复CCRotateBy动作  
   CCRepeatForever *repeat = CCRepeatForever ::create(rotate);
   sprite-> runAction(repeat); 

也能够利 用CCRepeatForever重复一个动作序列(CCSequence)
// 变为红色  
   CCTintTo *tintTo1 = CCTintTo::create(1,255,0,0);
// 变为绿色  
   CCTintTo *tintTo2 = CCTintTo::create(1,0,255,0);
// 变为蓝色  
   CCTintTo *tintTo3 = CCTintTo::create(1,0,0,255);
   CCSequence *sequence = CCSequence ::create(tintTo1, tintTo2, tintTo3,NULL);
   CCRepeatForever *repeat = CCRepeatForever::create(sequence);
   sprite ->runAction(repeat);  

你会发现精灵的颜色状态是:红 -> 绿 -> 蓝 -> 红 -> 绿 -> 蓝 -> 红 ...,一直在红绿蓝3种颜色之间按顺序切换


CCSpeed

CCSpeed也是直接继承自CCAction,可以影响间隔动作(继承自CCActionInterval的动作)的运行速度

// 1秒内顺时针旋转360°  
   CCRotateBy *rotate = CCRotateBy::create(1,360); 
// 速度变为原来的一半  
   CCSpeed *speed = CCSpeed::create(rotate,0.5); 
   sprite-> runAction(speed);  
本来 1秒就完成旋转的,设置speed为0.5后,就需要2秒才能 完成旋转

 PS:

   <1> [注1]

   

  <2>  

  cocos2d-x升级后取消了CCMutableArray,借用CCArray来代替。遍历方式也变了

   CCMutableArray使用有点像stl 中的vector,需要定义一个类型,CCArray全是CCObject,需要用什么类型都要转换。遍历数组方式也变了,之前的像stl中的   iterator,升级后使用CCARRAY_FOREACH宏。










  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值