前言:
精灵类是Sprite类。它的子类有PhysicsSprite 和 Skin。
PhysicsSprite 是物理引擎精灵类,而Skin是皮肤精灵类,用于骨骼动画。
创建Sprite精灵对象
创建精灵对象有多种方式,常用的函数如下:
1)创建一个精灵对象,纹理等属性需要在创建后设置
static Sprite* create();
2)指定图片创建精灵
static Sprite* create(const std::string& filename);
3)指定图片和裁剪的矩形区域来创建精灵
static Sprite* create(const std::string& filename, const Rect& rect);
4)指定纹理创建精灵
static Sprite* createWithTexture(Texture2D* texture);
5)指定纹理和裁剪的矩形区域来创建精灵,第3个参数指定是否旋转纹理,默认不旋转
static Sprite* createWithTexture(Texture2D* texture, const Rect& rect, bool rotated = false);
6)通过一个精灵帧对象创建另一个精灵对象
static Sprite* createWithSpriteFrame(SpriteFrame* pSpriteFrame);
7)通过指定帧缓存中精灵帧名 创建 精灵对象
static Sprite* createWithSpriteFrameName(cosnt std::string & spriteFrameName);
使用纹理图集
纹理图集(texture atlas)也称为精灵表(sprite sheet),它是把许多小的精灵图片组合到一张大图里面。
使用纹理图集(或精灵表)的优点如下:
1)减少文件读取次数,读取一张图片比读取一堆小文件要快;
2)减少OpenGL ES绘制调用并且加速渲染;
3)减少内存消耗
4)Cocos2d-x全面支持Zwoptex和 TexturePacker,所以创建和使用纹理图集是很容易的;
通常可以使用TexturePacker设计和生成纹理图集文件,以及纹理图集坐标文件(plist)组成。
通过 Director::getInstance()->getTextureCache() 函数可以获得 TextureCache 实例,TextureCache 的 addImage("tree1.png")函数可以创建纹理Texture2D对象,其中的tree1.png是纹理图片名。
使用纹理对象创建Sprite对象 代码示例:
1 auto spbk = Sprite::create("background.png"); 2 //// 此处没有设置position,默认的位置是 左下角 3 //spbk->setPosition(Point(origin.x + visibleSize.width / 2, origin.y + visibleSize.height / 2)); 4 spbk->setAnchorPoint(Point::ZERO); 5 this->addChild(spbk, 0); 6 7 //// 使用 纹理对象(Texture2D) 创建Sprite对象. 8 /// Rect(float x, float y, float width, float height); 9 // 参数rect是 tree1.png图片中,UI坐标系下,(604,38)坐标位置,宽302,高295的一个区域 10 auto tree1 = Sprite::create("tree1.png", Rect(604, 38, 302, 295)); 11 tree1->setPosition(Point(200, 230)); 12 this->addChild(tree1, 0); 13 14 Texture2D* cache = Director::getInstance()->getTextureCache()->addImage("tree1.png"); 15 auto tree2 = Sprite::create(); 16 tree2->setTexture(cache); 17 // 参数rect是 tree1.png图片中,UI坐标系下,(73,72)坐标位置,宽182,高270的一个区域 18 tree2->setTextureRect(Rect(73, 72, 182, 270)); 19 tree2->setPosition(Point(500, 200)); 20 this->addChild(tree2, 0);
使用精灵帧缓存
精灵帧缓存是缓存的一种。缓存有如下几种:
1)纹理缓存(TextureCache)。使用纹理缓存可以创建纹理对象。上面的部分有介绍。(一张 .png 图片即可)
2)精灵帧缓存(SpriteFrameCache)。能够从精灵表中创建精灵帧缓存,然后再从精灵帧缓存中获得精灵对象,反复使用精灵对象时,使用精灵帧缓存可以节省内存消耗。
(一个 .plist文件 以及 一张和 .plist文件对应的 .png图片)
3)动画缓存(AnimationCache)。动画缓存主要用于精灵动画,精灵动画中的每一帧是从动画缓存中获取的。
这里主要介绍 精灵帧缓存(SpriteFrameCache),要使用精灵帧缓存涉及的类有 SpriteFrame 和 SpriteFrameCache。
1 SpriteFrameCache* frameCache = SpriteFrameCache::getInstance(); 2 frameCache->addSpriteFramesWithFile("Demo3/SpriteSheet.plist"); /// 资源目录下必须有 SpriteSheet.png 文件 3 auto mountain1 = Sprite::createWithSpriteFrameName("mountain1.png"); // 通过精灵帧(SpriteSheet.png中的一张小图片),创建精灵对象
通过 SpriteFrameCache 创建精灵帧缓存对象,它是采用 单例设计模式进行设计的,getInstance()函数可以获得SpriteFrameCache单一实例,addSpriteFramesWithFile函数是将精灵帧添加到缓存中,其中SpriteSheet.plist 是坐标文件。可以多次调用 addSpriteFramesWithFile 函数添加更多的精灵帧到缓存中。
Sprite::createWithSpriteFrameName("mountain1.png") 是通过Sprite 的 createWithSpriteFrameName 函数创建精灵对象,其中的参数 mountain1.png 是 SpriteSheet.plist 在坐标文件中定义的精灵帧名。
1 /// SpriteFrameCache::getInstance()->addSpriteFramesWithFile("Demo3/SpriteSheet.plist"); 2 SpriteFrameCache* frameCache = SpriteFrameCache::getInstance(); 3 frameCache->addSpriteFramesWithFile("Demo3/SpriteSheet.plist"); 4 auto mountain1 = Sprite::createWithSpriteFrameName("mountain1.png"); /// 通过精灵帧(大图中的一个.png图片) 创建精灵 5 mountain1->setAnchorPoint(Point::ZERO); 6 mountain1->setPosition(Point(-200, 80)); 7 this->addChild(mountain1, 0); 8 9 /// SpriteFrameCache::getInstance()->getSpriteFrameByName("hero1.png"); 10 SpriteFrame* heroSpriteFrame = frameCache->getSpriteFrameByName("hero1.png"); /// 通过 精灵帧 创建 精灵帧对象 11 Sprite* hero1 = Sprite::createWithSpriteFrame(heroSpriteFrame); ///通过精灵帧对象(SpriteFrame类型) 创建精灵. 12 hero1->setPosition(Point(800, 200)); 13 this->addChild(hero1, 0);
精灵帧,精灵帧对象 的概念,有点类似于 变量和变量的指针。都可以用来表示同一个 object,只是表示的方式不一样。
精灵缓存不再使用后要移除相关精灵帧,否则如果再使用相同名称的精灵帧时,就会出现一些奇怪的现象。
移除精灵帧缓存的函数如下:
1)指定具体的精灵帧名移除
void removeSpriteFrameByName(const std::string& name);
2)指定移除精灵缓存
void removeSpriteFrames();
3)指定具体的坐标文件移除精灵帧
void removeSpriteFramesFromFile(const std::string& plist);
4)移除没有使用的精灵帧
void removeUnusedSpriteFrames();
为了防止该场景中的精灵缓存对下一个场景产生影响,可以在当前场景所在层的onExit函数中调用这些函数。
相关代码如下;
void HelloWorld::onExit()
{
Layer::onExit();
SpriteFrameCache::getInstance()->removeSpriteFrames();
}
当然,精灵帧缓存清除的工作也可以放到下一个场景创建时。也就是下一个场景所在层的init函数中实现。