1.cocos2d中的动画,(10帧的动画为例,每帧长宽6*6,需要展示10个动画,RGBA8888 图片模式)
动画一般是逐帧动画,由一个帧序列构成,每一帧是一张图片
2.成本考虑
制作动画需要考虑的因素:cpu和GPU时间,内存,程序加载速度
3.1 cpu和GPU时间主要体现为opengl渲染的次数,因为每一次渲染需要若干个opengl调用,这是主要花费时间的瓶颈,所以关键是减少调用次数
3.2 内存也就是加载图片的大小,这个主要是和图片大小,opengl处理图片方式,图像像素表示方式
1. 首先是图片大小,必须加载的图片资源是不可避免的,关键是避免重复加载,最理想就是一个相同图片只加载一次,所有使用者可以重复引用它
2. opengl处理图片的大小时候总是会补齐2的n次方大小,比如你的图片是64*65,那么实际加载是opengl会补齐到64*128。这明显是一种浪费
3. opengl里采用像素图,图由一个个像素点构成,每个点可能包含RGBA 4种信息,可以设置这4种信息的存储方式,举例来说RGBA8888 这种方式
那么RGBA分别占了8位,R8位也就是说可以表示256种R的深度,其实就是常用的RGB(255,255,255)+255通道的方式。相应的还有GRGA4444 方式
从名字可以看出,占用空间就会少一半,这样的图片内存大小就会少大概一半,RGBA888每个点大小:4字节,后者2字节
3.3 程序加载速度,就是程序读入内存,并且运行的过程,这中间有个重要的影响是图片格式的转换,图片需要从原本格式一步步转换为opengl所支持的格式,虽然也许
这个过程本来很快,但相对于本来就不多的加载时间,还是可以节省的。
4.制作方式
(1)最简单的制作方式是将每一张图片加载到一个精灵。通过不断切换精灵,达到动画效果
这种方式耗费的内存是:每张图片6*6大小每次要补齐到8*8,一共大小8*8*10=640左右个像素点,内存消耗640*4=2560字节
opengl需要渲染的次数是10*10=100次,(总次数100,每次由很多的小的函数构成)
(2)第二种方式是通过纹理贴图。将10张小图贴成一张大图,用一个plist文件记录原来每个小图的位置索引(名字也可以)
图片大小方面:那么可以排列成大小30*12(分成两排,每排5张小图),补齐后32*16*4=2048字节,这只是我随便的一种排列,利用编辑软件总能找到最好的方式
opengl调用次数:1次。
加载格式方面,PVR图像是专门为ios设备上面的PowerVR图形芯片指定的图像容器。它们在ios设备上非常好用,因为可以直接加载到显卡上面,而不需要经过中间的转 化。普通的png和别的格式总是要经过转化的。新版的cocos支持直接使用pvr格式。pvr就是一种图像格式而已,plist仍然是需要的opengl可以直接使用。
5.抖动
拿RGBA8888 和GRGA4444 两种模式来说,当采用的像素深度减少图像质量变差时,图像中颜色丰富变化的地方会出现颜色梯度,表现为一道道的颜色条。
直接的改变方式是调整图像模式,采用高质量图片,但是这样会增加大小。抖动功能用于在不改变图片质量的情况下尽量使这种梯度变化平滑,其实就是一种图像处理算 法。
6.图片编辑工具选择
用ps肯定是不现实的呵呵,流行的工具是Texture Packer 和Zwoptex,两者作用一样都是小图拼大图,并提供小图的索引文件
Texture Packer优势:有免费版本,支持抖动功能,同时支持命令行工具支持和GUI,能生成pvr格式
7.传统方式代码:
加载一个精灵:CCSprite *bloodItem0 = [CCSprite spriteWithFile:@"bloodItem0.png"];
[self addChild:bloodItem0 z:1];
制作动画:
//1.建立帧数组,按文件名将每一帧图像放入数组
NSMutableArray *frames=[ NSMutableArray arrayWithCapacity:10];
for(int i=1; i<10 ; i++)
{
//磁盘图像文件-》纹理对象-》帧对象
NSString *file = [ NSString stringWithFormat:@"bloodItem%d.png",i];
CCTexture2D *bloodtxe= [[CCTextureCache sharedTextureCache] addImage:file];
CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:bloodtxe rect:CGRectMake(0,0,bloodtxe.contentSize.width,bloodtxe.contentSize.height)];
[frames addObject:frame];
}
//2.根据帧数组建立动画
//帧数组-》animation->animate->action->sprite run action -> addsprite to player
CCAnimation *bloodChange=[ CCAnimation animationWithSpriteFrames:frames delay:0.3];
CCAnimate *animate = [CCAnimate actionWithAnimation:bloodChange];
CCSpriteFrame *frame1 = [frames objectAtIndex:0];
CCSprite *blood=[CCSprite spriteWithSpriteFrame:frame1];
blood.position = ccp(100,100);
CCAction *repeat=[CCRepeatForever actionWithAction:animate];
[self addChild:blood];
[blood runAction:repeat];
8.贴图方式:
//1.加载大图(CCSpriteBatchNode对象)
CCSpriteBatchNode *spritesBgNode=[ CCSpriteBatchNode batchNodeWithFile:@"sprites-hd.pvr.ccz"];
[self addChild:spritesBgNode];
//2.将大图中的每个精灵作为一帧加载到帧缓冲区(以供别人引用)
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"sprites-hd.pv.plist"];
//3.制作帧数组
NSMutableArray *frames=[ NSMutableArray arrayWithCapacity:10];
for(int i=1; i<10 ; i++)
{
//磁盘图像文件-》纹理对象-》帧对象
NSString *file = [ NSString stringWithFormat:@"bloodItem%d.png",i];
CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:file];
[frames addObject:frame];
}
//动画制作同上