cocos2d-X 进度条

在Cocos2d-x 2.0中有一个工程例子叫"ActionsProgressTest",故明思义是进度动画的演示,应该说在几乎所有的RPG类游戏中我们都会看到进度条,所以进度动画的作用之大是无须我多言。我们本节就来学习一下Cocos2d-x 2.0的进度动画。

          首先,先把那个"ActionsProgressTest"放一边,我要做的不是让大家去知其然,而是要知其所以然。所以我们要学习一下进度动画的原理与实现,在此我们向大家介绍一下所要用到的三个关键功能类:

1.CCProgressTimer :  进度动画的渲染器,核心实现了进度动画的显示功能,本身是一个结点,通过渲染一个精灵来表现进度的变化。

2.CCProgressTo:    TO进度控制器,控制进度从当前进度变化到某个值.

3.CCProgressFromTo:   FromTo进度控制器,控制进度从一个指定值到另一个值的变化.

 

          咱们先来看一下CCProgressTimer,这个类是整个进度动画的重中之重。


打开CCProgressTimer .h:

[cpp] 
#ifndef __MISC_NODE_CCPROGRESS_TIMER_H__ 
#define __MISC_NODE_CCPROGRESS_TIMER_H__ 
//使用精灵类 
#include "sprite_nodes/CCSprite.h" 
//使用Cocos2d命名空间 
NS_CC_BEGIN 
 
//定义一个枚举,代表两种不同的进度动画目标渲染类型。 
typedef enum { 
    ///绕圆心转动的进度动画 
        kCCProgressTimerTypeRadial, 
    ///条形的进度动画。 
    kCCProgressTimerTypeBar, 
} CCProgressTimerType; 
 
//由CCNode和CCRGBAProtocol派生出CCProgressTimer类。 
class CC_DLL CCProgressTimer : public CCNode, public CCRGBAProtocol 

public: 
    //构造函数。 
    CCProgressTimer(); 
    //析构函数。 
    ~CCProgressTimer(void); 
 
    //取得当前的进度动画目标渲染类型 
    inline CCProgressTimerType getType(void) { return m_eType; } 
 
    //返回当前时刻的进度值。 
    inline float getPercentage(void) {return m_fPercentage; } 
 
    //取得当前进度动画所渲染的精灵。 
    inline CCSprite* getSprite(void) { return m_pSprite; } 
 
    //设置当前进度动画所渲染的精灵,并初始化动画。 
    bool initWithSprite(CCSprite* sp); 
    //设置当前时刻的进度值。 
    void setPercentage(float fPercentage); 
    //设置当前进度动画所渲染的精灵 
    void setSprite(CCSprite *pSprite); 
    //设置当前的进度动画目标渲染类型 
    void setType(CCProgressTimerType type); 
    //设置是否反向播放进度动画。 
    void setReverseProgress(bool reverse); 
    //渲染当前结点。 
    virtual void draw(void); 
    //设置锚点位置。 
    void setAnchorPoint(CCPoint anchorPoint); 
    //设置颜色。 
    virtual void setColor(const ccColor3B& color); 
    //取得颜色。 
    virtual const ccColor3B& getColor(void); 
    //取得透明度。 
    virtual GLubyte getOpacity(void); 
    //设置透明度。 
    virtual void setOpacity(GLubyte opacity); 
    //设置透明度是否按颜色值变动而变动。 
    virtual void setOpacityModifyRGB(bool bValue); 
    //取得透明度是否按颜色值变动而变动。 
    virtual bool isOpacityModifyRGB(void); 
    //取得是否是按反方向播放动画。 
    inline bool isReverseDirection() { return m_bReverseDirection; }; 
    //设置是否按反方向播放动画。 
    inline void setReverseDirection(bool value) { m_bReverseDirection = value; }; 
 
public: 
    //静态函数,创建一个进度时间控制器,内部调用create实现. 
    CC_DEPRECATED_ATTRIBUTE static CCProgressTimer* progressWithSprite(CCSprite* sp); 
    //同上. 
    static CCProgressTimer* create(CCSprite* sp); 
protected: 
    //由一个二维插值参数值计算出纹理坐标U,V。 
    ccTex2F textureCoordFromAlphaPoint(CCPoint alpha); 
    //由一个二维插值参数值计算出顶点坐标X,Y。 
    ccVertex2F vertexFromAlphaPoint(CCPoint alpha); 
    //更新进度 
    void updateProgress(void); 
    //更新条形进度的状态 
    void updateBar(void); 
    //更新绕圆心转动的状态 
    void updateRadial(void); 
    //更新颜色 
    void updateColor(void); 
    // 
    CCPoint boundaryTexCoord(char index); 
 
protected: 
    //进度动画目标渲染类型 
    CCProgressTimerType m_eType; 
    //当前的进度值 
    float m_fPercentage; 
    //所渲染的精灵. 
    CCSprite *m_pSprite; 
    //顶点数量 
    int m_nVertexDataCount; 
    //顶点数据指针。 
    ccV2F_C4B_T2F *m_pVertexData; 
 
    //这里是一个称为“中点”的成员变量值,但它的意义绝不是这么简单,如果是绕中心旋转的进度动画,它就是中心,如果是条形动画,它代表了UV随进度变化的起始位置,如果是在最左边,其值为(0,y),如果是在最右边,其值为(1,y),如果在最上面(x,0),如果在最下面(x,1);如果是在中心(0.5,0.5)。 
    CC_PROPERTY(CCPoint, m_tMidpoint, Midpoint); 
     
    //设里是一个表示动画方向的成员变量值,如果是横向方向,则设为(1,0),如果是纵向方向,则设为(0,1); 
    CC_SYNTHESIZE(CCPoint, m_tBarChangeRate, BarChangeRate); 
    //bool变量,代表是否反方向播放动画。 
    bool m_bReverseDirection; 
}; 
 
NS_CC_END 
 
#endif  

再来看CPP文件:

[cpp] 
#include "CCProgressTimer.h" 
 
#include "ccMacros.h" 
#include "textures/CCTextureCache.h" 
#include "support/CCPointExtension.h" 
#include "shaders/CCGLProgram.h" 
#include "shaders/CCShaderCache.h" 
#include "shaders/ccGLStateCache.h" 
#include "CCDirector.h" 
#include "support/TransformUtils.h" 
#include "CCDrawingPrimitives.h" 
// extern 
#include "kazmath/GL/matrix.h" 
 
#include <float.h> 
//使用Cocos2d命名空间 
NS_CC_BEGIN 
 
//定义动画的四边形的四个角的纹理UV数量 
#define kProgressTextureCoordsCount 4 
// 将动画的四边形的四个角的纹理UV按位压缩到一个char中,从左下角{0,1}起,然后左上角{0,0},右上角{1,0},最后右下角{1,1},对应为0x4b,也就是01001011啊,貌似很方便,其实很坑爹。 
const char kCCProgressTextureCoords = 0x4b; 
 
//构造函数 
CCProgressTimer::CCProgressTimer() 
:m_eType(kCCProgressTimerTypeRadial) 
,m_fPercentage(0.0f) 
,m_pSprite(NULL) 
,m_nVertexDataCount(0) 
,m_pVertexData(NULL) 
,m_tMidpoint(0,0) 
,m_tBarChangeRate(0,0) 
,m_bReverseDirection(false) 
{} 
//静态函数,创建一个进度时间控制器,内部调用create实现.CCProgressTimer* CCProgressTimer::progressWithSprite(CCSprite* sp) 

    return CCProgressTimer::create(sp); 

//同上 
CCProgressTimer* CCProgressTimer::create(CCSprite* sp) 

    //先用new创建一个CCProgressTimer 实例对象。 
    CCProgressTimer *pProgressTimer = new CCProgressTimer(); 
    //对其进行初始化,这里应该先做一个有效性判断。 
    if (pProgressTimer->initWithSprite(sp)) 
    { 
    //交由内存管理器进行释放。 
        pProgressTimer->autorelease(); 
    } 
    else 
    { 
    //如果初始化失败,删除实例并置空。 
        delete pProgressTimer; 
        pProgressTimer = NULL; 
    }         
    //返回新创建的CCProgressTimer 实例对象指针。 
    return pProgressTimer; 

 
//初始化。 
bool CCProgressTimer::initWithSprite(CCSprite* sp) 

    //设置当前进度为0 
    setPercentage(0.0f); 
    //设置顶点BUF的指针为空,顶点数量为0,。 
    m_pVertexData = NULL; 
    m_nVertexDataCount = 0; 
    //设置锚点。 
    setAnchorPoint(ccp(0.5f,0.5f)); 
    //设置动画形式为绕圆心旋转。 
    m_eType = kCCProgressTimerTypeRadial; 
    //正方向播放动画。 
    m_bReverseDirection = false; 
    //设置圆心位置。 
    setMidpoint(ccp(0.5f, 0.5f)); 
    // 
    setBarChangeRate(ccp(1,1)); 
    //设置渲染的精灵。 
    setSprite(sp); 
     
    // 设置使用的Shader代码片段.动画的效果由Shader来渲染。 
setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTextureColor)); 
    return true; 

//析构函数。 
CCProgressTimer::~CCProgressTimer(void) 

    //释放顶点BUF,并对所占用的精灵进行引用计数减1操作。 
    CC_SAFE_FREE(m_pVertexData); 
    CC_SAFE_RELEASE(m_pSprite); 

//设置当前的进度值。 
void CCProgressTimer::setPercentage(float fPercentage) 

    //如果进度值有更新。 
    if (m_fPercentage != fPercentage) 
    { 
    //先将进度值限定在0~100间,然后更新进度。 
        m_fPercentage = clampf(fPercentage, 0, 100); 
        updateProgress(); 
    } 

//设置演示当前动画的精灵。 
void CCProgressTimer::setSprite(CCSprite *pSprite) 

    //先做个判断,防止重复进行设置。 
    if (m_pSprite != pSprite) 
    { 
    //占用新的精灵,对其引用计数器加1 
        CC_SAFE_RETAIN(pSprite); 
    //释放老的精灵,对其引用计数器减1 
        CC_SAFE_RELEASE(m_pSprite); 
       //将新的精灵设置为当前演示动画的精灵。 
        m_pSprite = pSprite; 
       //设置绘制当前精灵的区域大小 
        setContentSize(m_pSprite->getContentSize()); 
 
        //  如果顶点BUF有值, 
        if (m_pVertexData) 
        { 
       //释放并置空 
            CC_SAFE_FREE(m_pVertexData); 
           //设置顶点数量为0 
            m_nVertexDataCount = 0; 
        } 
    }         

//设置当前的进度动画目标渲染类型 
void CCProgressTimer::setType(CCProgressTimerType type) 

    //做个判断,避免重复设置。 
    if (type != m_eType) 
    { 
      //  如果顶点BUF有值, 
        if (m_pVertexData) 
        {          //释放并置空 
            CC_SAFE_FREE(m_pVertexData); 
            m_pVertexData = NULL; 
            //设置顶点数量为0 
            m_nVertexDataCount = 0; 
        } 
        //设置进度动画目标渲染类型. 
        m_eType = type; 
    } 

//设置是否按反方向播放动画。 
void CCProgressTimer::setReverseProgress(bool reverse) 

    //做个判断,避免重复设置。 
    if( m_bReverseDirection != reverse ) { 
        m_bReverseDirection = reverse; 
 
       //如果顶点BUF有值,释放并置空并置顶点数量为0 
        CC_SAFE_FREE(m_pVertexData); 
        m_nVertexDataCount = 0; 
    } 

//设置颜色。 
void CCProgressTimer::setColor(const ccColor3B& color) 

    //对所控制的精灵进行设置颜色。 
    m_pSprite->setColor(color); 
    //更新颜色。 
    updateColor(); 

//取得颜色。 
const ccColor3B& CCProgressTimer::getColor(void) 

    //由所控制的精灵取得颜色。 
    return m_pSprite->getColor(); 

//设置透明度。 
void CCProgressTimer::setOpacity(GLubyte opacity) 

    //由所控制的精灵设置透明度。 
    m_pSprite->setOpacity(opacity); 
    //更新颜色。 
    updateColor(); 

//取得透明度。 
GLubyte CCProgressTimer::getOpacity(void) 

    //由所控制的精灵取得透明度。 
    return m_pSprite->getOpacity(); 

//设置透明度是否按颜色值变动而变动。 
void CCProgressTimer::setOpacityModifyRGB(bool bValue) 

    CC_UNUSED_PARAM(bValue); 

//取得透明度是否按颜色值变动而变动。 
bool CCProgressTimer::isOpacityModifyRGB(void) 

    return false; 

 
//根据一个二维插值参数值计算当前进度的纹理UV。 
ccTex2F CCProgressTimer::textureCoordFromAlphaPoint(CCPoint alpha) 

    //定义一个2维纹理坐标结构,初始化u,v为0,0 
    ccTex2F ret = {0.0f, 0.0f}; 
    //如果没有操控的精灵,返回. 
    if (!m_pSprite) { 
        return ret; 
    } 
    //取得精灵的绘制四边形的顶点 
    ccV3F_C4B_T2F_Quad quad = m_pSprite->getQuad(); 
     
    //左下角的纹理坐标存入min 
    CCPoint min = ccp(quad.bl.texCoords.u,quad.bl.texCoords.v); 
    //右上角的纹理坐标存入max 
    CCPoint max = ccp(quad.tr.texCoords.u,quad.tr.texCoords.v); 
     
    //如果精灵切换需要旋转90度,这里交换一下x,y值. 
    if (m_pSprite->isTextureRectRotated()) { 
        CC_SWAP(alpha.x, alpha.y, float); 
    } 
    //通过插值计算出对应的UV坐标位置存入一个ccTex2F 值返回. 
    return tex2(min.x * (1.f - alpha.x) + max.x * alpha.x, min.y * (1.f - alpha.y) + max.y * alpha.y); 

//根据一个二维插值参数值计算当前进度的顶点X,Y。 
ccVertex2F CCProgressTimer::vertexFromAlphaPoint(CCPoint alpha) 

    //定义一个2维顶点值,初始化x,y为0,0 
    ccVertex2F ret = {0.0f, 0.0f}; 
    //如果没有操控的精灵,返回. 
    if (!m_pSprite) { 
        return ret; 
    } 
    //取得精灵的绘制四边形的顶点 
    ccV3F_C4B_T2F_Quad quad = m_pSprite->getQuad(); 
    //左下角的位置存入min 
    CCPoint min = ccp(quad.bl.vertices.x,quad.bl.vertices.y); 
    //右上角的位置存入max 
    CCPoint max = ccp(quad.tr.vertices.x,quad.tr.vertices.y); 
    //通过插值计算出对应的顶点位置存入ret. 
    ret.x = min.x * (1.f - alpha.x) + max.x * alpha.x; 
    ret.y = min.y * (1.f - alpha.y) + max.y * alpha.y; 
    return ret; 

//更新颜色 
void CCProgressTimer::updateColor(void) 

    //如果没有操控的精灵,返回. 
    if (!m_pSprite) { 
        return; 
    } 
    //如果有顶点数据. 
    if (m_pVertexData) 
    { 
    //取得左上角顶点的色彩存入临时色彩变量sc,然后遍历所有顶点设置为sc。 
        ccColor4B sc = m_pSprite->getQuad().tl.colors; 
        for (int i = 0; i < m_nVertexDataCount; ++i) 
        { 
            m_pVertexData[i].colors = sc; 
        }             
    } 

//更新进度。 
v

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值