动画由帧组成。在最简单的情况下,每一帧都是一个纹理。我们可以使用一个纹理序列来创建动画。然而显卡在绘图时,在纹理间的切换是一个巨大的开销,由于精灵可以显示部分纹理,因此通常更为高效的做法是把动画用到的多个纹理按照一定的顺序排列起来,然后放置在同一个纹理下。在创建动画时,我们不仅需要指定动画所使用的纹理,还需要指定每一帧所使用的是纹理的哪一部分。
为了方便地记录纹理的显示信息,cocos2d-x提供了框帧类SpriteFrame。一个框帧包含两个属性,纹理与区域。纹理指的是将要被显示的纹理,而区域指此纹理将要被显示的部分。因此在动画中我们使用框帧来表示每一帧的内容。
我们准备好了框帧的序列,匀速地播放这一系列帧动画就不成问题了,然而我们也经常需要非匀速的动画效果,此时每一帧显示的时间就需要特殊设置了。为了描述每一帧,除了框帧,我们还需要记录帧的持续时间。动画帧类AnimationFrame同样包含两个属性,框帧的引用和帧的延时。
当游戏中有个界面用到的图片非常多,第一次点进这界面时速度非常慢(因为要加载绘制很多图片)出现卡顿,我们可以使用TextureCache提前异步加载纹理,等加载结束,进入到这个界面再使用这些图片速度就会非常快。
我们使用Animation类描述一个动画,而精灵显示动画的动作则是一个Animate对象。动画动作Animate是精灵显示动画的动作,它由一个动画对象创建,并由精灵执行。
我们可以手动添加序列帧到Animation类,或者使用文件初始化Animation类。
auto animation = Animation::create(); for(int i = 0; i < 10; ++i) { char s[100] = {0}; sprintf(s,"%d.png",i); // 添加精灵帧到Animation实例 animation->addSpriteFrameWithFile(s); } // 设置每一帧持续时间,以秒为单位 animation->setDelayPerUnit(2.8f / 10.0f); // 设置是否在动画播放结束后恢复到第一帧 animation->setRestoreOriginalFrame(true); auto action = Animate::create(animation); auto sprite = Sprite::create(); sprite->setPosition(100,100); this->addChild(sprite); sprite->runAction(Sequence::create(action,action->reverse(),NULL));
// 缓存plist文件 SpriteFrameCache::getInstance()->addSpriteFramesWithFile("gameArts-hd.plist","gameArts-hd.png"); Vector<SpriteFrame *> spriteFrame; SpriteFrame *s1 = SpriteFrameCache::getInstance()->getSpriteFrameByName("hero_fly_1.png"); SpriteFrame *s2 = SpriteFrameCache::getInstance()->getSpriteFrameByName("hero_fly_2.png"); spriteFrame.pushBack(s1); spriteFrame.pushBack(s2); auto animation = Animation::createWithSpriteFrames(spriteFrame,0.2f); auto animate = Animate::create(animation); auto repeatAction = RepeatForever::create(animate); this->runAction(repeatAction);