5.5 用打包后的图片创建动画
上一节学习了怎样利用一组连续的图像来播放动画,但是这种方式有一个缺点,就是非常浪费资源。现在看上一节范例5-4的第09行,该行用于获取图片素材并加载到动画中,而范例用到了8个素材图片,也就是说要连续读取8次文件,这就造成了一定的资源浪费。也许此时由于耗费的资源太少还看不出来,但是一个完整的游戏所需要的素材无疑是海量的,因此就需要有一种办法来解决。
可以使用一个叫做texturepacker的软件来将所需要的素材文件打包,获得一个大的图像文件和一个plist格式的XML文件,然后通过将它们读入到缓存中,可以达到只打开一次文件就实现了读取全部对象素材的作用。如图5-10就是一个使用texturepacker打包后得到的素材图片的例子。
图5-10 使用texturepacker打包后得到的素材图片
可以看到,texturepacker的作用实际上就是将各种素材拼接在了同一张图片中,而打包后所得到的一个plist文件,则是存放了这张图片中的单位与原图片素材中的映射关系,保证了程序可以知道自己该获取哪些需要的部分。Texturepacker的安装文件已经被收录到配套光盘的本章目录下,可以自行安装或者是上网搜索最新的版本进行安装。
Texturepacker安装好之后,运行界面如图5-11所示,可以单击图中圈出的按钮导入所需要的图片素材。然后单击Publish按钮保存生成的文件,如图5-12所示。
图5-11 Texturepacker运行界面
图5-12 保存生成的文件
之后就可以保存生成的文件,此时需要在弹出的对话框中填写生成文件的文件名,比如此时将文件生成至桌面并命名为run,就会弹出图5-13所示的对话框,以及桌面生成的文件run.png、run.plist。在范例5-5中将学习如何使用这两个文件。完整项目可查看ChapterFive05。
图5-13 run.plist文件内容
【范例5-5】用打包后的图片创建动画。
01 auto* sprite = Sprite::create("run1.png"); //创建精灵 02 sprite->setPosition(320, 180); 03 addChild(sprite); //将精灵加入到场景中 04 auto* m_frameCache = SpriteFrameCache::getInstance(); //获取动画缓存实例对象 05 m_frameCache->addSpriteFramesWithFile("run.plist", "run.png"); //添加帧动画文件到缓存 06 Vector<SpriteFrame*> frameArray; //创建序列备用 07 for (int i = 1; i < 9; i++) 08 { 09 auto* frame = m_frameCache->getSpriteFrameByName(String:: createWithFormat("run%d.png", 10 i)->getCString()); 11 frameArray.pushBack(frame); //将帧加入到序列中 12 } 13 Animation* animation = Animation::createWithSpriteFrames (frameArray); //创建动画 14 animation->setLoops(-1); //表示无限循环播放 15 animation->setDelayPerUnit(0.1f); //每两张图片的时间间隔,图片数目越少,间隔就越小 16 auto* action = Animate::create(animation); 17 sprite->runAction(action);
运行后的效果与图5-9完全相同,只不过这次运行效率提高了。
在第05行将动画文件加入到缓存之后,就可以通过原素材的文件名调用它们了,使用notepad打开文件run.plist,可以看到该文件内容,如图5-13所示,这样就不难理解第09行能够根据原素材文件的文件名索引到所需要的帧了。
需要注意,使用该方法创建动画必须在使用完之后清理缓存,清理缓存的方法如下:
AnimationCache::destroyInstance(); SpriteFrameCache::getInstance()->removeUnusedSpriteFrames(); TextureCache::getInstance()->removeUnuserdTextures();
提示:清理缓存的顺序一定是先清理动画缓存再清理精灵帧缓存,最后才是纹理缓存。按照引用的顺序从高层到底层才能避免不必要的错误。