Cocos2d-x 实现技能冷却效果

CD动画,也就是技能冷却。

介绍:技能冷却的效果跟魔兽世界中的技能冷却类似,功能如下:技能图标点击时会有按下效果,抬起后开始冷却计时,冷却计时技术后该图标才可以再次进行点击。
实现:三层实现:
最下方是CCMenuItemImage 按钮图片 -- normal
中间是半透明模版图片 -- stencil
最上方是CCProgressTimer 图片是最下图中较大的图片 -- click
这是使用的图片资源(normal,click,stencil)
 
动画原理:
非冷却状态时只显示CCMenuItemImage,当冷却开始计时时,将按钮设为不可点击状态,同将半透明模板和进度条精灵设置为可见状态,并且进度条精灵开始进行旋转动作,旋转结束后在回调函数中将半透明模板和进度条精灵设为不可见,按钮重新设置为可点击状态。
 
下面先看看原作者的实现方案:
 1 /** 
 2     实现技能冷却效果 
 3 
 4     Notice:添加child时要注意上下层关系
 5     最下方是按钮 其次是半透明的模版图片 最上方是CCProgressTimer进度条精灵
 6 */
 7 #ifndef _SKILLBUTTON_H_
 8 #define _SKILLBUTTON_H_
 9 #include <cocos2d.h>
10 
11 class SkillButton : public cocos2d::CCNode
12 {
13 public:
14     SkillButton();
15     virtual ~SkillButton();
16 
17     /** 创建一个SkillButton对象
18         */
19     static SkillButton* createSkillButton(float cdTime,
20                                         const char* stencil_file_name, 
21                                         const char* button_normal_name, 
22                                         const char* button_click_name);
23 
24     /** CD时间设置
25         */
26     void    setCDTime(float time) { mCDTime = time; }
27     float   getCDTime() const { return mCDTime; }
28 
29     /** 技能按钮点击回调 */
30     void    skillClickCallBack(cocos2d::CCObject* obj);
31 
32     /** 技能冷却完毕回调*/
33     void    skillCoolDownCallBack(cocos2d::CCNode* node);
34 
35 private:
36 
37     /** 初始化 */
38     bool    init(float cdTime, const char* stencil_file_name, const char* button_normal_name, const char* button_click_name);
39 
40 private:
41     cocos2d::CCMenuItemImage*   mItemSkill;     // 技能按钮
42     cocos2d::CCMenu*            mMenuSkill;     // 技能按钮所在menu
43     cocos2d::CCSprite*          mStencil;       // 蒙板精灵,黑色半透明(这个是为了显示一个冷却计时效果)
44     cocos2d::CCProgressTimer*   mProgressTimer; // 时间进度条精灵(360度旋转)
45     float                       mCDTime;          // CD时间
46 };
47 #endif
  1 #include "SkillButton.h"
  2 
  3 USING_NS_CC;
  4 
  5 SkillButton::SkillButton():
  6     mItemSkill(NULL),
  7     mMenuSkill(NULL),
  8     mStencil(NULL),
  9     mProgressTimer(NULL),
 10     mCDTime(1.f)
 11 {
 12 
 13 }
 14 
 15 SkillButton::~SkillButton()
 16 {
 17 
 18 }
 19 
 20 SkillButton* SkillButton::createSkillButton(float cdTime, const char* stencil_file_name, const char* button_normal_name, const char* button_click_name)
 21 {
 22     SkillButton* skillButton = new SkillButton();
 23     if (skillButton && skillButton->init(cdTime, stencil_file_name, button_normal_name, button_click_name))
 24     {
 25         skillButton->autorelease();
 26         return skillButton;
 27     }
 28     else
 29     {
 30         delete skillButton;
 31         skillButton = NULL;
 32     }
 33 
 34     return NULL;
 35 }
 36 
 37 bool SkillButton::init(float cdTime, const char* stencil_file_name, const char* button_normal_name, const char* button_click_name)
 38 {
 39     CCAssert(stencil_file_name, "SkillButton::init stencil_file_name != NULL");
 40     CCAssert(button_normal_name, "SkillButton::init button_normal_name != NULL");
 41     CCAssert(button_click_name, "SkillButton::init button_click_name != NULL");
 42 
 43     // Notice:添加child时要注意上下层
 44     // 最下方是CCMenuItemImage 其次是模版图片 最上方是CCProgressTimer
 45 
 46     // 添加技能按钮 下层
 47     mItemSkill = CCMenuItemImage::create(button_normal_name, button_click_name, this, menu_selector(SkillButton::skillClickCallBack));
 48     mItemSkill->setPosition(CCPointZero);
 49 
 50     mMenuSkill = CCMenu::create(mItemSkill, NULL);
 51     mMenuSkill->setPosition(CCPointZero);
 52     addChild(mMenuSkill, -100);
 53 
 54     // 添加阴影模版 中间层
 55     mStencil = CCSprite::create(stencil_file_name);
 56     mStencil->setPosition(CCPointZero);
 57     mStencil->setVisible(false);
 58     addChild(mStencil);
 59 
 60     // 添加旋转进度条精灵 上层
 61     CCSprite* progressSprite = CCSprite::create(button_normal_name);
 62     mProgressTimer = CCProgressTimer::create(progressSprite);
 63     mProgressTimer->setPosition(CCPointZero);
 64     mProgressTimer->setVisible(false);
 65     addChild(mProgressTimer, 100);
 66 
 67     mCDTime = cdTime;
 68     return true;
 69 }
 70 
 71 /** 技能按钮点击回调 */
 72 void SkillButton::skillClickCallBack(cocos2d::CCObject* obj)
 73 {
 74     // 冷却计时,即时状态技能按钮不可点击
 75     mItemSkill->setEnabled(false);
 76 
 77     // 模版可见
 78     mStencil->setVisible(true);
 79 
 80     // 设置精灵进度条为顺时针
 81     mProgressTimer->setVisible(true);
 82     mProgressTimer->setType(kCCProgressTimerTypeRadial);
 83 
 84     //准备一个旋转360度的动画(逐渐覆盖半透模板形成冷却效果;这里进行计时冷却动画的实现和时间控制)
 85     CCActionInterval* action_progress_to = CCProgressTo::create(mCDTime, 100);
 86     CCCallFunc* action_callback = CCCallFuncN::create(this, callfuncN_selector(SkillButton::skillCoolDownCallBack));
 87     mProgressTimer->runAction(CCSequence::create(action_progress_to, action_callback, NULL));
 88 }
 89 
 90 /** 技能冷却完成回调 */
 91 void SkillButton::skillCoolDownCallBack(CCNode* node)
 92 {
 93     // 设置蒙板不可见
 94     mStencil->setVisible(false);
 95 
 96     // 进度条技能不可见
 97     mProgressTimer->setVisible(false);
 98 
 99     // 按钮置为可用
100     mItemSkill->setEnabled(true);
101 }

使用:(注意创建时其中的参数:第一个是冷却时间,其他都是图片)

1 CCSize s = CCDirector::sharedDirector()->getWinSize();
2     SkillButton* mSkillButton = SkillButton::createSkillButton(2.f, "stencil.png", "normal.png", "click.png");
3     mSkillButton->setPosition(ccp(s.width/2, s.height/2));
4     addChild(mSkillButton);

技能效果:

改进实现:我觉得其实这种实现方式有点麻烦,其实两层就可以实现了。

两层实现:
下层:CCMenuItemImage 按钮图片 -- normal
上层:CCProgressTimer 图片是半透明模版图片 -- stencil
 
实现过程:飞冷却状态下,只显示CCMenuItemImage,而上层的半透明图片是隐藏的。当实现冷却技能的效果时,下层的CCMenuItemImage设置为不可点击状态,而上层的半透明图片实现进度条的环形旋转,从360度顺时针减少到0度。

下面给出改进版的实现
只列出有变化的代码:

1、关于 cocos2d::CCSprite*  mStencil; 这个精灵的所有代码都去掉
2、修改实现文件中的函数有如下:
 1 bool SkillButton::init(float cdTime, const char* stencil_file_name, const char* button_normal_name, const char* button_click_name)
 2 {
 3     CCAssert(stencil_file_name, "SkillButton::init stencil_file_name != NULL");
 4     CCAssert(button_normal_name, "SkillButton::init button_normal_name != NULL");
 5     CCAssert(button_click_name, "SkillButton::init button_click_name != NULL");
 6     
 7     // 添加技能按钮 下层
 8     mItemSkill = CCMenuItemImage::create(button_normal_name, button_click_name, this, menu_selector(SkillButton::skillClickCallBack));
 9     mItemSkill->setPosition(CCPointZero);
10     
11     mMenuSkill = CCMenu::create(mItemSkill, NULL);
12     mMenuSkill->setPosition(CCPointZero);
13     addChild(mMenuSkill, -100);
14     
15     // 添加旋转进度条精灵---半阴影 上层
16     CCSprite* progressSprite = CCSprite::create(stencil_file_name);
17     mProgressTimer = CCProgressTimer::create(progressSprite);
18     mProgressTimer->setPosition(CCPointZero);
19     mProgressTimer->setVisible(false);
20     addChild(mProgressTimer, 100);
21     
22     mCDTime = cdTime;
23     return true;
24 }
25 
26 /** 技能按钮点击回调 */
27 void SkillButton::skillClickCallBack(cocos2d::CCObject* obj)
28 {
29     // 冷却计时,即时状态技能按钮不可点击
30     mItemSkill->setEnabled(false);
31     
32     
33     mProgressTimer->setVisible(true);
34     mProgressTimer->setType(kCCProgressTimerTypeRadial);
35     mProgressTimer->setReverseProgress(true); // 设置进度条为逆时针
36 
37     //准备一个旋转360度的动画(逐渐覆盖半透模板形成冷却效果;这里进行计时冷却动画的实现和时间控制)
38     
39     //注意这里冷却效果是从100%到0%顺时针变化的
40     CCActionInterval* action_progress_from_to = CCProgressFromTo::create(mCDTime, 100, 0); 
41     
42     CCCallFunc* action_callback = CCCallFuncN::create(this, callfuncN_selector(SkillButton::skillCoolDownCallBack));
43     mProgressTimer->runAction(CCSequence::create(action_progress_from_to, action_callback, NULL));
44 }
45 
46 /** 技能冷却完成回调 */
47 void SkillButton::skillCoolDownCallBack(CCNode* node)
48 {
49     // 进度条技能不可见
50     mProgressTimer->setVisible(false);
51     
52     // 按钮置为可用
53     mItemSkill->setEnabled(true);
54 }

ok,再次运行,效果是完全一致的。

原文链接: http://blog.csdn.net/crayondeng/article/details/11265207

原文地址:https://www.cnblogs.com/atong/p/3309755.html