cocos2d-x-2.2.3-CCLayer源码学习(一)

| 分类 cocos2d-x  | 标签 CCLayerColor  CCLayer 

本文主要讲的是CCLayer,通过TestCpp来学习CCLayer。

typedef CCLayer* (*NEWTESTFUNC)();先来学习这一段代码。还是先看下度娘是怎么解释typedef的。typedef是用来为复杂的声明定义简单的别名,与宏定义有些差异。而上面一堆代码则引入了NEWTESTFUNC类型作为函数指针的同义词,该函数没有参数,返回值是CCLayer*类型。

  1. #define TESTLAYER_CREATE_FUNC(className) \
  2. static CCLayer* create##className() \
  3. { return new className(); }
  4. #define CF(className) create##className 上面一段代码是两个宏定义,关于宏定义-[#define](http://baike.baidu.com/view/1441209.htm),还是度娘好啊!!! 在#define中,标准只定义了#和##两种操作。#用来把参数转换成字符串,##则用来连接前后两个参数,把它们变成一个字符串。`#define paster( n ) printf( "token " #n" = %d\n ", token##n )`

下面就熟悉下CCLayer的源代码吧…

  1. //通过typedef声明了该枚举类型的别名ccTouchesMode,通过setTouchMode(ccTouchesMode mode)设置是单点触摸还是多点触摸
  2. typedef enum {
  3. kCCTouchesAllAtOnce,//单点
  4. kCCTouchesOneByOne,//多点
  5. } ccTouchesMode;
  6. //以下方法都是基本方法
  7. CCLayer();
  8. virtual ~CCLayer();
  9. virtual bool init();
  10. static CCLayer *create(void);
  11. virtual void onEnter();
  12. virtual void onExit();
  13. virtual void onEnterTransitionDidFinish();
  14. // 单点触摸
  15. virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
  16. virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
  17. virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
  18. virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);
  19. // 多点触摸
  20. virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);
  21. virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent);
  22. virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent);
  23. virtual void ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent);
  24. virtual void registerWithTouchDispatcher(void);//注册触摸事件,在该方法中注册单点CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this,INT_MIN+1,true);注册多点 CCTouchDispatcher::sharedDispatcher()->addStandardDelegate(this,0);
  25. //设置是否可以触摸
  26. virtual bool isTouchEnabled();
  27. virtual void setTouchEnabled(bool value);
  28. //设置触摸方式
  29. virtual void setTouchMode(ccTouchesMode mode);
  30. virtual int getTouchMode();
  31. //设置触摸优先级
  32. virtual void setTouchPriority(int priority);
  33. virtual int getTouchPriority();
  34. //设置是否启用加速
  35. virtual bool isAccelerometerEnabled();
  36. virtual void setAccelerometerEnabled(bool value);
  37. virtual void setAccelerometerInterval(double interval);
  38. //是否接受键盘事件
  39. virtual bool isKeypadEnabled();
  40. virtual void setKeypadEnabled(bool value);
  41. //返回键以及menu键的回调事件
  42. virtual void keyBackClicked(void);
  43. virtual void keyMenuClicked(void); 下面是CCLayer的类图:
![image](/assets/classcocos2d_1_1_c_c_layer.png)

从上图可以晓得,CCLayer的子类有CCLayermultlplex,CCLayerRGBA,CCLayerColor,CCLayerGradient等一系列的子类。下面我们就看下其子类的相关代码。

  1. //CCLayerRGBA继承于CCLayer以及CCRGBAProtocol,下面是CCLayerRGBA的基本方法
  2. CCLayerRGBA();
  3. virtual ~CCLayerRGBA();
  4. virtual bool init();
  5. //下面的方法都是继承于CCRGBAProtocol
  6. virtual GLubyte getOpacity(); //获取透明度
  7. virtual GLubyte getDisplayedOpacity();////获取显示的透明度,显示的透明度指的是如果cascadeOpacityEnabled为true的时候,则还需要乘上父类的透明度
  8. virtual void setOpacity(GLubyte opacity);
  9. virtual void updateDisplayedOpacity(GLubyte parentOpacity);
  10. virtual bool isCascadeOpacityEnabled();//是否将父类透明度传递给子类
  11. virtual void setCascadeOpacityEnabled(bool cascadeOpacityEnabled);
  12. virtual const ccColor3B& getColor();//获取色值
  13. virtual const ccColor3B& getDisplayedColor();//获取显示的色值,显示的色值指的是如果cascadeOpacityEnabled为true的时候,则还需要乘上父类的色值
  14. virtual void setColor(const ccColor3B& color);
  15. virtual void updateDisplayedColor(const ccColor3B& parentColor);
  16. virtual bool isCascadeColorEnabled();//是否将父类色值传递给子类
  17. virtual void setCascadeColorEnabled(bool cascadeColorEnabled);

CCLayerColor继承于CCLayerRGBA,CCBlendProtocol,下面是CCLayerColor的主要方法

  1. ccVertex2F m_pSquareVertices[4];//该数组是放置四个顶点的
  2. ccColor4F m_pSquareColors[4];//该数组是放置色值的rgba
  3. //以下方法都是相关初始化相关方法
  4. CCLayerColor();
  5. virtual ~CCLayerColor();
  6. static CCLayerColor* create();
  7. static CCLayerColor * create(const ccColor4B& color, GLfloat width, GLfloat height);
  8. static CCLayerColor * create(const ccColor4B& color);
  9. virtual bool init();
  10. virtual bool initWithColor(const ccColor4B& color, GLfloat width, GLfloat height);
  11. virtual bool initWithColor(const ccColor4B& color);
  12. //改变宽高
  13. void changeWidth(GLfloat w);
  14. void changeHeight(GLfloat h);
  15. void changeWidthAndHeight(GLfloat w ,GLfloat h);
  16. virtual void setContentSize(const CCSize & var);
  17. CC_PROPERTY(ccBlendFunc, m_tBlendFunc, BlendFunc) //默认值是m_tBlendFunc.src = CC_BLEND_SRC;m_tBlendFunc.dst = CC_BLEND_DST;
  18. #define CC_BLEND_SRC GL_ONE
  19. #define CC_BLEND_DST GL_ONE_MINUS_SRC_ALPHA
  20. virtual void draw();//将位置以及颜色绘制到屏幕上

CCLayerColor的相关方法的具体实现:

  1. //初始化m_pSquareVertices四个顶点以及m_pSquareColors,该方法是在init()方法中回调的 bool CCLayerColor::initWithColor(const ccColor4B& color, GLfloat w, GLfloat h)
  2. {
  3. if (CCLayer::init())
  4. {
  5. // default blend function
  6. m_tBlendFunc.src = GL_SRC_ALPHA; //BlendFunc的src赋值为GL_SRC_ALPHA
  7. m_tBlendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
  8. //设置_displayedColor以及_realColor的RGB,由于在initWithColor这个方法中没有回调CCLayeRGB的updateDisplayedColor方法,所以通过create创建的CCLayerColor,在没有单独调用setColor()或者setOpacity之前_displayedColor和_realColor的值是一样的,即使cascadeOpacityEnabled为true也没用,因为没有调用updateDisplayedColor方法,话说这里是不是cocos2d-x忘了啊????
  9. _displayedColor.r = _realColor.r = color.r;
  10. _displayedColor.g = _realColor.g = color.g;
  11. _displayedColor.b = _realColor.b = color.b;
  12. _displayedOpacity = _realOpacity = color.a;
  13. for (size_t i = 0; i<sizeof(m_pSquareVertices) / sizeof( m_pSquareVertices[0]); i++ )
  14. {
  15. m_pSquareVertices[i].x = 0.0f;
  16. m_pSquareVertices[i].y = 0.0f;
  17. }
  18. updateColor();//将_displayedColor赋值到m_pSquareColors
  19. setContentSize(CCSizeMake(w,h)); //在该方法中将宽度以及长度赋值给m_pSquareVertices
  20. setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionColor));//设置CCGLProgram,该处的CCGLProgram是通过CCShaderCache::sharedShaderCache()缓存获取的。通过CCGLProgram类来处理着色器相关操作,对当前绘图程序进行了封装
  21. }
  22. return true;
  23. }
  24. 下面接着就看下updateColor()方法,将_displayedColor赋值到m_pSquareColors方法中,在setContentSize方法也是类似的将长.宽赋值到m_pSquareVertices
  25. void CCLayerColor::updateColor()
  26. {
  27. for( unsigned int i=0; i < 4; i++ )
  28. {
  29. m_pSquareColors[i].r = _displayedColor.r / 255.0f;
  30. m_pSquareColors[i].g = _displayedColor.g / 255.0f;
  31. m_pSquareColors[i].b = _displayedColor.b / 255.0f;
  32. m_pSquareColors[i].a = _displayedOpacity / 255.0f;
  33. }
  34. }
  35. //CCLayerColor的设置颜色的方法,在其中调用了CCLayerRGBA的设置颜色方法。关于CCLayerColor的setOpacity也是相似的情况。
  36. void CCLayerColor::setColor(const ccColor3B &color)
  37. {
  38. CCLayerRGBA::setColor(color);//调用了CCLayerRGBA的设置颜色方法
  39. updateColor();//赋值到m_pSquareColors
  40. }
  41. //下面是CCLayerRGBA的设置颜色方法
  42. void CCLayerRGBA::setColor(const ccColor3B& color)
  43. {
  44. _displayedColor = _realColor = color;
  45. if (_cascadeColorEnabled)//表明父类可不可以可以传递颜色给自己,,首先得判断自己可以不可以传递给子类,如果自己不可以传给其他人,不好意思,你baba也不传给你。_cascadeColorEnabled在cocos2d-x中有两个作用,但是在cocos2d-x源码注释中:whether or not color should be propagated to its children.(是否将颜色传递给子类)。在实际的代码当中,_cascadeColorEnabled有两种作用,第一种是:通过_cascadeColorEnabled来判断我接不接受父类的颜色。第二种是:我可不可以传递给子类颜色。但是这两种作用仅仅通过这一个_cascadeColorEnabled属性来判断觉得有点别扭,能不能用两个属性来判断啊???
  46. {
  47. ccColor3B parentColor = ccWHITE;//默认父类颜色为白色
  48. CCRGBAProtocol* parent = dynamic_cast<CCRGBAProtocol*>(m_pParent);
  49. if (parent && parent->isCascadeColorEnabled())//表明父类可以传递颜色给子类
  50. {
  51. parentColor = parent->getDisplayedColor();//获取父类的显示颜色
  52. }
  53. updateDisplayedColor(parentColor);//将父类颜色传递给到updateDisplayedColor方法,如果父类的isCascadeColorEnabled为false,则可以将默认的ccWHITE颜色传递过去
  54. }
  55. }
  56. //更新显示颜色
  57. void CCLayerRGBA::updateDisplayedColor(const ccColor3B& parentColor)
  58. {
  59. //将parentColor传递给子类,改变了_displayedColor的值
  60. _displayedColor.r = _realColor.r * parentColor.r/255.0;
  61. _displayedColor.g = _realColor.g * parentColor.g/255.0;
  62. _displayedColor.b = _realColor.b * parentColor.b/255.0;
  63. if (_cascadeColorEnabled)//现在的判断和CCLayerRGBA::setColor中的判断是不一样,因为下面的操作中,你将作为父类传递给子类,很明确其作用为:我可不可以传递给子类颜色
  64. {
  65. CCObject *obj = NULL;
  66. CCARRAY_FOREACH(m_pChildren, obj)//CCARRAY_FOREACH是一个宏定义,遍历m_pChildren中的CCNode,赋值给obj。其中m_pChildren是当前CCLayerRGBA的子类
  67. {
  68. CCRGBAProtocol *item = dynamic_cast<CCRGBAProtocol*>(obj);
  69. if (item)
  70. {
  71. item->updateDisplayedColor(_displayedColor);//将当前CCLayerRGBA的_displayedColor传递给其子类
  72. }
  73. }
  74. }
  75. }

下面来看个例子关于CCLayerColor的问题demo???

  1. LayerTest::onEnter();
  2. CCLayerColor *ccLayer01=CCLayerColor::create(ccc4(125, 20, 240, 230), 150, 150);//创建一个长宽150*150,色值为(125,20,240,230)的正方形
  3. ccLayer01->setPosition(VisibleRect::center());
  4. ccLayer01->ignoreAnchorPointForPosition(false);
  5. this->addChild(ccLayer01);//添加到CCLayer中
  6. ccLayer01->setCascadeColorEnabled(true);//表明我可以接受父类的颜色,但是父类传不传递是一回事。同时表明我可以传递颜色给子类,子类接不接受还是另一回事,好变扭啊,但就是这意思。。。对了ccLayer01的父亲是CCLayer,如果父亲不能传递给子类,那么默认其颜色也就是白色传递给ccLayer01
  7. CCLayerColor *ccLayer02=CCLayerColor::create(ccc4(125, 80, 150, 230), 100, 100);////创建一个长宽100*100,色值为(125,80,150,230)的正方形
  8. ccLayer02->setPosition(CCPoint(0, 0));
  9. ccLayer01->addChild(ccLayer02);//将ccLayer02添加到ccLayer01上
  10. ccLayer02->setCascadeColorEnabled(true);//表明ccLayer02可以接受父类的颜色,同时可以传递颜色给其子类
  11. ccLayer02->setColor(ccc3(125, 80, 150));//当助掉这行代码的时候,setCascadeColorEnabled为true,父类也为true,父类的颜色也传不过来,究其原因在上文已经说明,没有掉updateDisplayedColor这个方法啊,导致_displayedColor不会变化。 如下图:
![image](/assets/layercolor_01.png)
图-1-父类的颜色传给ccLayer02
![image](/assets/layercolor_02.png)
图-2-ccLayer02真实颜色-也就是注释掉ccLayer02->setColor方法或者setCascadeColorEnabled(false)

下面接着看CCLayerColor的源码:

  1. void CCLayerColor::draw()
  2. {
  3. CC_NODE_DRAW_SETUP();//启用shader
  4. ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_Color );//该方法封装了glEnableVertexAttribArray和glDisableVertexAttribArray。要启用或者禁用顶点属性数组,调用glEnableVertexAttribArray和glDisableVertexAttribArray传入参数index。如果启用,那么当glDrawArrays或者glDrawElements被调用时,顶点属性数组会被使用
  5. glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, m_pSquareVertices);////设置顶点,m_pSquareVertices是一个4元素的数组,每个元素表示一个顶点,依次是左下角、右下角、左上角、右上角
  6. glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_FLOAT, GL_FALSE, 0, m_pSquareColors);//设置颜色
  7. ccGLBlendFunc( m_tBlendFunc.src, m_tBlendFunc.dst );//设置像素渲染模式,这里是 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA),即“不论叠加多少次,亮度是不变的”
  8. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);//提供绘制功能。当采用顶点数组方式绘制图形时,使用该函数。该函数根据顶点数组中的坐标数据和指定的模式,进行绘制。
  9. CC_INCREMENT_GL_DRAWS(1);
  10. }
  11. /**
  12. CC_NODE_DRAW_SETUP宏定义,启用shader
  13. */
  14. #define CC_NODE_DRAW_SETUP() \
  15. do { \
  16. ccGLEnable(m_eGLServerState); \
  17. CCAssert(getShaderProgram(), "No shader program set for this node"); \
  18. { \
  19. getShaderProgram()->use(); \
  20. getShaderProgram()->setUniformsForBuiltins(); \
  21. } \
  22. } while(0)
  23. /**
  24. glVertexAttribPointer 指定了渲染时索引值为 index 的顶点属性数组的数据格式和位置。size指定每个属性值的组件数量且必须为1、2、3、4之一。type指定每个组件的数据格式,stride指定了一个属性到下一个属性之间的步长(这就允许属性值被存储在单一数组或者不同的数组中)。当数组中的值被访问并被转换至浮点值时,如果normalized被设置为GL_TRUE,意味着整数型的值会被映射至区间[-1,1](有符号整数),或者区间[0,1](无符号整数),反之,这些值会被直接转换为浮点值而不进行归一化处理。
  25. */
  26. void glVertexAttribPointer( GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride,const GLvoid * pointer);
  27. index:指定要修改的顶点属性的索引值
  28. size:指定每个顶点属性的组件数量。必须为123或者4。初始值为4。(如position是由3个(x,y,z)组成,而颜色是4个(r,g,b,a))
  29. type:指定数组中每个组件的数据类型。可用的符号常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,GL_UNSIGNED_SHORT, GL_FIXED, GL_FLOAT,初始值为GL_FLOAT
  30. normalized:指定当被访问时,固定点数据值是否应该被归一化(GL_TRUE)或者直接转换为固定点值(GL_FALSE)。
  31. stride:指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0
  32. pointer:指定一个指针,指向数组中第一个顶点属性的第一个组件。初始值为0
  33. /**
  34. 提供绘制功能。当采用顶点数组方式绘制图形时,使用该函数。该函数根据顶点数组中的坐标数据和指定的模式,进行绘制。调用该函数之前需要,调用glEnableVertexAttribArray、glVertexAttribPointer等设置顶点属性和数据。
  35. */
  36. glDrawArrays (GLenum mode, GLint first, GLsizei count);
  37. 1.mode,绘制方式,OpenGL2.0以后提供以下参数:GL_POINTSGL_LINESGL_LINE_LOOPGL_LINE_STRIPGL_TRIANGLESGL_TRIANGLE_STRIPGL_TRIANGLE_FAN
  38. 2.first,从数组缓存中的哪一位开始绘制,一般为0
  39. 3.count,数组中顶点的数量。
  40. /**
  41. openGl还有一个绘制功能的方法glDrawElements。glDrawElements是一个OPENGL的图元绘制函数,从数组中获得数据渲染图元.glDrawElements函数能够通过较少的函数调用绘制多个几何图元,而不是通过OPENGL函数调用来传递每一个顶点,法线,颜色信息。你可以事先准备一系列分离的顶点、法线、颜色数组,并且调用一次glDrawElements把这些数组定义成一个图元序列。当调用glDrawElements函数的时候,它将通过索引使用count个成序列的元素来创建一系列的几何图元。mode指定待创建的图元类型和数组元素如何用来创建这些图元
  42. */
  43. void glDrawElements( GLenum mode, GLsizei count,GLenum type, const GLvoid *indices
  44. 1.mode指定绘制图元的类型,它应该是下列值之一,GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRIANGLES, GL_QUAD_STRIP, GL_QUADS, and GL_POLYGON.
  45. 2.count为绘制图元的数量乘上一个图元的顶点数。
  46. 3.type为索引值的类型,只能是下列值之一:GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, or GL_UNSIGNED_INT
  47. 4.indices:指向索引存贮位置的指针。
  48. 例如:glDrawElements(GL_TRIANGLES, (GLsizei)n*6, GL_UNSIGNED_SHORT, m_pIndices);这样实现绘制,等效替代glDrawArrays(GL_TRIANGLES,0,(GLsizei)n*6)。
  49. glArrayElementglDrawArrays的区别:glArrayElement函数用法简单直接,只要把所有的顶点、法向量等数据,按照三角形的顺序准备好,就可以直接渲染,但缺点是不支持顶点索引,所以内存占用比较大。举例来说,如果一个网格有100个顶点,一般大约会有200个三角面,如果使用glArrayElement就需要存储200×3600个顶点的数据,相比原有的数据多了5倍。如果是已经条带化的数据,这种冗余数据多的可能就不只5倍了。权衡之下还是决定使用glDrawElements函数。
  50. glDrawElements函数支持顶点数据列表,更为方便的是它还支持顶点索引,所以就成为了快速渲染的首选。注意type为索引值的类型,只能是下列值之一:GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, or GL_UNSIGNED_INT
  51. /**
  52. 绘制界面的主要步骤
  53. */
  54. a、纹理创建的时候使用 setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTextureColor)); 设置shader,在CCLayerColorinitWithColor设置
  55. bdraw的时候先开启颜色设置 ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords | kCCVertexAttribFlag_Color);
  56. c、启用shader:m_pShaderProgram->use(); m_pShaderProgram->setUniformsForBuiltins();
  57. d、把颜色值传入: glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, colors);
  58. e、通过glDrawElements或者glDrawArrays绘制 #####mode指定绘制图元的类型
  1. GL_POINTS:把每一个顶点作为一个点进行处理,顶点n即定义了点n,共绘制N个点

  2. GL_LINES:把每一个顶点作为一个独立的线段,顶点2n-1和2n之间共定义了n条线段,总共绘制N/2条线段

  3. GL_LINE_STRIP:绘制从第一个顶点到最后一个顶点依次相连的一组线段,第n和n+1个顶点定义了线段n,总共绘制n-1条线段

  4. GL_LINE_LOOP:绘制从第一个顶点到最后一个顶点依次相连的一组线段,然后最后一个顶点和第一个顶点相连,第n和n+1个顶点定义了线段n,总共绘制n条线段

  5. GL_TRIANGLES:把每个顶点作为一个独立的三角形,顶点3n-2、3n-1和3n定义了第n个三角形,总共绘制N/3个三角形

  6. GL_TRIANGLE_STRIP:绘制一组相连的三角形,对于奇数n,顶点n、n+1和n+2定义了第n个三角形;对于偶数n,顶点n+1、n和n+2定义了第n个三角形,总共绘制N-2个三角形

  7. GL_TRIANGLE_FAN:绘制一组相连的三角形,三角形是由第一个顶点及其后给定的顶点确定,顶点1、n+1和n+2定义了第n个三角形,总共绘制N-2个三角形

  8. GL_QUADS:绘制由四个顶点组成的一组单独的四边形。顶点4n-3、4n-2、4n-1和4n定义了第n个四边形。总共绘制N/4个四边形

  9. GL_QUAD_STRIP:绘制一组相连的四边形。每个四边形是由一对顶点及其后给定的一对顶点共同确定的。顶点2n-1、2n、2n+2和2n+1定义了第n个四边形,总共绘制N/2-1个四边形

  10. GL_POLYGON:绘制一个凸多边形。顶点1到n定义了这个多边形。
    可以参考下这个文档:http://blog.sina.com.cn/s/blog_6084f58801019dja.html

好了,下面接着看CCLayerGradient的源码吧:

  1. CCLayerGradient继承于CCLayerColor,使用该类我们可以通过代码创建渐变效果
  2. static CCLayerGradient* create(const ccColor4B& start, const ccColor4B& end);//初始化CCLayerGradient,会回调updateColor方法
  3. static CCLayerGradient* create(const ccColor4B& start, const ccColor4B& end, const CCPoint& v);
  4. virtual bool init();
  5. virtual bool initWithColor(const ccColor4B& start, const ccColor4B& end);
  6. virtual bool initWithColor(const ccColor4B& start, const ccColor4B& end, const CCPoint& v);
  7. CC_PROPERTY_PASS_BY_REF(ccColor3B, m_startColor, StartColor)
  8. CC_PROPERTY_PASS_BY_REF(ccColor3B, m_endColor, EndColor)
  9. CC_PROPERTY(GLubyte, m_cStartOpacity, StartOpacity)
  10. CC_PROPERTY(GLubyte, m_cEndOpacity, EndOpacity)
  11. CC_PROPERTY_PASS_BY_REF(CCPoint, m_AlongVector, Vector)
  12. virtual void setCompressedInterpolation(bool bCompressedInterpolation);//是否通过插值压缩通过规范和非规范的向量来显示所在的渐变 默认:yes
  13. virtual bool isCompressedInterpolation();
  14. virtual void updateColor(); //在上诉的一切方法中都回调了该方法,下面就来欣赏下updateColor
/** updateColor方法是CCLayerGradient的重点方法 */
  1. void CCLayerGradient::updateColor()
  2. {
  3. CCLayerColor::updateColor();//回调了CCLayerColor中的updateColor方法
  4. /**
  5. float
  6. ccpLength(const CCPoint& v)//ccpLength是返回CCPoint的长度
  7. {
  8. return v.getLength();
  9. }
  10. inline float getLength() const {
  11. return sqrtf(x*x + y*y);
  12. };
  13. */
  14. float h = ccpLength(m_AlongVector);//m_AlongVector就是通过initWithColor赋值的CCPoint。
  15. if (h == 0)
  16. return;
  17. float c = sqrtf(2.0f);
  18. CCPoint u = ccp(m_AlongVector.x / h, m_AlongVector.y / h);//就是此时就相当于ccp(cosx,sinx)
  19. // Compressed Interpolation mode
  20. if (m_bCompressedInterpolation)
  21. {
  22. float h2 = 1 / ( fabsf(u.x) + fabsf(u.y) );//由于cosx+sinx的范围是1<=cosx+sinx<=sqrtf(2.0f),所以h2的范围就是1/2<=h2<=sqrtf(2.0f)/2,(h2 * (float)c)的范围也就是sqrtf(2.0f)/2<=(h2 * (float)c)<=1
  23. u = ccpMult(u, h2 * (float)c);//通过上诉可明白通过h2 * (float)c的作用,u变小了。
  24. }
  25. float opacityf = (float)_displayedOpacity / 255.0f;
  26. ccColor4F S = {
  27. _displayedColor.r / 255.0f,
  28. _displayedColor.g / 255.0f,
  29. _displayedColor.b / 255.0f,
  30. m_cStartOpacity * opacityf / 255.0f
  31. };
  32. //ccColor4F c4 = {c.r/255.f, c.g/255.f, c.b/255.f, 1.f};把ccColor3B转化为ccColor4F
  33. ccColor4F E = {
  34. m_endColor.r / 255.0f,
  35. m_endColor.g / 255.0f,
  36. m_endColor.b / 255.0f,
  37. m_cEndOpacity * opacityf / 255.0f
  38. };
  39. // (-1, -1) 给cclayerColor的m_pSquareColors赋值
  40. m_pSquareColors[0].r = E.r + (S.r - E.r) * ((c + u.x + u.y) / (2.0f * c));
  41. m_pSquareColors[0].g = E.g + (S.g - E.g) * ((c + u.x + u.y) / (2.0f * c));
  42. m_pSquareColors[0].b = E.b + (S.b - E.b) * ((c + u.x + u.y) / (2.0f * c));
  43. m_pSquareColors[0].a = E.a + (S.a - E.a) * ((c + u.x + u.y) / (2.0f * c));
  44. // (1, -1)
  45. m_pSquareColors[1].r = E.r + (S.r - E.r) * ((c - u.x + u.y) / (2.0f * c));
  46. m_pSquareColors[1].g = E.g + (S.g - E.g) * ((c - u.x + u.y) / (2.0f * c));
  47. m_pSquareColors[1].b = E.b + (S.b - E.b) * ((c - u.x + u.y) / (2.0f * c));
  48. m_pSquareColors[1].a = E.a + (S.a - E.a) * ((c - u.x + u.y) / (2.0f * c));
  49. // (-1, 1)
  50. m_pSquareColors[2].r = E.r + (S.r - E.r) * ((c + u.x - u.y) / (2.0f * c));
  51. m_pSquareColors[2].g = E.g + (S.g - E.g) * ((c + u.x - u.y) / (2.0f * c));
  52. m_pSquareColors[2].b = E.b + (S.b - E.b) * ((c + u.x - u.y) / (2.0f * c));
  53. m_pSquareColors[2].a = E.a + (S.a - E.a) * ((c + u.x - u.y) / (2.0f * c));
  54. // (1, 1)
  55. m_pSquareColors[3].r = E.r + (S.r - E.r) * ((c - u.x - u.y) / (2.0f * c));
  56. m_pSquareColors[3].g = E.g + (S.g - E.g) * ((c - u.x - u.y) / (2.0f * c));
  57. m_pSquareColors[3].b = E.b + (S.b - E.b) * ((c - u.x - u.y) / (2.0f * c));
  58. m_pSquareColors[3].a = E.a + (S.a - E.a) * ((c - u.x - u.y) / (2.0f * c));
  59. }
  60. 以上就是CCLayerGradient的主要讲解 下面接着就看看CCLayerMultiplex的源码吧,他继承自CCLayer
  61. unsigned int m_nEnabledLayer;//表示当前使用的CCLayer
  62. CCArray* m_pLayers;//把CCLayer存储在CCArray*中。
  63. /**
  64. 下面这些方法都跟CCLayerMultiplex的初始化有关,主要的思想是把CCLayer加入到m_pLayers中
  65. */
  66. static CCLayerMultiplex* create();
  67. static CCLayerMultiplex* createWithArray(CCArray* arrayOfLayers);//直接把含有CCLayer的数组添加到m_pLayers中
  68. static CCLayerMultiplex * create(CCLayer* layer, ... );//初始化的时候(layer1,layer2,null)
  69. static CCLayerMultiplex * createWithLayer(CCLayer* layer);
  70. void addLayer(CCLayer* layer);
  71. bool initWithLayers(CCLayer* layer, va_list params);
  72. bool initWithArray(CCArray* arrayOfLayers);
  73. bool initWithArray(CCArray* arrayOfLayers);
  74. void switchTo(unsigned int n);//移除原先的CCLayer,把序列号为n的CCLayer添加上去
  75. void switchToAndReleaseMe(unsigned int n);移除原先的CCLayer,同时把m_pLayers数组中的CCLayer也去除,再把序列号为nCCLayer添加上去
  76. 下面看具体方法详解
  77. CCLayerMultiplex * CCLayerMultiplex::create(CCLayer * layer, ...)
  78. {
  79. va_list args;//va_list在前面的文章已经讲解过,具体看:http://blog.xulingmin.com/CCString难点方法解析/
  80. va_start(args,layer);//args指向可变参数的第一个参数
  81. CCLayerMultiplex * pMultiplexLayer = new CCLayerMultiplex();
  82. if(pMultiplexLayer && pMultiplexLayer->initWithLayers(layer, args))//把args指针传给initWithLayers
  83. {
  84. pMultiplexLayer->autorelease();
  85. va_end(args);//获取所有的参数之后,我们有必要将这个 args 指针关掉
  86. return pMultiplexLayer;
  87. }
  88. va_end(args);
  89. CC_SAFE_DELETE(pMultiplexLayer);
  90. return NULL;
  91. }
  92. //在上一个方法中,我们知道传给initWithLayers方法CCLayer *以及va_list指针,
  93. bool CCLayerMultiplex::initWithLayers(CCLayer *layer, va_list params)
  94. {
  95. if (CCLayer::init())
  96. {
  97. m_pLayers = CCArray::createWithCapacity(5);//先创建5个空间的CCArray
  98. m_pLayers->retain();
  99. m_pLayers->addObject(layer);//把create中的第一个参数列表的layer加入到CCArray中
  100. CCLayer *l = va_arg(params,CCLayer*);//通过指针params指向参数列表中的下一个layer,并返回
  101. while( l ) {//判断是否为空
  102. m_pLayers->addObject(l);//加入到CCArray中
  103. l = va_arg(params,CCLayer*);
  104. }
  105. m_nEnabledLayer = 0;//设置添加到parent的layer序号为0
  106. this->addChild((CCNode*)m_pLayers->objectAtIndex(m_nEnabledLayer));//把序号为0的layer添加到父类中
  107. return true;
  108. }
  109. return false;
  110. }
  111. //initWithArray的方法跟initWithLayers方法类似
  112. bool CCLayerMultiplex::initWithArray(CCArray* arrayOfLayers)
  113. {
  114. if (CCLayer::init())
  115. {
  116. m_pLayers = CCArray::createWithCapacity(arrayOfLayers->count());//创建CCArray,空间为arrayOfLayers的个数
  117. m_pLayers->addObjectsFromArray(arrayOfLayers);//直接把arrayOfLayers赋值给m_pLayers
  118. m_pLayers->retain();
  119. m_nEnabledLayer = 0;//设置添加到parent的layer序号为0
  120. this->addChild((CCNode*)m_pLayers->objectAtIndex(m_nEnabledLayer));//把序号为0的layer添加到父类中
  121. return true;
  122. }
  123. return false;
  124. }
  125. //切换CCLayer,同时remove数组中的CCLayer
  126. void CCLayerMultiplex::switchToAndReleaseMe(unsigned int n)
  127. {
  128. CCAssert( n < m_pLayers->count(), "Invalid index in MultiplexLayer switchTo message" );
  129. this->removeChild((CCNode*)m_pLayers->objectAtIndex(m_nEnabledLayer), true);//从parent中移除序号为m_nEnabledLayer的cclayer
  130. m_pLayers->replaceObjectAtIndex(m_nEnabledLayer, NULL);//把m_nEnabledLayer序号的CCLayer置为NULL
  131. m_nEnabledLayer = n;//把需要转换的CCLayer序号赋值给m_nEnabledLayer
  132. this->addChild((CCNode*)m_pLayers->objectAtIndex(n));//把序号为n的CCLayer赋值add到parent
  133. }

以上内容就是CCLayer相关类的源码解析,主要讲了CCLayer,CCLayerRGBA,CCLayerColor,CCLayerGradient四个类,下面就解读下在TestCpp中,上诉四个类的表现,参见cocos2d-x-2.2.3-CCLayer源码学习(二)

青春是一场大雨,即使感冒了,还盼回头再淋一次...image...微笑永远是一个人身上最好看的东西...


PREVIOUS     NEXT