动画实际上是眼睛造成的错觉。一般情况下,如果每秒连续放映24张以上图片,人眼就看不出有停顿。如果帧速达到了60,甚至更高,那么基本上没人可以感觉到停顿了。动画就是利用这一特性,在每个连续的帧里面,让物体做一些小的变化,从而让人感觉物体自己在动一样。
就像下面的马儿,8张图片以1/60秒的速度播放,就是一只奔跑中的马儿。
动画相比与动作,可以完成更加复杂精细的动态效果,这是动作做不到的。动画需要做的就是在渲染每一帧的时候,连续地显示另外一张图片即可。但是图片是以文件形式存在的,我们要显示它,就需要把它读入内存,然后传给显存,最后再在屏幕上显示出来。图片文件一般都很大,特别是没有压缩过的文件。帧的绘制又必须在特定的时间内完成,如果不能完成,会导致显示错误,比如显示不全,抖动等。因此我们需要减少读文件和大量图片数据的传输。可以采取的办法有:
-
将动画的每帧纹理都放到一个大的文件当中。显示的时候,指定显示的区域即可。把显示的区域称为帧框。由于减少了文件的读取次数。文件一次读入后,就存在于内存,移动帧框比重新读取就要快很多。
-
将动画需要的纹理预先读入,并且缓存起来。在绘制帧的时候,再去读取文件,可能还是来不及了。因此,我们可以在使用之前就将纹理全部读入。现在的内存/显存容量已经很大,小游戏使用的纹理完全可以在游戏开始之前就全部载入。
这里先澄清下纹理和图片。纹理指的是一张表示物体表面细节的位图。位图是一种图片,但并不是所有的图片都可以作为纹理的,比如矢量图,或者当前平台不支持的图片格式。纹理的制作,一般不是码农可以兼任的。我们关心的是拿到纹理后怎么创建动画效果。
方式一:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
CCAnimation*animation=CCAnimation::create();
for
(
int
i=1;i<15;i++)
{
char
szName[100]={0};
sprintf
(szName,
"Images/horse_%02d.png"
,i);
animation->addSpriteFrameWithFileName(szName);
}
//shouldlast1.5seconds.Andthereare8frames.
animation->setDelayPerUnit(1.5f/8f);
//whetherornotitshallrestoretheoriginalframewhentheanimationfinishes
animation->setRestoreOriginalFrame(
true
);
CCAnimate*action=CCAnimate::create(animation);
m_grossini->runAction(CCSequence::create(action,action->reverse(),NULL));
|
方式二:
float
w=texture->getContentSize().width/numOfHorseFrame;
h=texture->getContentSize().height;
CCAnimation*animation=CCAnimation::create();
//shouldlast1.5seconds.Andthereare8frames.
animation->setDelayPerUnit(1.5f/8f);
//whetherornotitshallrestoretheoriginalframewhentheanimationfinishes
);
i=0;i<numOfHorseFrame;i++)
animation->addFrameWithTexture(texture,CCRectMake(i*w,w,h));
CCAnimate*animate=CCAnimate::create(animation);
horse->runAction(CCRepeatForever::create(animate));