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