Cocos2d-x游戏开发实战精解
上QQ阅读APP看书,第一时间看更新

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();

提示:清理缓存的顺序一定是先清理动画缓存再清理精灵帧缓存,最后才是纹理缓存。按照引用的顺序从高层到底层才能避免不必要的错误。