精灵帧SpriteFrame的特性是记录一个纹理的指定渲染区域。通过Sprite::createWithSpriteFrame即可渲染纹理的这块区域。这样做的好处就是减少纹理创建次数(glTexImage2D),另一方面可以支持batch drawing。

一、使用示例

语雀内容

二、数据结构

  1. class CC_DLL SpriteFrame : public Ref, public Clonable
  2. {
  3. // ***********************
  4. // **** 纹理绘制区域相关数据
  5. // ***********************
  6. Vec2 _offset;
  7. Vec2 _anchorPoint;
  8. Size _originalSize;
  9. Rect _rectInPixels;
  10. bool _rotated;
  11. Rect _rect;
  12. Rect _centerRect;
  13. Vec2 _offsetInPixels;
  14. Size _originalSizeInPixels;
  15. Texture2D *_texture; // 绘制的纹理
  16. std::string _textureFilename; // 纹理的image file path
  17. PolygonInfo _polygonInfo;
  18. };

三、创建方法

  1. class CC_DLL SpriteFrame : public Ref, public Clonable
  2. {
  3. public:
  4. // filename: texture filename,注意并不会立即加载,而是在getTexture时,“懒加载”
  5. // rect: 指定在image file纹理的渲染区域。
  6. static SpriteFrame* create(const std::string& filename, const Rect& rect);
  7. static SpriteFrame* createWithTexture(Texture2D* pobTexture, const Rect& rect);
  8. static SpriteFrame* create(
  9. const std::string& filename, // texture filename
  10. const Rect& rect,
  11. bool rotated, // 为true,texture顺时针旋转90°
  12. const Vec2& offset, // A specified offset.
  13. const Size& originalSize); // size in pixels of the frame before being trimmed
  14. static SpriteFrame* createWithTexture(
  15. Texture2D* pobTexture,
  16. const Rect& rect,
  17. bool rotated,
  18. const Vec2& offset,
  19. const Size& originalSize);
  20. // Overrides
  21. virtual SpriteFrame *clone() const override;
  22. bool initWithTextureFilename(const std::string& filename, const Rect& rect);
  23. bool initWithTextureFilename(const std::string& filename, const Rect& rect, bool rotated, const Vec2& offset, const Size& originalSize);
  24. bool initWithTexture(Texture2D* pobTexture, const Rect& rect);
  25. bool initWithTexture(Texture2D* pobTexture, const Rect& rect, bool rotated, const Vec2& offset, const Size& originalSize);
  26. SpriteFrame* clone() const {
  27. // no copy constructor
  28. SpriteFrame *copy = new (std::nothrow) SpriteFrame();
  29. // 注意这里只考虑了_texture,并没有考虑_textureFilename情况
  30. copy->initWithTexture(_texture, _rectInPixels, _rotated, _offsetInPixels, _originalSizeInPixels);
  31. copy->setPolygonInfo(_polygonInfo);
  32. copy->autorelease();
  33. return copy;
  34. }
  35. }

四、SpriteFrameCache

SpriteFrameCache用于从plist文件批量加载并缓存spriteFrame。

1、plist格式

plist文件包含的内容如下:

  1. <!-- **************************************************************** -->
  2. <!-- *************************plist文件格式*************************** -->
  3. <!-- **************************************************************** -->
  4. <?xml version="1.0" encoding="UTF-8"?>
  5. <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  6. <plist version="1.0"> <!-- 最顶层标签总是plist -->
  7. <dict> <!-- 内容总是一个dict标签中,其实就可以看成是一个字典 -->
  8. <key>frames</key> <!-- Dictionary of sprites -->
  9. <dict>
  10. <!-- ******************************************************** -->
  11. <!-- ********************format=3的 frame******************** -->
  12. <!-- ******************************************************** -->
  13. <key>grossinis_sister1.png</key> <!-- sprite frame -->
  14. <dict>
  15. <key>aliases</key> <!-- 别名,和sprite frame等价 -->
  16. <array/>
  17. <!--
  18. difference vector between the original sprite's center
  19. and the center of the trimmed sprite.
  20. -->
  21. <key>spriteOffset</key>
  22. <string>{0,-11.5}</string>
  23. <key>spriteSize</key> <!-- size of the trimmed sprite -->
  24. <string>{50,116}</string>
  25. <key>spriteSourceSize</key> <!-- size of the original sprite -->
  26. <string>{52,139}</string>
  27. <key>textureRect</key> <!-- the position of the sprite in the sprite sheet -->
  28. <string>{{336,1},{50,116}}</string>
  29. <key>textureRotated</key> <!-- true if the sprite is rotated clockwise -->
  30. <false/>
  31. <!-- 以下是可选属性(optional) -->
  32. <key>triangles</key> <!-- 顶点索引,和下面vertices、verticesUV一一对应 -->
  33. <string>16 18 19 16 17 18 ......</string>
  34. <key>vertices</key> <!-- 顶点坐标(xy) in sprite coordinates -->
  35. <string>45 29 48 46 48 65 ......</string>
  36. <key>verticesUV</key> <!-- 纹理坐标(uv) in sprite sheet -->
  37. <string>380 7 383 24 383 4 ......</string>
  38. <key>anchor</key> <!-- spriteframe ancho point -->
  39. <string>{0,0}</string>
  40. </dict>
  41. <!-- ******************************************************** -->
  42. <!-- ********************format=0的 frame******************** -->
  43. <!-- ******************************************************** -->
  44. <key> grossinis_sister1.png </key> <!-- sprite frame -->
  45. <dict>
  46. <key>x</key>
  47. <integer>1</integer>
  48. <key>y</key>
  49. <integer>0</integer>
  50. <key>width</key>
  51. <integer>54</integer>
  52. <key>height</key>
  53. <integer>130</integer>
  54. <key>offsetX</key>
  55. <real>7.5</real>
  56. <key>offsetY</key>
  57. <real>-0.5</real>
  58. <key>originalWidth</key>
  59. <integer>91</integer>
  60. <key>originalHeight</key>
  61. <integer>139</integer>
  62. </dict>
  63. <!-- ********************************************************** -->
  64. <!-- ********************format=1/2的 frame******************** -->
  65. <!-- ********************************************************** -->
  66. <key> grossinis_sister1.png </key> <!-- sprite frame -->
  67. <dict>
  68. <key>frame</key>
  69. <string>{{336,1},{50,116}}</string>
  70. <key>rotated</key> <!-- format = 2 -->
  71. <false/>
  72. <key>offset</key>
  73. <string>{336,1}</string>
  74. <key>sourceSize</key>
  75. <string>{336,1}</string>
  76. </dict>
  77. </dict>
  78. <key>metadata</key> <!-- additional information about the sprite sheet -->
  79. <dict>
  80. <key>format</key> <!-- plist file format,0 ~ 3 -->
  81. <integer>3</integer>
  82. <key>textureFileName</key>
  83. <string>test_polygon.png</string>
  84. <key>size</key> <!-- size of the texture (optional) -->
  85. <string>{387,157}</string>
  86. <key>smartupdate</key>
  87. <string>$TexturePacker:SmartUpdate:5d4bd9b2c1ccd4361684aa299e869f18:750202f899ee4528e778a4b6691034fc:2c73308d8a452f8dfa4d258c8527607b$</string>
  88. <key>textureFileName</key> <!-- name of the texture's image file -->
  89. <string>test_polygon.png</string>
  90. </dict>
  91. <key>texture</key> <!-- key标签后面接了一个dict标签,通过这个key可以找到这个dict -->
  92. <dict>
  93. <key>width</key> <!-- key标签后面接了一个integer标签,通过这个key可以找到这个integer-->
  94. <integer>256</integer>
  95. <key>height</key>
  96. <integer>256</integer>
  97. </dict>
  98. </dict>
  99. </plist>

plist图片制作工具

  • TexturePacker
  • Zwoptex

    2、数据结构

    ```cpp

class CC_DLL SpriteFrameCache : public Ref { ValueMap _spriteFramesAliases; PlistFramesCache _spriteFramesCache; // 缓存SpriteFrame的地方 };

/**

  • used to wrap plist & frame names & SpriteFrames */ // 缓存SpriteFrame,并缓存了plist、frame name、sprite frame之间的对应关系。 class PlistFramesCache {

    // ** // *数 据 结 构 // ** // key: plist // value: SpriteFrame // 注意使用的CCMap结构,不是weak reference,因此这里是真正保存spriteframe的地方。 Map _spriteFrames;

    // key: plist // value: frame name std::unordered_map> _indexPlist2Frames;

    // key: frame name // value: plist std::unordered_map _indexFrame2plist;

    // key: plist // value: isFull std::unordered_map _isPlistFull;

  1. // ****************************************************
  2. // *********方 法
  3. // ****************************************************
  4. // 记录 plist <-> frame name <-> sprite frame的对应关系
  5. void insertFrame(const std::string &plist, const std::string &frame, SpriteFrame *frameObj);
  6. // 仅仅删除了plist <-> frame name 映射记录,没有清除spriteframe
  7. // 即只清除了_indexPlist2Frames、_indexFrame2plist里的相关数据
  8. // 注意,并没有清除_spriteFrames的相关数据,即
  9. bool eraseFrame(const std::string &frame);
  10. bool eraseFrames(const std::vector<std::string> &frame);
  11. // 同上,只不过是通过plist删除
  12. bool erasePlistIndex(const std::string &plist);
  13. // 这里将所有数据清空了,包括spriteFrame
  14. void clear();

};

  1. <a name="zTPV1"></a>
  2. ## 3、加载SpriteFrame
  3. ```cpp
  4. class CC_DLL SpriteFrameCache : public Ref
  5. {
  6. // 假设plist文件路径:"Images/grossini.plist",则加载plist配置和Images/grossini.png纹理
  7. void addSpriteFramesWithFile(const std::string& plist);
  8. // 功能同上,只不过另外指定了texture
  9. void addSpriteFramesWithFile(const std::string& plist, const std::string& textureFileName);
  10. void addSpriteFramesWithFile(const std::string& plist, Texture2D *texture);
  11. // 功能同上,只不过提供的直接就是plist文件的数据
  12. // auto plist_content = FileUtils::getInstnace()->getStringFromFile(plist)
  13. // plist name都是by#addSpriteFramesWithFileContent()
  14. void addSpriteFramesWithFileContent(const std::string& plist_content, Texture2D *texture);
  15. // 缓存单个SpriteFrame,
  16. // plist name都是:by#addSpriteFrame()
  17. void addSpriteFrame(SpriteFrame *frame, const std::string& frameName);
  18. // 重新加载
  19. bool reloadTexture(const std::string& plist);
  20. }

4、清除SpriteFrame

  1. class CC_DLL SpriteFrameCache : public Ref
  2. {
  3. // 清空所有缓存数据,一般是Memory Warning的时候调用。
  4. void removeSpriteFrames();
  5. // 清除所有没有被Sprite使用的SpriteFrame,即没有在被渲染绘制的。
  6. // 也即是清除引用计数=1的SpriteFrameCount
  7. // call this method after when starting a new Scene
  8. void removeUnusedSpriteFrames();
  9. // 清除指定SpriteFrame
  10. void removeSpriteFrameByName(const std::string& name);
  11. // 清除指定plist的所有SpriteFrame
  12. void removeSpriteFramesFromFile(const std::string& plist);
  13. void removeSpriteFramesFromFileContent(const std::string& plist_content);
  14. // 清除指定texture的所有SpriteFrame
  15. void removeSpriteFramesFromTexture(Texture2D* texture);
  16. }

5、获取SpriteFrame

  1. class CC_DLL SpriteFrameCache : public Ref
  2. {
  3. // 返回指定name的SpriteFrame
  4. // 注意: 返回的SpriteFrame可能会被SpriteFrameCache清除,因此最好自己retain。
  5. SpriteFrame* getSpriteFrameByName(const std::string& name);
  6. }