现在的位置: 首页 > 综合 > 正文

Cocos2d-x 实现技能冷却效果

2013年12月03日 ⁄ 综合 ⁄ 共 6016字 ⁄ 字号 评论关闭


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

下面先看看 http://blog.csdn.net/z104207/article/details/8059098 中对技能冷却的介绍和实现!

介绍:技能冷却的效果跟魔兽世界中的技能冷却类似,功能如下:技能图标点击时会有按下效果,抬起后开始冷却计时,冷却计时技术后该图标才可以再次进行点击。
实现:三层实现:

最下方是CCMenuItemImage 按钮图片 -- normal
中间是半透明模版图片 -- stencil
最上方是CCProgressTimer 图片是最下图中较大的图片 -- click

这是使用的图片资源(normal,click,stencil)
    


动画原理:
非冷却状态时只显示CCMenuItemImage,当冷却开始计时时,将按钮设为不可点击状态,同将半透明模板和进度条精灵设置为可见状态,并且进度条精灵开始进行旋转动作,旋转结束后在回调函数中将半透明模板和进度条精灵设为不可见,按钮重新设置为可点击状态。

下面先看看原作者的实现方案:
/** 
    实现技能冷却效果 

    Notice:添加child时要注意上下层关系
    最下方是按钮 其次是半透明的模版图片 最上方是CCProgressTimer进度条精灵
*/
#ifndef _SKILLBUTTON_H_
#define _SKILLBUTTON_H_
#include <cocos2d.h>

class SkillButton : public cocos2d::CCNode
{
public:
    SkillButton();
    virtual ~SkillButton();

    /** 创建一个SkillButton对象
        */
    static SkillButton* createSkillButton(float cdTime,
                                        const char* stencil_file_name, 
                                        const char* button_normal_name, 
                                        const char* button_click_name);

    /** CD时间设置
        */
    void    setCDTime(float time) { mCDTime = time; }
    float   getCDTime() const { return mCDTime; }

    /** 技能按钮点击回调 */
    void    skillClickCallBack(cocos2d::CCObject* obj);

    /** 技能冷却完毕回调*/
    void    skillCoolDownCallBack(cocos2d::CCNode* node);

private:

    /** 初始化 */
    bool    init(float cdTime, const char* stencil_file_name, const char* button_normal_name, const char* button_click_name);

private:
    cocos2d::CCMenuItemImage*   mItemSkill;     // 技能按钮
    cocos2d::CCMenu*            mMenuSkill;     // 技能按钮所在menu
    cocos2d::CCSprite*          mStencil;       // 蒙板精灵,黑色半透明(这个是为了显示一个冷却计时效果)
    cocos2d::CCProgressTimer*   mProgressTimer; // 时间进度条精灵(360度旋转)
    float                       mCDTime;          // CD时间
};
#endif

#include "SkillButton.h"

USING_NS_CC;

SkillButton::SkillButton():
    mItemSkill(NULL),
    mMenuSkill(NULL),
    mStencil(NULL),
    mProgressTimer(NULL),
    mCDTime(1.f)
{

}

SkillButton::~SkillButton()
{

}

SkillButton* SkillButton::createSkillButton(float cdTime, const char* stencil_file_name, const char* button_normal_name, const char* button_click_name)
{
    SkillButton* skillButton = new SkillButton();
    if (skillButton && skillButton->init(cdTime, stencil_file_name, button_normal_name, button_click_name))
    {
        skillButton->autorelease();
        return skillButton;
    }
    else
    {
        delete skillButton;
        skillButton = NULL;
    }

    return NULL;
}

bool SkillButton::init(float cdTime, const char* stencil_file_name, const char* button_normal_name, const char* button_click_name)
{
    CCAssert(stencil_file_name, "SkillButton::init stencil_file_name != NULL");
    CCAssert(button_normal_name, "SkillButton::init button_normal_name != NULL");
    CCAssert(button_click_name, "SkillButton::init button_click_name != NULL");

    // Notice:添加child时要注意上下层
    // 最下方是CCMenuItemImage 其次是模版图片 最上方是CCProgressTimer

    // 添加技能按钮 下层
    mItemSkill = CCMenuItemImage::create(button_normal_name, button_click_name, this, menu_selector(SkillButton::skillClickCallBack));
    mItemSkill->setPosition(CCPointZero);

    mMenuSkill = CCMenu::create(mItemSkill, NULL);
    mMenuSkill->setPosition(CCPointZero);
    addChild(mMenuSkill, -100);

    // 添加阴影模版 中间层
    mStencil = CCSprite::create(stencil_file_name);
    mStencil->setPosition(CCPointZero);
    mStencil->setVisible(false);
    addChild(mStencil);

    // 添加旋转进度条精灵 上层
    CCSprite* progressSprite = CCSprite::create(button_normal_name);
    mProgressTimer = CCProgressTimer::create(progressSprite);
    mProgressTimer->setPosition(CCPointZero);
    mProgressTimer->setVisible(false);
    addChild(mProgressTimer, 100);

    mCDTime = cdTime;
    return true;
}

/** 技能按钮点击回调 */
void SkillButton::skillClickCallBack(cocos2d::CCObject* obj)
{
    // 冷却计时,即时状态技能按钮不可点击
    mItemSkill->setEnabled(false);

    // 模版可见
    mStencil->setVisible(true);

    // 设置精灵进度条为顺时针
    mProgressTimer->setVisible(true);
    mProgressTimer->setType(kCCProgressTimerTypeRadial);

    //准备一个旋转360度的动画(逐渐覆盖半透模板形成冷却效果;这里进行计时冷却动画的实现和时间控制)
    CCActionInterval* action_progress_to = CCProgressTo::create(mCDTime, 100);
    CCCallFunc* action_callback = CCCallFuncN::create(this, callfuncN_selector(SkillButton::skillCoolDownCallBack));
    mProgressTimer->runAction(CCSequence::create(action_progress_to, action_callback, NULL));
}

/** 技能冷却完成回调 */
void SkillButton::skillCoolDownCallBack(CCNode* node)
{
    // 设置蒙板不可见
    mStencil->setVisible(false);

    // 进度条技能不可见
    mProgressTimer->setVisible(false);

    // 按钮置为可用
    mItemSkill->setEnabled(true);
}

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

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

技能效果:

                           


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

两层实现:
下层:CCMenuItemImage 按钮图片 --
normal
上层:CCProgressTimer 图片是半透明模版图片
-- stencil

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

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

1、关于 cocos2d::CCSprite*  mStencil; 这个精灵的所有代码都去掉
2、修改实现文件中的函数有如下:
bool SkillButton::init(float cdTime, const char* stencil_file_name, const char* button_normal_name, const char* button_click_name)
{
    CCAssert(stencil_file_name, "SkillButton::init stencil_file_name != NULL");
    CCAssert(button_normal_name, "SkillButton::init button_normal_name != NULL");
    CCAssert(button_click_name, "SkillButton::init button_click_name != NULL");
    
    // 添加技能按钮 下层
    mItemSkill = CCMenuItemImage::create(button_normal_name, button_click_name, this, menu_selector(SkillButton::skillClickCallBack));
    mItemSkill->setPosition(CCPointZero);
    
    mMenuSkill = CCMenu::create(mItemSkill, NULL);
    mMenuSkill->setPosition(CCPointZero);
    addChild(mMenuSkill, -100);
    
    // 添加旋转进度条精灵---半阴影 上层
    CCSprite* progressSprite = CCSprite::create(stencil_file_name);
    mProgressTimer = CCProgressTimer::create(progressSprite);
    mProgressTimer->setPosition(CCPointZero);
    mProgressTimer->setVisible(false);
    addChild(mProgressTimer, 100);
    
    mCDTime = cdTime;
    return true;
}

/** 技能按钮点击回调 */
void SkillButton::skillClickCallBack(cocos2d::CCObject* obj)
{
    // 冷却计时,即时状态技能按钮不可点击
    mItemSkill->setEnabled(false);
    
    
    mProgressTimer->setVisible(true);
    mProgressTimer->setType(kCCProgressTimerTypeRadial);
    mProgressTimer->setReverseProgress(true); // 设置进度条为逆时针

    //准备一个旋转360度的动画(逐渐覆盖半透模板形成冷却效果;这里进行计时冷却动画的实现和时间控制)
    
    //注意这里冷却效果是从100%到0%顺时针变化的
    CCActionInterval* action_progress_from_to = CCProgressFromTo::create(mCDTime, 100, 0); 
    
    CCCallFunc* action_callback = CCCallFuncN::create(this, callfuncN_selector(SkillButton::skillCoolDownCallBack));
    mProgressTimer->runAction(CCSequence::create(action_progress_from_to, action_callback, NULL));
}

/** 技能冷却完成回调 */
void SkillButton::skillCoolDownCallBack(CCNode* node)
{
    // 进度条技能不可见
    mProgressTimer->setVisible(false);
    
    // 按钮置为可用
    mItemSkill->setEnabled(true);
}


ok,再次运行,效果是完全一致的,关于变化内容大家看代码就知道了,不解释了大笑


抱歉!评论已关闭.