深入分析Cocos2d-x 2.0中的“纹理”


我们来看一下cocos2d-x中的libcocos2d库,其下有许多目录,找到textures展开,可以看到有CCTexture2D,CCTextureAtlas,CCTextureCache,CCTexturePVR四个类。


这四个类的功能分别是:

CCTexture2D: 纹理,即图片加载入内存后供CPU和GPU操作的贴图对象。

CCTexturePVR:处理PVR文件生成纹理的类,提示:大家可以用它解析愤怒的小鸟中的图片。

CCTextureCache:纹理管理器,负责加载图片并对生成的纹理进行管理。通过“字典”来进行快速的查询。

CCTextureAtlas:纹理块管理器,如果图片是由多个小图块组成的,则纹理块管理器用来存储这些小图块的相关信息,以方便绘制相应图块。


为了让大家更好的学习纹理,在讲解纹理的代码之前我已经先给大家分析了本章用到的两个功能类:

CCImageCCDictionary。这两个类分别在纹理模块中担任加载图片和管理纹理指针的作用。希望大家先顶一下这两篇贴子之后再开始下面的代码学习,你一定会感到非常容易。

一.CCTexture2D:

好,咱们现在开始看CCTexture2D:

  1. #ifndef__CCTEXTURE2D_H__
  2. #define__CCTEXTURE2D_H__
  3. #include<string>
  4. #include"cocoa/CCObject.h"
  5. #include"cocoa/CCGeometry.h"
  6. #include"ccTypes.h"
  7. //Cocos2d命名空间
  8. NS_CC_BEGIN
  9. //需要用到CCImage,这里声明一下。
  10. classCCImage;
  11. //纹理格式:即每个纹理中的像素单位分别是怎么为颜色值进行实际内存分配的。这个非常重要,我们在进行游戏开发的过程中,会常常与各种图片类型打交通。每种图片往往也有各自的像素格式。但当它们一旦加载到游戏中后,就会根据我们的要求变成以下某种类型的纹理。不同的纹理格式所占据的内存大小可能不同,我们要根据实际情况和需求来选择相应的纹理格式。比如我们用RGBA8888纹理格式来创建纹理,它占据的内存容量很大,如果我们要显示的纹理中没有ALPHA值,那就不应该使用带ALPHA通道的纹理格式。我们就可以改成RGB565像素格式。
  12. typedefenum{
  13. //32位真彩色,最真但最耗内存
  14. kCCTexture2DPixelFormat_RGBA8888,
  15. //24位真彩色,去掉了ALPHA通道
  16. kCCTexture2DPixelFormat_RGB888,
  17. //16位色,将RGB压缩在一个字中。绿色多了1位,因为人眼对绿色更敏感。
  18. kCCTexture2DPixelFormat_RGB565,
  19. //8位色,只存ALPHA值,做遮罩图用
  20. kCCTexture2DPixelFormat_A8,
  21. //8位色,只存灰度或者强度值,做灰度图用
  22. kCCTexture2DPixelFormat_I8,
  23. //16位色,只存ALPHA值与强度值,双功能
  24. kCCTexture2DPixelFormat_AI88,
  25. //16位色,RGBA四通道各占4位。
  26. kCCTexture2DPixelFormat_RGBA4444,
  27. //16位色,RGB三通道各占5位,多1位留做ALPHA镂空使用
  28. kCCTexture2DPixelFormat_RGB5A1,
  29. //PVR的PVRTC4压缩格式
  30. kCCTexture2DPixelFormat_PVRTC4,
  31. //PVRTC的PVRTC2压缩格式
  32. kCCTexture2DPixelFormat_PVRTC2,
  33. //默认格式RGBA8888
  34. kCCTexture2DPixelFormat_Default=kCCTexture2DPixelFormat_RGBA8888,
  35. //为了兼容性而保留的枚举值
  36. kTexture2DPixelFormat_RGBA8888=kCCTexture2DPixelFormat_RGBA8888,
  37. kTexture2DPixelFormat_RGB888=kCCTexture2DPixelFormat_RGB888,
  38. kTexture2DPixelFormat_RGB565=kCCTexture2DPixelFormat_RGB565,
  39. kTexture2DPixelFormat_A8=kCCTexture2DPixelFormat_A8,
  40. kTexture2DPixelFormat_RGBA4444=kCCTexture2DPixelFormat_RGBA4444,
  41. kTexture2DPixelFormat_RGB5A1=kCCTexture2DPixelFormat_RGB5A1,
  42. kTexture2DPixelFormat_Default=kCCTexture2DPixelFormat_Default
  43. }CCTexture2DPixelFormat;
  44. //需要使用Shader代码片段,这里声明一下
  45. classCCGLProgram;
  46. //定义了纹理的一些参数
  47. typedefstruct_ccTexParams{
  48. GLuintminFilter;//纹理过滤器:缩小过滤器
  49. GLuintmagFilter;//纹理过滤器:放大过滤器
  50. GLuintwrapS;//横向纹理寻址模式
  51. GLuintwrapT;//纵向纹理寻址模式
  52. }ccTexParams;
  53. //CCTexture2D类可以方便的从图片,文本或raw数据文件中创建OpenGL所用贴图,创建的贴图会自动转为2的幂次方大小,所以要注意对于贴图坐标的影响。
  54. classCC_DLLCCTexture2D:publicCCObject
  55. {
  56. public:
  57. //构造
  58. CCTexture2D();
  59. //析构
  60. virtual~CCTexture2D();
  61. //取得纹理的描述
  62. constchar*description(void);
  63. //释放数据
  64. voidreleaseData(void*data);
  65. //保存数据
  66. void*keepData(void*data,unsignedintlength);
  67. //由数据指针和指定的像素格式,图片宽高,来生成OpenGL贴图。
  68. boolinitWithData(constvoid*data,CCTexture2DPixelFormatpixelFormat,unsignedintpixelsWide,unsignedintpixelsHigh,constCCSize&contentSize);
  69. //在指定的位置绘制贴图
  70. voiddrawAtPoint(constCCPoint&point);
  71. //纹制贴图上的一个图像块
  72. voiddrawInRect(constCCRect&rect);
  73. //由CCImage指针生成OpenGL贴图
  74. boolinitWithImage(CCImage*uiImage);
  75. //由一个字符串生成OpenGL贴图。
  76. boolinitWithString(constchar*text,constCCSize&dimensions,CCTextAlignmenthAlignment,CCVerticalTextAlignmentvAlignment,constchar*fontName,floatfontSize);
  77. //由一个字符串和指定的字体与大小生成OpenGL贴图
  78. boolinitWithString(constchar*text,floatfontSize);
  79. //如果支持PVR的压缩格式
  80. #ifdefCC_SUPPORT_PVRTC
  81. //由一个PVR压缩格式的数据生成OpenGL贴图
  82. boolinitWithPVRTCData(constvoid*data,intlevel,intbpp,boolhasAlpha,intlength,CCTexture2DPixelFormatpixelFormat);
  83. #endif//CC_SUPPORT_PVRTC
  84. //从普通PVR文件生成OpenGL贴图
  85. boolinitWithPVRFile(constchar*file);
  86. //设置贴图参数
  87. voidsetTexParameters(ccTexParams*texParams);
  88. //设置为抗锯齿的贴图过滤方式(线性过滤)
  89. voidsetAntiAliasTexParameters();
  90. //设置为非抗锯齿的贴图过滤方式(最近点采样)
  91. voidsetAliasTexParameters();
  92. //生成多级贴图:由图片数据生成一系列尺寸为2的幂次方直至当前贴图大小的贴图。系统会根据距离自动选择纹理图片。可以解决大图片显示在小空间时的闪烁问题。
  93. voidgenerateMipmap();
  94. //取得像素格式名称
  95. constchar*stringForFormat();
  96. //返回当前贴图色深,即每个像素占多少位
  97. unsignedintbitsPerPixelForFormat();
  98. //通过参数贴图格式返回纹理色深
  99. unsignedintbitsPerPixelForFormat(CCTexture2DPixelFormatformat);
  100. //静态函数,用于设置默认带ALPHA通道的贴图像素格式。则图片创建为贴图时,如果有ALPHA通道,则生成此默认贴图像素格式。
  101. staticvoidsetDefaultAlphaPixelFormat(CCTexture2DPixelFormatformat);
  102. //静态函数,取得默认带ALPHA通道的贴图像素格式。
  103. staticCCTexture2DPixelFormatdefaultAlphaPixelFormat();
  104. //静态函数,设置载入PVR时是否开启ALPHA渐变,默认不开启,则ALPHA值只有是与否,无渐变。
  105. staticvoidPVRImagesHavePremultipliedAlpha(boolhaveAlphaPremultiplied);
  106. //取得图片大小(以像素为单位)
  107. constCCSize&getContentSizeInPixels();
  108. //是否有ALPHA渐变值
  109. boolhasPremultipliedAlpha();
  110. //是否有多级贴图
  111. boolhasMipmaps();
  112. private:
  113. //加载一个带ALPHA渐变的图片生成OpenGL贴图
  114. boolinitPremultipliedATextureWithImage(CCImage*image,unsignedintpixelsHigh);
  115. //ALPHA渐变开关
  116. boolm_bPVRHaveAlphaPremultiplied;
  117. //贴图格式变量及get接口
  118. CC_PROPERTY_READONLY(CCTexture2DPixelFormat,m_ePixelFormat,PixelFormat)
  119. //贴图宽度及get接口
  120. CC_PROPERTY_READONLY(unsignedint,m_uPixelsWide,PixelsWide)
  121. //贴图高度及get接口
  122. CC_PROPERTY_READONLY(unsignedint,m_uPixelsHigh,PixelsHigh)
  123. //OpenGL贴图索引及get接口
  124. CC_PROPERTY_READONLY(GLuint,m_uName,Name)
  125. //横向贴图坐标终点。因为图片如果不是2的幂次方,图片大小会小于贴图的大小,贴图一定是2的幂次方嘛,这时候横向的贴图坐标终点不是1.0。
  126. CC_PROPERTY(GLfloat,m_fMaxS,MaxS)
  127. //纵向贴图坐标终点。
  128. CC_PROPERTY(GLfloat,m_fMaxT,MaxT)
  129. //图片大小及get接口
  130. CC_PROPERTY_READONLY(CCSize,m_tContentSize,ContentSize)
  131. //ALPHA渐变开关
  132. boolm_bHasPremultipliedAlpha;
  133. //多级纹理开关
  134. boolm_bHasMipmaps;
  135. //Shader代码片段指针
  136. CC_PROPERTY(CCGLProgram*,m_pShaderProgram,ShaderProgram);
  137. };
  138. NS_CC_END
  139. #endif//__CCTEXTURE2D_H__

再来看CCTexture2D.cpp:


  1. #include"CCTexture2D.h"
  2. #include"ccConfig.h"
  3. #include"ccMacros.h"
  4. #include"CCConfiguration.h"
  5. #include"platform/platform.h"
  6. #include"platform/CCImage.h"
  7. #include"CCGL.h"
  8. #include"support/ccUtils.h"
  9. #include"platform/CCPlatformMacros.h"
  10. #include"textures/CCTexturePVR.h"
  11. #include"CCDirector.h"
  12. #include"shaders/CCGLProgram.h"
  13. #include"shaders/ccGLStateCache.h"
  14. #include"shaders/CCShaderCache.h"
  15. //这里定义是否使用可变纹理
  16. #ifCC_ENABLE_CACHE_TEXTURE_DATA
  17. #include"CCTextureCache.h"
  18. #endif
  19. //Cocos2d-x命名空间
  20. NS_CC_BEGIN
  21. //静态全局的默认贴图像素格式。缺省为kCCTexture2DPixelFormat_Default,即RGBA8888。
  22. staticCCTexture2DPixelFormatg_defaultAlphaPixelFormat=kCCTexture2DPixelFormat_Default;
  23. //静态全局的PVR是否有ALPHA渐变的开关变量,默认为否。
  24. staticboolPVRHaveAlphaPremultiplied_=false;
  25. //构造函数。
  26. CCTexture2D::CCTexture2D()
  27. :m_uPixelsWide(0)
  28. ,m_uPixelsHigh(0)
  29. ,m_uName(0)
  30. ,m_fMaxS(0.0)
  31. ,m_fMaxT(0.0)
  32. ,m_bHasPremultipliedAlpha(false)
  33. ,m_bHasMipmaps(false)
  34. ,m_bPVRHaveAlphaPremultiplied(true)
  35. ,m_pShaderProgram(NULL)
  36. {
  37. }
  38. //析构
  39. CCTexture2D::~CCTexture2D()
  40. {
  41. //如果使用可变纹理,删除此可变纹理中的数据。
  42. #ifCC_ENABLE_CACHE_TEXTURE_DATA
  43. VolatileTexture::removeTexture(this);
  44. #endif
  45. //打印日志。
  46. CCLOGINFO("cocos2d:deallocingCCTexture2D%u.",m_uName);
  47. //释放所用到的Shader代码片段
  48. CC_SAFE_RELEASE(m_pShaderProgram);
  49. //释放OpenGL所用到的贴图。
  50. if(m_uName)
  51. {
  52. ccGLDeleteTexture(m_uName);
  53. }
  54. }
  55. //取得当前纹理的贴图像素格式。
  56. CCTexture2DPixelFormatCCTexture2D::getPixelFormat()
  57. {
  58. returnm_ePixelFormat;
  59. }
  60. //取得贴图宽度。
  61. unsignedintCCTexture2D::getPixelsWide()
  62. {
  63. returnm_uPixelsWide;
  64. }
  65. //取得贴图高度。
  66. unsignedintCCTexture2D::getPixelsHigh()
  67. {
  68. returnm_uPixelsHigh;
  69. }
  70. //取得贴图索引。
  71. GLuintCCTexture2D::getName()
  72. {
  73. returnm_uName;
  74. }
  75. //取得图片大小(以点为单位)
  76. CCSizeCCTexture2D::getContentSize()
  77. {
  78. //CC_CONTENT_SCALE_FACTOR宏返回的是在不同屏幕下的点与像素的比率。Mac电脑上返回1.而使用Retina显示屏的iphone上返回2。
  79. CCSizeret;
  80. ret.width=m_tContentSize.width/CC_CONTENT_SCALE_FACTOR();
  81. ret.height=m_tContentSize.height/CC_CONTENT_SCALE_FACTOR();
  82. returnret;
  83. }
  84. //取得图片大小(以像素为单位)
  85. constCCSize&CCTexture2D::getContentSizeInPixels()
  86. {
  87. returnm_tContentSize;
  88. }
  89. //取得横向的贴图坐标终点
  90. GLfloatCCTexture2D::getMaxS()
  91. {
  92. returnm_fMaxS;
  93. }
  94. //设置横向的贴图坐标终点
  95. voidCCTexture2D::setMaxS(GLfloatmaxS)
  96. {
  97. m_fMaxS=maxS;
  98. }
  99. //取得纵向的贴图坐标终点
  100. GLfloatCCTexture2D::getMaxT()
  101. {
  102. returnm_fMaxT;
  103. }
  104. //设置纵向的贴图坐标终点
  105. voidCCTexture2D::setMaxT(GLfloatmaxT)
  106. {
  107. m_fMaxT=maxT;
  108. }
  109. //所用到的Shader代码片段。
  110. CCGLProgram*CCTexture2D::getShaderProgram(void)
  111. {
  112. returnm_pShaderProgram;
  113. }
  114. //设置用到的Shader代码片段。
  115. voidCCTexture2D::setShaderProgram(CCGLProgram*pShaderProgram)
  116. {
  117. CC_SAFE_RETAIN(pShaderProgram);
  118. CC_SAFE_RELEASE(m_pShaderProgram);
  119. m_pShaderProgram=pShaderProgram;
  120. }
  121. //释放数据
  122. voidCCTexture2D::releaseData(void*data)
  123. {
  124. free(data);
  125. }
  126. //保存数据
  127. void*CCTexture2D::keepData(void*data,unsignedintlength)
  128. {
  129. //这里只是使用CC_UNUSED_PARAM宏用一下length,没什么实际功能。作者给出这个函数是预备未来供子类重载。
  130. CC_UNUSED_PARAM(length);
  131. returndata;
  132. }
  133. //是否有ALPHA渐变的通道数据。
  134. boolCCTexture2D::hasPremultipliedAlpha()
  135. {
  136. returnm_bHasPremultipliedAlpha;
  137. }
  138. //由数据指针创建指定大小和格式的贴图。取得创建成功后图片在贴图中的实际区域。
  139. boolCCTexture2D::initWithData(constvoid*data,constCCSize&contentSize)
  140. {
  141. //如果是RGBA8888格式或者大小正好就是2的幂次方。像素数据按四字节(DWORD)对齐。否则按1字节(BYTE)进行对齐。
  142. if(pixelFormat==kCCTexture2DPixelFormat_RGBA8888||(ccNextPOT(pixelsWide)==pixelsWide&&ccNextPOT(pixelsHigh)==pixelsHigh))
  143. {
  144. glPixelStorei(GL_UNPACK_ALIGNMENT,4);
  145. }
  146. else
  147. {
  148. glPixelStorei(GL_UNPACK_ALIGNMENT,1);
  149. }
  150. //产生一个OpenGL的贴图索引。
  151. glGenTextures(1,&m_uName);
  152. //将此贴图绑定为GL_TEXTURE_2D纹理。
  153. ccGLBindTexture2D(m_uName);
  154. //设置OpenGL中的贴图的过滤参数。
  155. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  156. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  157. //设置贴图的横向纹理寻址模式为边缘截取模式。总是忽略边界。
  158. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
  159. //设置贴图的纵向纹理寻址模式为边缘截取模式。总是忽略边界。
  160. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
  161. //这里根据不同的像素格式来生成不同的OpenGL所用的贴图。注意:传入的宽和高在成功生成贴图后会返回实际贴图的宽和高。如果图片不是2的幂次方,这个数值会改成2的幂次方。比如你传入的图片宽高是148x245,则调用完成后宽高会转成256x256。
  162. switch(pixelFormat)
  163. {
  164. casekCCTexture2DPixelFormat_RGBA8888:
  165. glTexImage2D(GL_TEXTURE_2D,GL_RGBA,(GLsizei)pixelsWide,(GLsizei)pixelsHigh,GL_UNSIGNED_BYTE,data);
  166. break;
  167. casekCCTexture2DPixelFormat_RGB888:
  168. glTexImage2D(GL_TEXTURE_2D,GL_RGB,data);
  169. break;
  170. casekCCTexture2DPixelFormat_RGBA4444:
  171. glTexImage2D(GL_TEXTURE_2D,GL_UNSIGNED_SHORT_4_4_4_4,data);
  172. break;
  173. casekCCTexture2DPixelFormat_RGB5A1:
  174. glTexImage2D(GL_TEXTURE_2D,GL_UNSIGNED_SHORT_5_5_5_1,data);
  175. break;
  176. casekCCTexture2DPixelFormat_RGB565:
  177. glTexImage2D(GL_TEXTURE_2D,GL_UNSIGNED_SHORT_5_6_5,data);
  178. break;
  179. casekCCTexture2DPixelFormat_AI88:
  180. glTexImage2D(GL_TEXTURE_2D,GL_LUMINANCE_ALPHA,data);
  181. break;
  182. casekCCTexture2DPixelFormat_A8:
  183. glTexImage2D(GL_TEXTURE_2D,GL_ALPHA,data);
  184. break;
  185. casekCCTexture2DPixelFormat_I8:
  186. glTexImage2D(GL_TEXTURE_2D,GL_LUMINANCE,data);
  187. break;
  188. default:
  189. CCAssert(0,"NSInternalInconsistencyException");
  190. }
  191. //图片大小
  192. m_tContentSize=contentSize;
  193. //保存实际的贴图宽高
  194. m_uPixelsWide=pixelsWide;
  195. m_uPixelsHigh=pixelsHigh;
  196. //保存贴图的像素格式
  197. m_ePixelFormat=pixelFormat;
  198. //计算图片处于贴图中的横向和纵向的纹理坐标终点。
  199. m_fMaxS=contentSize.width/(float)(pixelsWide);
  200. m_fMaxT=contentSize.height/(float)(pixelsHigh);
  201. //默认不使用ALPHA渐变通道。
  202. m_bHasPremultipliedAlpha=false;
  203. //默认不使用多级纹理。
  204. m_bHasMipmaps=false;
  205. //设置使用kCCShader_PositionTexture对应类型的Shader。此Shader的顶点格式由位置和纹理坐标组成。
  206. setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTexture));
  207. returntrue;
  208. }
  209. //取得纹理的描述
  210. constchar*CCTexture2D::description(void)
  211. {
  212. returnCCString::createWithFormat("<CCTexture2D|Name=%u|Dimensions=%ux%u|Coordinates=(%.2f,%.2f)>",m_fMaxT)->getCString();
  213. }
  214. //由CCImage对象来初始化纹理生成OpenGL贴图。
  215. boolCCTexture2D::initWithImage(CCImage*uiImage)
  216. {
  217. //参数有效性判断。
  218. if(uiImage==NULL)
  219. {
  220. CCLOG("cocos2d:CCTexture2D.Can'tcreateTexture.UIImageisnil");
  221. this->release();
  222. returnfalse;
  223. }
  224. //取得图片的宽高
  225. unsignedintimageWidth=uiImage->getWidth();
  226. unsignedintimageHeight=uiImage->getHeight();
  227. //取得引擎的配置信息
  228. CCConfiguration*conf=CCConfiguration::sharedConfiguration();
  229. //取得配置信息中指定的最大纹理大小
  230. unsignedmaxTextureSize=conf->getMaxTextureSize();
  231. //如果当前图片大于指定的最大纹理大小,提示错误警告交释放当前纹理返回NULL。
  232. if(imageWidth>maxTextureSize||imageHeight>maxTextureSize)
  233. {
  234. CCLOG("cocos2d:WARNING:Image(%ux%u)isbiggerthanthesupported%ux%u",imageWidth,imageHeight,maxTextureSize,maxTextureSize);
  235. this->release();
  236. returnNULL;
  237. }
  238. //总是按加载ALPHA渐变的图片方式来生成OpenGL贴图
  239. returninitPremultipliedATextureWithImage(uiImage,imageHeight);
  240. }
  241. //加载一个带ALPHA渐变的图片生成OpenGL贴图
  242. boolCCTexture2D::initPremultipliedATextureWithImage(CCImage*image,unsignedintwidth,unsignedintheight)
  243. {
  244. //取得图片的相关信息
  245. //定义指针变量指向图片像素数据。
  246. unsignedchar*tempData=image->getData();
  247. //定义无符号int指针变量,也是为了指向32位色深的图片像素数据,以便使指针直接对应指定的一个像素数据位置。
  248. unsignedint*inPixel32=NULL;
  249. //定义无符号char指针变量,也是为了指向8位色深的图片像素数据,以便使指针直接对应指定的一个像素数据位置。
  250. unsignedchar*inPixel8=NULL;
  251. //定义无符号short指针变量,指向16位色深的贴图像素数据,以便使指针直接对应指定的一个像素数据位置。
  252. unsignedshort*outPixel16=NULL;
  253. //定义bool变量hasAlpha取得图片是否有Alpha通道。
  254. boolhasAlpha=image->hasAlpha();
  255. //定义变量imageSize保存图片大小。
  256. CCSizeimageSize=CCSizeMake((float)(image->getWidth()),(float)(image->getHeight()));
  257. //定义变量pixelFormat用来保存贴图的像素格式。
  258. CCTexture2DPixelFormatpixelFormat;
  259. //定义变量bpp保存图片的色深。
  260. size_tbpp=image->getBitsPerComponent();
  261. //如果有ALPHA通道,使用默认的RGBA8888格式。
  262. if(hasAlpha)
  263. {
  264. pixelFormat=g_defaultAlphaPixelFormat;
  265. }
  266. else
  267. {//如果没有ALPHA通道
  268. //如果色深大于等于8,则转为RGB888格式,否则转为RGB565格式。这里有点问题,感觉应该按色深大于16来进行判断。即24和32位都转为RGB888,而16位及以下转为RGB565。
  269. if(bpp>=8)
  270. {
  271. pixelFormat=kCCTexture2DPixelFormat_RGB888;
  272. }
  273. else
  274. {
  275. pixelFormat=kCCTexture2DPixelFormat_RGB565;
  276. }
  277. }
  278. //取得数据的长度
  279. unsignedintlength=width*height;
  280. //根据图片的不同格式和要创建的纹理格式,将数据填充到纹理中。
  281. if(pixelFormat==kCCTexture2DPixelFormat_RGB565)
  282. {
  283. //根据是否有ALPHA通道来分别进行填充处理
  284. if(hasAlpha)
  285. {
  286. //转换RGBA8888到RGB565
  287. //Convert"RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA"to"RRRRRGGGGGGBBBBB"
  288. //一个像素占2个字节,所以图像中所有像素占用的字节数为width*height*2。由此大小申请内存作为贴图的像素数据。
  289. tempData=newunsignedchar[width*height*2];
  290. //将贴图像素数据的地址返回给unsignedshort指针。这样outPixel16就指向了贴图中的第一个像素的数据位置。
  291. outPixel16=(unsignedshort*)tempData;
  292. //因为有alpha,则图片是32位RGBA8888格式。取得图像的像素数据地址返回给unsignedint指针,则inPixel32指向了贴图中第一个像素的数据位置。
  293. inPixel32=(unsignedint*)image->getData();
  294. //遍历图片中所有的像素,逐像素处理。
  295. for(unsignedinti=0;i<length;++i,++inPixel32)
  296. {//将inPixel32指向的unsignedint数据通过取出R,G,B各8位数据值,然后组成RGB565值。放入outPixel16指向的unsignedshort数据中。
  297. *outPixel16++=
  298. ((((*inPixel32>>0)&0xFF)>>3)<<11)|//R
  299. ((((*inPixel32>>8)&0xFF)>>2)<<5)|//G
  300. ((((*inPixel32>>16)&0xFF)>>3)<<0);//B
  301. }
  302. }
  303. else
  304. {//转换RGB888到RGB565
  305. //Convert"RRRRRRRRRGGGGGGGGBBBBBBBB"to"RRRRRGGGGGGBBBBB"
  306. //一个像素占2个字节,所以图像中所有像素占用的字节数为width*height*2。由此大小申请内存作为贴图的像素数据。
  307. tempData=newunsignedchar[width*height*2];
  308. //将贴图像素数据的地址返回给unsignedshort指针。这样outPixel16就指向了贴图中的第一个像素的数据位置。
  309. outPixel16=(unsignedshort*)tempData;
  310. //如果图像的格式为RGB888。取得图像的像素数据地址返回给unsignedchar指针,则inPixel8指向了贴图中第一个像素的R值位置。
  311. inPixel8=(unsignedchar*)image->getData();
  312. //遍历图片中所有的像素,逐像素处理。
  313. for(unsignedinti=0;i<length;++i)
  314. {//inPixel8指向的是unsignedchar值,通过++操作来取出R,B数据值,然后组成RGB565值。放入outPixel16指向的unsignedshort数据中。
  315. *outPixel16++=
  316. (((*inPixel8++&0xFF)>>3)<<11)|//R
  317. (((*inPixel8++&0xFF)>>2)<<5)|//G
  318. (((*inPixel8++&0xFF)>>3)<<0);//B
  319. }
  320. }
  321. }
  322. elseif(pixelFormat==kCCTexture2DPixelFormat_RGBA4444)
  323. {//转换RGBA8888到RGBA4444
  324. //Convert"RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA"to"RRRRGGGGBBBBAAAA"
  325. //取得图像的像素数据地址返回给unsignedint指针,则inPixel32指向了贴图中第一个像素的数据位置。
  326. inPixel32=(unsignedint*)image->getData();
  327. //一个像素占2个字节,所以图像中所有像素占用的字节数为width*height*2。由此大小申请内存作为贴图的像素数据。
  328. tempData=newunsignedchar[width*height*2];
  329. //将贴图像素数据的地址返回给unsignedshort指针。这样outPixel16就指向了贴图中的第一个像素的数据位置。
  330. outPixel16=(unsignedshort*)tempData;
  331. //遍历图片中所有的像素,逐像素处理。
  332. for(unsignedinti=0;i<length;++i,B,A各8位数据值,然后组成RGBA4444值。放入outPixel16指向的unsignedshort数据中。
  333. *outPixel16++=
  334. ((((*inPixel32>>0)&0xFF)>>4)<<12)|//R
  335. ((((*inPixel32>>8)&0xFF)>>4)<<8)|//G
  336. ((((*inPixel32>>16)&0xFF)>>4)<<4)|//B
  337. ((((*inPixel32>>24)&0xFF)>>4)<<0);//A
  338. }
  339. }
  340. elseif(pixelFormat==kCCTexture2DPixelFormat_RGB5A1)
  341. {//转换RGBA8888到RGBA5551
  342. //Convert"RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA"to"RRRRRGGGGGBBBBBA"
  343. inPixel32=(unsignedint*)image->getData();
  344. //一个像素占2个字节,所以图像中所有像素占用的字节数为width*height*2。由此大小申请内存作为贴图的像素数据。
  345. tempData=newunsignedchar[width*height*2];
  346. //将贴图像素数据的地址返回给unsignedshort指针。这样outPixel16就指向了贴图中的第一个像素的数据位置。
  347. outPixel16=(unsignedshort*)tempData;
  348. //遍历图片中所有的像素,逐像素处理。
  349. for(unsignedinti=0;i<length;++i,A各8位数据值,然后组成RGB5A1值。放入outPixel16指向的unsignedshort数据中。
  350. *outPixel16++=
  351. ((((*inPixel32>>0)&0xFF)>>3)<<11)|//R
  352. ((((*inPixel32>>8)&0xFF)>>3)<<6)|//G
  353. ((((*inPixel32>>16)&0xFF)>>3)<<1)|//B
  354. ((((*inPixel32>>24)&0xFF)>>7)<<0);//A
  355. }
  356. }
  357. elseif(pixelFormat==kCCTexture2DPixelFormat_A8)
  358. {//转换RGBA8888到A8,同理,不再赘述
  359. //Convert"RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA"to"AAAAAAAA"
  360. inPixel32=(unsignedint*)image->getData();
  361. tempData=newunsignedchar[width*height];
  362. unsignedchar*outPixel8=tempData;
  363. for(unsignedinti=0;i<length;++i,++inPixel32)
  364. {
  365. *outPixel8++=(*inPixel32>>24)&0xFF;//A
  366. }
  367. }
  368. if(hasAlpha&&pixelFormat==kCCTexture2DPixelFormat_RGB888)
  369. {//转换RGBA8888到RGB888,同理,不再赘述
  370. //Convert"RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA"to"RRRRRRRRGGGGGGGGBBBBBBBB"
  371. inPixel32=(unsignedint*)image->getData();
  372. tempData=newunsignedchar[width*height*3];
  373. unsignedchar*outPixel8=tempData;
  374. for(unsignedinti=0;i<length;++i,++inPixel32)
  375. {
  376. *outPixel8++=(*inPixel32>>0)&0xFF;//R
  377. *outPixel8++=(*inPixel32>>8)&0xFF;//G
  378. *outPixel8++=(*inPixel32>>16)&0xFF;//B
  379. }
  380. }
  381. //因为最终相应像素格式的数据都存放在tempData中,所以这里通过像素数据来生成OpenGL贴图。
  382. initWithData(tempData,pixelFormat,width,height,imageSize);
  383. //如果是以上相应格式,则tempData都是新申请的内存块,则在这里释放申请的内存。
  384. if(tempData!=image->getData())
  385. {
  386. delete[]tempData;
  387. }
  388. //取得是否有ALPHA渐变通道数据
  389. m_bHasPremultipliedAlpha=image->isPremultipliedAlpha();
  390. returntrue;
  391. }
  392. //从字符串中创建OpenGL贴图。
  393. //参1:字符串
  394. //参2:字体名称
  395. //参3:字体大小
  396. boolCCTexture2D::initWithString(constchar*text,floatfontSize)
  397. {
  398. returninitWithString(text,CCSizeMake(0,0),kCCTextAlignmentCenter,kCCVerticalTextAlignmentTop,fontName,fontSize);
  399. }
  400. //从字符串中创建OpenGL贴图,可指定更多参数。
  401. //参1:字符串
  402. //参2:返回参数,代表在屏幕上占用的区域大小
  403. //参3:文字的横向对齐方式
  404. //参4:文字的纵向对齐方式
  405. //参5:字体名称
  406. //参6:字体大小
  407. boolCCTexture2D::initWithString(constchar*text,floatfontSize)
  408. {
  409. //如果定义使用可变纹理
  410. #ifCC_ENABLE_CACHE_TEXTURE_DATA
  411. //cachethetexturedata
  412. VolatileTexture::addStringTexture(this,text,dimensions,hAlignment,vAlignment,fontSize);
  413. #endif
  414. //定义一个CCImage实例对象
  415. CCImageimage;
  416. //定义一个CCImage进行由字符串创建图片时指定的文字对齐方式的变量eAlign
  417. CCImage::ETextAligneAlign;
  418. //如果文字纵向对齐方式为顶部对齐。
  419. if(kCCVerticalTextAlignmentTop==vAlignment)
  420. {
  421. //根据文字横向对齐方式的不同分别对eAlign进行设置。
  422. eAlign=(kCCTextAlignmentCenter==hAlignment)?CCImage::kAlignTop
  423. :(kCCTextAlignmentLeft==hAlignment)?CCImage::kAlignTopLeft:CCImage::kAlignTopRight;
  424. }
  425. //如果文字纵向对齐方式为居中对齐。
  426. elseif(kCCVerticalTextAlignmentCenter==vAlignment)
  427. {
  428. //根据文字横向对齐方式的不同分别对eAlign进行设置。
  429. eAlign=(kCCTextAlignmentCenter==hAlignment)?CCImage::kAlignCenter
  430. :(kCCTextAlignmentLeft==hAlignment)?CCImage::kAlignLeft:CCImage::kAlignRight;
  431. }
  432. //如果文字纵向对齐方式为底部对齐。
  433. elseif(kCCVerticalTextAlignmentBottom==vAlignment)
  434. {
  435. //根据文字横向对齐方式的不同分别对eAlign进行设置。
  436. eAlign=(kCCTextAlignmentCenter==hAlignment)?CCImage::kAlignBottom
  437. :(kCCTextAlignmentLeft==hAlignment)?CCImage::kAlignBottomLeft:CCImage::kAlignBottomRight;
  438. }
  439. else
  440. {
  441. //其它对齐方式不应存在,故打印错误。
  442. CCAssert(false,"Notsupportedalignmentformat!");
  443. }
  444. //调用CCImage的成员函数由字符串创建出图片数据。
  445. if(!image.initWithString(text,(int)dimensions.width,(int)dimensions.height,eAlign,(int)fontSize))
  446. {
  447. returnfalse;
  448. }
  449. //再由CCImage实例对象来创建出OpenGL贴图,初始化纹理。
  450. returninitWithImage(&image);
  451. }
  452. //在指定的位置绘制贴图。
  453. voidCCTexture2D::drawAtPoint(constCCPoint&point)
  454. {//定义贴图中图像区域的UV坐标。从左上至右下。
  455. GLfloatcoordinates[]={
  456. 0.0f,
  457. m_fMaxS,
  458. 0.0f,0.0f,0.0f};
  459. //取得贴图中图像区域的宽高
  460. GLfloatwidth=(GLfloat)m_uPixelsWide*m_fMaxS,
  461. height=(GLfloat)m_uPixelsHigh*m_fMaxT;
  462. //定义对应的顶点坐标
  463. GLfloatvertices[]={
  464. point.x,point.y,
  465. width+point.x,
  466. point.x,height+point.y,height+point.y};
  467. //Shader中使用位置和纹理坐标通道。
  468. ccGLEnableVertexAttribs(kCCVertexAttribFlag_Position|kCCVertexAttribFlag_TexCoords);
  469. //后面的代码便用Shader进行渲染
  470. m_pShaderProgram->use();
  471. //设置Shader使用的最终结果矩阵
  472. m_pShaderProgram->setUniformForModelViewProjectionMatrix();
  473. //将贴图绑定
  474. ccGLBindTexture2D(m_uName);
  475. //将vertices设置为顶点位置参数
  476. glVertexAttribPointer(kCCVertexAttrib_Position,2,GL_FLOAT,GL_FALSE,vertices);
  477. //将coordinates设置为顶点的纹理坐标参数
  478. glVertexAttribPointer(kCCVertexAttrib_TexCoords,coordinates);
  479. //绘制三角形,参1为绘图方式,参2为顶点起始索引,参3为三角形面数。
  480. glDrawArrays(GL_TRIANGLE_STRIP,4);
  481. }
  482. //绘制纹理上的一个区域。
  483. voidCCTexture2D::drawInRect(constCCRect&rect)
  484. {//定义贴图中图像区域的UV坐标。从左上至右下。
  485. GLfloatcoordinates[]={
  486. 0.0f,
  487. m_fMaxS,
  488. 0.0f,0.0f};
  489. //绘制到的区域
  490. GLfloatvertices[]={rect.origin.x,rect.origin.y,/*0.0f,*/
  491. rect.origin.x+rect.size.width,*/
  492. rect.origin.x,rect.origin.y+rect.size.height,/*0.0f*/};
  493. //Shader中使用位置和纹理坐标通道。
  494. ccGLEnableVertexAttribs(kCCVertexAttribFlag_Position|kCCVertexAttribFlag_TexCoords);
  495. //后面的代码便用Shader进行渲染
  496. m_pShaderProgram->use();
  497. //设置Shader使用的最终结果矩阵
  498. m_pShaderProgram->setUniformForModelViewProjectionMatrix();
  499. //将贴图绑定
  500. ccGLBindTexture2D(m_uName);
  501. //将vertices设置为顶点位置参数
  502. glVertexAttribPointer(kCCVertexAttrib_Position,4);
  503. }
  504. #ifdefCC_SUPPORT_PVRTC
  505. //如果支持PVR文件的压缩格式。提供的读取PVR压缩文件的函数。
  506. boolCCTexture2D::initWithPVRTCData(constvoid*data,CCTexture2DPixelFormatpixelFormat)
  507. {
  508. if(!(CCConfiguration::sharedConfiguration()->supportsPVRTC()))
  509. {
  510. CCLOG("cocos2d:WARNING:PVRTCimagesisnotsupported.");
  511. this->release();
  512. returnfalse;
  513. }
  514. //产生一个OpenGL的贴图索引。
  515. glGenTextures(1,&m_uName);
  516. //绑定纹理
  517. glBindTexture(GL_TEXTURE_2D,m_uName);
  518. //设置纹理抗锯齿
  519. this->setAntiAliasTexParameters();
  520. //贴图格式
  521. GLenumformat;
  522. //数据大小
  523. GLsizeisize=length*length*bpp/8;
  524. //根据是否有Alpha来取得贴图格式
  525. if(hasAlpha){
  526. format=(bpp==4)?GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
  527. }else{
  528. format=(bpp==4)?GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
  529. }
  530. if(size<32){
  531. size=32;
  532. }
  533. //加载压缩纹理。
  534. glCompressedTexImage2D(GL_TEXTURE_2D,level,format,length,size,data);
  535. //设置其它属性。
  536. m_tContentSize=CCSizeMake((float)(length),(float)(length));
  537. m_uPixelsWide=length;
  538. m_uPixelsHigh=length;
  539. m_fMaxS=1.0f;
  540. m_fMaxT=1.0f;
  541. m_bHasPremultipliedAlpha=PVRHaveAlphaPremultiplied_;
  542. m_ePixelFormat=pixelFormat;
  543. returntrue;
  544. }
  545. #endif//CC_SUPPORT_PVRTC
  546. //加载PVR普通文件的函数。
  547. boolCCTexture2D::initWithPVRFile(constchar*file)
  548. {
  549. boolbRet=false;
  550. //nothingtodowithCCObject::init
  551. CCTexturePVR*pvr=newCCTexturePVR;
  552. bRet=pvr->initWithContentsOfFile(file);
  553. if(bRet)
  554. {
  555. pvr->setRetainName(true);//don'tdealloctextureonrelease
  556. m_uName=pvr->getName();
  557. m_fMaxS=1.0f;
  558. m_fMaxT=1.0f;
  559. m_uPixelsWide=pvr->getWidth();
  560. m_uPixelsHigh=pvr->getHeight();
  561. m_tContentSize=CCSizeMake((float)m_uPixelsWide,(float)m_uPixelsHigh);
  562. m_bHasPremultipliedAlpha=PVRHaveAlphaPremultiplied_;
  563. m_ePixelFormat=pvr->getFormat();
  564. m_bHasMipmaps=pvr->getNumberOfMipmaps()>1;
  565. pvr->release();
  566. }
  567. else
  568. {
  569. CCLOG("cocos2d:Couldn'tloadPVRimage%s",file);
  570. }
  571. returnbRet;
  572. }
  573. //设置PVR文件加载时是否使用ALPHA渐变。
  574. voidCCTexture2D::PVRImagesHavePremultipliedAlpha(boolhaveAlphaPremultiplied)
  575. {
  576. PVRHaveAlphaPremultiplied_=haveAlphaPremultiplied;
  577. }
  578. //生成多级纹理。
  579. voidCCTexture2D::generateMipmap()
  580. {
  581. CCAssert(m_uPixelsWide==ccNextPOT(m_uPixelsWide)&&m_uPixelsHigh==ccNextPOT(m_uPixelsHigh),"MimpaptextureonlyworksinPOTtextures");
  582. ccGLBindTexture2D(m_uName);
  583. glGenerateMipmap(GL_TEXTURE_2D);
  584. m_bHasMipmaps=true;
  585. }
  586. //是否有多级纹理
  587. boolCCTexture2D::hasMipmaps()
  588. {
  589. returnm_bHasMipmaps;
  590. }
  591. //设置纹理参数。
  592. voidCCTexture2D::setTexParameters(ccTexParams*texParams)
  593. {
  594. CCAssert((m_uPixelsWide==ccNextPOT(m_uPixelsWide)||texParams->wrapS==GL_CLAMP_TO_EDGE)&&
  595. (m_uPixelsHigh==ccNextPOT(m_uPixelsHigh)||texParams->wrapT==GL_CLAMP_TO_EDGE),
  596. "GL_CLAMP_TO_EDGEshouldbeusedinNPOTdimensions");
  597. ccGLBindTexture2D(m_uName);
  598. glTexParameteri(GL_TEXTURE_2D,texParams->minFilter);
  599. glTexParameteri(GL_TEXTURE_2D,texParams->magFilter);
  600. glTexParameteri(GL_TEXTURE_2D,texParams->wrapS);
  601. glTexParameteri(GL_TEXTURE_2D,texParams->wrapT);
  602. }
  603. //设置为非抗锯齿纹理模式
  604. voidCCTexture2D::setAliasTexParameters()
  605. {//绑定纹理
  606. ccGLBindTexture2D(m_uName);
  607. //设置多级纹理
  608. if(!m_bHasMipmaps)
  609. {
  610. //设置最小滤波方式为最近点采样,这种方式最快,但有锯齿。
  611. glTexParameteri(GL_TEXTURE_2D,GL_NEAREST);
  612. }
  613. else
  614. {//设置最小滤波方式为多级纹理方式。
  615. glTexParameteri(GL_TEXTURE_2D,GL_NEAREST_MIPMAP_NEAREST);
  616. }
  617. //设置放大滤波方式为最近点采样
  618. glTexParameteri(GL_TEXTURE_2D,GL_NEAREST);
  619. }
  620. //设置为抗锯齿纹理模式
  621. voidCCTexture2D::setAntiAliasTexParameters()
  622. {//绑定纹理
  623. ccGLBindTexture2D(m_uName);
  624. //设置多级纹理
  625. if(!m_bHasMipmaps)
  626. {
  627. //设置最小滤波方式为线性过滤,这种方式纹理会有一定程度模糊。
  628. glTexParameteri(GL_TEXTURE_2D,GL_LINEAR);
  629. }
  630. else
  631. {//设置最小滤波方式为多级纹理方式。
  632. glTexParameteri(GL_TEXTURE_2D,GL_LINEAR_MIPMAP_NEAREST);
  633. }
  634. //设置放大滤波方式为最近点采样
  635. glTexParameteri(GL_TEXTURE_2D,GL_LINEAR);
  636. }
  637. //取得纹理格式的名字字符串
  638. constchar*CCTexture2D::stringForFormat()
  639. {
  640. switch(m_ePixelFormat)
  641. {
  642. casekCCTexture2DPixelFormat_RGBA8888:
  643. return"RGBA8888";
  644. casekCCTexture2DPixelFormat_RGB888:
  645. return"RGB888";
  646. casekCCTexture2DPixelFormat_RGB565:
  647. return"RGB565";
  648. casekCCTexture2DPixelFormat_RGBA4444:
  649. return"RGBA4444";
  650. casekCCTexture2DPixelFormat_RGB5A1:
  651. return"RGB5A1";
  652. casekCCTexture2DPixelFormat_AI88:
  653. return"AI88";
  654. casekCCTexture2DPixelFormat_A8:
  655. return"A8";
  656. casekCCTexture2DPixelFormat_I8:
  657. return"I8";
  658. casekCCTexture2DPixelFormat_PVRTC4:
  659. return"PVRTC4";
  660. casekCCTexture2DPixelFormat_PVRTC2:
  661. return"PVRTC2";
  662. default:
  663. CCAssert(false,"unrecognisedpixelformat");
  664. CCLOG("stringForFormat:%ld,cannotgiveusefulresult",(long)m_ePixelFormat);
  665. break;
  666. }
  667. returnNULL;
  668. }
  669. //设置默认带ALPHA通道的纹理格式
  670. voidCCTexture2D::setDefaultAlphaPixelFormat(CCTexture2DPixelFormatformat)
  671. {
  672. g_defaultAlphaPixelFormat=format;
  673. }
  674. //取得默认带ALPHA通道的纹理格式
  675. CCTexture2DPixelFormatCCTexture2D::defaultAlphaPixelFormat()
  676. {
  677. returng_defaultAlphaPixelFormat;
  678. }
  679. //取得相应纹理格式的色深。
  680. unsignedintCCTexture2D::bitsPerPixelForFormat(CCTexture2DPixelFormatformat)
  681. {
  682. unsignedintret=0;
  683. switch(format){
  684. casekCCTexture2DPixelFormat_RGBA8888:
  685. ret=32;//32位真彩色
  686. break;
  687. casekCCTexture2DPixelFormat_RGB888:
  688. //看起来是用24位,但内部实际是用DWORD来存数据的,所以还是32位。只不过Alpha通道没用。
  689. ret=32;
  690. break;
  691. casekCCTexture2DPixelFormat_RGB565:
  692. ret=16;
  693. break;
  694. casekCCTexture2DPixelFormat_RGBA4444:
  695. ret=16;
  696. break;
  697. casekCCTexture2DPixelFormat_RGB5A1:
  698. ret=16;
  699. break;
  700. casekCCTexture2DPixelFormat_AI88:
  701. ret=16;
  702. break;
  703. casekCCTexture2DPixelFormat_A8:
  704. ret=8;
  705. break;
  706. casekCCTexture2DPixelFormat_I8:
  707. ret=8;
  708. break;
  709. casekCCTexture2DPixelFormat_PVRTC4:
  710. ret=4;
  711. break;
  712. casekCCTexture2DPixelFormat_PVRTC2:
  713. ret=2;
  714. break;
  715. default:
  716. ret=-1;
  717. CCAssert(false,"unrecognisedpixelformat");
  718. CCLOG("bitsPerPixelForFormat:%ld,(long)format);
  719. break;
  720. }
  721. returnret;
  722. }
  723. //取得当前纹理格式的色深。
  724. unsignedintCCTexture2D::bitsPerPixelForFormat()
  725. {
  726. returnthis->bitsPerPixelForFormat(m_ePixelFormat);
  727. }
  728. NS_CC_END

二.CCTexturePVR:

CCTexturePVR.h:

  1. #ifndef__CCPVRTEXTURE_H__
  2. #define__CCPVRTEXTURE_H__
  3. #include"CCStdC.h"
  4. #include"CCGL.h"
  5. #include"cocoa/CCObject.h"
  6. #include"cocoa/CCArray.h"
  7. //Cocos2d命名空间
  8. NS_CC_BEGIN
  9. //用于多级纹理的结构
  10. structCCPVRMipmap{
  11. unsignedchar*address;
  12. unsignedintlen;
  13. };
  14. //最大的多级纹理级数
  15. enum{
  16. CC_PVRMIPMAP_MAX=16,
  17. };
  18. //所支持的PVR图片格式:
  19. -RGBA8888
  20. -BGRA8888
  21. -RGBA4444
  22. -RGBA5551
  23. -RGB565
  24. -A8
  25. -I8
  26. -AI88
  27. -PVRTC4BPP
  28. -PVRTC2BPP
  29. classCCTexturePVR:publicCCObject
  30. {
  31. public:
  32. //构造
  33. CCTexturePVR();
  34. //析构
  35. virtual~CCTexturePVR();
  36. //成员函数:载入一个PVR图片文件
  37. boolinitWithContentsOfFile(constchar*path);
  38. //导出的静态函数:载入一个PVR图片文件。此函数为可供js调用。
  39. CC_DEPRECATED_ATTRIB一个UTEstaticCCTexturePVR*pvrTextureWithContentsOfFile(constchar*path);
  40. //静态函数:载入一个PVR图片文件
  41. staticCCTexturePVR*create(constchar*path);
  42. //相关属性的获取
  43. //取得贴图索引
  44. inlineunsignedintgetName(){returnm_uName;}
  45. //取得
  46. inlineunsignedintgetWidth(){returnm_uWidth;}
  47. inlineunsignedintgetHeight(){returnm_uHeight;}
  48. //取得是否有ALPHA通道
  49. inlineboolhasAlpha(){returnm_bHasAlpha;}
  50. //取得多级纹理的级数
  51. inlineunsignedintgetNumberOfMipmaps(){returnm_uNumberOfMipmaps;}
  52. //取得图片格式
  53. inlineCCTexture2DPixelFormatgetFormat(){returnm_eFormat;}
  54. //取得是否是供Retain显示屏使用的高清图片。
  55. inlineboolisRetainName(){returnm_bRetainName;}
  56. //设置为供Retain显示屏使用的高清图片。
  57. inlinevoidsetRetainName(boolretainName){m_bRetainName=retainName;}
  58. private:
  59. //解压PVR图片数据
  60. boolunpackPVRData(unsignedchar*data,unsignedintlen);
  61. //创建OpenGL纹理
  62. boolcreateGLTexture();
  63. protected:
  64. //多级纹理的各级信息结构。
  65. structCCPVRMipmapm_asMipmaps[CC_PVRMIPMAP_MAX];//pointertomipmapimages
  66. //多级纹理的最大级别数
  67. unsignedintm_uNumberOfMipmaps;//numberofmipmapused
  68. //
  69. unsignedintm_uTableFormatIndex;
  70. unsignedintm_uWidth,m_uHeight;
  71. //贴图索引
  72. GLuintm_uName;
  73. //是否有Alpha通道
  74. boolm_bHasAlpha;
  75. //是否是供Retain显示屏使用的高清图片。
  76. boolm_bRetainName;
  77. //图片格式
  78. CCTexture2DPixelFormatm_eFormat;
  79. };
  80. NS_CC_END
  81. #endif//__CCPVRTEXTURE_H__

CCTexturePVR.cpp:

  1. #include"CCTexture2D.h"
  2. #include"CCTexturePVR.h"
  3. #include"ccMacros.h"
  4. #include"CCConfiguration.h"
  5. #include"support/ccUtils.h"
  6. #include"CCStdC.h"
  7. #include"platform/CCFileUtils.h"
  8. #include"support/zip_support/ZipUtils.h"
  9. #include"shaders/ccGLStateCache.h"
  10. #include<ctype.h>
  11. #include<cctype>
  12. //Cocos2d命名空间
  13. NS_CC_BEGIN
  14. #definePVR_TEXTURE_FLAG_TYPE_MASK0xff
  15. //PVR文件的信息标志位的各bit位意义
  16. enum{
  17. kPVRTextureFlagMipmap=(1<<8),//有多级纹理
  18. kPVRTextureFlagTwiddle=(1<<9),//istwiddled
  19. kPVRTextureFlagBumpmap=(1<<10),//是法线贴图(用于产生凹凸感)
  20. kPVRTextureFlagTiling=(1<<11),//isborderedfortiledpvr
  21. kPVRTextureFlagCubemap=(1<<12),//是立方体环境映射贴图(一般用于做天空盒)
  22. kPVRTextureFlagFalseMipCol=(1<<13),//aretherefalsecolouredMIPlevels
  23. kPVRTextureFlagVolume=(1<<14),//立体纹理,相当于有多层的纹理。
  24. kPVRTextureFlagAlpha=(1<<15),//v2.1istheretransparencyinfointhetexture
  25. kPVRTextureFlagVerticalFlip=(1<<16),//v2.1isthetextureverticallyflipped
  26. };
  27. //PVR文件头标识
  28. staticchargPVRTexIdentifier[5]="PVR!";
  29. //所有PVR文件的格式
  30. enum
  31. {
  32. kPVRTexturePixelTypeRGBA_4444=0x10,
  33. kPVRTexturePixelTypeRGBA_5551,
  34. kPVRTexturePixelTypeRGBA_8888,
  35. kPVRTexturePixelTypeRGB_565,
  36. kPVRTexturePixelTypeRGB_555,//这个Cocos2d-x暂不支持
  37. kPVRTexturePixelTypeRGB_888,
  38. kPVRTexturePixelTypeI_8,
  39. kPVRTexturePixelTypeAI_88,
  40. kPVRTexturePixelTypePVRTC_2,
  41. kPVRTexturePixelTypePVRTC_4,
  42. kPVRTexturePixelTypeBGRA_8888,
  43. kPVRTexturePixelTypeA_8,
  44. };
  45. //信息数组
  46. staticconstunsignedinttableFormats[][7]={
  47. //数组元素的结构为:
  48. //1-PVR文件格式
  49. //2-OpenGL内部格式
  50. //3-OpenGL格式
  51. //4-OpenGL数据类型
  52. //5-色深
  53. //6-是否压缩
  54. //7-Cocos2d像素格式
  55. {kPVRTexturePixelTypeRGBA_4444,16,false,kCCTexture2DPixelFormat_RGBA4444},
  56. {kPVRTexturePixelTypeRGBA_5551,kCCTexture2DPixelFormat_RGB5A1},
  57. {kPVRTexturePixelTypeRGBA_8888,32,kCCTexture2DPixelFormat_RGBA8888},
  58. {kPVRTexturePixelTypeRGB_565,kCCTexture2DPixelFormat_RGB565},
  59. {kPVRTexturePixelTypeRGB_888,24,kCCTexture2DPixelFormat_RGB888},
  60. {kPVRTexturePixelTypeA_8,8,kCCTexture2DPixelFormat_A8},
  61. {kPVRTexturePixelTypeI_8,kCCTexture2DPixelFormat_I8},
  62. {kPVRTexturePixelTypeAI_88,kCCTexture2DPixelFormat_AI88},
  63. #if(CC_TARGET_PLATFORM==CC_PLATFORM_IOS)
  64. //如果程序运行在IOS上,还可支持以下信息
  65. {kPVRTexturePixelTypePVRTC_2,GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG,(unsignedint)-1,(unsignedint)-1,true,kCCTexture2DPixelFormat_PVRTC2},
  66. {kPVRTexturePixelTypePVRTC_4,GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,4,kCCTexture2DPixelFormat_PVRTC4},
  67. {kPVRTexturePixelTypeBGRA_8888,GL_BGRA,
  68. #endif
  69. };
  70. //信息表的元素数量
  71. #defineMAX_TABLE_ELEMENTS(sizeof(tableFormats)/sizeof(tableFormats[0]))
  72. //
  73. enum{
  74. kCCInternalPVRTextureFormat,
  75. kCCInternalOpenGLInternalFormat,
  76. kCCInternalOpenGLFormat,
  77. kCCInternalOpenGLType,
  78. kCCInternalBPP,
  79. kCCInternalCompressedImage,
  80. kCCInternalCCTexture2DPixelFormat,
  81. };
  82. //PVR文件头信息结构
  83. typedefstruct_PVRTexHeader
  84. {
  85. unsignedintheaderLength;//头信息长度
  86. unsignedintheight;//高
  87. unsignedintwidth;//宽
  88. unsignedintnumMipmaps;//是否有多级纹理
  89. unsignedintflags;//标记位
  90. unsignedintdataLength;//后面的像素数据长度
  91. unsignedintbpp;//色深
  92. unsignedintbitmaskRed;//对应红色的像素位
  93. unsignedintbitmaskGreen;//对应绿色的像素位
  94. unsignedintbitmaskBlue;//对应蓝色的像素位
  95. unsignedintbitmaskAlpha;//对应ALPHA色的像素位
  96. unsignedintpvrTag;//
  97. unsignedintnumSurfs;//是否有多层
  98. }PVRTexHeader;
  99. //构造函数
  100. CCTexturePVR::CCTexturePVR()
  101. :m_uTableFormatIndex(0)
  102. ,m_uNumberOfMipmaps(0)
  103. ,m_uWidth(0)
  104. ,m_uHeight(0)
  105. ,m_bRetainName(false)
  106. ,m_bHasAlpha(false)
  107. ,m_eFormat(kCCTexture2DPixelFormat_Default)
  108. {
  109. }
  110. //析构函数
  111. CCTexturePVR::~CCTexturePVR()
  112. {
  113. CCLOGINFO("cocos2d:deallocingCCTexturePVR");
  114. //释放OpenGL贴图
  115. if(m_uName!=0&&!m_bRetainName)
  116. {
  117. ccGLDeleteTexture(m_uName);
  118. }
  119. }
  120. //解压PVR像素数据
  121. boolCCTexturePVR::unpackPVRData(unsignedchar*data,unsignedintlen)
  122. {
  123. boolsuccess=false;
  124. PVRTexHeader*header=NULL;
  125. unsignedintflags,pvrTag;
  126. unsignedintdataLength=0,dataOffset=0,dataSize=0;
  127. unsignedintblockSize=0,widthBlocks=0,heightBlocks=0;
  128. unsignedintwidth=0,height=0,bpp=4;
  129. unsignedchar*bytes=NULL;
  130. unsignedintformatFlags;
  131. //将数据地址转为头信息指针,这个就可以直接通过结构指针进行存取。
  132. header=(PVRTexHeader*)data;
  133. //格式有效性检查
  134. pvrTag=CC_SWAP_INT32_LITTLE_TO_HOST(header->pvrTag);
  135. /*
  136. Checkthatgivendatareallyrepresentspvrtexture
  137. [0]='P'
  138. [1]='V'
  139. [2]='R'
  140. [3]='!'
  141. */
  142. if(gPVRTexIdentifier[0]!=((pvrTag>>0)&0xff)||
  143. gPVRTexIdentifier[1]!=((pvrTag>>8)&0xff)||
  144. gPVRTexIdentifier[2]!=((pvrTag>>16)&0xff)||
  145. gPVRTexIdentifier[3]!=((pvrTag>>24)&0xff))
  146. {
  147. CCLOG("UnsupportedPVRformat.UsetheLegacyformatuntilthenewformatissupported");
  148. returnfalse;
  149. }
  150. //取得配置信息
  151. CCConfiguration*configuration=CCConfiguration::sharedConfiguration();
  152. //取得标记
  153. flags=CC_SWAP_INT32_LITTLE_TO_HOST(header->flags);
  154. formatFlags=flags&PVR_TEXTURE_FLAG_TYPE_MASK;
  155. boolflipped=(flags&kPVRTextureFlagVerticalFlip)?true:false;
  156. if(flipped)
  157. {
  158. CCLOG("cocos2d:WARNING:Imageisflipped.RegenerateitusingPVRTexTool");
  159. }
  160. //查看是否支持非2的幂次方大小的纹理
  161. if(!configuration->supportsNPOT()&&
  162. (header->width!=ccNextPOT(header->width)||header->height!=ccNextPOT(header->height)))
  163. {
  164. CCLOG("cocos2d:ERROR:LodinganNPOTtexture(%dx%d)butisnotsupportedonthisdevice",header->width,header->height);
  165. returnfalse;
  166. }
  167. //遍历所有的格式信息数据,找到对应的格式信息。
  168. for(m_uTableFormatIndex=0;m_uTableFormatIndex<(unsignedint)MAX_TABLE_ELEMENTS;m_uTableFormatIndex++)
  169. {
  170. if(tableFormats[m_uTableFormatIndex][kCCInternalPVRTextureFormat]==formatFlags)
  171. {
  172. //Resetnumofmipmaps
  173. m_uNumberOfMipmaps=0;
  174. //取得图片大小
  175. m_uWidth=width=CC_SWAP_INT32_LITTLE_TO_HOST(header->width);
  176. m_uHeight=height=CC_SWAP_INT32_LITTLE_TO_HOST(header->height);
  177. //检查是否有ALPHA通道
  178. if(CC_SWAP_INT32_LITTLE_TO_HOST(header->bitmaskAlpha))
  179. {
  180. m_bHasAlpha=true;
  181. }
  182. else
  183. {
  184. m_bHasAlpha=false;
  185. }
  186. //取得数据长度
  187. dataLength=CC_SWAP_INT32_LITTLE_TO_HOST(header->dataLength);
  188. //将数据指针偏移到头信息之后,即像素数据所在位置
  189. bytes=((unsignedchar*)data)+sizeof(PVRTexHeader);
  190. m_eFormat=(CCTexture2DPixelFormat)(tableFormats[m_uTableFormatIndex][kCCInternalCCTexture2DPixelFormat]);
  191. bpp=tableFormats[m_uTableFormatIndex][kCCInternalBPP];
  192. //遍历每个多级纹理图像块
  193. while(dataOffset<dataLength)
  194. {
  195. switch(formatFlags){
  196. casekPVRTexturePixelTypePVRTC_2:
  197. blockSize=8*4;//Pixelbypixelblocksizefor2bpp
  198. widthBlocks=width/8;
  199. heightBlocks=height/4;
  200. break;
  201. casekPVRTexturePixelTypePVRTC_4:
  202. blockSize=4*4;//Pixelbypixelblocksizefor4bpp
  203. widthBlocks=width/4;
  204. heightBlocks=height/4;
  205. break;
  206. casekPVRTexturePixelTypeBGRA_8888:
  207. if(CCConfiguration::sharedConfiguration()->supportsBGRA8888()==false)
  208. {
  209. CCLOG("cocos2d:TexturePVR.BGRA8888notsupportedonthisdevice");
  210. returnfalse;
  211. }
  212. default:
  213. blockSize=1;
  214. widthBlocks=width;
  215. heightBlocks=height;
  216. break;
  217. }
  218. //Clamptominimumnumberofblocks
  219. if(widthBlocks<2)
  220. {
  221. widthBlocks=2;
  222. }
  223. if(heightBlocks<2)
  224. {
  225. heightBlocks=2;
  226. }
  227. dataSize=widthBlocks*heightBlocks*((blockSize*bpp)/8);
  228. unsignedintpacketLength=(dataLength-dataOffset);
  229. packetLength=packetLength>dataSize?dataSize:packetLength;
  230. //记录每个多级纹理图像块的像素数据地址和长度。
  231. m_asMipmaps[m_uNumberOfMipmaps].address=bytes+dataOffset;
  232. m_asMipmaps[m_uNumberOfMipmaps].len=packetLength;
  233. m_uNumberOfMipmaps++;
  234. //检查是否超出最大级数
  235. CCAssert(m_uNumberOfMipmaps<CC_PVRMIPMAP_MAX,
  236. "TexturePVR:Maximumnumberofmimpapsreached.IncreatetheCC_PVRMIPMAP_MAXvalue");
  237. //偏移到下一个多级纹理图像块。
  238. dataOffset+=packetLength;
  239. //大小减为原来1/2。
  240. width=MAX(width>>1,1);
  241. height=MAX(height>>1,1);
  242. }
  243. //读取完成
  244. success=true;
  245. break;
  246. }
  247. }
  248. //成功判断
  249. if(!success)
  250. {
  251. CCLOG("cocos2d:WARNING:UnsupportedPVRPixelFormat:0x%2x.Re-encodeitwithaOpenGLpixelformatvariant",formatFlags);
  252. }
  253. returnsuccess;
  254. }
  255. //创建OpenGL贴图
  256. boolCCTexturePVR::createGLTexture()
  257. {
  258. //保存宽高
  259. unsignedintwidth=m_uWidth;
  260. unsignedintheight=m_uHeight;
  261. GLenumerr;
  262. //如果文件中有多级纹理
  263. if(m_uNumberOfMipmaps>0)
  264. {
  265. //先释放原来的纹理
  266. if(m_uName!=0)
  267. {
  268. ccGLDeleteTexture(m_uName);
  269. }
  270. //像素数据每字节对齐
  271. glPixelStorei(GL_UNPACK_ALIGNMENT,1);
  272. //产生OpenGL贴图
  273. glGenTextures(1,&m_uName);
  274. glBindTexture(GL_TEXTURE_2D,m_uName);
  275. //如果无多级纹理,设置最小滤波方式为线性过滤,产生抗锯齿效果。
  276. if(m_uNumberOfMipmaps==1)
  277. {
  278. glTexParameteri(GL_TEXTURE_2D,GL_LINEAR);
  279. }
  280. else
  281. {//设置最小滤波方式为最近点采样,这种方式有锯齿。
  282. glTexParameteri(GL_TEXTURE_2D,GL_LINEAR_MIPMAP_NEAREST);
  283. }
  284. //设置最大滤波方式为线性过滤
  285. glTexParameteri(GL_TEXTURE_2D,GL_CLAMP_TO_EDGE);
  286. }
  287. //检错
  288. CHECK_GL_ERROR_DEBUG();//cleanpossibleGLerror
  289. //取得对应格式的相关信息。
  290. GLenuminternalFormat=tableFormats[m_uTableFormatIndex][kCCInternalOpenGLInternalFormat];
  291. GLenumformat=tableFormats[m_uTableFormatIndex][kCCInternalOpenGLFormat];
  292. GLenumtype=tableFormats[m_uTableFormatIndex][kCCInternalOpenGLType];
  293. boolcompressed=(0==tableFormats[m_uTableFormatIndex][kCCInternalCompressedImage])?false:true;
  294. //循环产生多级纹理贴图。
  295. for(unsignedinti=0;i<m_uNumberOfMipmaps;++i)
  296. {
  297. //检查配置信息是否支持压缩格式。
  298. if(compressed&&!CCConfiguration::sharedConfiguration()->supportsPVRTC())
  299. {
  300. CCLOG("cocos2d:WARNING:PVRTCimagesarenotsupported");
  301. returnfalse;
  302. }
  303. //取得当前级别的图像块的像素数据地址和长度。
  304. unsignedchar*data=m_asMipmaps[i].address;
  305. unsignedintdatalen=m_asMipmaps[i].len;
  306. //如果是压缩格式,则产生压缩格式的贴图。
  307. if(compressed)
  308. {
  309. glCompressedTexImage2D(GL_TEXTURE_2D,i,internalFormat,datalen,data);
  310. }
  311. else
  312. {//产生一般格式的贴图。
  313. glTexImage2D(GL_TEXTURE_2D,type,data);
  314. }
  315. //如果是非2的幂次方大小,则提示。
  316. if(i>0&&(width!=height||ccNextPOT(width)!=width))
  317. {
  318. CCLOG("cocos2d:TexturePVR.WARNING.Mipmaplevel%uisnotsquared.Texturewon'trendercorrectly.width=%u!=height=%u",height);
  319. }
  320. //检错
  321. err=glGetError();
  322. if(err!=GL_NO_ERROR)
  323. {
  324. CCLOG("cocos2d:TexturePVR:Erroruploadingcompressedtexturelevel:%u.glError:0x%04X",err);
  325. returnfalse;
  326. }
  327. //变为原来大小的1/2。
  328. width=MAX(width>>1,1);
  329. }
  330. returntrue;
  331. }
  332. //成员函数:加载PVR图片
  333. boolCCTexturePVR::initWithContentsOfFile(constchar*path)
  334. {
  335. unsignedchar*pvrdata=NULL;
  336. intpvrlen=0;
  337. //定义字符串变量,存储转换为小写的路径字符串。
  338. std::stringlowerCase(path);
  339. for(unsignedinti=0;i<lowerCase.length();++i)
  340. {
  341. lowerCase[i]=tolower(lowerCase[i]);
  342. }
  343. //检查是否是ccz格式。
  344. if(lowerCase.find(".ccz")!=std::string::npos)
  345. {
  346. //调用压缩库函数将文件数据读取到为pvrdata申请的内存中。取得其大小存入pvrlen变量中。
  347. pvrlen=ZipUtils::ccInflateCCZFile(path,&pvrdata);
  348. }
  349. //检查是否是gz格式。
  350. elseif(lowerCase.find(".gz")!=std::string::npos)
  351. {
  352. //调用压缩库函数将文件数据读取到为pvrdata申请的内存中。取得其大小存入pvrlen变量中。
  353. pvrlen=ZipUtils::ccInflateGZipFile(path,&pvrdata);
  354. }
  355. else
  356. {
  357. //普通PVR文件,将文件数据读取到一块内存中返回给pvrdata。取得其大小存入pvrlen变量中。
  358. pvrdata=CCFileUtils::sharedFileUtils()->getFileData(path,"rb",(unsignedlong*)(&pvrlen));
  359. }
  360. //如果读取失败则返回
  361. if(pvrlen<0)
  362. {
  363. this->release();
  364. returnfalse;
  365. }
  366. m_uNumberOfMipmaps=0;
  367. m_uName=0;
  368. m_uWidth=m_uHeight=0;
  369. m_bHasAlpha=false;
  370. m_bRetainName=false;
  371. //如果解压数据失败则返回。
  372. //解压后,如果创建贴图失败则返回。
  373. if(!unpackPVRData(pvrdata,pvrlen)||!createGLTexture())
  374. {
  375. CC_SAFE_DELETE_ARRAY(pvrdata);
  376. this->release();
  377. returnfalse;
  378. }
  379. //释放数据占用的内存。
  380. CC_SAFE_DELETE_ARRAY(pvrdata);
  381. returntrue;
  382. }
  383. //导出的静态函数:加载PVR图片
  384. CCTexturePVR*CCTexturePVR::pvrTextureWithContentsOfFile(constchar*path)
  385. {
  386. returnCCTexturePVR::create(path);
  387. }
  388. //静态函数:加载PVR图片
  389. CCTexturePVR*CCTexturePVR::create(constchar*path)
  390. {
  391. //new一个新的CCTexturePVR
  392. CCTexturePVR*pTexture=newCCTexturePVR();
  393. if(pTexture)
  394. {
  395. //调用成员函数加载PVR图片
  396. if(pTexture->initWithContentsOfFile(path))
  397. {
  398. //如果成功,设置交由内存管理器使用引用计数器进行内存管理。
  399. pTexture->autorelease();
  400. }
  401. else
  402. {
  403. //否则释放纹理
  404. deletepTexture;
  405. pTexture=NULL;
  406. }
  407. }
  408. //返回这个CCTexturePVR
  409. returnpTexture;
  410. }
  411. NS_CC_END

三.CCTextureCache:

打开CCTextureCache.h:

  1. #ifndef__CCTEXTURE_CACHE_H__
  2. #define__CCTEXTURE_CACHE_H__
  3. //由CCObject派生
  4. #include"cocoa/CCObject.h"
  5. //需要用到字典
  6. #include"cocoa/CCDictionary.h"
  7. #include"textures/CCTexture2D.h"
  8. #include<string>
  9. //这里用到CCImage类和STL容器之一list
  10. #ifCC_ENABLE_CACHE_TEXTURE_DATA
  11. #include"platform/CCImage.h"
  12. #include<list>
  13. #endif
  14. //Cocos2d命名空间
  15. NS_CC_BEGIN
  16. //用到线程锁
  17. classCCLock;
  18. //用到CCImage处理图片
  19. classCCImage;
  20. //纹理管理器
  21. classCC_DLLCCTextureCache:publicCCObject
  22. {
  23. protected:
  24. //字典对象指针。
  25. CCDictionary*m_pTextures;
  26. //线程临界区。用于锁定字典访问,貌似用不到。这里屏蔽了~
  27. //pthread_mutex_t*m_pDictLock;
  28. private:
  29. //设置多线程加载图片时的回调函数。
  30. voidaddImageAsyncCallBack(floatdt);
  31. public:
  32. //构造函数
  33. CCTextureCache();
  34. //析构函数
  35. virtual~CCTextureCache();
  36. //取得当前类描述
  37. constchar*description(void);
  38. //取得当前字典的快照(拷贝)
  39. CCDictionary*snapshotTextures();
  40. //返回唯一纹理管理器的实例指针
  41. staticCCTextureCache*sharedTextureCache();
  42. //销毁唯一纹理管理器的实例指针
  43. staticvoidpurgeSharedTextureCache();
  44. //加载一个图片生成纹理,文件名做为字典的查询对应关键字。返回生成的纹理指针,支持png,bmp,tiff,jpeg,pvr,gif等格式。
  45. CCTexture2D*addImage(constchar*fileimage);
  46. //此函数可以支持多线程载入图片,调用时会创建一个线程进行异步加载,加载成功后由主线程调用设置的回调函数,当然创建的纹理会做为参数传递。支持png和jpg
  47. voidaddImageAsync(constchar*path,CCObject*target,SEL_CallFuncOselector);
  48. //加载一个图片生成纹理,指定参数key(其实要求是图片的相对路径字符串)做为字典的查询对应关键字。
  49. CCTexture2D*addUIImage(CCImage*image,constchar*key);
  50. //通过查询关键字(其实要求是图片的相对路径字符串)从字典里找到对应的纹理。
  51. CCTexture2D*textureForKey(constchar*key);
  52. //清空字典,释放所有纹理。
  53. voidremoveAllTextures();
  54. //清除未被外部使用的纹理。怎么知道未使用呢?因为在Cocos2d-x中使用“引用计数器”来管理各种资源的使用情况,纹理也不例外。在资源类构造时,纹理的计数器值为0,但由CCTextureCache来创建完成后,会对纹理的资源计数器做加1操作以通知纹理说“你现在被我占用呢”。如果纹理被外部使用,应该再次调用其资源计数器做加1操作,退出使用时做减1操作通知其“我现在不用你了”。所以这里只需要遍历下计数器值为1的纹理即未被外部使用的纹理进行释放即可。
  55. voidremoveUnusedTextures();
  56. //移除一个纹理
  57. voidremoveTexture(CCTexture2D*texture);
  58. //由字典查询关键字找到相应纹理并移除。
  59. voidremoveTextureForKey(constchar*textureKeyName);
  60. //打印出当前管理的纹理信息,包括现在纹理占用的内存和总的纹理内存。
  61. voiddumpCachedTextureInfo();
  62. #ifdefCC_SUPPORT_PVRTC
  63. //如果开启支持PVR的压缩格式,这里提供加载PVR压缩文件生成纹理的函数。
  64. //参1:PVR压缩文件名
  65. //参2:压缩质量参数,只能设为2或4,4比2质量高,但压缩比低。2则相反。
  66. //参3:是否有Alpha通道。这里会根据是否有ALPHA通道以生成相应的默认纹理格式。
  67. //参4:图片必须是2的幂次方大小的正方形,所以这里只需要填写一下宽度,也就是图片大小。
  68. CCTexture2D*addPVRTCImage(constchar*fileimage,intwidth);
  69. #endif//CC_SUPPORT_PVRTC
  70. //加载普通的PVR图片文件生成纹理。
  71. CCTexture2D*addPVRImage(constchar*filename);
  72. //如果CC_ENABLE_CACHE_TEXTURE_DATA宏定义为可用(即值为1),则调用此函数会将所有的纹理都预加载进内存生成相应纹理。
  73. staticvoidreloadAllTextures();
  74. };
  75. //如果定义了CC_ENABLE_CACHE_TEXTURE_DATA,这里定义一个新的类
  76. #ifCC_ENABLE_CACHE_TEXTURE_DATA
  77. //新定义的类名称为VolatileTexture,意思是多变纹理。这里代表了多种数据源生成的纹理的管理器。
  78. classVolatileTexture
  79. {
  80. //这里声明了一个枚举,代表了多变纹理对应的几种数据源类型
  81. typedefenum{
  82. kInvalid=0,//无效未加载任何数据的状态
  83. kImageFile,//图片文件
  84. kImageData,//内存中的图片数据
  85. kString,//字符串
  86. kImage,//图片对象(CCImage)
  87. }ccCachedImageType;
  88. public:
  89. //构造
  90. VolatileTexture(CCTexture2D*t);
  91. //析构
  92. ~VolatileTexture();
  93. //静态函数:通过图片文件生成的纹理及相关信息生成一个多变纹理并将其指针放入容器。
  94. staticvoidaddImageTexture(CCTexture2D*tt,constchar*imageFileName,CCImage::EImageFormatformat);
  95. //静态函数:通过字符串生成的纹理及相关信息生成一个多变纹理并将其指针放入容器。
  96. staticvoidaddStringTexture(CCTexture2D*tt,constchar*text,CCTextAlignmentalignment,
  97. CCVerticalTextAlignmentvAlignment,constchar*fontName,floatfontSize);
  98. //通过图片数据生成的纹理及相关信息生成一个多变纹理并将其指针放入容器。
  99. staticvoidaddDataTexture(CCTexture2D*tt,void*data,constCCSize&contentSize);
  100. //通过图片对象生成的纹理及相关信息生成一个多变纹理并将其指针放入容器。
  101. staticvoidaddCCImage(CCTexture2D*tt,CCImage*image);
  102. //通过纹理指针参数从容器中删除对应的多变纹理
  103. staticvoidremoveTexture(CCTexture2D*t);
  104. //重新载入所有的纹理
  105. staticvoidreloadAllTextures();
  106. public:
  107. //静态多变纹理指针容器,用来存储所有的多变纹理对象指针。
  108. staticstd::list<VolatileTexture*>textures;
  109. //是否正在进行全部重新载入
  110. staticboolisReloading;
  111. private:
  112. //通过纹理指针参数从容器找到对应的多变纹理对象指针
  113. staticVolatileTexture*findVolotileTexture(CCTexture2D*tt);
  114. protected:
  115. //与当前多变纹理对应的纹理指针
  116. CCTexture2D*texture;
  117. //对应的图片对象
  118. CCImage*uiImage;
  119. //数据源类型
  120. ccCachedImageTypem_eCashedImageType;
  121. //纹理数据指针
  122. void*m_pTextureData;
  123. //纹理的实际大小
  124. CCSizem_TextureSize;
  125. //纹理的像素格式
  126. CCTexture2DPixelFormatm_PixelFormat;
  127. //对应的图片名称
  128. std::stringm_strFileName;
  129. //图片的像素格式
  130. CCImage::EImageFormatm_FmtImage;
  131. //图片的大小
  132. CCSizem_size;
  133. //横向文字的对齐方式
  134. CCTextAlignmentm_alignment;
  135. //纵向文字的对齐方式
  136. CCVerticalTextAlignmentm_vAlignment;
  137. //字体名称
  138. std::stringm_strFontName;
  139. //文字
  140. std::stringm_strText;
  141. //字体大小
  142. floatm_fFontSize;
  143. };
  144. #endif
  145. NS_CC_END
  146. #endif//__CCTEXTURE_CACHE_H__

然后是CPP文件:

  1. #include"CCTextureCache.h"
  2. #include"CCTexture2D.h"
  3. #include"ccMacros.h"
  4. #include"CCDirector.h"
  5. #include"platform/platform.h"
  6. #include"platform/CCFileUtils.h"
  7. #include"platform/CCThread.h"
  8. #include"platform/CCImage.h"
  9. #include"support/ccUtils.h"
  10. #include"CCScheduler.h"
  11. #include"cocoa/CCString.h"
  12. #include<errno.h>
  13. #include<stack>
  14. #include<string>
  15. #include<cctype>
  16. #include<queue>
  17. #include<list>
  18. #include<pthread.h>
  19. #include<semaphore.h>
  20. //使用标准库命名空间
  21. usingnamespacestd;
  22. //使用Cocos2d命名空间
  23. NS_CC_BEGIN
  24. //异步加载所用的消息结构
  25. typedefstruct_AsyncStruct
  26. {
  27. std::stringfilename;//文件名
  28. CCObject*target;//调用者
  29. SEL_CallFuncOselector;//载回完的回调函数
  30. }AsyncStruct;
  31. //图片信息
  32. typedefstruct_ImageInfo
  33. {
  34. AsyncStruct*asyncStruct;//异步加载消息结构
  35. CCImage*image;//图片指针
  36. CCImage::EImageFormatimageType//图片类型
  37. }ImageInfo;
  38. //加载图片的线程
  39. staticpthread_ts_loadingThread;
  40. //用于读取异步消息队列的线程临界区
  41. staticpthread_mutex_ts_asyncStructQueueMutex;
  42. //用于存储图片信息结构处理的临界区
  43. staticpthread_mutex_ts_ImageInfoMutex;
  44. //信号量指针。信号量是当前进程中的多个线程通信的一种方式。
  45. staticsem_t*s_pSem=NULL;
  46. //多线程加载图片的数量。
  47. staticunsignedlongs_nAsyncRefCount=0;
  48. //如果是IOS平台,则定义是否使用信号量命名。
  49. #ifCC_TARGET_PLATFORM==CC_PLATFORM_IOS
  50. #defineCC_ASYNC_TEXTURE_CACHE_USE_NAMED_SEMAPHORE1
  51. #else
  52. #defineCC_ASYNC_TEXTURE_CACHE_USE_NAMED_SEMAPHORE0
  53. #endif
  54. //如果使用信号量命名,则定义命名的字符串宏,否则定义静态全局的信号量结构。
  55. #ifCC_ASYNC_TEXTURE_CACHE_USE_NAMED_SEMAPHORE
  56. #defineCC_ASYNC_TEXTURE_CACHE_SEMAPHORE"ccAsync"
  57. #else
  58. staticsem_ts_sem;
  59. #endif
  60. //是否在当前加载线程处理完手上的活儿就退出。
  61. staticboolneed_quit=false;
  62. //异步加载图片的消息结构指针容器,即消息队列。
  63. staticstd::queue<AsyncStruct*>*s_pAsyncStructQueue=NULL;
  64. //异步存储图片信息结构指针的容器。
  65. staticstd::queue<ImageInfo*>*s_pImageQueue=NULL;
  66. //通过文件扩展名取得图片格式
  67. staticCCImage::EImageFormatcomputeImageFormatType(string&filename)
  68. {
  69. CCImage::EImageFormatret=CCImage::kFmtUnKnown;
  70. //JPG
  71. if((std::string::npos!=filename.find(".jpg"))||(std::string::npos!=filename.find(".jpeg")))
  72. {
  73. ret=CCImage::kFmtJpg;
  74. }//PNG
  75. elseif((std::string::npos!=filename.find(".png"))||(std::string::npos!=filename.find(".PNG")))
  76. {
  77. ret=CCImage::kFmtPng;
  78. }//TIFF
  79. elseif((std::string::npos!=filename.find(".tiff"))||(std::string::npos!=filename.find(".TIFF")))
  80. {
  81. ret=CCImage::kFmtTiff;
  82. }
  83. returnret;
  84. }
  85. //加载图片的线程函数
  86. staticvoid*loadImage(void*data)
  87. {
  88. //创建一个线程信息对象
  89. CCThreadthread;
  90. thread.createAutoreleasePool();
  91. //多线程加载消息结构
  92. AsyncStruct*pAsyncStruct=NULL;
  93. //线程将处理所有随时要进行多线程加载的图片,所以会有一个While循环。
  94. while(true)
  95. {
  96. //当前线程等待信号量变为非零值,并减1。
  97. intsemWaitRet=sem_wait(s_pSem);
  98. //如果信号量为负值,打印出错信息并中断。
  99. if(semWaitRet<0)
  100. {
  101. CCLOG("CCTextureCacheasyncthreadsemaphoreerror:%s\n",strerror(errno));
  102. break;
  103. }
  104. //取得全局的异步加载信息结构指针容器
  105. std::queue<AsyncStruct*>*pQueue=s_pAsyncStructQueue;
  106. //下面代码作为临界区上锁
  107. pthread_mutex_lock(&s_asyncStructQueueMutex);
  108. //如果没有需要异步加载的图片
  109. if(pQueue->empty())
  110. {
  111. //解锁临界区
  112. pthread_mutex_unlock(&s_asyncStructQueueMutex);
  113. //如果退出线程标记为true则中断退出,否则继续。
  114. if(need_quit)
  115. break;
  116. else
  117. continue;
  118. }
  119. else
  120. {
  121. //如果有需要异步加载的图片,则从队列中取第一个消息指针保存在变量pAsyncStruct中随后将其从队列中移除。
  122. pAsyncStruct=pQueue->front();
  123. pQueue->pop();
  124. //解锁临界区
  125. pthread_mutex_unlock(&s_asyncStructQueueMutex);
  126. }
  127. //取得要进行异步加载的图片名称
  128. constchar*filename=pAsyncStruct->filename.c_str();
  129. //取得图片类型
  130. CCImage::EImageFormatimageType=computeImageFormatType(pAsyncStruct->filename);
  131. //如果不是PNG,JPG或TIFF就不支持了。打印错误后进行相应处理。
  132. if(imageType==CCImage::kFmtUnKnown)
  133. {
  134. CCLOG("unsupporttedformat%s",filename);
  135. deletepAsyncStruct;
  136. continue;
  137. }
  138. //如果是有效格式,生成一个新的CCImage对象
  139. CCImage*pImage=newCCImage();
  140. //由文件名和图片格式将图片加载到CCImage中。
  141. if(!pImage->initWithImageFileThreadSafe(filename,imageType))
  142. {//如果失败,释放CCImage对象并打印错误。
  143. deletepImage;
  144. CCLOG("cannotload%s",filename);
  145. continue;
  146. }
  147. //动态创建一个新的图片信息结构并填充相应信息
  148. ImageInfo*pImageInfo=newImageInfo();
  149. pImageInfo->asyncStruct=pAsyncStruct;
  150. pImageInfo->image=pImage;
  151. pImageInfo->imageType=imageType;
  152. //下面代码作为临界区上锁
  153. pthread_mutex_lock(&s_ImageInfoMutex);
  154. //将新的图片信息放入图片信息结构容器。
  155. s_pImageQueue->push(pImageInfo);
  156. //解锁临界区
  157. pthread_mutex_unlock(&s_ImageInfoMutex);
  158. }
  159. //如果退出循环,释放信号量
  160. if(s_pSem!=NULL)
  161. {
  162. #ifCC_ASYNC_TEXTURE_CACHE_USE_NAMED_SEMAPHORE
  163. sem_unlink(CC_ASYNC_TEXTURE_CACHE_SEMAPHORE);
  164. sem_close(s_pSem);
  165. #else
  166. sem_destroy(s_pSem);
  167. #endif
  168. s_pSem=NULL;
  169. //释放多线程加载所用的消息队列和与之对应的图片信息队列。
  170. deletes_pAsyncStructQueue;
  171. deletes_pImageQueue;
  172. }
  173. return0;
  174. }
  175. //唯一的全局纹理数据缓冲区对象指针
  176. staticCCTextureCache*g_sharedTextureCache=NULL;
  177. //取得唯一的全局纹理数据缓冲区对象指针
  178. CCTextureCache*CCTextureCache::sharedTextureCache()
  179. {
  180. if(!g_sharedTextureCache)
  181. {
  182. g_sharedTextureCache=newCCTextureCache();
  183. }
  184. returng_sharedTextureCache;
  185. }
  186. //构造函数
  187. CCTextureCache::CCTextureCache()
  188. {
  189. CCAssert(g_sharedTextureCache==NULL,"Attemptedtoallocateasecondinstanceofasingleton.");
  190. //生成一个字典
  191. m_pTextures=newCCDictionary();
  192. }
  193. //析构函数
  194. CCTextureCache::~CCTextureCache()
  195. {
  196. CCLOGINFO("cocos2d:deallocingCCTextureCache.");
  197. need_quit=true;
  198. if(s_pSem!=NULL)
  199. {
  200. sem_post(s_pSem);
  201. }
  202. //释放字典
  203. CC_SAFE_RELEASE(m_pTextures);
  204. }
  205. //释放唯一的全局纹理数据缓冲区对象
  206. voidCCTextureCache::purgeSharedTextureCache()
  207. {
  208. CC_SAFE_RELEASE_NULL(g_sharedTextureCache);
  209. }
  210. //取得当前类描述
  211. constchar*CCTextureCache::description()
  212. {
  213. returnCCString::createWithFormat("<CCTextureCache|Numberoftextures=%u>",m_pTextures->count())->getCString();
  214. }
  215. //取得当前字典的快照
  216. CCDictionary*CCTextureCache::snapshotTextures()
  217. {
  218. //动态创建一个新的字典
  219. CCDictionary*pRet=newCCDictionary();
  220. CCDictElement*pElement=NULL;
  221. //遍历原来字典将数据填充到新字典中
  222. CCDICT_FOREACH(m_pTextures,pElement)
  223. {
  224. pRet->setObject(pElement->getObject(),pElement->getStrKey());
  225. }
  226. returnpRet;
  227. }
  228. //使用多线程载入图片。
  229. //参1:图片相对路径名。
  230. //参2:载入完成后要通知的对象。
  231. //参3:载入完成后要通知对象调用的函数。
  232. voidCCTextureCache::addImageAsync(constchar*path,SEL_CallFuncOselector)
  233. {
  234. //文件名不能为空
  235. CCAssert(path!=NULL,"TextureCache:fileimageMUSTnotbeNULL");
  236. //定义一个纹理指针并置空
  237. CCTexture2D*texture=NULL;
  238. //创建字符串pathKey做为字典查询关键字。
  239. std::stringpathKey=path;
  240. //取得图片所在位置的全路径名
  241. pathKey=CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(pathKey.c_str());
  242. //先查询一下是否字典里已经有了此纹理。
  243. texture=(CCTexture2D*)m_pTextures->objectForKey(pathKey.c_str());
  244. std::stringfullpath=pathKey;
  245. //如果已经有了,则直接把纹理做为参数调用要通知的对象的函数。
  246. if(texture!=NULL)
  247. {
  248. if(target&&selector)
  249. {
  250. (target->*selector)(texture);
  251. }
  252. return;
  253. }
  254. //如果是第一次调用多线程载入,创建信号量并进行相应初始化。
  255. if(s_pSem==NULL)
  256. {
  257. //判断是否使用信号量命名,如果是,创建一个信号量返回其地址给指针s_pSem。
  258. #ifCC_ASYNC_TEXTURE_CACHE_USE_NAMED_SEMAPHORE
  259. s_pSem=sem_open(CC_ASYNC_TEXTURE_CACHE_SEMAPHORE,O_CREAT,0644,0);
  260. if(s_pSem==SEM_FAILED)
  261. {
  262. CCLOG("CCTextureCacheasyncthreadsemaphoreiniterror:%s\n",strerror(errno));
  263. s_pSem=NULL;
  264. return;
  265. }
  266. #else
  267. //如果不使用信号量命名,直接用sem_init来初始化信号量对象s_sem。
  268. intsemInitRet=sem_init(&s_sem,0);
  269. if(semInitRet<0)
  270. {
  271. //如果失败,打印出错并退出。
  272. CCLOG("CCTextureCacheasyncthreadsemaphoreiniterror:%s\n",strerror(errno));
  273. return;
  274. }
  275. //如果成功,将信号量对象地址给指针s_pSem。
  276. s_pSem=&s_sem;
  277. #endif
  278. //建立加载消息队列
  279. s_pAsyncStructQueue=newqueue<AsyncStruct*>();
  280. //建立加载的图片信息结构队列
  281. s_pImageQueue=newqueue<ImageInfo*>();
  282. //线程锁初始化
  283. pthread_mutex_init(&s_asyncStructQueueMutex,NULL);
  284. pthread_mutex_init(&s_ImageInfoMutex,NULL);
  285. //创建加载线程。
  286. pthread_create(&s_loadingThread,NULL,loadImage,NULL);
  287. //将退出指令设为false。
  288. need_quit=false;
  289. }
  290. //多线程加载图片的引用计数器如果为0,
  291. if(0==s_nAsyncRefCount)
  292. {
  293. //将addImageAsyncCallBack函数加入显示设备上的回调函数处理器中。
  294. CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(CCTextureCache::addImageAsyncCallBack),this,false);
  295. }
  296. //计数器加1
  297. ++s_nAsyncRefCount;
  298. //
  299. if(target)
  300. {
  301. target->retain();
  302. }
  303. //产生一个新的加载消息,放入加载消息队列中。
  304. AsyncStruct*data=newAsyncStruct();
  305. data->filename=fullpath.c_str();
  306. data->target=target;
  307. data->selector=selector;
  308. //当然,放入时得锁一下,放入后再解锁。
  309. pthread_mutex_lock(&s_asyncStructQueueMutex);
  310. s_pAsyncStructQueue->push(data);
  311. pthread_mutex_unlock(&s_asyncStructQueueMutex);
  312. //给信号量加1,sem_post是原子操作,即多个线程同时调用并不会产生冲突。
  313. sem_post(s_pSem);
  314. }
  315. //多线程加载图片时的回调函数。
  316. voidCCTextureCache::addImageAsyncCallBack(floatdt)
  317. {
  318. //取得多线程加载的图片信息队列
  319. std::queue<ImageInfo*>*imagesQueue=s_pImageQueue;
  320. //下面代码作为临界区上锁
  321. pthread_mutex_lock(&s_ImageInfoMutex);
  322. //如果图片信息队列为空直接解锁,否则进行处理
  323. if(imagesQueue->empty())
  324. {
  325. pthread_mutex_unlock(&s_ImageInfoMutex);
  326. }
  327. else
  328. {
  329. //取出图片信息队列的头一个信息从队列中弹出。
  330. ImageInfo*pImageInfo=imagesQueue->front();
  331. imagesQueue->pop();
  332. //解锁临界区
  333. pthread_mutex_unlock(&s_ImageInfoMutex);
  334. //取得信息中的加载消息。
  335. AsyncStruct*pAsyncStruct=pImageInfo->asyncStruct;
  336. //取得图片信息中的CCImage指针。
  337. CCImage*pImage=pImageInfo->image;
  338. //取得加载完成后要通知的对象以及要调用的函数。
  339. CCObject*target=pAsyncStruct->target;
  340. SEL_CallFuncOselector=pAsyncStruct->selector;
  341. //取得图片文件名
  342. constchar*filename=pAsyncStruct->filename.c_str();
  343. //新建一个纹理。
  344. CCTexture2D*texture=newCCTexture2D();
  345. //使用CCImage指针pImage来初始化纹理生成OpenGL贴图。
  346. #if0//TODO:(CC_TARGET_PLATFORM==CC_PLATFORM_IOS)
  347. texture->initWithImage(pImage,kCCResolutioniPhone);
  348. #else
  349. texture->initWithImage(pImage);
  350. #endif
  351. #ifCC_ENABLE_CACHE_TEXTURE_DATA
  352. //使用纹理和图片信息生成相应的可变纹理
  353. VolatileTexture::addImageTexture(texture,filename,pImageInfo->imageType);
  354. #endif
  355. //使用文件名做为查询关键字将纹理存入字典
  356. m_pTextures->setObject(texture,filename);
  357. texture->autorelease();
  358. //调用通知目标的相应函数。
  359. if(target&&selector)
  360. {
  361. (target->*selector)(texture);
  362. target->release();
  363. }
  364. //释放CCImage对象。
  365. pImage->release();
  366. //释放new出来的消息结构和图片信息结构。
  367. deletepAsyncStruct;
  368. deletepImageInfo;
  369. //多线程加载引用计数器减1,
  370. --s_nAsyncRefCount;
  371. if(0==s_nAsyncRefCount)
  372. {
  373. //从显示设备上的回调函数处理器中移除加载回调函数。
  374. CCDirector::sharedDirector()->getScheduler()->unscheduleSelector(schedule_selector(CCTextureCache::addImageAsyncCallBack),this);
  375. }
  376. }
  377. }
  378. //加载一个图片生成纹理。
  379. CCTexture2D*CCTextureCache::addImage(constchar*path)
  380. {
  381. //参数有效性判断
  382. CCAssert(path!=NULL,"TextureCache:fileimageMUSTnotbeNULL");
  383. //定义纹理指针变量并置空
  384. CCTexture2D*texture=NULL;
  385. //非多线程,故屏蔽,如果addImageAsync在其它线程调用此函数,则打开这段代码。
  386. //pthread_mutex_lock(m_pDictLock);
  387. //创建字符串pathKey做为字典查询关键字。
  388. std::stringpathKey=path;
  389. //取得图片所在位置的全路径名
  390. pathKey=CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(pathKey.c_str());
  391. //用pathKey查询字典中是否有此纹理。
  392. texture=(CCTexture2D*)m_pTextures->objectForKey(pathKey.c_str());
  393. //新建字符串fullpath存储全路径。
  394. std::stringfullpath=pathKey;
  395. //如果没有找到,
  396. if(!texture)
  397. {
  398. //将文件路径放入新字符串lowerCase。并将字符串中的所有字母转为小写。
  399. std::stringlowerCase(path);
  400. for(unsignedinti=0;i<lowerCase.length();++i)
  401. {
  402. lowerCase[i]=tolower(lowerCase[i]);
  403. }
  404. //
  405. do
  406. {
  407. //如果字符串能够找到".pvr",则代表是pvr文件。调用相应函数将其载入。
  408. if(std::string::npos!=lowerCase.find(".pvr"))
  409. {
  410. texture=this->addPVRImage(fullpath.c_str());
  411. }
  412. else
  413. {
  414. //否则分别取得文件的格式。
  415. CCImage::EImageFormateImageFormat=CCImage::kFmtUnKnown;
  416. if(std::string::npos!=lowerCase.find(".png"))
  417. {
  418. eImageFormat=CCImage::kFmtPng;
  419. }
  420. elseif(std::string::npos!=lowerCase.find(".jpg")||std::string::npos!=lowerCase.find(".jpeg"))
  421. {
  422. eImageFormat=CCImage::kFmtJpg;
  423. }
  424. elseif(std::string::npos!=lowerCase.find(".tif")||std::string::npos!=lowerCase.find(".tiff"))
  425. {
  426. eImageFormat=CCImage::kFmtTiff;
  427. }
  428. //创建CCImage对象,从文件中读取文件的数据并初始化CCImage对象。
  429. CCImageimage;
  430. //取得文件大小
  431. unsignedlongnSize=0;
  432. //读入数据返回给BYTE类型指针。
  433. unsignedchar*pBuffer=CCFileUtils::sharedFileUtils()->getFileData(fullpath.c_str(),"rb",&nSize);
  434. //使用读入的数据初始化相应的图片对象。
  435. CC_BREAK_IF(!image.initWithImageData((void*)pBuffer,nSize,eImageFormat));
  436. //读完后释放数据占用的内存。
  437. CC_SAFE_DELETE_ARRAY(pBuffer);
  438. //创建一个纹理。
  439. texture=newCCTexture2D();
  440. //使用图片对象创建纹理。
  441. if(texture&&
  442. texture->initWithImage(&image))
  443. {
  444. #ifCC_ENABLE_CACHE_TEXTURE_DATA
  445. //使用图片对象生成可变纹理
  446. VolatileTexture::addImageTexture(texture,fullpath.c_str(),eImageFormat);
  447. #endif
  448. //利用路径名做为查询关键字将纹理存入字典。
  449. m_pTextures->setObject(texture,pathKey.c_str());
  450. //计数器减1。则刚存入字典的纹理的引用计数器值标记为尚未使用。
  451. texture->release();
  452. }
  453. else
  454. {
  455. //失败则打印错误。
  456. CCLOG("cocos2d:Couldn'taddimage:%sinCCTextureCache",path);
  457. }
  458. }
  459. }while(0);
  460. }
  461. //与上面屏蔽加锁一样,这里屏蔽解锁。
  462. //pthread_mutex_unlock(m_pDictLock);
  463. returntexture;
  464. }
  465. //如果支持PVR的压缩格式。
  466. #ifdefCC_SUPPORT_PVRTC
  467. //加载一个PVR的压缩格式的图片。
  468. CCTexture2D*CCTextureCache::addPVRTCImage(constchar*path,intwidth)
  469. {
  470. //参数有效性判断
  471. CCAssert(path!=NULL,"TextureCache:fileimageMUSTnotbenill");
  472. //压缩类型参数有效性判断,只能为2或4
  473. CCAssert(bpp==2||bpp==4,"TextureCache:bppmustbeeither2or4");
  474. //定义一个新的纹理指针
  475. CCTexture2D*texture;
  476. //定义临时字符串存储相对路径名。
  477. std::stringtemp(path);
  478. //查询字典中是否已经有此纹理。有则取得并直接返回纹理。
  479. if((texture=(CCTexture2D*)m_pTextures->objectForKey(temp.c_str())))
  480. {
  481. returntexture;
  482. }
  483. //取得文件的全路径字符串。
  484. std::stringfullpath(CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(path));
  485. //新建变量nLeng用于存储读取到的数据大小。初始化为0。
  486. unsignedlongnLen=0;
  487. //新建字符指针pData用于存储读取到的数据并实际读取文件数据。
  488. unsignedchar*pData=CCFileUtils::sharedFileUtils()->getFileData(fullpath.c_str(),&nLen);
  489. //新建创一个纹理。
  490. texture=newCCTexture2D();
  491. //使用读取到的数据创建纹理。
  492. if(texture->initWithPVRTCData(pData,bpp,hasAlpha,
  493. (bpp==2?kCCTexture2DPixelFormat_PVRTC2:kCCTexture2DPixelFormat_PVRTC4)))
  494. {
  495. //将纹理以文件名做为关键字存入字典。
  496. m_pTextures->setObject(texture,temp.c_str());
  497. //将纹理交由内存管理器处理。
  498. texture->autorelease();
  499. }
  500. else
  501. {
  502. //如果创建失败或读取PVR文件失败,打印错误日志。\
  503. CCLOG("cocos2d:Couldn'taddPVRTCImage:%sinCCTextureCache",path);
  504. }
  505. //释放读取文件的数据所占用的内存。
  506. CC_SAFE_DELETE_ARRAY(pData);
  507. returntexture;
  508. }
  509. #endif//CC_SUPPORT_PVRTC
  510. //加载一个普通的PVR图片文件
  511. CCTexture2D*CCTextureCache::addPVRImage(constchar*path)
  512. {
  513. //文件名参数有效性判断。
  514. CCAssert(path!=NULL,"TextureCache:fileimageMUSTnotbenill");
  515. //新建纹理指针变量置空。
  516. CCTexture2D*texture=NULL;
  517. //定义临时字符串存储相对路径名。
  518. std::stringkey(path);
  519. //先使用文件名查询是否字典中已经有此纹理了。如果有直接取得并返回纹理。
  520. if((texture=(CCTexture2D*)m_pTextures->objectForKey(key.c_str())))
  521. {
  522. returntexture;
  523. }
  524. //由文件名字符串取得图片的全路径字符串。
  525. std::stringfullpath=CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(key.c_str());
  526. //动态创建一个纹理。
  527. texture=newCCTexture2D();
  528. //如果创建成功,则读取相应的PVR文件来初始化纹理。
  529. if(texture!=NULL&&texture->initWithPVRFile(fullpath.c_str()))
  530. {
  531. //初始化成功。
  532. #ifCC_ENABLE_CACHE_TEXTURE_DATA
  533. //使用纹理和图片信息生成可变纹理。
  534. VolatileTexture::addImageTexture(texture,CCImage::kFmtRawData);
  535. #endif
  536. //将纹理以文件名做为查询关键字存入字典。
  537. m_pTextures->setObject(texture,key.c_str());
  538. texture->autorelease();
  539. }
  540. else
  541. {
  542. //如果创建失败或读取PVR文件失败,打印错误日志。
  543. CCLOG("cocos2d:Couldn'taddPVRImage:%sinCCTextureCache",key.c_str());
  544. CC_SAFE_DELETE(texture);
  545. }
  546. returntexture;
  547. }
  548. //加载一个图片生成纹理,指定参数key做为字典的查询对应关键字。
  549. CCTexture2D*CCTextureCache::addUIImage(CCImage*image,constchar*key)
  550. {
  551. //参数有效性判断
  552. CCAssert(image!=NULL,"TextureCache:imageMUSTnotbenill");
  553. //定义纹理指针变量texure做为返回值。这里初始化为空。
  554. CCTexture2D*texture=NULL;
  555. //定义字符串变量forKey用来存储完整的图片路径名称。
  556. std::stringforKey;
  557. if(key)
  558. {
  559. //取得文件名所对应的全路径名,呵呵,这个key也还是个相对路径名啊。
  560. forKey=CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(key);
  561. }
  562. do
  563. {
  564. //查询字典是否已经有此纹理了。如果有,取出纹理返回给texture,中断退出。
  565. if(key&&(texture=(CCTexture2D*)m_pTextures->objectForKey(forKey.c_str())))
  566. {
  567. break;
  568. }
  569. //动态创建一个纹理对象.返回给texture。
  570. texture=newCCTexture2D();
  571. //使用image来初始化纹理.注意:这一句应该移到下面的if中。
  572. texture->initWithImage(image);
  573. //初始化完成后以路径名做为查询关键字将纹理存入字典。
  574. if(key&&texture)
  575. {
  576. m_pTextures->setObject(texture,forKey.c_str());
  577. texture->autorelease();
  578. }
  579. else
  580. {
  581. //如果key为空或texture为空打印错误
  582. CCLOG("cocos2d:Couldn'taddUIImageinCCTextureCache");
  583. }
  584. }while(0);
  585. #ifCC_ENABLE_CACHE_TEXTURE_DATA
  586. //使用纹理和CCImage对象生成可变纹理。
  587. VolatileTexture::addCCImage(texture,image);
  588. #endif
  589. returntexture;
  590. }
  591. //清空字典,释放所有纹理。
  592. voidCCTextureCache::removeAllTextures()
  593. {
  594. m_pTextures->removeAllObjects();
  595. }
  596. //清除未被外部使用的纹理
  597. voidCCTextureCache::removeUnusedTextures()
  598. {
  599. /*原来的做法,因为有问题给屏蔽了,仍然解释下:
  600. //定义字典词汇指针变量pElement。
  601. CCDictElement*pElement=NULL;
  602. //遍历字典
  603. CCDICT_FOREACH(m_pTextures,pElement)
  604. {
  605. //打印词汇信息
  606. CCLOG("cocos2d:CCTextureCache:texture:%s",pElement->getStrKey());
  607. //取得词汇对应的纹理
  608. CCTexture2D*value=(CCTexture2D*)pElement->getObject();
  609. //如果引用计数器值为1,从字典中删除。
  610. if(value->retainCount()==1)
  611. {
  612. CCLOG("cocos2d:CCTextureCache:removingunusedtexture:%s",pElement->getStrKey());
  613. m_pTextures->removeObjectForElememt(pElement);
  614. }
  615. }
  616. */
  617. //现在的做法
  618. //判断字典不为空
  619. if(m_pTextures->count())
  620. {
  621. //定义字典词汇指针变量pElement。
  622. CCDictElement*pElement=NULL;
  623. //定义一个list容器用来存储未被外部使用的纹理指针。
  624. list<CCDictElement*>elementToRemove;
  625. //遍历字典
  626. CCDICT_FOREACH(m_pTextures,pElement)
  627. {
  628. //打印词汇信息
  629. CCLOG("cocos2d:CCTextureCache:texture:%s",pElement->getStrKey());
  630. //取得词汇对应的纹理
  631. CCTexture2D*value=(CCTexture2D*)pElement->getObject();
  632. if(value->retainCount()==1)
  633. {
  634. //如果引用计数器值为1,先存入容器中。
  635. elementToRemove.push_back(pElement);
  636. }
  637. }
  638. //遍历list中的元素从字典中删除
  639. for(list<CCDictElement*>::iteratoriter=elementToRemove.begin();iter!=elementToRemove.end();++iter)
  640. {
  641. //打印删除元素日志。
  642. CCLOG("cocos2d:CCTextureCache:removingunusedtexture:%s",(*iter)->getStrKey());
  643. //从字典中删除
  644. m_pTextures->removeObjectForElememt(*iter);
  645. }
  646. }
  647. //好吧,答案是因为CCDICT_FOREACH和removeObjectForElememt会互相影响,CCDICT_FOREACH中会调用HASH_ITER循环遍历。而循环的计数器是位置,通过地址对比来找下一个结点位置。而removeObjectForElememt会调用HASH_DELETE删除元素导致链表的重构。重构后会影响到HASK_ITER的查询。
  648. }
  649. //移除一个纹理
  650. voidCCTextureCache::removeTexture(CCTexture2D*texture)
  651. {
  652. //参数有效性判断
  653. if(!texture)
  654. {
  655. return;
  656. }
  657. //查询所有对应此纹理的词汇
  658. CCArray*keys=m_pTextures->allKeysForObject(texture);
  659. //从字典中把这些词汇及相应纹理删除。
  660. m_pTextures->removeObjectsForKeys(keys);
  661. }
  662. //由字典查询关键字找到相应纹理并移除。
  663. voidCCTextureCache::removeTextureForKey(constchar*textureKeyName)
  664. {
  665. //参数有效性判断
  666. if(textureKeyName==NULL)
  667. {
  668. return;
  669. }
  670. //查询关键字实际是文件的相对路径,这里取得全路径。
  671. stringfullPath=CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(textureKeyName);
  672. //将全路径做为查询关键字从字典中删除相应词汇及纹理
  673. m_pTextures->removeObjectForKey(fullPath.c_str());
  674. }
  675. //由字典查询关键字找到相应纹理
  676. CCTexture2D*CCTextureCache::textureForKey(constchar*key)
  677. {
  678. return(CCTexture2D*)m_pTextures->objectForKey(CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(key));
  679. }
  680. //重新载入所有的纹理
  681. voidCCTextureCache::reloadAllTextures()
  682. {
  683. #ifCC_ENABLE_CACHE_TEXTURE_DATA
  684. //调用可变纹理的静态函数重新载入所有的纹理
  685. VolatileTexture::reloadAllTextures();
  686. #endif
  687. }
  688. //打印字典中的纹理统计信息。
  689. voidCCTextureCache::dumpCachedTextureInfo()
  690. {
  691. unsignedintcount=0;
  692. unsignedinttotalBytes=0;
  693. CCDictElement*pElement=NULL;
  694. //遍历字典中的所有词汇信息
  695. CCDICT_FOREACH(m_pTextures,pElement)
  696. {
  697. //取得词汇对应的纹理
  698. CCTexture2D*tex=(CCTexture2D*)pElement->getObject();
  699. //取得纹理对应贴图的色深
  700. unsignedintbpp=tex->bitsPerPixelForFormat();
  701. //生成贴图占用的内存大小(字节数量)
  702. unsignedintbytes=tex->getPixelsWide()*tex->getPixelsHigh()*bpp/8;
  703. //统计内存总大小
  704. totalBytes+=bytes;
  705. count++;
  706. //打印纹理信息
  707. CCLOG("cocos2d:\"%s\"rc=%luid=%lu%lux%lu@%ldbpp=>%luKB",
  708. pElement->getStrKey(),//查询关键字
  709. (long)tex->retainCount(),//使用次数
  710. (long)tex->getName(),//图片名称
  711. (long)tex->getPixelsWide(),//对应贴图的宽度
  712. (long)tex->getPixelsHigh(),//对应贴图的高度
  713. (long)bpp,//对应贴图色深
  714. (long)bytes/1024);//占用内存大小(千字节数量)
  715. }
  716. //打印总的数量数量,占用内存数量。
  717. CCLOG("cocos2d:CCTextureCachedumpDebugInfo:%ldtextures,for%luKB(%.2fMB)",(long)count,(long)totalBytes/1024,totalBytes/(1024.0f*1024.0f));
  718. }
  719. //如果开启了使用多变纹理
  720. #ifCC_ENABLE_CACHE_TEXTURE_DATA
  721. //定义全局的list容器,用来存储产生的多变纹理对象指针
  722. std::list<VolatileTexture*>VolatileTexture::textures;
  723. //定义布尔变量标记是否在全部重新载入
  724. boolVolatileTexture::isReloading=false;
  725. //构造函数
  726. VolatileTexture::VolatileTexture(CCTexture2D*t)
  727. :texture(t)
  728. ,m_eCashedImageType(kInvalid)
  729. ,m_pTextureData(NULL)
  730. ,m_PixelFormat(kTexture2DPixelFormat_RGBA8888)
  731. ,m_strFileName("")
  732. ,m_FmtImage(CCImage::kFmtPng)
  733. ,m_alignment(kCCTextAlignmentCenter)
  734. ,m_vAlignment(kCCVerticalTextAlignmentCenter)
  735. ,m_strFontName("")
  736. ,m_strText("")
  737. ,uiImage(NULL)
  738. ,m_fFontSize(0.0f)
  739. {
  740. m_size=CCSizeMake(0,0);
  741. textures.push_back(this);
  742. }
  743. //析构函数
  744. VolatileTexture::~VolatileTexture()
  745. {
  746. textures.remove(this);
  747. CC_SAFE_RELEASE(uiImage);
  748. }
  749. //通过纹理图片属性信息生成可变纹理。
  750. voidVolatileTexture::addImageTexture(CCTexture2D*tt,CCImage::EImageFormatformat)
  751. {
  752. //如果正在重新载入过程中,直接返回。
  753. if(isReloading)
  754. {
  755. return;
  756. }
  757. //通过纹理指针找到相应的可变纹理,如果没有则new一个返回其指针。
  758. VolatileTexture*vt=findVolotileTexture(tt);
  759. //设置相关属性,注意:这里最好对vt做下有效性检查,如果为NULL的话会崩溃的。
  760. vt->m_eCashedImageType=kImageFile;
  761. vt->m_strFileName=imageFileName;
  762. vt->m_FmtImage=format;
  763. vt->m_PixelFormat=tt->getPixelFormat();
  764. }
  765. //通过CCImage对象生成可变纹理。
  766. voidVolatileTexture::addCCImage(CCTexture2D*tt,CCImage*image)
  767. {
  768. //通过纹理指针找到相应的可变纹理,如果没有则new一个返回其指针。
  769. VolatileTexture*vt=findVolotileTexture(tt);
  770. image->retain();
  771. //设置相关属性
  772. vt->uiImage=image;
  773. vt->m_eCashedImageType=kImage;
  774. }
  775. //通过纹理指针找到相应的可变纹理,如果没有则new出一个返回。
  776. VolatileTexture*VolatileTexture::findVolotileTexture(CCTexture2D*tt)
  777. {
  778. VolatileTexture*vt=0;
  779. //遍历list容器,对比查询。
  780. std::list<VolatileTexture*>::iteratori=textures.begin();
  781. while(i!=textures.end())
  782. {
  783. VolatileTexture*v=*i++;
  784. if(v->texture==tt)
  785. {
  786. vt=v;
  787. break;
  788. }
  789. }
  790. //如果没有找到,则由纹理参数new出一个可变纹理,new会调用其带参数的拷贝构造函数设置其对应纹理。
  791. if(!vt)
  792. {
  793. vt=newVolatileTexture(tt);
  794. }
  795. returnvt;
  796. }
  797. //通过指定图像数据,像素格式和图片大小来生成可变纹理。
  798. voidVolatileTexture::addDataTexture(CCTexture2D*tt,constCCSize&contentSize)
  799. {
  800. //如果正在重新载入过程中,直接返回。
  801. if(isReloading)
  802. {
  803. return;
  804. }
  805. //通过纹理指针找到相应的可变纹理,如果没有则new一个返回其指针。
  806. VolatileTexture*vt=findVolotileTexture(tt);
  807. //设置相关属性
  808. vt->m_eCashedImageType=kImageData;
  809. vt->m_pTextureData=data;
  810. vt->m_PixelFormat=pixelFormat;
  811. vt->m_TextureSize=contentSize;
  812. }
  813. //由字符串和相应信息生成可变纹理
  814. voidVolatileTexture::addStringTexture(CCTexture2D*tt,floatfontSize)
  815. {
  816. //如果正在重新载入过程中,直接返回。
  817. if(isReloading)
  818. {
  819. return;
  820. }
  821. //通过纹理指针找到相应的可变纹理,如果没有则new一个返回其指针。
  822. VolatileTexture*vt=findVolotileTexture(tt);
  823. //设置相关属性
  824. vt->m_eCashedImageType=kString;
  825. vt->m_size=dimensions;
  826. vt->m_strFontName=fontName;
  827. vt->m_alignment=alignment;
  828. vt->m_vAlignment=vAlignment;
  829. vt->m_fFontSize=fontSize;
  830. vt->m_strText=text;
  831. }
  832. //通过纹理指针找到相应的可变纹理并删除。
  833. voidVolatileTexture::removeTexture(CCTexture2D*t)
  834. {
  835. std::list<VolatileTexture*>::iteratori=textures.begin();
  836. while(i!=textures.end())
  837. {
  838. VolatileTexture*vt=*i++;
  839. if(vt->texture==t)
  840. {
  841. deletevt;
  842. break;
  843. }
  844. }
  845. }
  846. //重新载入所有的纹理。
  847. voidVolatileTexture::reloadAllTextures()
  848. {
  849. //设置开始进行重新载入所有纹理。
  850. isReloading=true;
  851. CCLOG("reloadalltexture");
  852. //通过迭代器遍历list容器
  853. std::list<VolatileTexture*>::iteratoriter=textures.begin();
  854. while(iter!=textures.end())
  855. {
  856. VolatileTexture*vt=*iter++;
  857. //根据不同的格式进行纹理的重建
  858. switch(vt->m_eCashedImageType)
  859. {
  860. casekImageFile:
  861. {
  862. //这里定义一个CCImage对象image
  863. CCImageimage;
  864. //先将路径名都变成小写字符串。
  865. std::stringlowerCase(vt->m_strFileName.c_str());
  866. for(unsignedinti=0;i<lowerCase.length();++i)
  867. {
  868. lowerCase[i]=tolower(lowerCase[i]);
  869. }
  870. //扩展名对比,如果是PVR文件
  871. if(std::string::npos!=lowerCase.find(".pvr"))
  872. {
  873. //取得原来的默认带ALPHA通道的像素格式。
  874. CCTexture2DPixelFormatoldPixelFormat=CCTexture2D::defaultAlphaPixelFormat();
  875. //重设默认带ALPHA通道的像素格式。
  876. CCTexture2D::setDefaultAlphaPixelFormat(vt->m_PixelFormat);
  877. //纹理重新由PVR文件进行初始化。会用到新的默认带ALPHA通道的像素格式。
  878. vt->texture->initWithPVRFile(vt->m_strFileName.c_str());
  879. //重设原来的默认带ALPHA通道的像素格式。
  880. CCTexture2D::setDefaultAlphaPixelFormat(oldPixelFormat);
  881. }
  882. else
  883. {
  884. //如果是非PVR文件。
  885. unsignedlongnSize=0;
  886. //通过文件工具集中的接口读入图片文件并返回数据地址。
  887. unsignedchar*pBuffer=CCFileUtils::sharedFileUtils()->getFileData(vt->m_strFileName.c_str(),&nSize);
  888. //使用数据地址对前面定义的CCImage对象image进行初始化。
  889. if(image.initWithImageData((void*)pBuffer,vt->m_FmtImage))
  890. {
  891. //取得原来的默认带ALPHA通道的像素格式。
  892. CCTexture2DPixelFormatoldPixelFormat=CCTexture2D::defaultAlphaPixelFormat();
  893. //重设默认带ALPHA通道的像素格式。CCTexture2D::setDefaultAlphaPixelFormat(vt->m_PixelFormat);
  894. //纹理重新由图片对象初始化。会用到新的默认带ALPHA通道的像素格式。
  895. vt->texture->initWithImage(&image);
  896. //重设原来的默认带ALPHA通道的像素格式。
  897. CCTexture2D::setDefaultAlphaPixelFormat(oldPixelFormat);
  898. }
  899. CC_SAFE_DELETE_ARRAY(pBuffer);
  900. }
  901. }
  902. break;
  903. casekImageData:
  904. {
  905. //纹理重新由图片数据初始化。
  906. vt->texture->initWithData(vt->m_pTextureData,
  907. vt->m_PixelFormat,
  908. vt->m_TextureSize.width,
  909. vt->m_TextureSize.height,
  910. vt->m_TextureSize);
  911. }
  912. break;
  913. casekString:
  914. {
  915. //纹理重新由字符串初始化。
  916. vt->texture->initWithString(vt->m_strText.c_str(),
  917. vt->m_size,
  918. vt->m_alignment,
  919. vt->m_vAlignment,
  920. vt->m_strFontName.c_str(),
  921. vt->m_fFontSize);
  922. }
  923. break;
  924. casekImage:
  925. {
  926. //纹理重新由图片对象初始化。
  927. vt->texture->initWithImage(vt->uiImage);
  928. }
  929. break;
  930. default:
  931. break;
  932. }
  933. }
  934. //设置重新载入完成
  935. isReloading=false;
  936. }
  937. #endif//CC_ENABLE_CACHE_TEXTURE_DATA
  938. NS_CC_END

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


    本文实践自 RayWenderlich、Ali Hafizji 的文章《How To Create Dynamic Textures with CCRenderTexture in Cocos2D 2.X》,文中使用Cocos2D,我在这里使用Cocos2D-x 2.1.4进行学习和移植。在这篇文章,将会学习到如何创建实时纹理、如何用Gimp创建无缝拼接纹
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@163.com微信公众号:HopToad 欢迎转载,转载标注出处:http://blog.csdn.netotbaron/article/details/424343991.  软件准备 下载地址:http://cn.cocos2d-x.org/download 2.  简介2.1         引用C
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从Cocos2D-x官网上下载,进入网页http://www.cocos2d-x.org/download,点击Cocos2d-x以下的Download  v3.0,保存到自定义的文件夹2:从python官网上下载。进入网页https://www.python.org/downloads/,我当前下载的是3.4.0(当前最新
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发引擎,易学易用,支持多种智能移动平台。官网地址:http://cocos2d-x.org/当前版本:2.0    有很多的学习资料,在这里我只做为自己的笔记记录下来,错误之处还请指出。在VisualStudio2008平台的编译:1.下载当前稳
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《最强大脑》娱乐节目。将2048改造成一款挑战玩家对数字记忆的小游戏。邮箱:appdevzw@163.com微信公众号:HopToadAPK下载地址:http://download.csdn.net/detailotbaron/8446223源码下载地址:http://download.csdn.net/
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试以QtCreatorIDE来进行CMake构建。Cocos2d-x3.X地址:https://github.com/cocos2d/cocos2d-x1.打开QtCreator,菜单栏→"打开文件或项目...",打开cocos2d-x目录下的CMakeLists.txt文件;2.弹出CMake向导,如下图所示:设置
 下载地址:链接:https://pan.baidu.com/s/1IkQsMU6NoERAAQLcCUMcXQ提取码:p1pb下载完成后,解压进入build目录使用vs2013打开工程设置平台工具集,打开设置界面设置: 点击开始编译等待编译结束编译成功在build文件下会出现一个新文件夹Debug.win32,里面就是编译
分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net前言上次用象棋演示了cocos2dx的基本用法,但是对cocos2dx并没有作深入的讨论,这次以超级马里奥的源代码为线索,我们一起来学习超级马里奥的实
1. 圆形音量button事实上作者的本意应该是叫做“电位计button”。可是我觉得它和我们的圆形音量button非常像,所以就这么叫它吧~先看效果:好了,不多解释,本篇到此为止。(旁白: 噗。就这样结束了?)啊才怪~我们来看看代码:[cpp] viewplaincopyprint?CCContro
原文链接:http://www.cnblogs.com/physwf/archive/2013/04/26/3043912.html为了进一步深入学习贯彻Cocos2d,我们将自己写一个场景类,但我们不会走的太远,凡是都要循序渐进,哪怕只前进一点点,那也至少是前进了,总比贪多嚼不烂一头雾水的好。在上一节中我们建
2019独角兽企业重金招聘Python工程师标准>>>cocos2d2.0之后加入了一种九宫格的实现,主要作用是用来拉伸图片,这样的好处在于保留图片四个角不变形的同时,对图片中间部分进行拉伸,来满足一些控件的自适应(PS: 比如包括按钮,对话框,最直观的形象就是ios里的短信气泡了),这就要求图
原文链接:http://www.cnblogs.com/linji/p/3599478.html1.环境和工具准备Win7VS2010/2012,至于2008v2版本之后似乎就不支持了。 2.安装pythonv.2.0版本之前是用vs模板创建工程的,到vs2.2之后就改用python创建了。到python官网下载版本2.7.5的,然后
环境:ubuntu14.04adt-bundle-linux-x86_64android-ndk-r9d-linux-x86_64cocos2d-x-3.0正式版apache-ant1.9.3python2.7(ubuntu自带)加入环境变量exportANDROID_SDK_ROOT=/home/yangming/adt-bundle-linux/sdkexportPATH=${PATH}:/$ANDROID_SDK_ROOTools/export
1开发背景游戏程序设计涉及了学科中的各个方面,鉴于目的在于学习与进步,本游戏《FlappyBird》采用了两个不同的开发方式来开发本款游戏,一类直接采用win32底层API来实现,另一类采用当前火热的cocos2d-x游戏引擎来开发本游戏。2需求分析2.1数据分析本项目要开发的是一款游
原文链接:http://www.cnblogs.com/linji/p/3599912.html//纯色色块控件(锚点默认左下角)CCLayerColor*ccc=CCLayerColor::create(ccc4(255,0,0,128),200,100);//渐变色块控件CCLayerGradient*ccc=CCLayerGradient::create(ccc4(255,0,0,
原文链接:http://www.cnblogs.com/linji/p/3599488.html//载入一张图片CCSprite*leftDoor=CCSprite::create("loading/door.png");leftDoor->setAnchorPoint(ccp(1,0.5));//设置锚点为右边中心点leftDoor->setPosition(ccp(240,160));/
为了答谢广大学员对智捷课堂以及关老师的支持,现购买51CTO学院关老师的Cocos2d-x课程之一可以送智捷课堂编写图书一本(专题可以送3本)。一、Cocos2d-x课程列表:1、Cocos2d-x入门与提高视频教程__Part22、Cocos2d-x数据持久化与网络通信__Part33、Cocos2d-x架构设计与性能优化内存优
Spawn让多个action同时执行。Spawn有多种不同的create方法,最终都调用了createWithTwoActions(FiniteTimeAction*action1,FiniteTimeAction*action2)方法。createWithTwoActions调用initWithTwoActions方法:对两个action变量初始化:_one=action1;_two=action2;如果两个a
需要环境:php,luajit.昨天在cygwin上安装php和luajit环境,这真特么是一个坑。建议不要用虚拟环境安装打包环境,否则可能会出现各种莫名问题。折腾了一下午,最终将环境转向linux。其中,luajit的安装脚本已经在quick-cocos2d-x-develop/bin/中,直接luajit_install.sh即可。我的lin
v3.0相对v2.2来说,最引人注意的。应该是对触摸层级的优化。和lambda回调函数的引入(嗯嗯,不枉我改了那么多类名。话说,每次cocos2dx大更新。总要改掉一堆类名函数名)。这些特性应该有不少人研究了,所以今天说点跟图片有关的东西。v3.0在载入图片方面也有了非常大改变,仅仅只是